"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _classnames = _interopRequireDefault(require("classnames"));
var _react = require("react");
var _constants = require("../../constants");
var _utils = require("../../utils");
var _Badge = _interopRequireDefault(require("../Badge"));
var _Button = _interopRequireDefault(require("../Button"));
var _DistractionFreeModeContext = _interopRequireDefault(require("../DistractionFreeModeContext"));
var _Input = _interopRequireDefault(require("../Input"));
var _Menu = _interopRequireWildcard(require("../Menu"));
var _ResponsiveContext = _interopRequireDefault(require("../ResponsiveContext"));
var _utils2 = require("../utils");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

/**
 * `SearchBar` component is used for providing type-as-you-go search.
 * @since 0.0.58
 */
class SearchBar extends _react.Component {
  constructor() {
    super(...arguments);
    (0, _defineProperty2.default)(this, "state", {
      focused: false,
      overMenu: false,
      value: `${this.props.inputProps?.value || ''}`,
      highlightedValue: null
    });
    (0, _defineProperty2.default)(this, "isFocusScheduled", false);
    (0, _defineProperty2.default)(this, "search", void 0);
    (0, _defineProperty2.default)(this, "keyboardNavigation", key => {
      const {
        onItemSelect,
        results
      } = this.props;
      const highlightedValue = this.getHighlightedValue();
      if (!results || !onItemSelect) {
        return;
      }
      const res = this.getResults();
      const currentIndex = res.indexOf(highlightedValue);
      let nextIndex;
      if (key === 'ArrowUp') {
        nextIndex = Math.max(currentIndex - 1, 0);
      } else {
        nextIndex = Math.min(currentIndex + 1, res.length - 1);
      }
      this.setState({
        highlightedValue: currentIndex === -1 ? null : res[nextIndex]
      });
    });
    (0, _defineProperty2.default)(this, "handleFocus", () => {
      this.setState({
        focused: true
      });
      this.search && this.search.focus();
    });
    (0, _defineProperty2.default)(this, "handleBlur", () => {
      this.setState({
        focused: false
      });
      this.search && this.search.blur();
    });
    (0, _defineProperty2.default)(this, "handleMenuMouseOver", () => {
      this.setState({
        overMenu: true
      });
    });
    (0, _defineProperty2.default)(this, "handleMenuMouseOut", () => {
      this.setState({
        overMenu: false
      });
    });
    (0, _defineProperty2.default)(this, "handleKeyDown", e => {
      const {
        onTyping
      } = this.props;
      const {
        value
      } = e.currentTarget;
      if (['Enter', 'Escape', 'ArrowUp', 'ArrowDown'].indexOf(e.key) !== -1) {
        this.checkKeys(e.key);
        return;
      }
      this.setState({
        value
      });
      if (onTyping) {
        onTyping(value, () => this.clearInput());
      }
    });
    (0, _defineProperty2.default)(this, "handleSearch", () => {
      const {
        onSearch,
        onTyping
      } = this.props;
      const {
        value
      } = this.state;
      if (onSearch) {
        onSearch(value, () => this.clearInput());
      } else if (onTyping) {
        onTyping(value, () => this.clearInput());
      }
    });
    (0, _defineProperty2.default)(this, "handleReset", () => {
      this.clearInput();
      this.handleFocus();
    });
    (0, _defineProperty2.default)(this, "handleSelect", value => () => {
      const {
        onItemSelect
      } = this.props;
      this.setState({
        highlightedValue: null
      });
      this.handleBlur();
      if (onItemSelect) {
        onItemSelect(value, () => this.clearInput());
      } else {
        this.clearInput();
      }
    });
    (0, _defineProperty2.default)(this, "handleExpand", () => {
      const {
        onExpand,
        distractionFreeMode
      } = this.props;
      this.isFocusScheduled = true;
      (0, _utils2.safeInvoke)(onExpand);
      if (distractionFreeMode) {
        distractionFreeMode.toggle();
      }
    });
    (0, _defineProperty2.default)(this, "handleCollapse", () => {
      const {
        onCollapse,
        distractionFreeMode
      } = this.props;
      (0, _utils2.safeInvoke)(onCollapse);
      if (distractionFreeMode) {
        distractionFreeMode.toggle();
      }
    });
  }
  static getDerivedStateFromProps(props, state) {
    const {
      inputProps: {
        value: inputPropsValue
      } = {}
    } = props;
    const {
      prevInputProps: {
        value: prevInputPropsValue
      } = {}
    } = state;
    const nextState = {};
    if (inputPropsValue !== prevInputPropsValue) {
      nextState.value = inputPropsValue ?? '';
    }
    nextState.prevInputProps = props.inputProps;
    return nextState;
  }
  componentDidUpdate() {
    if (this.isFocusScheduled) {
      this.handleFocus();
      this.isFocusScheduled = false;
    }
  }
  isResponsive() {
    return this.props.responsive;
  }
  getResults(innerResults) {
    const {
      results
    } = this.props;
    if (!results) {
      return [];
    }
    if ('type' in results && results.type === _Menu.default || innerResults) {
      let res = [];
      const children = innerResults || results.props.children;
      if (!Array.isArray(children)) {
        return res;
      }
      for (let i = 0; i < children.length; i++) {
        const child = children[i];
        if (!child) {
          continue;
        }
        if (_react.Children.count(child) > 1) {
          res = res.concat(this.getResults(child));
        } else if ((child.type === _Menu.MenuItem || child.type === _Menu.MenuSelectableItem) && child.key) {
          res.push(child.key.toString());
        }
      }
      return res;
    }
    return results.map(_ref => {
      let {
        value
      } = _ref;
      return value;
    });
  }
  getHighlightedValue() {
    return (this.state.highlightedValue || this.getResults()[0]) ?? null;
  }
  searchAction() {
    const {
      onItemSelect,
      results
    } = this.props;
    const highlightedValue = this.getHighlightedValue();
    if (onItemSelect && results) {
      const res = this.getResults();
      const currentIndex = res.indexOf(highlightedValue);
      if (currentIndex === -1) {
        this.handleSearch();
      } else {
        this.handleSelect(highlightedValue)();
      }
    } else {
      this.handleSearch();
    }
  }
  checkKeys(key) {
    if (key === 'Enter') {
      this.searchAction();
    } else if (key === 'Escape') {
      if (this.state.value) {
        this.handleReset();
      } else {
        this.handleBlur();
        this.handleMenuMouseOut();
      }
    } else if (key === 'ArrowUp' || key === 'ArrowDown') {
      this.keyboardNavigation(key);
    }
  }
  clearInput() {
    this.setState({
      value: ''
    }, this.handleSearch);
  }
  elementsIndexToKeyMapping(elements) {
    let result = [];
    if (!Array.isArray(elements)) {
      return result;
    }
    for (let i = 0; i < elements.length; i++) {
      const element = elements[i];
      if (!element) {
        continue;
      }
      if (Array.isArray(element)) {
        result = result.concat(this.elementsIndexToKeyMapping(element));
      } else {
        result.push(element.key);
      }
    }
    return result;
  }
  renderResults(results) {
    const {
      baseClassName
    } = this.props;
    const {
      focused,
      overMenu
    } = this.state;
    const highlightedValue = this.getHighlightedValue();
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Menu.default, {
      className: (0, _classnames.default)(`${baseClassName}__results`, {
        [`${baseClassName}__results--hidden`]: !focused && !overMenu
      }),
      onMouseOver: this.handleMenuMouseOver,
      onMouseOut: this.handleMenuMouseOut,
      children: results.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Menu.MenuItem, {
        active: item.value === highlightedValue,
        onClick: this.handleSelect(item.value),
        children: item.title
      }, item.value))
    });
  }
  renderResultsMenu(results) {
    const {
      baseClassName,
      onItemSelect
    } = this.props;
    const {
      focused,
      overMenu
    } = this.state;
    const highlightedValue = this.getHighlightedValue();
    return /*#__PURE__*/(0, _react.cloneElement)(results, {
      className: (0, _classnames.default)(`${baseClassName}__results`, {
        [`${baseClassName}__results--hidden`]: !focused && !overMenu
      }, results.props.className),
      onMouseOver: this.handleMenuMouseOver,
      onMouseOut: this.handleMenuMouseOut,
      onItemClick: (_item, index) => {
        const indexMap = this.elementsIndexToKeyMapping(results.props.children);
        this.handleSelect(indexMap[index])();
      },
      children: _react.Children.map(results.props.children, child => {
        if (onItemSelect && child && typeof child === 'object' && 'type' in child && (child.type === _Menu.MenuItem || child.type === _Menu.MenuSelectableItem)) {
          return /*#__PURE__*/(0, _react.cloneElement)(child, {
            active: child.key === highlightedValue
          });
        }
        return child;
      })
    });
  }
  render() {
    const {
      baseClassName,
      className,
      maxWidth,
      minWidth,
      loading,
      responsive,
      onSearch,
      onTyping,
      onItemSelect,
      collapsable,
      onCollapse,
      onExpand,
      results,
      inputProps,
      distractionFreeMode,
      ...props
    } = this.props;
    const {
      focused,
      value
    } = this.state;
    const isCollapsed = this.isResponsive();
    const distractionFreeModeEnabled = Boolean(distractionFreeMode && distractionFreeMode.enabled);
    return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: (0, _classnames.default)(baseClassName, {
        [`${baseClassName}--focused`]: focused
      }, className),
      style: isCollapsed || distractionFreeModeEnabled ? undefined : {
        maxWidth,
        minWidth
      },
      ...props,
      children: isCollapsed && (collapsable || !distractionFreeModeEnabled) ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Badge.default, {
        intent: "info",
        hidden: !value,
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
          icon: "search",
          onClick: this.handleExpand
        })
      }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
        className: `${baseClassName}__group`,
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Input.default, {
          innerRef: ref => this.search = ref,
          className: `${baseClassName}__input`,
          size: "fill",
          onChange: this.handleKeyDown,
          onFocus: this.handleFocus,
          onBlur: this.handleBlur,
          onKeyDown: this.handleKeyDown,
          ...inputProps,
          value: value,
          prefix: (collapsable && !isCollapsed || distractionFreeModeEnabled) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
            icon: {
              name: 'chevron-right',
              flipHorizontal: (0, _utils.isRtl)()
            },
            ghost: true,
            onClick: this.handleCollapse
          }),
          suffix: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
            children: [value && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
              icon: "remove",
              onClick: this.handleReset,
              ghost: true
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
              icon: "search",
              onClick: this.handleSearch,
              state: loading ? 'loading' : undefined,
              ghost: true
            })]
          })
        }), Array.isArray(results) && this.renderResults(results), results && !Array.isArray(results) && results.type === _Menu.default && this.renderResultsMenu(results)]
      })
    });
  }
}
(0, _defineProperty2.default)(SearchBar, "defaultProps", {
  baseClassName: `${_constants.CLS_PREFIX}search-bar`,
  maxWidth: 500,
  minWidth: 270,
  inputProps: {}
});
const SearchBarWrapper = props => {
  const distractionFreeMode = (0, _react.useContext)(_DistractionFreeModeContext.default);
  let responsive = (0, _react.useContext)(_ResponsiveContext.default);
  responsive = props.responsive === undefined ? responsive || false : Boolean(props.responsive);
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(SearchBar, {
    ...props,
    responsive: responsive,
    distractionFreeMode: distractionFreeMode
  });
};
SearchBarWrapper.displayName = 'SearchBar';
var _default = exports.default = SearchBarWrapper;