"use strict";

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

function _tslib() {
  const data = require("tslib");

  _tslib = function () {
    return data;
  };

  return data;
}

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 _icons() {
  const data = require("@react-vant/icons");

  _icons = function () {
    return data;
  };

  return data;
}

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

  _clsx = function () {
    return data;
  };

  return data;
}

var _cell = _interopRequireDefault(require("../cell"));

var _dialog = _interopRequireDefault(require("../dialog"));

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

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

var _constant = require("../utils/constant");

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 react-hooks/exhaustive-deps */
const ICON_SIZE = '16px';
const Field = (0, _react().forwardRef)((props, ref) => {
  const {
    prefixCls,
    createNamespace
  } = (0, _react().useContext)(_ConfigProviderContext.default);
  const [bem] = createNamespace('field', prefixCls);
  const [inputFocus, setInputFocus] = (0, _react().useState)(false);
  const fieldRef = (0, _react().useRef)(null);
  const inputRef = (0, _react().useRef)(null);
  (0, _react().useEffect)(() => {
    if (props.getFieldRef) props.getFieldRef(fieldRef);
    if (props.getInputRef) props.getInputRef(inputRef);
  }, [props.getFieldRef, props.getInputRef]);

  const focus = () => {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  };

  const blur = () => {
    if (inputRef.current) {
      inputRef.current.blur();
    }
  };

  (0, _react().useImperativeHandle)(ref, () => ({
    focus,
    blur
  }));

  const getProp = key => {
    if ((0, _utils.isDef)(props[key])) {
      return props[key];
    }

    return null;
  };

  const getModelValue = () => {
    var _a;

    return String((_a = props.value) !== null && _a !== void 0 ? _a : '');
  };

  const showClear = (0, _react().useMemo)(() => {
    const readonly = getProp('readonly');

    if (props.clearable && !readonly) {
      const hasValue = getModelValue() !== '';
      const trigger = props.clearTrigger === 'always' || props.clearTrigger === 'focus' && inputFocus;
      return hasValue && trigger;
    }

    return false;
  }, [props.value, props.clearTrigger, inputFocus]);

  const labelStyle = () => {
    const labelW = getProp('labelWidth');

    if (labelW) {
      return {
        width: (0, _utils.addUnit)(labelW)
      };
    }

    return {};
  };

  const adjustSize = () => {
    const input = inputRef.current;

    if (!(props.type === 'textarea' && props.autosize) || !input) {
      return;
    }

    input.style.height = 'auto';
    let height = input.scrollHeight;

    if ((0, _utils.isObject)(props.autosize)) {
      const {
        maxHeight,
        minHeight
      } = props.autosize;

      if (maxHeight) {
        height = Math.min(height, maxHeight);
      }

      if (minHeight) {
        height = Math.max(height, minHeight);
      }
    }

    if (height) {
      input.style.height = `${height}px`;
    }
  };

  (0, _react().useEffect)(() => {
    adjustSize();
  }, [props.value]);

  const formatValue = (inputValue, trigger = 'onChange') => {
    const {
      formatTrigger,
      formatter
    } = props;

    if (formatter && trigger === formatTrigger) {
      return formatter(inputValue);
    }

    return inputValue;
  };

  const renderInput = () => {
    const {
      type,
      error,
      name,
      rows,
      value,
      placeholder,
      disabled,
      readonly
    } = props;
    const controlClass = bem('control', [getProp('inputAlign'), {
      error,
      custom: !!props.children,
      'min-height': props.type === 'textarea' && !props.autosize
    }]);

    if (props.children) {
      return (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(controlClass)
      }, {
        children: props.children
      }));
    }

    const handleChange = e => {
      var _a;

      const {
        maxlength,
        onChange
      } = props;
      const inputValue = (_a = e === null || e === void 0 ? void 0 : e.currentTarget) === null || _a === void 0 ? void 0 : _a.value;
      let finalValue = inputValue;

      if ((0, _utils.isDef)(maxlength) && finalValue.length > +maxlength) {
        finalValue = finalValue.slice(0, maxlength);
      }

      if (type === 'number' || type === 'digit') {
        const isNumber = type === 'number';
        finalValue = (0, _utils.formatNumber)(finalValue, isNumber, isNumber);
      }

      finalValue = formatValue(finalValue, 'onChange'); // if (inputRef.value && inputValue !== inputRef.value.value) {
      //   inputRef.value.value = inputValue;
      // }

      if (onChange && typeof onChange === 'function') {
        onChange(finalValue);
      }
    };

    const handleFocus = e => {
      const {
        onFocus
      } = props;
      setInputFocus(true);

      if (onFocus && typeof onFocus === 'function') {
        onFocus(e);
      } // readonly not work in legacy mobile safari


      if (readonly) {
        blur();
      }
    };

    const handleBulr = e => {
      const {
        onBlur
      } = props;
      setInputFocus(false);

      if (onBlur && typeof onBlur === 'function') {
        onBlur(e);
      }

      (0, _utils.resetScroll)();
    };

    const handleKeypress = e => {
      const {
        onKeypress
      } = props;

      if (e.key === 'Enter' || +e.charCode === 13) {
        if (props.type !== 'textarea') {
          (0, _utils.preventDefault)(e);
        } // trigger blur after click keyboard search button


        if (props.type === 'search') {
          blur();
        }
      }

      if (onKeypress && typeof onKeypress === 'function') {
        onKeypress(e);
      }
    };

    if (type === 'textarea') {
      return (0, _jsxRuntime().jsx)("textarea", {
        ref: inputRef,
        name: name,
        rows: rows,
        className: (0, _clsx().default)(controlClass),
        value: value,
        disabled: disabled,
        readOnly: readonly,
        placeholder: placeholder || '',
        onBlur: handleBulr,
        onFocus: handleFocus,
        onChange: handleChange,
        onKeyPress: handleKeypress
      });
    }

    let inputType = type;
    let inputMode; // type="number" is weired in iOS, and can't prevent dot in Android
    // so use inputmode to set keyboard in mordern browers

    if (type === 'number') {
      inputType = 'text';
      inputMode = 'decimal';
    }

    if (type === 'digit') {
      inputType = 'tel';
      inputMode = 'numeric';
    }

    return (0, _jsxRuntime().jsx)("input", {
      value: value,
      type: inputType,
      inputMode: inputMode,
      ref: inputRef,
      name: name,
      className: (0, _clsx().default)(controlClass),
      disabled: disabled,
      readOnly: readonly,
      placeholder: placeholder || '',
      onBlur: handleBulr,
      onFocus: handleFocus,
      onChange: handleChange,
      onKeyPress: handleKeypress
    });
  };

  const renderLeftIcon = () => {
    const {
      leftIcon,
      onClickLeftIcon
    } = props;
    if (!leftIcon) return null;
    return (0, _jsxRuntime().jsx)("div", Object.assign({
      className: (0, _clsx().default)(bem('left-icon')),
      onClick: onClickLeftIcon
    }, {
      children: leftIcon
    }));
  };

  const renderRightIcon = () => {
    const {
      rightIcon,
      onClickRightIcon
    } = props;
    if (!rightIcon) return null;
    return (0, _jsxRuntime().jsx)("div", Object.assign({
      className: (0, _clsx().default)(bem('right-icon')),
      onClick: onClickRightIcon
    }, {
      children: rightIcon
    }));
  };

  const renderWordLimit = () => {
    const {
      value,
      showWordLimit,
      maxlength
    } = props;

    if (showWordLimit && maxlength) {
      const count = (value ? `${value}` : '').length;
      return (0, _jsxRuntime().jsxs)("div", Object.assign({
        className: (0, _clsx().default)(bem('word-limit'))
      }, {
        children: [(0, _jsxRuntime().jsx)("span", Object.assign({
          className: (0, _clsx().default)(bem('word-num'))
        }, {
          children: count
        })), "/", maxlength]
      }));
    }

    return null;
  };

  const renderMessage = () => {
    const message = props.errorMessage;

    if (message) {
      const errorMessageAlign = getProp('errorMessageAlign');
      return (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('error-message', errorMessageAlign))
      }, {
        children: message
      }));
    }

    return null;
  };

  const renderIntro = () => {
    if (props.intro) {
      return (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('intro', getProp('inputAlign')))
      }, {
        children: props.intro
      }));
    }

    return null;
  };

  const renderTooltip = () => {
    const {
      tooltip
    } = props;

    if (tooltip) {
      let icon = (0, _jsxRuntime().jsx)(_icons().QuestionO, {});
      let dialogProps = {
        message: tooltip
      };

      if (!(_react().default.isValidElement(tooltip) || typeof tooltip === 'string')) {
        const _a = tooltip,
              {
          icon: customIcon
        } = _a,
              customDialogProps = (0, _tslib().__rest)(_a, ["icon"]);
        icon = customIcon || icon;
        dialogProps = customDialogProps;
      }

      return (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('tooltip')),
        onClick: () => _dialog.default.show(dialogProps)
      }, {
        children: icon
      }));
    }

    return null;
  };

  const renderLabel = () => {
    const {
      label,
      colon
    } = props;

    if (label) {
      return (0, _jsxRuntime().jsxs)(_jsxRuntime().Fragment, {
        children: [label, colon && ':', renderTooltip()]
      });
    }

    return null;
  };

  const handleClear = e => {
    const {
      onClear,
      onChange
    } = props;
    inputRef.current.value = '';

    if (onChange && typeof onChange === 'function') {
      onChange('');
    }

    if (onClear && typeof onClear === 'function') {
      onClear(e);
    }
  };

  const {
    type,
    size,
    center,
    border,
    isLink,
    required,
    clickable,
    labelAlign,
    className,
    labelClass,
    valueClass,
    arrowDirection,
    autosize,
    disabled,
    button,
    titleStyle,
    error
  } = props;
  return (0, _jsxRuntime().jsxs)(_cell.default, Object.assign({
    title: renderLabel(),
    size: size,
    icon: renderLeftIcon(),
    center: center,
    border: border,
    isLink: isLink,
    required: required,
    clickable: clickable,
    extra: props.extra,
    titleStyle: Object.assign(Object.assign({}, labelStyle()), titleStyle),
    valueClass: (0, _clsx().default)(bem('value'), valueClass),
    titleClass: (0, _clsx().default)(bem('label', labelAlign), labelClass),
    arrowDirection: arrowDirection,
    onClick: props.onClick,
    style: props.style,
    className: (0, _clsx().default)(bem({
      error,
      disabled,
      [`label-${labelAlign}`]: labelAlign,
      'min-height': type === 'textarea' && !autosize
    }), className)
  }, {
    children: [(0, _jsxRuntime().jsxs)("div", Object.assign({
      className: (0, _clsx().default)(bem('body'))
    }, {
      children: [(0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('control-wrapper')),
        onClick: props.onClickInput
      }, {
        children: renderInput()
      })), showClear && _react().default.cloneElement(props.clearIcon, {
        className: (0, _clsx().default)(bem('clear')),
        onTouchStart: handleClear,
        size: ICON_SIZE
      }), renderRightIcon(), button && (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('button'))
      }, {
        children: button
      }))]
    })), renderWordLimit(), renderMessage(), renderIntro()]
  }));
});
Field.defaultProps = {
  clearIcon: (0, _jsxRuntime().jsx)(_icons().Clear, {}),
  clearTrigger: 'focus',
  formatTrigger: 'onChange'
};
const FIELD_KEY = Symbol('field');
exports.FIELD_KEY = FIELD_KEY;
const FieldNamespace = Object.assign(Field, {
  [_constant.COMPONENT_TYPE_KEY]: FIELD_KEY
});
var _default = FieldNamespace;
exports.default = _default;