"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = require("react");
var _classnames = _interopRequireDefault(require("classnames"));
var _constants = require("../../constants");
var _utils = require("../utils");
var _Input = _interopRequireDefault(require("../Input"));
var _Icon = _interopRequireDefault(require("../Icon"));
var _ComboBoxDropdown = _interopRequireWildcard(require("../ComboBoxDropdown"));
var _ComboBoxOption = _interopRequireDefault(require("./ComboBoxOption"));
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

const collect = function (children) {
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  _react.Children.forEach(children, child => {
    if ( /*#__PURE__*/(0, _react.isValidElement)(child) && child.type === _ComboBoxOption.default) {
      // eslint-disable-next-line prefer-const
      let {
        disabled,
        children: value,
        children,
        ...props
      } = child.props;
      if (typeof value !== 'string') {
        throw new Error('The value can only be a number or a string.');
      }
      const option = {
        value: String(value),
        children,
        disabled: Boolean(disabled),
        props
      };
      options.push(option);
    }
  });
  return {
    options
  };
};
/**
 * `ComboBox` component is a combination of [Select](#!/Select) and [Input](#!/Input)
 *  which allows to either enter a value directly into the field or choose from a list of existing options.
 * @since 2.6.0
 */
const ComboBox = _ref => {
  let {
    baseClassName = `${_constants.CLS_PREFIX}combobox`,
    className,
    value = '',
    onChange,
    disabled = false,
    size,
    textAlign,
    placeholder,
    children,
    ...props
  } = _ref;
  const [opened, setOpened] = (0, _react.useState)(false);
  const [highlightedIndex, setHighlightedIndex] = (0, _react.useState)(-1);
  const inputRef = (0, _react.useRef)(null);
  const controlRef = (0, _react.useRef)(null);
  const emitterRef = (0, _react.useRef)(new _utils.EventEmitter());
  const {
    options
  } = collect(children);
  const handleClose = () => {
    setOpened(false);
    setHighlightedIndex(-1);
  };
  const handleToggle = () => {
    if (opened) {
      handleClose();
    } else {
      setOpened(true);
      if (inputRef.current) {
        inputRef.current.focus();
      }
    }
  };
  const handleChange = nextValue => (0, _utils.safeInvoke)(onChange, nextValue);
  const handleInputChange = e => handleChange(e.target.value);
  const handleSelect = nextValue => {
    handleChange(nextValue);
    handleClose();
  };
  const moveHighlightedIndex = diff => {
    if (!opened) {
      setOpened(true);
    }
    const nextIndex = (0, _ComboBoxDropdown.findNextSafeIndex)(highlightedIndex, diff, options);
    if (nextIndex !== -1) {
      setHighlightedIndex(nextIndex);
      emitterRef.current.emit('focus', nextIndex);
    }
  };
  const confirmHighlightedIndex = index => {
    if (!opened && index === undefined) {
      return;
    }
    const option = options[index === undefined ? highlightedIndex : index];
    if (!option) {
      return;
    }
    if (option.disabled) {
      return;
    }
    const nextValue = option.value;
    (0, _utils.safeInvoke)(onChange, nextValue);
  };
  const handleHighlightedIndexChange = index => {
    setHighlightedIndex(index);
  };
  const handleKeyDown = e => {
    switch (e.key) {
      case 'ArrowUp':
        e.preventDefault();
        setOpened(true);
        moveHighlightedIndex(-1);
        break;
      case 'ArrowDown':
        e.preventDefault();
        setOpened(true);
        moveHighlightedIndex(1);
        break;
      case 'Enter':
        if (opened) {
          e.preventDefault();
          confirmHighlightedIndex(highlightedIndex);
          handleClose();
        }
        break;
      case 'Escape':
        e.preventDefault();
        handleClose();
        break;
    }
  };
  const button = /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
    className: `${baseClassName}__dropdown-button`,
    onClick: handleToggle,
    onMouseDown: e => e.preventDefault(),
    disabled: disabled,
    type: "button",
    tabIndex: -1,
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
      name: "chevron-down"
    })
  });
  const control = /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input.default, {
    className: (0, _classnames.default)(`${baseClassName}__input`, {
      [`${baseClassName}__input--disabled`]: disabled
    }),
    value: value,
    suffix: button,
    disabled: disabled,
    onChange: handleInputChange,
    onKeyDown: handleKeyDown,
    size: "fill",
    textAlign: textAlign,
    placeholder: placeholder,
    innerRef: el => {
      inputRef.current = el;
    },
    rootProps: {
      ref: controlRef
    }
  });
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ComboBoxDropdown.default, {
    className: (0, _classnames.default)(baseClassName, className, {
      [`${baseClassName}--size-${size}`]: size
    }),
    control: control,
    controlRef: controlRef,
    opened: opened && !disabled,
    disabled: disabled,
    groups: [{
      options
    }],
    options: options,
    onSelect: handleSelect,
    highlightedIndex: highlightedIndex,
    onHighlightedIndexChange: handleHighlightedIndexChange,
    onClose: handleClose,
    value: value,
    emitter: emitterRef.current,
    ...props
  });
};
const withDefaultValue = Component => {
  const Wrapper = props => {
    const {
      defaultValue,
      onChange
    } = props;
    const [value, setValue] = (0, _react.useState)(defaultValue);
    let propOverrides;
    if (props.value === undefined) {
      propOverrides = {
        value,
        onChange: nextValue => {
          setValue(nextValue);
          (0, _utils.safeInvoke)(onChange, nextValue);
        }
      };
    }
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(Component, {
      ...props,
      ...propOverrides
    });
  };
  Wrapper.displayName = `withDefaultValue(${Component.name})`;
  return Wrapper;
};
var _default = exports.default = withDefaultValue(ComboBox);