linkmore-design
Version:
π πlmη»δ»ΆεΊγπ
307 lines (291 loc) β’ 11.8 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _rcFieldForm = require("rc-field-form");
var _useState = _interopRequireDefault(require("rc-util/lib/hooks/useState"));
var _ref = require("rc-util/lib/ref");
var React = _interopRequireWildcard(require("react"));
var _useFormItemStatus = _interopRequireDefault(require("../hooks/useFormItemStatus"));
var _configProvider = require("../../config-provider");
var _reactNode = require("../../_util/reactNode");
var _type = require("../../_util/type");
var _warning = _interopRequireDefault(require("../../_util/warning"));
var _context = require("../context");
var _useFrameState = _interopRequireDefault(require("../hooks/useFrameState"));
var _useItemRef = _interopRequireDefault(require("../hooks/useItemRef"));
var _util = require("../util");
var _ItemHolder = _interopRequireDefault(require("./ItemHolder"));
var _omit = _interopRequireDefault(require("rc-util/lib/omit"));
const NAME_SPLIT = '__SPLIT__';
const ValidateStatuses = (0, _type.tuple)('success', 'warning', 'error', 'validating', '');
const MemoInput = /*#__PURE__*/React.memo(({
children
}) => children, (prev, next) => prev.value === next.value && prev.update === next.update && prev.childProps.length === next.childProps.length && prev.childProps.every((value, index) => value === next.childProps[index]));
function hasValidName(name) {
if (name === null) {
(0, _warning.default)(false, 'Form.Item', '`null` is passed as `name` property');
}
return !(name === undefined || name === null);
}
function genEmptyMeta() {
return {
errors: [],
warnings: [],
touched: false,
validating: false,
name: []
};
}
function getRuleTime(rules) {
if (!rules) {
return 0;
}
for (let rule of rules) {
if (rule && typeof rule === 'object' && rule.time) {
return rule.time;
}
}
return 0;
}
function InternalFormItem(props) {
const {
name,
noStyle,
dependencies,
prefixCls: customizePrefixCls,
shouldUpdate,
rules,
children,
required,
label,
messageVariables,
trigger = 'onChange',
validateTrigger,
hidden,
ruleTime
} = props;
const timerRef = (0, React.useRef)(null);
const [errors, setErrors] = (0, _useState.default)([]);
const [warnings, setWarnings] = (0, _useState.default)([]);
const {
getPrefixCls
} = (0, React.useContext)(_configProvider.ConfigContext);
const {
name: formName
} = (0, React.useContext)(_context.FormContext);
const isRenderProps = typeof children === 'function';
const notifyParentMetaChange = (0, React.useContext)(_context.NoStyleItemContext);
const {
validateTrigger: contextValidateTrigger
} = (0, React.useContext)(_rcFieldForm.FieldContext);
const mergedValidateTrigger = validateTrigger !== undefined ? validateTrigger : contextValidateTrigger;
const hasName = hasValidName(name);
const prefixCls = getPrefixCls('form', customizePrefixCls);
// ========================= MISC =========================
// Get `noStyle` required info
const listContext = React.useContext(_rcFieldForm.ListContext);
const fieldKeyPathRef = React.useRef();
// ======================== Errors ========================
// >>>>> Collect sub field errors
const [subFieldErrors, setSubFieldErrors] = (0, _useFrameState.default)({});
// >>>>> Current field errors
const [meta, setMeta] = (0, _useState.default)(() => genEmptyMeta());
const onMetaChange = nextMeta => {
// This keyInfo is not correct when field is removed
// Since origin keyManager no longer keep the origin key anymore
// Which means we need cache origin one and reuse when removed
const keyInfo = listContext?.getKey(nextMeta.name);
// Destroy will reset all the meta
setMeta(nextMeta.destroy ? genEmptyMeta() : nextMeta, true);
// Bump to parent since noStyle
if (noStyle && notifyParentMetaChange) {
let namePath = nextMeta.name;
if (!nextMeta.destroy) {
if (keyInfo !== undefined) {
const [fieldKey, restPath] = keyInfo;
namePath = [fieldKey, ...restPath];
fieldKeyPathRef.current = namePath;
}
} else {
// Use origin cache data
namePath = fieldKeyPathRef.current || namePath;
}
notifyParentMetaChange(nextMeta, namePath);
}
};
// >>>>> Collect noStyle Field error to the top FormItem
const onSubItemMetaChange = (subMeta, uniqueKeys) => {
// Only `noStyle` sub item will trigger
setSubFieldErrors(prevSubFieldErrors => {
const clone = {
...prevSubFieldErrors
};
// name: ['user', 1] + key: [4] = ['user', 4]
const mergedNamePath = [...subMeta.name.slice(0, -1), ...uniqueKeys];
const mergedNameKey = mergedNamePath.join(NAME_SPLIT);
if (subMeta.destroy) {
// Remove
delete clone[mergedNameKey];
} else {
// Update
clone[mergedNameKey] = subMeta;
}
return clone;
});
};
// >>>>> Get merged errors
// guyue start
const [mergedErrors, mergedWarnings] = React.useMemo(() => {
const errorList = [...meta.errors];
const warningList = [...meta.warnings];
Object.values(subFieldErrors).forEach(subFieldError => {
errorList.push(...(subFieldError.errors || []));
warningList.push(...(subFieldError.warnings || []));
});
return [errorList.slice(0, 1), warningList.slice(0, 1)];
}, [subFieldErrors, meta.errors, meta.warnings]);
(0, React.useEffect)(() => {
setErrors(mergedErrors);
setWarnings(mergedWarnings);
const time = ruleTime || getRuleTime(rules);
if (time) {
clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
setErrors([]);
setWarnings([]);
}, time);
}
}, [mergedErrors, mergedWarnings]);
// guyue end
// ===================== Children Ref =====================
const getItemRef = (0, _useItemRef.default)();
const _props = (0, _omit.default)(props, ['ruleTime']);
// ======================== Render ========================
function renderLayout(baseChildren, fieldId, isRequired) {
if (noStyle && !hidden) {
return baseChildren;
}
return /*#__PURE__*/React.createElement(_ItemHolder.default, (0, _extends2.default)({
key: "row"
}, _props, {
prefixCls: prefixCls,
fieldId: fieldId,
isRequired: isRequired
// errors={mergedErrors}
// warnings={mergedWarnings}
,
errors: errors,
warnings: warnings,
meta: meta,
onSubItemMetaChange: onSubItemMetaChange
}), baseChildren);
}
if (!hasName && !isRenderProps && !dependencies) {
return renderLayout(children);
}
let variables = {};
if (typeof label === 'string') {
variables.label = label;
} else if (name) {
variables.label = String(name);
}
if (messageVariables) {
variables = {
...variables,
...messageVariables
};
}
// >>>>> With Field
return /*#__PURE__*/React.createElement(_rcFieldForm.Field, (0, _extends2.default)({}, props, {
messageVariables: variables,
trigger: trigger,
validateTrigger: mergedValidateTrigger,
onMetaChange: onMetaChange
}), (control, renderMeta, context) => {
const mergedName = (0, _util.toArray)(name).length && renderMeta ? renderMeta.name : [];
const fieldId = (0, _util.getFieldId)(mergedName, formName);
const isRequired = required !== undefined ? required : !!(rules && rules.some(rule => {
if (rule && typeof rule === 'object' && rule.required && !rule.warningOnly) {
return true;
}
if (typeof rule === 'function') {
const ruleEntity = rule(context);
return ruleEntity && ruleEntity.required && !ruleEntity.warningOnly;
}
return false;
}));
// ======================= Children =======================
const mergedControl = {
...control
};
let childNode = null;
(0, _warning.default)(!(shouldUpdate && dependencies), 'Form.Item', "`shouldUpdate` and `dependencies` shouldn't be used together. See https://u.ant.design/form-deps.");
if (Array.isArray(children) && hasName) {
(0, _warning.default)(false, 'Form.Item', 'A `Form.Item` with a `name` prop must have a single child element. For information on how to render more complex form items, see https://u.ant.design/complex-form-item.');
childNode = children;
} else if (isRenderProps && (!(shouldUpdate || dependencies) || hasName)) {
(0, _warning.default)(!!(shouldUpdate || dependencies), 'Form.Item', 'A `Form.Item` with a render function must have either `shouldUpdate` or `dependencies`.');
(0, _warning.default)(!hasName, 'Form.Item', "A `Form.Item` with a render function cannot be a field, and thus cannot have a `name` prop.");
} else if (dependencies && !isRenderProps && !hasName) {
(0, _warning.default)(false, 'Form.Item', 'Must set `name` or use a render function when `dependencies` is set.');
} else if ((0, _reactNode.isValidElement)(children)) {
(0, _warning.default)(children.props.defaultValue === undefined, 'Form.Item', '`defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.');
const childProps = {
...children.props,
...mergedControl
};
if (!childProps.id) {
childProps.id = fieldId;
}
if (props.help || mergedErrors.length > 0 || mergedWarnings.length > 0 || props.extra) {
const describedbyArr = [];
if (props.help || mergedErrors.length > 0) {
describedbyArr.push(`${fieldId}_help`);
}
if (props.extra) {
describedbyArr.push(`${fieldId}_extra`);
}
childProps['aria-describedby'] = describedbyArr.join(' ');
}
if (mergedErrors.length > 0) {
childProps['aria-invalid'] = 'true';
}
if (isRequired) {
childProps['aria-required'] = 'true';
}
if ((0, _ref.supportRef)(children)) {
childProps.ref = getItemRef(mergedName, children);
}
// We should keep user origin event handler
const triggers = new Set([...(0, _util.toArray)(trigger), ...(0, _util.toArray)(mergedValidateTrigger)]);
triggers.forEach(eventName => {
childProps[eventName] = (...args) => {
mergedControl[eventName]?.(...args);
children.props[eventName]?.(...args);
};
});
// List of props that need to be watched for changes -> if changes are detected in MemoInput -> rerender
const watchingChildProps = [childProps['aria-required'], childProps['aria-invalid'], childProps['aria-describedby']];
childNode = /*#__PURE__*/React.createElement(MemoInput, {
value: mergedControl[props.valuePropName || 'value'],
update: children,
childProps: watchingChildProps
}, (0, _reactNode.cloneElement)(children, childProps));
} else if (isRenderProps && (shouldUpdate || dependencies) && !hasName) {
childNode = children(context);
} else {
(0, _warning.default)(!mergedName.length, '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, isRequired);
});
}
const FormItem = InternalFormItem;
FormItem.useStatus = _useFormItemStatus.default;
var _default = FormItem;
exports.default = _default;