rsuite 5.70.1 → 5.70.3

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/esm/Form/Form.js CHANGED
@@ -53,7 +53,7 @@ var Form = /*#__PURE__*/React.forwardRef(function (props, ref) {
53
53
  onError = props.onError,
54
54
  onChange = props.onChange,
55
55
  rest = _objectWithoutPropertiesLoose(props, _excluded);
56
- var _useSchemaModel = useSchemaModel(formModel),
56
+ var _useSchemaModel = useSchemaModel(formModel, nestedField),
57
57
  getCombinedModel = _useSchemaModel.getCombinedModel,
58
58
  pushFieldRule = _useSchemaModel.pushFieldRule,
59
59
  removeFieldRule = _useSchemaModel.removeFieldRule;
@@ -6,7 +6,7 @@ export interface FormErrorProps {
6
6
  onError?: (formError: any) => void;
7
7
  nestedField?: boolean;
8
8
  }
9
- export default function useFormValidate(formError: any, props: FormErrorProps): {
9
+ export default function useFormValidate(_formError: any, props: FormErrorProps): {
10
10
  formError: any;
11
11
  check: (...args: any[]) => any;
12
12
  checkForField: (...args: any[]) => any;
@@ -8,13 +8,13 @@ import omit from 'lodash/omit';
8
8
  import set from 'lodash/set';
9
9
  import { useControlled, useEventCallback } from "../../internals/hooks/index.js";
10
10
  import { nameToPath } from "../../FormControl/utils.js";
11
- export default function useFormValidate(formError, props) {
11
+ export default function useFormValidate(_formError, props) {
12
12
  var formValue = props.formValue,
13
13
  getCombinedModel = props.getCombinedModel,
14
14
  onCheck = props.onCheck,
15
15
  onError = props.onError,
16
16
  nestedField = props.nestedField;
17
- var _useControlled = useControlled(formError, {}),
17
+ var _useControlled = useControlled(_formError, {}),
18
18
  realFormError = _useControlled[0],
19
19
  setFormError = _useControlled[1];
20
20
  var checkOptions = {
@@ -32,12 +32,29 @@ export default function useFormValidate(formError, props) {
32
32
  var formError = {};
33
33
  var errorCount = 0;
34
34
  var model = getCombinedModel();
35
- Object.keys(model.getSchemaSpec()).forEach(function (key) {
36
- var checkResult = model.checkForField(key, formValue || {}, checkOptions);
35
+ var checkField = function checkField(key, type, value, formErrorObj) {
36
+ var checkResult = type.check(value);
37
37
  if (checkResult.hasError === true) {
38
38
  errorCount += 1;
39
- formError[key] = (checkResult === null || checkResult === void 0 ? void 0 : checkResult.errorMessage) || checkResult;
39
+ formErrorObj[key] = (checkResult === null || checkResult === void 0 ? void 0 : checkResult.errorMessage) || checkResult;
40
+ }
41
+
42
+ // Check nested object
43
+ if (type !== null && type !== void 0 && type.objectTypeSchemaSpec) {
44
+ Object.entries(type.objectTypeSchemaSpec).forEach(function (_ref) {
45
+ var nestedKey = _ref[0],
46
+ nestedType = _ref[1];
47
+ formErrorObj[key] = formErrorObj[key] || {
48
+ object: {}
49
+ };
50
+ checkField(nestedKey, nestedType, value === null || value === void 0 ? void 0 : value[nestedKey], formErrorObj[key].object);
51
+ });
40
52
  }
53
+ };
54
+ Object.entries(model.getSchemaSpec()).forEach(function (_ref2) {
55
+ var key = _ref2[0],
56
+ type = _ref2[1];
57
+ checkField(key, type, formValue[key], formError);
41
58
  });
42
59
  setFormError(formError);
43
60
  onCheck === null || onCheck === void 0 ? void 0 : onCheck(formError);
@@ -51,7 +68,7 @@ export default function useFormValidate(formError, props) {
51
68
  var checkFieldForNextValue = useEventCallback(function (fieldName, nextValue, callback) {
52
69
  var model = getCombinedModel();
53
70
  var resultOfCurrentField = model.checkForField(fieldName, nextValue, checkOptions);
54
- var nextFormError = _extends({}, formError);
71
+ var nextFormError = _extends({}, realFormError);
55
72
  /**
56
73
  * when using proxy of schema-typed, we need to use getCheckResult to get all errors,
57
74
  * but if nestedField is used, it is impossible to distinguish whether the nested object has an error here,
@@ -134,7 +151,7 @@ export default function useFormValidate(formError, props) {
134
151
  var checkFieldAsyncForNextValue = useEventCallback(function (fieldName, nextValue) {
135
152
  var model = getCombinedModel();
136
153
  return model.checkForFieldAsync(fieldName, nextValue, checkOptions).then(function (resultOfCurrentField) {
137
- var nextFormError = _extends({}, formError);
154
+ var nextFormError = _extends({}, realFormError);
138
155
  /**
139
156
  * when using proxy of schema-typed, we need to use getCheckResult to get all errors,
140
157
  * but if nestedField is used, it is impossible to distinguish whether the nested object has an error here,
@@ -203,7 +220,7 @@ export default function useFormValidate(formError, props) {
203
220
  setFormError(formError);
204
221
  });
205
222
  var cleanErrorForField = useEventCallback(function (fieldName) {
206
- setFormError(omit(formError, [nestedField ? nameToPath(fieldName) : fieldName]));
223
+ setFormError(omit(realFormError, [nestedField ? nameToPath(fieldName) : fieldName]));
207
224
  });
208
225
  return {
209
226
  formError: realFormError,
@@ -1,7 +1,7 @@
1
1
  import type { MutableRefObject } from 'react';
2
2
  import type { CheckType, Schema } from 'schema-typed';
3
3
  export type FieldRuleType = MutableRefObject<CheckType<unknown, any> | undefined>;
4
- declare function useSchemaModel(formModel: Schema): {
4
+ declare function useSchemaModel(formModel: Schema, nestedField: boolean): {
5
5
  getCombinedModel: () => Schema<any, string>;
6
6
  pushFieldRule: (name: string, fieldRule: FieldRuleType) => void;
7
7
  removeFieldRule: (name: string) => void;
@@ -1,7 +1,59 @@
1
1
  'use client';
2
- import { SchemaModel } from 'schema-typed';
2
+ import { SchemaModel, ObjectType } from 'schema-typed';
3
3
  import { useRef, useCallback } from 'react';
4
- function useSchemaModel(formModel) {
4
+ /**
5
+ * Convert a flat schema object to a nested schema object
6
+ *
7
+ * @example
8
+ *
9
+ * ```js
10
+ * const schema = {
11
+ * 'address.city': StringType().isRequired('City is required'),
12
+ * 'address.street': StringType().isRequired('Street is required')
13
+ * };
14
+ *
15
+ * const result = unflattenSchemaObject(schema);
16
+ *
17
+ * // result
18
+ * {
19
+ * address: ObjectType().shape({
20
+ * city: StringType().isRequired('City is required'),
21
+ * street: StringType().isRequired('Street is required')
22
+ * })
23
+ * }
24
+ * ```
25
+ */
26
+ function unflattenSchemaObject(schema) {
27
+ var result = {};
28
+ var $type = Symbol('schema-type');
29
+ Object.keys(schema).forEach(function (key) {
30
+ if (key.includes('.')) {
31
+ var keys = key.split('.');
32
+ var lastKey = keys.pop() || '';
33
+ var current = result;
34
+ keys.forEach(function (subKey) {
35
+ var _ref;
36
+ current[subKey] = current[subKey] || (_ref = {}, _ref[$type] = 'object-type', _ref);
37
+ current = current[subKey];
38
+ });
39
+ current[lastKey] = schema[key];
40
+ } else {
41
+ result[key] = schema[key];
42
+ }
43
+ });
44
+ function convertToShape(obj) {
45
+ Object.keys(obj).forEach(function (key) {
46
+ var _obj$key;
47
+ if (((_obj$key = obj[key]) === null || _obj$key === void 0 ? void 0 : _obj$key[$type]) === 'object-type') {
48
+ delete obj[key][$type];
49
+ obj[key] = ObjectType().shape(convertToShape(obj[key]));
50
+ }
51
+ });
52
+ return obj;
53
+ }
54
+ return convertToShape(result);
55
+ }
56
+ function useSchemaModel(formModel, nestedField) {
5
57
  var subRulesRef = useRef([]);
6
58
  var pushFieldRule = useCallback(function (name, fieldRule) {
7
59
  subRulesRef.current.push({
@@ -24,15 +76,16 @@ function useSchemaModel(formModel) {
24
76
  if (realSubRules.length === 0) {
25
77
  return formModel;
26
78
  }
27
- return SchemaModel.combine(formModel, SchemaModel(realSubRules.map(function (_ref) {
28
- var _ref2;
29
- var name = _ref.name,
30
- fieldRule = _ref.fieldRule;
31
- return _ref2 = {}, _ref2[name] = fieldRule.current, _ref2;
79
+ var subRuleObject = realSubRules.map(function (_ref2) {
80
+ var _ref3;
81
+ var name = _ref2.name,
82
+ fieldRule = _ref2.fieldRule;
83
+ return _ref3 = {}, _ref3[name] = fieldRule.current, _ref3;
32
84
  }).reduce(function (a, b) {
33
85
  return Object.assign(a, b);
34
- }, {})));
35
- }, [formModel]);
86
+ }, {});
87
+ return SchemaModel.combine(formModel, SchemaModel(nestedField ? unflattenSchemaObject(subRuleObject) : subRuleObject));
88
+ }, [formModel, nestedField]);
36
89
  return {
37
90
  getCombinedModel: getCombinedModel,
38
91
  pushFieldRule: pushFieldRule,
@@ -6,6 +6,10 @@ import set from 'lodash/set';
6
6
  import { nameToPath } from "../utils.js";
7
7
  function getErrorMessage(error) {
8
8
  var _error$array;
9
+ if (typeof error === 'string') {
10
+ return error;
11
+ }
12
+
9
13
  /**
10
14
  * When using some components as the field, such as TagInput, and using `ArrayType().of` as the validation rule,
11
15
  * the error object won't contain the errorMessage directly. @see https://github.com/rsuite/rsuite/issues/3866
@@ -85,8 +85,14 @@ function useFlattenTree(data, options) {
85
85
  updateTreeNodeCheckState(value);
86
86
  forceUpdate();
87
87
  }
88
+
89
+ /**
90
+ * Add a dependency on data, because when loading data asynchronously through getChildren,
91
+ * data may change and the node status needs to be updated.
92
+ * @see https://github.com/rsuite/rsuite/issues/3973
93
+ */
88
94
  // eslint-disable-next-line react-hooks/exhaustive-deps
89
- }, [value]);
95
+ }, [value, data]);
90
96
  return flattenedNodes.current;
91
97
  }
92
98
  export default useFlattenTree;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rsuite",
3
- "version": "5.70.1",
3
+ "version": "5.70.3",
4
4
  "description": "A suite of react components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",