'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
require('../../../utils/index.cjs');
require('../../../directives/index.cjs');
var util = require('./util.cjs');
var KeywordTrigger = require('./KeywordTrigger.cjs');
var mentionsProps = require('./mentionsProps.cjs');
var MentionsContext = require('./MentionsContext.cjs');
var initDefaultProps = require('../../../utils/vue/initDefaultProps.cjs');
var KeyCode = require('../../../utils/KeyCode.cjs');
var omit = require('../../../utils/lang/omit.cjs');
var _class = require('../../../utils/dom/class.cjs');
var index = require('../../../directives/ant-input/index.cjs');

function noop() {
}
var VcMentions = /* @__PURE__ */ vue.defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "Mentions",
  inheritAttrs: false,
  props: initDefaultProps.initDefaultProps(mentionsProps.vcMentionsProps, mentionsProps.defaultProps),
  emits: ["change", "select", "search", "focus", "blur", "pressenter"],
  setup(props, {
    emit,
    attrs,
    expose,
    slots
  }) {
    const measure = vue.ref(null);
    const textarea = vue.ref(null);
    const focusId = vue.ref();
    const state = vue.reactive({
      value: props.value || "",
      measuring: false,
      measureLocation: 0,
      measureText: null,
      measurePrefix: "",
      activeIndex: 0,
      isFocus: false
    });
    vue.watchEffect(() => {
      state.value = props.value;
    });
    const triggerChange = (val) => {
      emit("change", val);
    };
    const onChange = ({
      target: {
        value,
        composing
      },
      isComposing
    }) => {
      if (isComposing || composing)
        return;
      triggerChange(value);
    };
    const startMeasure = (measureText, measurePrefix, measureLocation) => {
      Object.assign(state, {
        measuring: true,
        measureText,
        measurePrefix,
        measureLocation,
        activeIndex: 0
      });
    };
    const stopMeasure = (callback) => {
      Object.assign(state, {
        measuring: false,
        measureLocation: 0,
        measureText: null
      });
      callback == null ? void 0 : callback();
    };
    const onKeyDown = (event) => {
      const {
        which
      } = event;
      if (!state.measuring)
        return;
      if (which === KeyCode.KeyCode.UP || which === KeyCode.KeyCode.DOWN) {
        const optionLen = options.value.length;
        const offset = which === KeyCode.KeyCode.UP ? -1 : 1;
        const newActiveIndex = (state.activeIndex + offset + optionLen) % optionLen;
        state.activeIndex = newActiveIndex;
        event.preventDefault();
      } else if (which === KeyCode.KeyCode.ESC) {
        stopMeasure();
      } else if (which === KeyCode.KeyCode.ENTER) {
        event.preventDefault();
        if (!options.value.length) {
          stopMeasure();
          return;
        }
        const option = options.value[state.activeIndex];
        selectOption(option);
      }
    };
    const onKeyUp = (event) => {
      const {
        key,
        which
      } = event;
      const {
        measureText: prevMeasureText,
        measuring
      } = state;
      const {
        prefix,
        validateSearch
      } = props;
      const target = event.target;
      if (target.composing)
        return;
      const selectionStartText = util.getBeforeSelectionText(target);
      const {
        location: measureIndex,
        prefix: measurePrefix
      } = util.getLastMeasureIndex(selectionStartText, prefix);
      if ([KeyCode.KeyCode.ESC, KeyCode.KeyCode.UP, KeyCode.KeyCode.DOWN, KeyCode.KeyCode.ENTER].includes(which))
        return;
      if (measureIndex !== -1) {
        const measureText = selectionStartText.slice(measureIndex + measurePrefix.length);
        const validateMeasure = validateSearch(measureText, props);
        const matchOption = !!getOptions(measureText).length;
        if (validateMeasure) {
          if (key === measurePrefix || key === "Shift" || measuring || measureText !== prevMeasureText && matchOption)
            startMeasure(measureText, measurePrefix, measureIndex);
        } else if (measuring) {
          stopMeasure();
        }
        if (validateMeasure)
          emit("search", measureText, measurePrefix);
      } else if (measuring) {
        stopMeasure();
      }
    };
    const onPressEnter = (event) => {
      if (!state.measuring)
        emit("pressenter", event);
    };
    const onInputFocus = (event) => {
      onFocus(event);
    };
    const onInputBlur = (event) => {
      onBlur(event);
    };
    const onFocus = (event) => {
      clearTimeout(focusId.value);
      const {
        isFocus
      } = state;
      if (!isFocus && event)
        emit("focus", event);
      state.isFocus = true;
    };
    const onBlur = (event) => {
      focusId.value = setTimeout(() => {
        state.isFocus = false;
        stopMeasure();
        emit("blur", event);
      }, 100);
    };
    const selectOption = (option) => {
      const {
        split
      } = props;
      const {
        value: mentionValue = ""
      } = option;
      const {
        text,
        selectionLocation
      } = util.replaceWithMeasure(state.value, {
        measureLocation: state.measureLocation,
        targetText: mentionValue,
        prefix: state.measurePrefix,
        selectionStart: textarea.value.selectionStart,
        split
      });
      triggerChange(text);
      stopMeasure(() => {
        util.setInputSelection(textarea.value, selectionLocation);
      });
      emit("select", option, state.measurePrefix);
    };
    const setActiveIndex = (activeIndex) => {
      state.activeIndex = activeIndex;
    };
    const getOptions = (measureText) => {
      const targetMeasureText = measureText || state.measureText || "";
      const {
        filterOption
      } = props;
      const list = props.options.filter((option) => {
        if (!!filterOption === false)
          return true;
        return filterOption(targetMeasureText, option);
      });
      return list;
    };
    const options = vue.computed(() => {
      return getOptions();
    });
    const focus = () => {
      textarea.value.focus();
    };
    const blur = () => {
      textarea.value.blur();
    };
    expose({
      blur,
      focus
    });
    vue.provide(MentionsContext.default, {
      activeIndex: vue.toRef(state, "activeIndex"),
      setActiveIndex,
      selectOption,
      onFocus,
      onBlur,
      loading: vue.toRef(props, "loading")
    });
    vue.onUpdated(() => {
      vue.nextTick(() => {
        if (state.measuring)
          measure.value.scrollTop = textarea.value.scrollTop;
      });
    });
    return () => {
      const {
        measureLocation,
        measurePrefix,
        measuring
      } = state;
      const {
        prefixCls,
        placement,
        transitionName,
        getPopupContainer,
        direction,
        ...restProps
      } = props;
      const {
        class: className,
        style,
        ...otherAttrs
      } = attrs;
      const inputProps = omit.omit(restProps, ["value", "prefix", "split", "validateSearch", "filterOption", "options", "loading"]);
      const textareaProps = {
        ...inputProps,
        ...otherAttrs,
        onChange: noop,
        onSelect: noop,
        value: state.value,
        onInput: onChange,
        onBlur: onInputBlur,
        onKeydown: onKeyDown,
        onKeyup: onKeyUp,
        onFocus: onInputFocus,
        onPressenter: onPressEnter
      };
      return vue.createVNode("div", {
        "class": _class.classNames(prefixCls, className),
        "style": style
      }, [vue.withDirectives(vue.createVNode("textarea", {
        "ref": textarea,
        ...textareaProps
      }, null), [[index.antInputDirective]]), measuring && vue.createVNode("div", {
        "ref": measure,
        "class": `${prefixCls}-measure`
      }, [state.value.slice(0, measureLocation), vue.createVNode(KeywordTrigger.default, {
        "prefixCls": prefixCls,
        "transitionName": transitionName,
        "dropdownClassName": props.dropdownClassName,
        "placement": placement,
        "options": measuring ? options.value : [],
        "visible": true,
        "direction": direction,
        "getPopupContainer": getPopupContainer
      }, {
        default: () => [vue.createVNode("span", null, [measurePrefix])],
        notFoundContent: slots.notFoundContent,
        option: slots.option
      }), state.value.slice(measureLocation + measurePrefix.length)])]);
    };
  }
});

exports.default = VcMentions;
//# sourceMappingURL=Mentions.cjs.map
