UNPKG

@vnmfify/core

Version:

```shell npm i @vnmfify/core -S ```

176 lines (168 loc) 5.55 kB
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