@vnmfify/core
Version:
```shell npm i @vnmfify/core -S ```
176 lines (168 loc) • 5.55 kB
JavaScript
import _map from "lodash/map";
import _isEmpty from "lodash/isEmpty";
import { cloneIconElement } from "@vnmfify/icons/utils";
import { View } from "@vnxjs/components";
import classNames from "classnames";
import * as React from "react";
import { Children, cloneElement, forwardRef, isValidElement, useCallback, useContext, useImperativeHandle, useMemo } from "react";
import { CellBase, CellValue } from "../cell";
import Form, { useFormField, useFormValue } from "../form";
import FormContext from "../form/form.context";
import { prefixClassname } from "../styles";
import { fulfillPromise } from "../utils/promisify";
import { useToRef } from "../utils/state";
import { isElementOf } from "../utils/validate";
import FormFeedback from "./form-feedback";
import FormItemContext from "./form-item.context";
import { validateRules } from "./form.rule";
import useFormError from "./use-form-error";
import useFormFieldValueEffect from "./use-form-field-value-effect";
function useFormItemChildren(children) {
return useMemo(() => {
var __children__ = {
feedbacks: []
};
Children.forEach(children, child => {
if (! /*#__PURE__*/isValidElement(child)) {
return;
}
var element = child;
var {
type: elementType
} = element;
if (isElementOf(element, Form.Label)) {
__children__.label = element;
} else if (elementType === Form.Control) {
__children__.control = element;
} else if (isElementOf(element, Form.Feedback)) {
var _children__$feedback;
(_children__$feedback = __children__.feedbacks) === null || _children__$feedback === void 0 ? void 0 : _children__$feedback.push(element);
}
});
return __children__;
}, [children]);
}
var FormItem = /*#__PURE__*/forwardRef((props, ref) => {
var {
className,
style,
name,
defaultValue,
align,
bordered,
icon,
rightIcon,
clickable,
required,
children: childrenProp,
rules: rulesProp,
onClick
} = props;
var {
label,
control,
feedbacks
} = useFormItemChildren(childrenProp);
var rulesRef = useToRef(rulesProp);
var {
validateTrigger
} = useContext(FormContext);
var {
validateStatus,
error,
setError,
resetError
} = useFormError(name);
var {
value,
getValue,
setValue
} = useFormValue(name, {
defaultValue
});
var validate = useCallback(function () {
var rules = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : rulesRef.current;
return new Promise((resolve, reject) => {
if (rules) {
resetError();
validateRules(getValue(), rules).then(errors => {
if (_isEmpty(errors)) {
resetError();
resolve();
} else {
setError({
errors
});
reject({
name,
errors
});
}
});
} else {
resolve();
}
});
}, [getValue, name, resetError, rulesRef, setError]);
var validateWithTrigger = useCallback(trigger => {
if (validateTrigger && rulesProp) {
var defaultTrigger = validateTrigger === trigger;
var rules = rulesProp.filter(rule => {
if (rule.trigger) {
return rule.trigger === trigger;
}
return defaultTrigger;
});
if (rules.length) {
fulfillPromise(validate(rulesProp));
} else if (defaultTrigger) {
resetError();
}
}
}, [resetError, rulesProp, validate, validateTrigger]);
var instance = useMemo(() => ({
name,
validate,
getValue,
setValue
}), [getValue, name, setValue, validate]);
useImperativeHandle(ref, () => instance, [instance]);
useFormField(name, instance);
useFormFieldValueEffect(() => validateWithTrigger("onChange"), [value]);
var explain = useMemo(() => !_isEmpty(feedbacks) || !_isEmpty(error === null || error === void 0 ? void 0 : error.errors), [error === null || error === void 0 ? void 0 : error.errors, feedbacks]);
var Control = useMemo(() => control && /*#__PURE__*/cloneElement(control, {
name,
value,
onBlur: () => validateWithTrigger("onBlur"),
onChange: setValue
}), [control, name, setValue, validateWithTrigger, value]);
return /*#__PURE__*/React.createElement(FormItemContext.Provider, {
value: {
validateStatus
}
}, /*#__PURE__*/React.createElement(CellBase, {
className: classNames(prefixClassname("form-item"), className),
style: style,
bordered: bordered,
align: align,
clickable: clickable,
icon: cloneIconElement(icon, {
className: prefixClassname("form-item__icon")
}),
rightIcon: cloneIconElement(rightIcon, {
className: prefixClassname("form-item__right-icon")
}),
required: required,
onClick: onClick
}, label, /*#__PURE__*/React.createElement(CellValue, {
alone: false
}, Control, explain && /*#__PURE__*/React.createElement(View, {
className: classNames(prefixClassname("form__feedbacks"))
}, feedbacks, _map(error === null || error === void 0 ? void 0 : error.errors, (message, messageKey) => /*#__PURE__*/React.createElement(FormFeedback, {
key: messageKey,
status: "invalid",
children: message
}))))));
});
export default FormItem;
//# sourceMappingURL=form-item.js.map