"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.FormItem = void 0;
var _tslib = require("tslib");
var _antdMobileIcons = require("antd-mobile-icons");
var _classnames = _interopRequireDefault(require("classnames"));
var _rcFieldForm = require("rc-field-form");
var _FieldContext = _interopRequireDefault(require("rc-field-form/lib/FieldContext"));
var _react = _interopRequireWildcard(require("react"));
var _devLog = require("../../utils/dev-log");
var _nativeProps = require("../../utils/native-props");
var _undefinedFallback = require("../../utils/undefined-fallback");
var _withDefaultProps = require("../../utils/with-default-props");
var _configProvider = require("../config-provider");
var _list = _interopRequireDefault(require("../list"));
var _popover = _interopRequireDefault(require("../popover"));
var _context = require("./context");
var _utils = require("./utils");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const NAME_SPLIT = '__SPLIT__';
const classPrefix = `adm-form-item`;
const MemoInput = _react.default.memo(({
  children
}) => children, (prev, next) => prev.value === next.value && prev.update === next.update);
const FormItemLayout = props => {
  var _a;
  const {
    locale,
    form: componentConfig = {}
  } = (0, _configProvider.useConfig)();
  const {
    style,
    extra,
    label,
    help,
    helpIcon,
    required,
    children,
    htmlFor,
    hidden,
    arrow,
    arrowIcon,
    childElementPosition = 'normal'
  } = (0, _withDefaultProps.mergeProps)(componentConfig, props);
  const context = (0, _react.useContext)(_context.FormContext);
  const hasFeedback = props.hasFeedback !== undefined ? props.hasFeedback : context.hasFeedback;
  const layout = props.layout || context.layout;
  const disabled = (_a = props.disabled) !== null && _a !== void 0 ? _a : context.disabled;
  const requiredMark = (() => {
    const {
      requiredMarkStyle
    } = context;
    switch (requiredMarkStyle) {
      case 'asterisk':
        return required && _react.default.createElement("span", {
          className: `${classPrefix}-required-asterisk`
        }, "*");
      case 'text-required':
        return required && _react.default.createElement("span", {
          className: `${classPrefix}-required-text`
        }, "(", locale.Form.required, ")");
      case 'text-optional':
        return !required && _react.default.createElement("span", {
          className: `${classPrefix}-required-text`
        }, "(", locale.Form.optional, ")");
      case 'none':
        return null;
      default:
        return null;
    }
  })();
  const labelElement = !!label && _react.default.createElement("label", {
    className: `${classPrefix}-label`,
    htmlFor: htmlFor
  }, label, requiredMark, help && _react.default.createElement(_popover.default, {
    content: help,
    mode: 'dark',
    trigger: 'click'
  }, _react.default.createElement("span", {
    className: `${classPrefix}-label-help`,
    onClick: e => {
      e.stopPropagation();
      e.preventDefault();
    }
  }, helpIcon || _react.default.createElement(_antdMobileIcons.QuestionCircleOutline, null))));
  const description = (!!props.description || hasFeedback) && _react.default.createElement(_react.default.Fragment, null, props.description, hasFeedback && _react.default.createElement(_react.default.Fragment, null, props.errors.map((error, index) => _react.default.createElement("div", {
    key: `error-${index}`,
    className: `${classPrefix}-feedback-error`
  }, error)), props.warnings.map((warning, index) => _react.default.createElement("div", {
    key: `warning-${index}`,
    className: `${classPrefix}-feedback-warning`
  }, warning))));
  return (0, _nativeProps.withNativeProps)(props, _react.default.createElement(_list.default.Item, {
    style: style,
    title: layout === 'vertical' && labelElement,
    prefix: layout === 'horizontal' && labelElement,
    extra: extra,
    description: description,
    className: (0, _classnames.default)(classPrefix, `${classPrefix}-${layout}`, {
      [`${classPrefix}-hidden`]: hidden,
      [`${classPrefix}-has-error`]: props.errors.length
    }),
    disabled: disabled,
    onClick: props.onClick,
    clickable: props.clickable,
    arrowIcon: arrowIcon || arrow
  }, _react.default.createElement("div", {
    className: (0, _classnames.default)(`${classPrefix}-child`, `${classPrefix}-child-position-${childElementPosition}`)
  }, _react.default.createElement("div", {
    className: (0, _classnames.default)(`${classPrefix}-child-inner`)
  }, children))));
};
const FormItem = props => {
  const {
      // 样式相关
      style,
      // FormItem 相关
      label,
      help,
      helpIcon,
      extra,
      hasFeedback,
      name,
      required,
      noStyle,
      hidden,
      layout,
      childElementPosition,
      description,
      // Field 相关
      disabled,
      rules,
      children,
      messageVariables,
      trigger = 'onChange',
      validateTrigger = trigger,
      onClick,
      shouldUpdate,
      dependencies,
      clickable,
      arrow,
      arrowIcon
    } = props,
    fieldProps = (0, _tslib.__rest)(props, ["style", "label", "help", "helpIcon", "extra", "hasFeedback", "name", "required", "noStyle", "hidden", "layout", "childElementPosition", "description", "disabled", "rules", "children", "messageVariables", "trigger", "validateTrigger", "onClick", "shouldUpdate", "dependencies", "clickable", "arrow", "arrowIcon"]);
  const {
    name: formName
  } = (0, _react.useContext)(_context.FormContext);
  const {
    validateTrigger: contextValidateTrigger
  } = (0, _react.useContext)(_FieldContext.default);
  const mergedValidateTrigger = (0, _undefinedFallback.undefinedFallback)(validateTrigger, contextValidateTrigger, trigger);
  const widgetRef = (0, _react.useRef)(null);
  const updateRef = (0, _react.useRef)(0);
  updateRef.current += 1;
  const [subMetas, setSubMetas] = (0, _react.useState)({});
  const onSubMetaChange = (0, _react.useCallback)((subMeta, namePath) => {
    setSubMetas(prevSubMetas => {
      const nextSubMetas = Object.assign({}, prevSubMetas);
      const nameKey = namePath.join(NAME_SPLIT);
      if (subMeta.destroy) {
        delete nextSubMetas[nameKey];
      } else {
        nextSubMetas[nameKey] = subMeta;
      }
      return nextSubMetas;
    });
  }, [setSubMetas]);
  function renderLayout(baseChildren, fieldId, meta, isRequired) {
    var _a, _b;
    if (noStyle && !hidden) {
      return baseChildren;
    }
    const curErrors = (_a = meta === null || meta === void 0 ? void 0 : meta.errors) !== null && _a !== void 0 ? _a : [];
    const errors = Object.keys(subMetas).reduce((subErrors, key) => {
      var _a, _b;
      const errors = (_b = (_a = subMetas[key]) === null || _a === void 0 ? void 0 : _a.errors) !== null && _b !== void 0 ? _b : [];
      if (errors.length) {
        subErrors = [...subErrors, ...errors];
      }
      return subErrors;
    }, curErrors);
    const curWarnings = (_b = meta === null || meta === void 0 ? void 0 : meta.warnings) !== null && _b !== void 0 ? _b : [];
    const warnings = Object.keys(subMetas).reduce((subWarnings, key) => {
      var _a, _b;
      const warnings = (_b = (_a = subMetas[key]) === null || _a === void 0 ? void 0 : _a.warnings) !== null && _b !== void 0 ? _b : [];
      if (warnings.length) {
        subWarnings = [...subWarnings, ...warnings];
      }
      return subWarnings;
    }, curWarnings);
    return (0, _nativeProps.withNativeProps)(props, _react.default.createElement(FormItemLayout, {
      style: style,
      label: label,
      extra: extra,
      help: help,
      helpIcon: helpIcon,
      description: description,
      required: isRequired,
      disabled: disabled,
      hasFeedback: hasFeedback,
      htmlFor: fieldId,
      errors: errors,
      warnings: warnings,
      onClick: onClick && (e => onClick(e, widgetRef)),
      hidden: hidden,
      layout: layout,
      childElementPosition: childElementPosition,
      clickable: clickable,
      arrow: arrow,
      arrowIcon: arrowIcon
    }, _react.default.createElement(_context.NoStyleItemContext.Provider, {
      value: onSubMetaChange
    }, baseChildren)));
  }
  const isRenderProps = typeof children === 'function';
  if (!name && !isRenderProps && !props.dependencies) {
    return renderLayout(children);
  }
  let Variables = {};
  Variables.label = typeof label === 'string' ? label : '';
  if (messageVariables) {
    Variables = Object.assign(Object.assign({}, Variables), messageVariables);
  }
  const notifyParentMetaChange = (0, _react.useContext)(_context.NoStyleItemContext);
  const onMetaChange = meta => {
    if (noStyle && notifyParentMetaChange) {
      const namePath = meta.name;
      notifyParentMetaChange(meta, namePath);
    }
  };
  return _react.default.createElement(_rcFieldForm.Field, Object.assign({}, fieldProps, {
    name: name,
    shouldUpdate: shouldUpdate,
    dependencies: dependencies,
    rules: rules,
    trigger: trigger,
    validateTrigger: mergedValidateTrigger,
    onMetaChange: onMetaChange,
    messageVariables: Variables
  }), (control, meta, context) => {
    let childNode = null;
    const isRequired = required !== undefined ? required : rules && rules.some(rule => !!(rule && typeof rule === 'object' && rule.required));
    const nameList = (0, _utils.toArray)(name).length && meta ? meta.name : [];
    const fieldId = (nameList.length > 0 && formName ? [formName, ...nameList] : nameList).join('_');
    if (shouldUpdate && dependencies) {
      (0, _devLog.devWarning)('Form.Item', "`shouldUpdate` and `dependencies` shouldn't be used together.");
    }
    if (isRenderProps) {
      if ((shouldUpdate || dependencies) && !name) {
        childNode = children(context);
      } else {
        if (!(shouldUpdate || dependencies)) {
          (0, _devLog.devWarning)('Form.Item', '`children` of render props only work with `shouldUpdate` or `dependencies`.');
        }
        if (name) {
          (0, _devLog.devWarning)('Form.Item', "Do not use `name` with `children` of render props since it's not a field.");
        }
      }
      // not render props
    } else if (dependencies && !name) {
      (0, _devLog.devWarning)('Form.Item', 'Must set `name` or use render props when `dependencies` is set.');
    } else if (_react.default.isValidElement(children)) {
      if (children.props.defaultValue) {
        (0, _devLog.devWarning)('Form.Item', '`defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.');
      }
      const childProps = Object.assign(Object.assign({}, children.props), control);
      if ((0, _utils.isSafeSetRefComponent)(children)) {
        childProps.ref = instance => {
          const originRef = children.ref;
          if (originRef) {
            if (typeof originRef === 'function') {
              originRef(instance);
            }
            if ('current' in originRef) {
              originRef.current = instance;
            }
          }
          widgetRef.current = instance;
        };
      }
      if (!childProps.id) {
        childProps.id = fieldId;
      }
      // We should keep user origin event handler
      const triggers = new Set([...(0, _utils.toArray)(trigger), ...(0, _utils.toArray)(mergedValidateTrigger)]);
      triggers.forEach(eventName => {
        childProps[eventName] = (...args) => {
          var _a, _b, _c;
          (_a = control[eventName]) === null || _a === void 0 ? void 0 : _a.call(control, ...args);
          (_c = (_b = children.props)[eventName]) === null || _c === void 0 ? void 0 : _c.call(_b, ...args);
        };
      });
      childNode = _react.default.createElement(MemoInput, {
        value: control[props.valuePropName || 'value'],
        update: updateRef.current
      }, _react.default.cloneElement(children, childProps));
    } else {
      if (name) {
        (0, _devLog.devWarning)('Form.Item', '`name` is only used for validate React element. If you are using Form.Item as layout display, please remove `name` instead.');
      }
      childNode = children;
    }
    return renderLayout(childNode, fieldId, meta, isRequired);
  });
};
exports.FormItem = FormItem;