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.
@@ -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, initialValue, feedbackIcons, extra, hideLabel, removeErrorMessageHeight, ...props }: FormItemProps): React.JSX.Element;
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
- fieldValue: RuleTypes;
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, useCallback, createContext, useImperativeHandle, useLayoutEffect } from 'react';
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 [errors, setErrors] = useState({});
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 errors[name] || [];
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(errors).map(([name, err]) => ({
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
- setErrors({
667
- [name]: []
668
- });
667
+ errorsRef.current[name] = [];
669
668
  return;
670
669
  }
671
- if (!errors?.length) {
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
- setErrors({
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
- setErrors(prev => ({
768
- ...prev,
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
- setErrors(prev => ({
795
- ...prev,
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
- value: value,
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
- fieldValue,
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
- const handleChange = useCallback((e, option) => {
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 ?? props.value;
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
- if (animationRef.current) {
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
- }, [fieldValue, props.value, name]);
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
- if (animationRef.current) {
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) {