"use strict";

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); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Select = void 0;
var _flatten2 = _interopRequireDefault(require("ramda/src/flatten"));
var _map2 = _interopRequireDefault(require("ramda/src/map"));
var _pipe2 = _interopRequireDefault(require("ramda/src/pipe"));
var _head2 = _interopRequireDefault(require("ramda/src/head"));
var _pathOr2 = _interopRequireDefault(require("ramda/src/pathOr"));
var _react = _interopRequireWildcard(require("react"));
var _react2 = require("@xstate/react");
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _Hooks = require("../../../common/Hooks");
var _wrappers = require("./lib/wrappers");
var _context = require("./lib/context");
var _defaults = require("./lib/defaults");
var _machine = require("./machine");
var _utils = require("../../../common/utils");
var _hooks = require("./lib/hooks");
var _constants = require("./lib/constants");
var _tracking = _interopRequireDefault(require("../../../common/tracking"));
var _utils2 = require("./lib/utils");
var _index = require("../../../index");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(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 && Object.prototype.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; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : 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(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(arr) { if (Array.isArray(arr)) return arr; }
var HiddenSelect = _styledComponents.default.select.withConfig({
  displayName: "Select__HiddenSelect",
  componentId: "sc-1ca7aak-0"
})(["display:none;"]);
var noop = function noop() {};
var getValuesForNativeSelect = function getValuesForNativeSelect(selectedItems, isMultiselect) {
  if (isMultiselect) {
    return selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.map(function (x) {
      return x.value;
    });
  }
  var value = (0, _utils2.getSingleSelectValue)(selectedItems);
  return (0, _pathOr2.default)(undefined, ['value'], (0, _head2.default)(value));
};
var Select = exports.Select = function Select(props) {
  (0, _utils.assert)(Boolean(props.id), "Input.Select: \"id\" is required.");
  (0, _utils.assert)(typeof props.value !== 'undefined' ? typeof props.onChange !== 'undefined' : true, "Input.Select: You can't use 'value' prop without onChange. It makes sense only if you want a readonly Input.Select, which is really weird. Don't do that.");
  var trackContext = (0, _react.useContext)(_tracking.default);
  var isFirstRender = (0, _hooks.useIsFirstRender)();
  var allOptions = (0, _react.useMemo)(function () {
    return (0, _pipe2.default)((0, _map2.default)(function (option) {
      return option.options ? [option, option.options] : option;
    }), _flatten2.default)(props.options);
  }, [props.options]);
  var smallScreen = (0, _index.useMedia)(function (t) {
    return t.media.lessThan(t.breakpoints.sm);
  });
  var isFullscreenOnMobile = smallScreen && props.fullscreenOnMobile && !props.withPortal;
  var isDisableSearchComponent = smallScreen && !props.showSearch ? true : props.disableSearchComponent;
  var machineHandlers = (0, _react2.useMachine)(_machine.SelectMachine, {
    context: {
      label: props.label,
      error: props.error || '',
      success: props.success || false,
      options: allOptions,
      selectedItems: [],
      disabled: props.disabled || false,
      open: false,
      itemFocusIdx: null,
      placeholder: props.placeholder || '',
      searchQuery: '',
      extraInfo: props.extraInfo || '',
      multiselect: props.multiselect || false,
      lastNavigationType: null,
      visibleOptions: allOptions,
      showSearch: props.showSearch || false,
      id: props.id,
      valueFromProps: props.value,
      uncommittedSelectedItems: [],
      actions: props.actions || [],
      disableSearchComponent: isDisableSearchComponent,
      fullscreenOnMobile: isFullscreenOnMobile || false,
      preventScroll: props.preventScroll || false
    }
  });
  var _machineHandlers = _slicedToArray(machineHandlers, 3),
    machineState = _machineHandlers[0],
    send = _machineHandlers[1],
    service = _machineHandlers[2];
  var currentPropsRef = (0, _react.useRef)(props);
  currentPropsRef.current = props;
  (0, _react.useEffect)(function () {
    var listener = function listener(e) {
      return trackContext && trackContext.track('Input.Select', e, currentPropsRef.current);
    };
    service.onEvent(listener);
    return function () {
      service.off(listener);
    };
  }, [trackContext, service]);
  (0, _react.useEffect)(function () {
    if (!props.onSearchQueryChange) return;
    var listener = function listener(e) {
      return e.type === _machine.ACTION_TYPES.SEARCH_QUERY_UPDATE && props.onSearchQueryChange(e);
    };
    service.onEvent(listener);
    return function () {
      service.off(listener);
    };
  }, [service, props.onSearchQueryChange]);
  (0, _hooks.usePropagateChangesThroughOnChange)(machineState, send, props.onChange, isFirstRender);
  (0, _hooks.useSyncPropsWithMachine)({
    searchQuery: props.searchQuery || machineState.context.searchQuery,
    label: props.label,
    options: allOptions,
    placeholder: props.placeholder,
    error: props.error,
    valueFromProps: props.value,
    success: props.success,
    disabled: props.disabled,
    extraInfo: props.extraInfo,
    multiselect: props.multiselect,
    showSearch: props.showSearch || false,
    id: props.id,
    actions: props.actions || [],
    disableSearchComponent: isDisableSearchComponent,
    fullscreenOnMobile: isFullscreenOnMobile || false,
    preventScroll: props.preventScroll || false
  }, [send, props.label, allOptions, props.placeholder, props.error, props.success, props.disabled, props.extraInfo, props.value, props.multiselect, props.showSearch, props.id, props.actions, props.searchQuery, isDisableSearchComponent, isFullscreenOnMobile, props.preventScroll]);
  var handleClickListItem = function handleClickListItem(option) {
    return function (e) {
      e.preventDefault();
      send({
        type: 'ITEM_CLICK',
        payload: option
      });
      return false;
    };
  };
  var handleClickActionItem = function handleClickActionItem(action) {
    return function (e) {
      e.preventDefault();
      send({
        type: 'SELECT_ITEM',
        payload: action
      });
      return false;
    };
  };
  var handleKeyDown = (0, _hooks.useDelegateKeyDownToMachine)(send, !props.showSearch);
  var isKeyboardNavigation = machineState.matches('interaction.enabled.active.navigation.keyboard');
  var handleMouseMove = (0, _react.useCallback)(function () {
    if (isKeyboardNavigation) {
      send('MOUSE_MOVE');
    }
  }, [send, isKeyboardNavigation]);
  var buttonRef = (0, _react.useRef)(null);
  var _useMultiRef = (0, _hooks.useMultiRef)(),
    _useMultiRef2 = _slicedToArray(_useMultiRef, 2),
    itemRefs = _useMultiRef2[0],
    setItemRef = _useMultiRef2[1];
  var listRef = (0, _react.useRef)(null);
  var formFieldRef = (0, _react.useRef)(null);
  var selectWrapperRef = (0, _react.useRef)(null);
  var inputRef = (0, _react.useRef)(null);
  var searchRef = (0, _react.useRef)(null);
  (0, _hooks.useAutofocus)(buttonRef, props.autoFocus);
  (0, _hooks.useFocusFromMachine)(machineState, buttonRef, itemRefs, searchRef, props.preventScroll);
  var _useOnBlurAndOnFocus = (0, _hooks.useOnBlurAndOnFocus)(machineState, send, props.onBlur, props.onFocus, formFieldRef, isFirstRender, inputRef, listRef),
    handleBlur = _useOnBlurAndOnFocus.handleBlur,
    handleFocus = _useOnBlurAndOnFocus.handleFocus;
  var _useComponentsWithDef = (0, _defaults.useComponentsWithDefaults)(props.components, {
      multiselect: machineState.context.multiselect
    }),
    ListItem = _useComponentsWithDef.ListItem,
    List = _useComponentsWithDef.List,
    ListFullScreen = _useComponentsWithDef.ListFullScreen,
    SelectedValue = _useComponentsWithDef.SelectedValue,
    Search = _useComponentsWithDef.Search,
    Action = _useComponentsWithDef.Action;
  var isOpen = machineState.context.open;
  var isDisabled = machineState.context.disabled;
  var error = machineState.context.error;
  var success = machineState.context.success;
  var extraInfo = machineState.context.extraInfo;
  var label = machineState.context.label;
  var placeholder = machineState.context.placeholder;
  var options = machineState.context.visibleOptions;
  var selectedItems = machineState.context.selectedItems;
  var multiselect = machineState.context.multiselect;
  var disableSearchComponent = machineState.context.disableSearchComponent;
  var isFullScreenMode = machineState.context.fullscreenOnMobile;
  var ListWrapperComponent = props.withPortal ? _wrappers.ListWrapperWithPortal : _wrappers.ListWrapper;
  var hiddenSelectValues = getValuesForNativeSelect(selectedItems, multiselect);
  (0, _Hooks.useOnClickOutside)([listRef, formFieldRef], function () {
    if (!isFullScreenMode) send({
      type: 'BLUR'
    });
  });
  var onClose = (0, _react.useCallback)(function () {
    send({
      type: 'CLOSE'
    });
  }, [send]);
  return _react.default.createElement("div", {
    className: props.className
  }, _react.default.createElement(HiddenSelect, _extends({
    name: props.name,
    disabled: isDisabled,
    ref: inputRef,
    "aria-hidden": "true"
  }, multiselect ? {
    multiple: true
  } : {}, {
    value: hiddenSelectValues,
    onChange: noop
  }), placeholder && _react.default.createElement("option", {
    label: placeholder,
    value: ""
  }), options === null || options === void 0 ? void 0 : options.map(function (x) {
    var _x$options;
    return x.options ? _react.default.createElement("optgroup", {
      label: x.label,
      key: x.label
    }, (_x$options = x.options) === null || _x$options === void 0 ? void 0 : _x$options.map(function (y) {
      return _react.default.createElement("option", {
        label: y.label,
        value: y.value,
        key: "".concat(y.label).concat(y.value)
      });
    })) : _react.default.createElement("option", {
      label: x.label,
      value: x.value,
      key: "".concat(x.label).concat(x.value)
    });
  })), _react.default.createElement(_context.SelectStateContext.Provider, {
    value: machineHandlers
  }, _react.default.createElement(_wrappers.FormFieldOrFragment, {
    label: label,
    hideLabel: props.hideLabel,
    labelToolTip: props.labelTooltip,
    labelTooltipPosition: props.labelTooltipPosition,
    labelTooltipInModal: props.labelTooltipInModal,
    noFormField: props.noFormField,
    ref: formFieldRef,
    innerRef: selectWrapperRef,
    disabled: isDisabled,
    open: isOpen,
    fullWidth: props.fullWidth,
    error: error,
    success: success,
    extraInfo: extraInfo,
    height: props.height,
    id: props.id,
    size: props.size,
    onFocus: handleFocus,
    onBlur: !isFullScreenMode ? handleBlur : undefined,
    width: props.width
  }, _react.default.createElement(_wrappers.SelectedValueWrapper, {
    ref: buttonRef,
    open: isOpen,
    label: label,
    disabled: isDisabled,
    noFormField: props.noFormField,
    placeholder: placeholder,
    component: SelectedValue,
    options: options,
    state: machineState,
    id: props.id
  }), isOpen && !isFullScreenMode && _react.default.createElement(ListWrapperComponent, {
    component: List,
    itemsPerColumn: props.itemsPerColumn,
    columnWidth: props.columnWidth,
    triggerElement: selectWrapperRef,
    noFormField: props.noFormField,
    onKeyDown: handleKeyDown,
    onMouseMove: handleMouseMove,
    ref: listRef,
    searchComponent: !disableSearchComponent && _react.default.createElement(_wrappers.SearchWrapper, {
      ref: searchRef,
      component: Search
    }),
    listPosition: props.listPosition,
    listWidth: props.listWidth,
    placement: props.placement,
    invertedColors: props.invertedColors,
    actionsComponent: machineState.context.actions.length > 0 ? _react.default.createElement(_wrappers.ActionsWrapper, {
      component: Action,
      onClickFactory: handleClickActionItem
    }) : null,
    maxHeight: props.listMaxHeight,
    width: props.listWidth || props.width
  }, options === null || options === void 0 ? void 0 : options.filter(function (x) {
    return !(props.hideDisabledOptions && x.disabled);
  }).map(function (x, index) {
    return _react.default.createElement(_wrappers.ListItemWrapper, {
      key: index,
      index: index,
      ref: setItemRef(index),
      option: x,
      id: props.id,
      onClick: x.disabled || x.options ? noop : handleClickListItem(x),
      component: ListItem
    });
  })), isOpen && isFullScreenMode && _react.default.createElement(_index.Modal, {
    open: isOpen,
    title: _react.default.createElement(_index.Typography, {
      type: "title1",
      weight: "bold"
    }, props.label),
    onClose: onClose
  }, _react.default.createElement(ListWrapperComponent, {
    component: ListFullScreen,
    triggerElement: selectWrapperRef,
    noFormField: props.noFormField,
    onKeyDown: handleKeyDown,
    onMouseMove: handleMouseMove,
    ref: listRef,
    searchComponent: !disableSearchComponent && _react.default.createElement(_wrappers.SearchWrapper, {
      ref: searchRef,
      component: Search
    }),
    listPosition: props.listPosition,
    listWidth: props.listWidth,
    placement: "top",
    invertedColors: props.invertedColors,
    actionsComponent: machineState.context.actions.length > 0 ? _react.default.createElement(_wrappers.ActionsWrapper, {
      component: Action,
      onClickFactory: handleClickActionItem
    }) : null,
    maxHeight: props.listMaxHeight
  }, options === null || options === void 0 ? void 0 : options.filter(function (x) {
    return !(props.hideDisabledOptions && x.disabled);
  }).map(function (x, index) {
    return _react.default.createElement(_wrappers.ListItemWrapper, {
      key: index,
      index: index,
      ref: setItemRef(index),
      option: x,
      id: props.id,
      onClick: x.disabled || x.options ? noop : handleClickListItem(x),
      component: ListItem
    });
  }))))));
};
Select.useSelectMachineFromContext = _context.useSelectMachineFromContext;
Select.ACTION_TYPES = _machine.ACTION_TYPES;
Select.SYMBOL_ALL = _constants.SYMBOL_ALL;
Select.defaults = {
  components: _defaults.defaultComponents,
  componentsMultiselect: _defaults.defaultComponentsMultiselect
};