"use strict";

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

function _jsxRuntime() {
  const data = require("react/jsx-runtime");

  _jsxRuntime = function () {
    return data;
  };

  return data;
}

function _react() {
  const data = _interopRequireWildcard(require("react"));

  _react = function () {
    return data;
  };

  return data;
}

function _clsx() {
  const data = _interopRequireDefault(require("clsx"));

  _clsx = function () {
    return data;
  };

  return data;
}

function _icons() {
  const data = require("@react-vant/icons");

  _icons = function () {
    return data;
  };

  return data;
}

var _utils = require("../utils");

var _hooks = require("../hooks");

var _tabs = _interopRequireDefault(require("../tabs"));

var _ConfigProviderContext = _interopRequireDefault(require("../config-provider/ConfigProviderContext"));

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

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; }

/* eslint-disable no-plusplus */
const INITIAL_STATE = {
  tabs: [],
  activeTab: 0
};

const Cascader = props => {
  const {
    prefixCls,
    createNamespace,
    locale
  } = (0, _react().useContext)(_ConfigProviderContext.default);
  const [bem] = createNamespace('cascader', prefixCls);
  const [internalValue, updateInternalValue] = (0, _react().useState)(undefined);
  const [state, updateState] = (0, _hooks.useSetState)(INITIAL_STATE);
  const {
    text: textKey,
    value: valueKey,
    children: childrenKey
  } = (0, _utils.extend)({
    text: 'text',
    value: 'value',
    children: 'children'
  }, props.fieldNames);

  const getSelectedOptionsByValue = (options, value) => {
    for (let i = 0; i < options.length; i++) {
      const option = options[i];

      if (option[valueKey] === value) {
        return [option];
      }

      if (option[childrenKey]) {
        const selectedOptions = getSelectedOptionsByValue(option[childrenKey], value);

        if (selectedOptions) {
          return [option, ...selectedOptions];
        }
      }
    }

    return undefined;
  };

  const updateTabs = () => {
    if (internalValue || internalValue === 0) {
      const selectedOptions = getSelectedOptionsByValue(props.options, internalValue);

      if (selectedOptions) {
        let optionsCursor = props.options;
        const tabs = selectedOptions.map(option => {
          const tab = {
            options: optionsCursor,
            selectedOption: option
          };
          const next = optionsCursor.find(item => item[valueKey] === option[valueKey]);

          if (next) {
            optionsCursor = next[childrenKey];
          }

          return tab;
        });

        if (optionsCursor) {
          tabs.push({
            options: optionsCursor,
            selectedOption: null
          });
        }

        updateState({
          tabs
        });
        setTimeout(() => {
          updateState({
            activeTab: tabs.length - 1
          });
        }, 0);
        return;
      }
    }

    updateState({
      tabs: [{
        options: props.options,
        selectedOption: null
      }]
    });
  };

  const onSelect = (option, tabIndex) => {
    var _a, _b;

    if (option.disabled) {
      return;
    }

    let tabs = JSON.parse(JSON.stringify(state.tabs));
    tabs[tabIndex].selectedOption = option;

    if (tabs.length > tabIndex + 1) {
      tabs = tabs.slice(0, tabIndex + 1);
    }

    if (option[childrenKey]) {
      const nextTab = {
        options: option[childrenKey],
        selectedOption: null
      };

      if (tabs[tabIndex + 1]) {
        tabs[tabIndex + 1] = nextTab;
      } else {
        tabs.push(nextTab);
      }

      updateState({
        tabs,
        activeTab: state.activeTab + 1
      });
    }

    const selectedOptions = tabs.map(tab => tab.selectedOption).filter(Boolean);
    const eventParams = {
      value: option[valueKey],
      tabIndex,
      selectedOptions
    };
    updateInternalValue(option[valueKey]);
    (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, eventParams);

    if (!option[childrenKey]) {
      (_b = props.onFinish) === null || _b === void 0 ? void 0 : _b.call(props, eventParams);
    }
  };

  const onClose = () => {
    var _a;

    return (_a = props.onClose) === null || _a === void 0 ? void 0 : _a.call(props);
  };

  const onClickTab = ({
    name,
    title
  }) => {
    var _a;

    updateState({
      activeTab: +name
    });
    (_a = props.onClickTab) === null || _a === void 0 ? void 0 : _a.call(props, +name, title);
  };

  const getStateFromValue = value => {
    if (!value || !value.length) return INITIAL_STATE;

    try {
      const initialState = {
        activeTab: value.length - 1,
        tabs: []
      };
      value.reduce((options, v) => {
        const selectedOption = options.find(tabs => tabs[valueKey] === v);
        if (!selectedOption) throw Error('Cascader: unable to match options correctly, Please check value or defaultValue props.');
        initialState.tabs.push({
          options,
          selectedOption
        });
        return selectedOption[childrenKey];
      }, props.options);
      return initialState;
    } catch (error) {
      // eslint-disable-next-line no-console
      console.error(error);
      return INITIAL_STATE;
    }
  };

  const renderCloseIcon = () => {
    if (!props.closeable) return null;

    if (props.closeIcon) {
      return _react().default.cloneElement(props.closeIcon, {
        className: (0, _clsx().default)(bem('close-icon')),
        onClick: onClose
      });
    }

    return (0, _jsxRuntime().jsx)(_icons().Cross, {
      className: (0, _clsx().default)(bem('close-icon')),
      onClick: onClose
    });
  };

  const renderHeader = () => (0, _jsxRuntime().jsxs)("div", Object.assign({
    className: (0, _clsx().default)(bem('header'))
  }, {
    children: [(0, _jsxRuntime().jsx)("h2", Object.assign({
      className: (0, _clsx().default)(bem('title'))
    }, {
      children: props.title
    })), renderCloseIcon()]
  }));

  const renderOption = (option, selectedOption, tabIndex) => {
    const selected = selectedOption && option[valueKey] === selectedOption[valueKey];
    const color = option.color || (selected ? props.activeColor : undefined);
    const Text = props.optionRender ? props.optionRender({
      option,
      selected
    }) : (0, _jsxRuntime().jsx)("span", {
      children: option[textKey]
    });
    return (0, _jsxRuntime().jsxs)("li", Object.assign({
      className: (0, _clsx().default)(bem('option', {
        selected,
        disabled: option.disabled
      }), option.className),
      style: {
        color
      },
      onClick: () => onSelect(option, tabIndex)
    }, {
      children: [Text, selected ? (0, _jsxRuntime().jsx)(_icons().Success, {
        className: (0, _clsx().default)(bem('selected-icon'))
      }) : null]
    }), option[valueKey]);
  };

  const renderOptions = (options, selectedOption, tabIndex) => (0, _jsxRuntime().jsx)("ul", Object.assign({
    className: (0, _clsx().default)(bem('options'))
  }, {
    children: options.map(option => renderOption(option, selectedOption, tabIndex))
  }), tabIndex);

  const renderTab = (tab, tabIndex) => {
    const {
      options,
      selectedOption
    } = tab;
    const title = selectedOption ? selectedOption[textKey] : props.placeholder || locale.vanCascader.select;
    return (0, _jsxRuntime().jsx)(_tabs.default.TabPane, Object.assign({
      title: title,
      titleClass: (0, _clsx().default)(bem('tab', {
        unselected: !selectedOption
      }))
    }, {
      children: renderOptions(options, selectedOption, tabIndex)
    }), tabIndex);
  };

  const renderTabs = () => (0, _jsxRuntime().jsx)(_tabs.default, Object.assign({
    animated: true,
    active: state.activeTab,
    className: (0, _clsx().default)(bem('tabs')),
    color: props.activeColor,
    swipeThreshold: 0,
    swipeable: props.swipeable,
    onClickTab: onClickTab
  }, {
    children: state.tabs.map(renderTab)
  }));

  (0, _react().useEffect)(() => {
    updateTabs();
  }, [JSON.stringify(props.options)]);
  (0, _react().useEffect)(() => {
    var _a;

    const value = (_a = props.value) !== null && _a !== void 0 ? _a : props.defaultValue;
    if (!value || Array.isArray(value) && !value.length) return;
    const initialState = getStateFromValue(value);
    updateState(initialState);
  }, []);
  (0, _hooks.useUpdateEffect)(() => {
    const initialState = getStateFromValue(props.value);
    updateState(initialState);
  }, [props.value]);
  (0, _hooks.useUpdateEffect)(() => {
    if (internalValue || internalValue === 0) {
      const values = state.tabs.map(tab => {
        var _a;

        return (_a = tab.selectedOption) === null || _a === void 0 ? void 0 : _a[valueKey];
      });

      if (values.includes(internalValue)) {
        return;
      }
    }

    updateTabs();
  }, [internalValue]);
  return (0, _jsxRuntime().jsxs)("div", Object.assign({
    className: (0, _clsx().default)(bem())
  }, {
    children: [renderHeader(), state.tabs.length ? renderTabs() : null]
  }));
};

Cascader.defaultProps = {
  closeable: true,
  swipeable: true,
  options: []
};
var _default = Cascader;
exports.default = _default;