x-ui-design 0.6.12 → 0.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/types/components/Form/Item/Item.d.ts +1 -1
- package/dist/esm/types/types/form.d.ts +2 -3
- package/dist/index.esm.js +67 -72
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +66 -71
- package/dist/index.js.map +1 -1
- package/lib/components/Form/Item/Item.tsx +42 -48
- package/lib/components/Input/Input.tsx +1 -7
- package/lib/hooks/useForm.ts +29 -9
- package/lib/types/form.ts +2 -8
- package/package.json +1 -1
- package/src/app/page.tsx +4 -5
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { FormItemProps } from '../../../types/form';
|
|
3
3
|
import './style.css';
|
|
4
4
|
declare const FormItem: {
|
|
5
|
-
({ prefixCls, name, label, rules, children, className, layout, style, dependencies,
|
|
5
|
+
({ prefixCls, name, label, rules, children, className, layout, style, dependencies, feedbackIcons, extra, hideLabel, removeErrorMessageHeight, ...props }: FormItemProps): React.JSX.Element;
|
|
6
6
|
displayName: string;
|
|
7
7
|
};
|
|
8
8
|
export default FormItem;
|
|
@@ -74,9 +74,7 @@ export interface FormItemChildComponentProps {
|
|
|
74
74
|
child: ReactElement;
|
|
75
75
|
name: string;
|
|
76
76
|
error: boolean;
|
|
77
|
-
|
|
78
|
-
value: RuleType;
|
|
79
|
-
setFieldValue: (name: string, value: RuleType, errors?: string[], reset?: boolean | null | undefined, touch?: boolean) => void;
|
|
77
|
+
initialValue: RuleTypes;
|
|
80
78
|
onChange?: (e: SyntheticBaseEvent, option?: OptionProps) => void;
|
|
81
79
|
size?: SizeType;
|
|
82
80
|
normalize?: (value: RuleType, prevValue: RuleType, allValues: RuleType) => RuleType;
|
|
@@ -114,4 +112,5 @@ export interface FormInstance {
|
|
|
114
112
|
setOnFinish?: (onFinish?: ((values: Record<string, RuleTypes>) => void) | undefined) => void;
|
|
115
113
|
setOnValuesChange?: (onValuesChange?: (changedValues: Record<string, RuleTypes>, allValues: Record<string, RuleTypes>) => void) => void;
|
|
116
114
|
changeStep: (step: number) => void;
|
|
115
|
+
subscribeToErrors?: (callback: (errors: FieldError[]) => void) => () => void;
|
|
117
116
|
}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import require$$1 from 'react/jsx-runtime';
|
|
2
|
-
import React, { useRef, useState, Children, isValidElement, Fragment, Suspense, useContext, useMemo, useEffect,
|
|
2
|
+
import React, { useRef, useState, Children, isValidElement, Fragment, Suspense, useContext, useMemo, useEffect, createContext, useImperativeHandle, useCallback, useLayoutEffect } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import ReactDOMServer from 'react-dom/server';
|
|
5
5
|
|
|
@@ -619,7 +619,8 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
619
619
|
});
|
|
620
620
|
const fieldInstancesRef = useRef({});
|
|
621
621
|
const [isReseting, setIsReseting] = useState(false);
|
|
622
|
-
const
|
|
622
|
+
const errorsRef = useRef({});
|
|
623
|
+
const errorSubscribers = useRef([]);
|
|
623
624
|
const fieldSubscribers = useRef({});
|
|
624
625
|
const formSubscribers = useRef([]);
|
|
625
626
|
function getFormFields() {
|
|
@@ -643,13 +644,13 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
643
644
|
}, {});
|
|
644
645
|
}
|
|
645
646
|
function getFieldError(name) {
|
|
646
|
-
return
|
|
647
|
+
return errorsRef.current[name] || [];
|
|
647
648
|
}
|
|
648
649
|
function getFieldWarning(name) {
|
|
649
650
|
return warningsRef.current[name] || [];
|
|
650
651
|
}
|
|
651
652
|
function getFieldsError() {
|
|
652
|
-
return Object.entries(
|
|
653
|
+
return Object.entries(errorsRef.current).map(([name, err]) => ({
|
|
653
654
|
name,
|
|
654
655
|
errors: err
|
|
655
656
|
}));
|
|
@@ -663,12 +664,10 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
663
664
|
touchedFieldsRef.current.add(name);
|
|
664
665
|
}
|
|
665
666
|
if (reset === null) {
|
|
666
|
-
|
|
667
|
-
[name]: []
|
|
668
|
-
});
|
|
667
|
+
errorsRef.current[name] = [];
|
|
669
668
|
return;
|
|
670
669
|
}
|
|
671
|
-
if (!
|
|
670
|
+
if (!errorsRef.current?.length) {
|
|
672
671
|
validateField(name).then(() => {
|
|
673
672
|
const allValues = getFieldsValue();
|
|
674
673
|
fieldSubscribers.current[name]?.forEach(callback => callback(value));
|
|
@@ -686,9 +685,7 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
686
685
|
}
|
|
687
686
|
});
|
|
688
687
|
} else {
|
|
689
|
-
|
|
690
|
-
[name]: errors
|
|
691
|
-
});
|
|
688
|
+
errorsRef.current[name] = errors || [];
|
|
692
689
|
}
|
|
693
690
|
}
|
|
694
691
|
function setFieldsValue(values, reset) {
|
|
@@ -764,11 +761,13 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
764
761
|
}
|
|
765
762
|
}
|
|
766
763
|
}));
|
|
767
|
-
|
|
768
|
-
...
|
|
764
|
+
errorsRef.current = {
|
|
765
|
+
...errorsRef.current,
|
|
769
766
|
[name]: fieldErrors
|
|
770
|
-
}
|
|
767
|
+
};
|
|
771
768
|
warningsRef.current[name] = fieldWarnings;
|
|
769
|
+
const currentErrors = getFieldsError();
|
|
770
|
+
errorSubscribers.current.forEach(callback => callback(currentErrors));
|
|
772
771
|
return fieldErrors.length === 0;
|
|
773
772
|
}
|
|
774
773
|
async function validateFields(nameList) {
|
|
@@ -791,10 +790,10 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
791
790
|
formData[name] = initialValues[name];
|
|
792
791
|
touchedFieldsRef.current.delete(name);
|
|
793
792
|
delete warningsRef.current[name];
|
|
794
|
-
|
|
795
|
-
...
|
|
793
|
+
errorsRef.current = {
|
|
794
|
+
...errorsRef.current,
|
|
796
795
|
[name]: []
|
|
797
|
-
}
|
|
796
|
+
};
|
|
798
797
|
setFieldValue(name, initialValues[name], undefined, showError);
|
|
799
798
|
});
|
|
800
799
|
} else {
|
|
@@ -807,6 +806,8 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
807
806
|
});
|
|
808
807
|
}
|
|
809
808
|
formSubscribers.current.forEach(callback => callback(getFieldsValue()));
|
|
809
|
+
const currentErrors = getFieldsError();
|
|
810
|
+
errorSubscribers.current.forEach(callback => callback(currentErrors));
|
|
810
811
|
setIsReseting(prev => !prev);
|
|
811
812
|
}
|
|
812
813
|
async function submit() {
|
|
@@ -840,6 +841,12 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
840
841
|
fieldCallbacks.forEach(unsubscribe => unsubscribe());
|
|
841
842
|
};
|
|
842
843
|
}
|
|
844
|
+
function subscribeToErrors(callback) {
|
|
845
|
+
errorSubscribers.current.push(callback);
|
|
846
|
+
return () => {
|
|
847
|
+
errorSubscribers.current = errorSubscribers.current.filter(cb => cb !== callback);
|
|
848
|
+
};
|
|
849
|
+
}
|
|
843
850
|
function setScrollToFirstError(value) {
|
|
844
851
|
_scrollToFirstError.current = value;
|
|
845
852
|
}
|
|
@@ -887,7 +894,8 @@ const useForm = (initialValues = {}, onFieldsChange, onValuesChange, scrollToFir
|
|
|
887
894
|
setOnFinish,
|
|
888
895
|
setOnFieldsChange,
|
|
889
896
|
setOnValuesChange,
|
|
890
|
-
changeStep
|
|
897
|
+
changeStep,
|
|
898
|
+
subscribeToErrors
|
|
891
899
|
};
|
|
892
900
|
return formInstance;
|
|
893
901
|
};
|
|
@@ -984,7 +992,6 @@ const FormItem$1 = ({
|
|
|
984
992
|
layout = 'vertical',
|
|
985
993
|
style = {},
|
|
986
994
|
dependencies = [],
|
|
987
|
-
initialValue,
|
|
988
995
|
feedbackIcons,
|
|
989
996
|
extra,
|
|
990
997
|
hideLabel = false,
|
|
@@ -993,6 +1000,7 @@ const FormItem$1 = ({
|
|
|
993
1000
|
}) => {
|
|
994
1001
|
const formContext = useContext(FormContext);
|
|
995
1002
|
const errorRef = useRef(null);
|
|
1003
|
+
const [errorMessage, setErrorMessage] = useState('');
|
|
996
1004
|
const fieldRef = useRef(null);
|
|
997
1005
|
if (!formContext) {
|
|
998
1006
|
throw new Error('FormItem must be used within a Form');
|
|
@@ -1000,13 +1008,11 @@ const FormItem$1 = ({
|
|
|
1000
1008
|
const {
|
|
1001
1009
|
isReseting,
|
|
1002
1010
|
registerField,
|
|
1003
|
-
getFieldError,
|
|
1004
|
-
getFieldValue,
|
|
1005
|
-
setFieldValue,
|
|
1006
1011
|
getFieldInstance,
|
|
1007
1012
|
setFieldInstance,
|
|
1008
1013
|
subscribeToFields,
|
|
1009
|
-
validateFields
|
|
1014
|
+
validateFields,
|
|
1015
|
+
subscribeToErrors
|
|
1010
1016
|
} = formContext;
|
|
1011
1017
|
const childrenList = useMemo(() => flattenChildren(children), [children]);
|
|
1012
1018
|
useEffect(() => {
|
|
@@ -1018,11 +1024,6 @@ const FormItem$1 = ({
|
|
|
1018
1024
|
setFieldInstance(name, fieldRef.current);
|
|
1019
1025
|
}, [name, fieldRef.current]);
|
|
1020
1026
|
useEffect(() => () => registerField(name, undefined, true), [name]);
|
|
1021
|
-
useEffect(() => {
|
|
1022
|
-
if (initialValue) {
|
|
1023
|
-
setFieldValue(name, initialValue);
|
|
1024
|
-
}
|
|
1025
|
-
}, []);
|
|
1026
1027
|
useEffect(() => {
|
|
1027
1028
|
if (name && dependencies.length > 0) {
|
|
1028
1029
|
const unsubscribe = subscribeToFields(dependencies, () => {
|
|
@@ -1033,8 +1034,13 @@ const FormItem$1 = ({
|
|
|
1033
1034
|
};
|
|
1034
1035
|
}
|
|
1035
1036
|
}, [dependencies, name]);
|
|
1037
|
+
useEffect(() => {
|
|
1038
|
+
const unsubscribe = subscribeToErrors?.(errors => {
|
|
1039
|
+
setErrorMessage(errors.find(error => error.name === name)?.errors?.[0] || '');
|
|
1040
|
+
});
|
|
1041
|
+
return () => unsubscribe?.();
|
|
1042
|
+
}, []);
|
|
1036
1043
|
const isRequired = useMemo(() => rules.some(rule => rule.required), [rules]);
|
|
1037
|
-
const errorMessage = getFieldError(name)?.[0];
|
|
1038
1044
|
return /*#__PURE__*/React.createElement("div", {
|
|
1039
1045
|
style: style,
|
|
1040
1046
|
"data-instance": name,
|
|
@@ -1050,14 +1056,6 @@ const FormItem$1 = ({
|
|
|
1050
1056
|
className: `${prefixCls}-required`
|
|
1051
1057
|
}, "*")), Children.map(childrenList, (child, key) => {
|
|
1052
1058
|
if (/*#__PURE__*/isValidElement(child)) {
|
|
1053
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1054
|
-
// @ts-expect-error
|
|
1055
|
-
const {
|
|
1056
|
-
onChange,
|
|
1057
|
-
value,
|
|
1058
|
-
...childProps
|
|
1059
|
-
} = child.props;
|
|
1060
|
-
const fieldValue = value ?? getFieldValue(name) ?? initialValue;
|
|
1061
1059
|
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(FormItemChildComponent, _extends({}, props, {
|
|
1062
1060
|
key: `${key}_${isReseting}`
|
|
1063
1061
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -1066,18 +1064,7 @@ const FormItem$1 = ({
|
|
|
1066
1064
|
ref: fieldRef,
|
|
1067
1065
|
name: name,
|
|
1068
1066
|
child: child,
|
|
1069
|
-
|
|
1070
|
-
error: !!errorMessage,
|
|
1071
|
-
fieldValue: fieldValue,
|
|
1072
|
-
setFieldValue: setFieldValue,
|
|
1073
|
-
feedbackIcons: feedbackIcons,
|
|
1074
|
-
onChange: onChange,
|
|
1075
|
-
noStyle: props.noStyle,
|
|
1076
|
-
normalize: props.normalize
|
|
1077
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1078
|
-
// @ts-expect-error
|
|
1079
|
-
,
|
|
1080
|
-
size: childProps.size || props.size
|
|
1067
|
+
error: !!errorMessage
|
|
1081
1068
|
})), extra ? /*#__PURE__*/React.createElement("div", {
|
|
1082
1069
|
className: `${prefixCls}-extra`
|
|
1083
1070
|
}, extra || '') : null, !props.noStyle && /*#__PURE__*/React.createElement("span", {
|
|
@@ -1102,9 +1089,7 @@ const FormItemChildComponent = ({
|
|
|
1102
1089
|
child,
|
|
1103
1090
|
name,
|
|
1104
1091
|
error,
|
|
1105
|
-
|
|
1106
|
-
setFieldValue,
|
|
1107
|
-
onChange,
|
|
1092
|
+
initialValue,
|
|
1108
1093
|
normalize,
|
|
1109
1094
|
noStyle,
|
|
1110
1095
|
feedbackIcons,
|
|
@@ -1112,32 +1097,43 @@ const FormItemChildComponent = ({
|
|
|
1112
1097
|
...props
|
|
1113
1098
|
}) => {
|
|
1114
1099
|
const formContext = useContext(FormContext);
|
|
1115
|
-
const animationRef = useRef(null);
|
|
1116
1100
|
const [wasNormalize, setWasNormalize] = useState(false);
|
|
1117
1101
|
const {
|
|
1118
|
-
getFieldsValue
|
|
1102
|
+
getFieldsValue,
|
|
1103
|
+
getFieldValue,
|
|
1104
|
+
setFieldValue
|
|
1119
1105
|
} = formContext || {};
|
|
1120
|
-
|
|
1106
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1107
|
+
// @ts-expect-error
|
|
1108
|
+
const {
|
|
1109
|
+
onChange,
|
|
1110
|
+
value
|
|
1111
|
+
} = child.props;
|
|
1112
|
+
const fieldValue = value ?? getFieldValue?.(name) ?? initialValue;
|
|
1113
|
+
useEffect(() => {
|
|
1114
|
+
if (initialValue) {
|
|
1115
|
+
setFieldValue?.(name, initialValue);
|
|
1116
|
+
}
|
|
1117
|
+
}, []);
|
|
1118
|
+
const handleChange = (e, option) => {
|
|
1121
1119
|
let rawValue = e?.target ? e.target.value : e;
|
|
1122
1120
|
if (normalize) {
|
|
1123
|
-
const prevValue = fieldValue
|
|
1121
|
+
const prevValue = fieldValue;
|
|
1124
1122
|
const allValues = getFieldsValue?.();
|
|
1125
1123
|
rawValue = normalize(rawValue, prevValue, allValues);
|
|
1126
1124
|
if (rawValue === prevValue) {
|
|
1127
1125
|
e.target.value = rawValue;
|
|
1128
1126
|
setWasNormalize(prev => !prev);
|
|
1129
|
-
|
|
1130
|
-
cancelAnimationFrame(animationRef.current);
|
|
1131
|
-
}
|
|
1132
|
-
animationRef.current = requestAnimationFrame(() => {
|
|
1127
|
+
const timeout = setTimeout(() => {
|
|
1133
1128
|
document.querySelector(`[name='${name}']`)?.focus();
|
|
1134
|
-
|
|
1129
|
+
clearTimeout(timeout);
|
|
1130
|
+
}, 0);
|
|
1135
1131
|
return;
|
|
1136
1132
|
}
|
|
1137
1133
|
}
|
|
1138
|
-
setFieldValue(name, rawValue, undefined, undefined, true);
|
|
1134
|
+
setFieldValue?.(name, rawValue, undefined, undefined, true);
|
|
1139
1135
|
onChange?.(e, option);
|
|
1140
|
-
}
|
|
1136
|
+
};
|
|
1141
1137
|
const injectPropsIntoFinalLeaf = child => {
|
|
1142
1138
|
if (! /*#__PURE__*/isValidElement(child)) {
|
|
1143
1139
|
return child;
|
|
@@ -1155,11 +1151,15 @@ const FormItemChildComponent = ({
|
|
|
1155
1151
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1156
1152
|
// @ts-expect-error
|
|
1157
1153
|
}, child.props, {
|
|
1158
|
-
name: name
|
|
1154
|
+
name: name
|
|
1155
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1156
|
+
// @ts-expect-error
|
|
1157
|
+
,
|
|
1158
|
+
size: childProps.size || props.size,
|
|
1159
1159
|
child: child,
|
|
1160
|
+
value: fieldValue,
|
|
1160
1161
|
onChange: handleChange,
|
|
1161
|
-
key: `${name}_${wasNormalize}
|
|
1162
|
-
value: fieldValue ?? props.value
|
|
1162
|
+
key: `${name}_${wasNormalize}`
|
|
1163
1163
|
}, 'dangerouslySetInnerHTML' in childProps ? {} : {
|
|
1164
1164
|
__injected: true,
|
|
1165
1165
|
...(error ? {
|
|
@@ -3006,12 +3006,7 @@ const InputComponent = ({
|
|
|
3006
3006
|
value: rawInput
|
|
3007
3007
|
}
|
|
3008
3008
|
};
|
|
3009
|
-
|
|
3010
|
-
cancelAnimationFrame(animationRef.current);
|
|
3011
|
-
}
|
|
3012
|
-
animationRef.current = requestAnimationFrame(() => {
|
|
3013
|
-
props.onChange?.(eventWithMaskedValue);
|
|
3014
|
-
});
|
|
3009
|
+
props.onChange?.(eventWithMaskedValue);
|
|
3015
3010
|
};
|
|
3016
3011
|
const handleClear = e => {
|
|
3017
3012
|
if (mask) {
|