@hi-ui/form 4.0.0-beta.8 → 4.0.1

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.
Files changed (70) hide show
  1. package/README.md +1 -1
  2. package/lib/cjs/Form.js +12 -10
  3. package/lib/cjs/FormField.js +11 -2
  4. package/lib/cjs/FormItem.js +28 -9
  5. package/lib/cjs/FormLabel.js +11 -10
  6. package/lib/cjs/FormList.js +9 -11
  7. package/lib/cjs/FormMessage.js +2 -3
  8. package/lib/cjs/FormReset.js +2 -3
  9. package/lib/cjs/FormSubmit.js +4 -3
  10. package/lib/cjs/context.js +1 -2
  11. package/lib/cjs/index.js +1 -2
  12. package/lib/cjs/styles/index.scss.js +3 -4
  13. package/lib/cjs/use-form-field.js +20 -17
  14. package/lib/cjs/use-form.js +133 -46
  15. package/lib/cjs/utils/index.js +29 -2
  16. package/lib/esm/Form.js +10 -8
  17. package/lib/esm/FormField.js +10 -2
  18. package/lib/esm/FormItem.js +25 -7
  19. package/lib/esm/FormLabel.js +6 -5
  20. package/lib/esm/FormList.js +2 -4
  21. package/lib/esm/FormMessage.js +1 -2
  22. package/lib/esm/FormReset.js +1 -2
  23. package/lib/esm/FormSubmit.js +3 -2
  24. package/lib/esm/context.js +1 -2
  25. package/lib/esm/index.js +2 -3
  26. package/lib/esm/styles/index.scss.js +4 -6
  27. package/lib/esm/use-form-field.js +21 -19
  28. package/lib/esm/use-form.js +128 -41
  29. package/lib/esm/utils/index.js +27 -3
  30. package/lib/types/Form.d.ts +4 -0
  31. package/lib/types/FormField.d.ts +5 -1
  32. package/lib/types/FormItem.d.ts +6 -2
  33. package/lib/types/FormLabel.d.ts +1 -1
  34. package/lib/types/FormList.d.ts +4 -3
  35. package/lib/types/FormReset.d.ts +3 -0
  36. package/lib/types/FormSubmit.d.ts +4 -1
  37. package/lib/types/context.d.ts +2 -0
  38. package/lib/types/types.d.ts +38 -21
  39. package/lib/types/use-form-field.d.ts +3 -1
  40. package/lib/types/use-form.d.ts +9 -7
  41. package/lib/types/utils/index.d.ts +2 -1
  42. package/package.json +16 -15
  43. package/lib/cjs/Form.js.map +0 -1
  44. package/lib/cjs/FormField.js.map +0 -1
  45. package/lib/cjs/FormItem.js.map +0 -1
  46. package/lib/cjs/FormLabel.js.map +0 -1
  47. package/lib/cjs/FormList.js.map +0 -1
  48. package/lib/cjs/FormMessage.js.map +0 -1
  49. package/lib/cjs/FormReset.js.map +0 -1
  50. package/lib/cjs/FormSubmit.js.map +0 -1
  51. package/lib/cjs/context.js.map +0 -1
  52. package/lib/cjs/index.js.map +0 -1
  53. package/lib/cjs/styles/index.scss.js.map +0 -1
  54. package/lib/cjs/use-form-field.js.map +0 -1
  55. package/lib/cjs/use-form.js.map +0 -1
  56. package/lib/cjs/utils/index.js.map +0 -1
  57. package/lib/esm/Form.js.map +0 -1
  58. package/lib/esm/FormField.js.map +0 -1
  59. package/lib/esm/FormItem.js.map +0 -1
  60. package/lib/esm/FormLabel.js.map +0 -1
  61. package/lib/esm/FormList.js.map +0 -1
  62. package/lib/esm/FormMessage.js.map +0 -1
  63. package/lib/esm/FormReset.js.map +0 -1
  64. package/lib/esm/FormSubmit.js.map +0 -1
  65. package/lib/esm/context.js.map +0 -1
  66. package/lib/esm/index.js.map +0 -1
  67. package/lib/esm/styles/index.scss.js.map +0 -1
  68. package/lib/esm/use-form-field.js.map +0 -1
  69. package/lib/esm/use-form.js.map +0 -1
  70. package/lib/esm/utils/index.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
@@ -47,8 +47,10 @@ var FormSubmit = /*#__PURE__*/forwardRef(function (_a, ref) {
47
47
  evt.preventDefault();
48
48
  evt.stopPropagation();
49
49
  submitForm().then(function (result) {
50
+ // @ts-ignore
50
51
  _onClick === null || _onClick === void 0 ? void 0 : _onClick(result, null);
51
52
  })["catch"](function (error) {
53
+ // @ts-ignore
52
54
  _onClick === null || _onClick === void 0 ? void 0 : _onClick(null, error);
53
55
  });
54
56
  }
@@ -60,4 +62,3 @@ if (__DEV__) {
60
62
  }
61
63
 
62
64
  export { FormSubmit };
63
- //# sourceMappingURL=FormSubmit.js.map
@@ -2,7 +2,7 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
@@ -22,4 +22,3 @@ var useFormContext = function useFormContext() {
22
22
  };
23
23
 
24
24
  export { FormProvider, useFormContext };
25
- //# sourceMappingURL=context.js.map
package/lib/esm/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
@@ -24,5 +24,4 @@ var Form = Object.assign(Form$1, {
24
24
  Submit: FormSubmit,
25
25
  Reset: FormReset
26
26
  });
27
- export default Form;
28
- //# sourceMappingURL=index.js.map
27
+ export { Form as default };
@@ -2,16 +2,14 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
- var css_248z = "@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n.hi-v4-form {\n max-width: 100%;\n position: relative; }\n.hi-v4-form fieldset {\n margin: 0;\n padding: 0;\n border: 0; }\n.hi-v4-form fieldset + fieldset {\n margin-top: 16px; }\n.hi-v4-form legend {\n margin: 0 0 16px;\n color: var(--hi-v4-color-gray-800, #1f2937); }\n.hi-v4-form--placement-horizontal {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap; }\n.hi-v4-form--placement-horizontal .hi-v4-form-label__indent {\n min-height: 32px; }\n.hi-v4-form-label {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n font-size: var(--hi-v4-text-size-normal, 0.875rem);\n margin-right: var(--hi-v4-spacing-4, 8px);\n margin-bottom: 24px; }\n.hi-v4-form-label__text, .hi-v4-form-label__indent {\n -ms-flex-negative: 0;\n flex-shrink: 0;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n vertical-align: top;\n color: var(--hi-v4-color-gray-800, #1f2937);\n overflow-wrap: break-word; }\n.hi-v4-form-label__text {\n padding-right: var(--hi-v4-spacing-6, 12px);\n min-height: 32px;\n line-height: 32px; }\n.hi-v4-form-label--placement-left .hi-v4-form-label__text {\n text-align: left; }\n.hi-v4-form-label--placement-right .hi-v4-form-label__text {\n text-align: right; }\n.hi-v4-form-label--placement-top .hi-v4-form-label__text {\n height: 22px;\n padding-right: 8px;\n margin-bottom: 8px; }\n.hi-v4-form-label--required .hi-v4-form-label__text::before {\n margin-right: var(--hi-v4-spacing-2, 4px);\n content: '*';\n color: var(--hi-v4-color-danger-500, var(--hi-v4-color-red-500, #ff5959)); }\n.hi-v4-form-label--placement-top {\n text-align: left;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n margin-bottom: var(--hi-v4-spacing-10, 20px);\n padding-right: 0; }\n.hi-v4-form-label__content {\n -webkit-box-flex: 1;\n -ms-flex: 1 1;\n flex: 1 1;\n position: relative;\n vertical-align: top;\n min-height: 32px;\n -ms-flex-negative: 0;\n flex-shrink: 0; }\n.hi-v4-form-message {\n display: block;\n font-size: var(--hi-v4-text-size-normal, 0.875rem);\n min-height: 24px;\n padding: 2px 0;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n line-height: 20px;\n -webkit-transform: translateY(-10%);\n transform: translateY(-10%);\n opacity: 0;\n color: var(--hi-v4-color-danger-500, var(--hi-v4-color-red-500, #ff5959));\n -webkit-transition: all 0.3s;\n transition: all 0.3s; }\n.hi-v4-form-message--show {\n opacity: 1;\n -webkit-transform: translateY(0);\n transform: translateY(0); }\n.hi-v4-form-item {\n position: relative; }\n.hi-v4-form-item__message {\n position: absolute; }\n";
11
-
12
- var __styleInject__ = require('style-inject/dist/style-inject.es.js')["default"];
10
+ import __styleInject__ from 'inject-head-style';
11
+ var css_248z = ".hi-v4-form {max-width: 100%;position: relative; }.hi-v4-form fieldset {margin: 0;padding: 0;border: 0; }.hi-v4-form fieldset + fieldset {margin-top: 16px; }.hi-v4-form legend {margin: 0 0 16px;color: var(--hi-v4-color-gray-800, #1f2937); }.hi-v4-form--placement-horizontal {display: -webkit-box;display: -ms-flexbox;display: flex;-ms-flex-wrap: wrap;flex-wrap: wrap;-webkit-column-gap: var(--hi-v4-spacing-10, 20px);-moz-column-gap: var(--hi-v4-spacing-10, 20px);column-gap: var(--hi-v4-spacing-10, 20px); }.hi-v4-form--placement-horizontal .hi-v4-form-label__indent {min-height: var(--hi-v4-height-8, 32px); }.hi-v4-form-label {display: -webkit-box;display: -ms-flexbox;display: flex;font-size: var(--hi-v4-text-size-md, 0.875rem);-webkit-box-sizing: border-box;box-sizing: border-box;margin-right: 0;margin-bottom: var(--hi-v4-spacing-12, 24px); }.hi-v4-form-label__text, .hi-v4-form-label__indent {-ms-flex-negative: 0;flex-shrink: 0;-webkit-box-sizing: border-box;box-sizing: border-box;vertical-align: top;color: var(--hi-v4-color-gray-800, #1f2937);overflow-wrap: break-word; }.hi-v4-form-label__text {padding-right: var(--hi-v4-spacing-6, 12px);min-height: var(--hi-v4-height-8, 32px);line-height: var(--hi-v4-height-8, 32px); }.hi-v4-form-label--placement-left .hi-v4-form-label__text {text-align: left; }.hi-v4-form-label--placement-right .hi-v4-form-label__text {text-align: right; }.hi-v4-form-label--placement-top .hi-v4-form-label__text {height: 22px;min-height: 22px;line-height: 22px;padding-right: 0;margin-bottom: var(--hi-v4-spacing-4, 8px); }.hi-v4-form-label--required .hi-v4-form-label__text::before {margin-right: var(--hi-v4-spacing-2, 4px);content: '*';color: var(--hi-v4-color-danger-500, var(--hi-v4-color-red-500, #ff5959)); }.hi-v4-form-label--placement-top {text-align: left;-webkit-box-orient: vertical;-webkit-box-direction: normal;-ms-flex-direction: column;flex-direction: column;margin-bottom: var(--hi-v4-spacing-12, 24px);padding-right: 0; }.hi-v4-form-label__content {-webkit-box-flex: 1;-ms-flex: 1 1;flex: 1 1;position: relative;vertical-align: top;min-height: var(--hi-v4-height-8, 32px);-ms-flex-negative: 0;flex-shrink: 0; }.hi-v4-form-label__control {min-width: 1px; }.hi-v4-form-message {display: block;font-size: var(--hi-v4-text-size-md, 0.875rem);min-height: 24px;padding: 2px 0;-webkit-box-sizing: border-box;box-sizing: border-box;line-height: 20px;-webkit-transform: translateY(-10%);transform: translateY(-10%);opacity: 0;color: var(--hi-v4-color-danger-500, var(--hi-v4-color-red-500, #ff5959));-webkit-transition: all 0.3s;transition: all 0.3s; }.hi-v4-form-message--show {opacity: 1;-webkit-transform: translateY(0);transform: translateY(0); }.hi-v4-form-item {position: relative; }.hi-v4-form-item__message {position: absolute; }";
13
12
 
14
13
  __styleInject__(css_248z);
15
14
 
16
- export default css_248z;
17
- //# sourceMappingURL=index.scss.js.map
15
+ export { css_248z as default };
@@ -2,29 +2,26 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import { useMemo, useCallback, useEffect } from 'react';
11
11
  import { useFormContext } from './context.js';
12
- import { isArrayNonEmpty, isNullish, isArray } from '@hi-ui/type-assertion';
12
+ import { isArrayNonEmpty } from '@hi-ui/type-assertion';
13
13
  import Validater from 'async-validator';
14
14
  import { normalizeArray } from '@hi-ui/array-utils';
15
- import { stringify } from './utils/index.js';
15
+ import { stringify, isValidField } from './utils/index.js';
16
16
 
17
- var useFormField = function useFormField(props) {
17
+ var useFiledRules = function useFiledRules(props) {
18
18
  var field = props.field,
19
19
  rulesProp = props.rules,
20
20
  _props$valueType = props.valueType,
21
21
  valueType = _props$valueType === void 0 ? 'any' : _props$valueType;
22
22
 
23
23
  var _useFormContext = useFormContext(),
24
- getFieldRules = _useFormContext.getFieldRules,
25
- getFieldProps = _useFormContext.getFieldProps,
26
- registerField = _useFormContext.registerField,
27
- unregisterField = _useFormContext.unregisterField;
24
+ getFieldRules = _useFormContext.getFieldRules;
28
25
  /**
29
26
  * 处理校验规则,item 优先级大于 form
30
27
  */
@@ -38,7 +35,19 @@ var useFormField = function useFormField(props) {
38
35
  type: valueType
39
36
  }, rule);
40
37
  });
41
- }, [rulesProp, field, getFieldRules, valueType]); // 当前 field 的唯一校验器
38
+ }, [rulesProp, field, getFieldRules, valueType]);
39
+ return fieldRules;
40
+ };
41
+
42
+ var useFormField = function useFormField(props) {
43
+ var field = props.field;
44
+
45
+ var _useFormContext2 = useFormContext(),
46
+ getFieldProps = _useFormContext2.getFieldProps,
47
+ registerField = _useFormContext2.registerField,
48
+ unregisterField = _useFormContext2.unregisterField;
49
+
50
+ var fieldRules = useFiledRules(props); // 当前 field 的唯一校验器
42
51
 
43
52
  var fieldValidate = useCallback(function (value) {
44
53
  var _Validater, _validater$validate;
@@ -56,23 +65,16 @@ var useFormField = function useFormField(props) {
56
65
  }, [fieldRules, field]); // 注入当前 field 及其验证规则到 Form
57
66
 
58
67
  useEffect(function () {
59
- if (isNullish(field) || field === '') return;
60
- if (isArray(field) && field.every(function (item) {
61
- return isNullish(item) || item === '';
62
- })) return;
68
+ if (!isValidField(field)) return;
63
69
  registerField(field, {
64
70
  validate: fieldValidate
65
71
  });
66
72
  return function () {
67
- if (isNullish(field) || field === '') return;
68
- if (isArray(field) && field.every(function (item) {
69
- return isNullish(item) || item === '';
70
- })) return;
73
+ if (!isValidField(field)) return;
71
74
  unregisterField(field);
72
75
  };
73
76
  }, [registerField, unregisterField, field, fieldValidate]);
74
77
  return getFieldProps(props);
75
78
  };
76
79
 
77
- export { useFormField };
78
- //# sourceMappingURL=use-form-field.js.map
80
+ export { useFiledRules, useFormField };
@@ -2,17 +2,17 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import _regeneratorRuntime from '@babel/runtime/regenerator';
11
11
  import { __rest, __awaiter } from 'tslib';
12
- import { stringify, parse } from './utils/index.js';
12
+ import { stringify, parse, mergeValues, isValidField } from './utils/index.js';
13
13
  import React, { useMemo, useReducer, useCallback, useRef } from 'react';
14
14
  import { useLatestRef, useLatestCallback } from '@hi-ui/use-latest';
15
- import { isArray, isObjectLike, isFunction } from '@hi-ui/type-assertion';
15
+ import { isArray, isFunction, isObjectLike } from '@hi-ui/type-assertion';
16
16
  import { callAllFuncs } from '@hi-ui/func-utils';
17
17
  import { getNested, setNested } from '@hi-ui/object-utils';
18
18
  import { stopEvent } from '@hi-ui/dom-utils';
@@ -21,12 +21,16 @@ var EMPTY_ERRORS = {};
21
21
  var EMPTY_TOUCHED = {};
22
22
  var DEFAULT_VALIDATE_TRIGGER = ['onChange', 'onBlur'];
23
23
 
24
+ var EMPTY_FUNC = function EMPTY_FUNC() {};
25
+
24
26
  var useForm = function useForm(_a) {
25
27
  var initialValues = _a.initialValues,
26
28
  _a$initialErrors = _a.initialErrors,
27
29
  initialErrors = _a$initialErrors === void 0 ? EMPTY_ERRORS : _a$initialErrors,
28
30
  _a$initialTouched = _a.initialTouched,
29
31
  initialTouched = _a$initialTouched === void 0 ? EMPTY_TOUCHED : _a$initialTouched,
32
+ _a$lazyValidate = _a.lazyValidate,
33
+ lazyValidate = _a$lazyValidate === void 0 ? false : _a$lazyValidate,
30
34
  onValuesChange = _a.onValuesChange,
31
35
  onReset = _a.onReset,
32
36
  onSubmit = _a.onSubmit,
@@ -152,11 +156,8 @@ var useForm = function useForm(_a) {
152
156
  type: 'SET_VALIDATING',
153
157
  payload: false
154
158
  }); // @ts-ignore
155
- // @ts-ignore
156
-
157
- setFieldError(field, (_c = (_b = (_a = errorMsg.fields[stringify(field)]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : ''); // TODO: 回调和promise支持
158
- // TODO: 回调和promise支持
159
159
 
160
+ setFieldError(field, (_c = (_b = (_a = errorMsg.fields[stringify(field)]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : '');
160
161
  throw errorMsg;
161
162
  }));
162
163
 
@@ -182,16 +183,104 @@ var useForm = function useForm(_a) {
182
183
 
183
184
  var validateAll = useCallback(function () {
184
185
  var fieldNames = getRegisteredKeys();
186
+ formDispatch({
187
+ type: 'SET_VALIDATING',
188
+ payload: true
189
+ });
185
190
  return Promise.all(fieldNames.map(function (fieldName) {
186
- return validateFieldState(fieldName);
187
- }));
188
- }, [getRegisteredKeys, validateFieldState]);
191
+ var value = getFieldValue(fieldName);
192
+ var fieldValidation = getValidation(fieldName);
193
+
194
+ if (!fieldValidation) {
195
+ return Promise.resolve(null);
196
+ } // catch 错误,保证检验所有表单项
197
+
198
+
199
+ return fieldValidation.validate(value)["catch"](function (error) {
200
+ // 第一个出错,即退出校验
201
+ if (lazyValidate) {
202
+ throw error;
203
+ }
204
+
205
+ return error;
206
+ });
207
+ })).then(function (result) {
208
+ // 合并错误,批量更新并返回
209
+ var combinedError = result.reduce(function (prev, cur, index) {
210
+ var _a, _b;
211
+
212
+ var fieldName = fieldNames[index];
213
+ var errorMsg;
214
+
215
+ if (cur instanceof Error) {
216
+ // @ts-ignore
217
+ errorMsg = ((_b = (_a = cur.fields[stringify(fieldName)]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || '';
218
+
219
+ if (typeof errorMsg === 'string' && !!errorMsg) {
220
+ return setNested(prev, fieldName, errorMsg);
221
+ }
222
+ }
223
+
224
+ return prev;
225
+ }, {});
226
+ formDispatch({
227
+ type: 'SET_VALIDATING',
228
+ payload: false
229
+ });
230
+ formDispatch({
231
+ type: 'SET_ERRORS',
232
+ payload: combinedError
233
+ });
234
+ return combinedError;
235
+ })["catch"](function (error) {
236
+ var _a, _b;
237
+
238
+ var fieldNameStrings = fieldNames.map(function (item) {
239
+ return stringify(item);
240
+ }); // @ts-ignore
241
+
242
+ var fieldNameString = Object.keys(error.fields).find(function (item) {
243
+ return fieldNameStrings.includes(item);
244
+ });
245
+ var combinedError = {};
246
+
247
+ if (!fieldNameString) {
248
+ formDispatch({
249
+ type: 'SET_VALIDATING',
250
+ payload: false
251
+ });
252
+ return error;
253
+ }
254
+
255
+ var errorMsg;
256
+
257
+ if (error instanceof Error) {
258
+ // @ts-ignore
259
+ errorMsg = ((_b = (_a = error.fields[fieldNameString]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || '';
260
+ }
261
+
262
+ var fieldName = parse(fieldNameString);
263
+
264
+ if (typeof errorMsg === 'string' && !!errorMsg) {
265
+ combinedError = setNested(combinedError, fieldName, errorMsg);
266
+ }
267
+
268
+ formDispatch({
269
+ type: 'SET_VALIDATING',
270
+ payload: false
271
+ });
272
+ formDispatch({
273
+ type: 'SET_ERRORS',
274
+ payload: combinedError
275
+ });
276
+ return combinedError;
277
+ });
278
+ }, [getRegisteredKeys, getFieldValue, getValidation, lazyValidate]);
189
279
  /**
190
280
  * 控件值更新策略
191
281
  */
192
282
 
193
283
  var setFieldValue = useCallback(function (field, value, shouldValidate) {
194
- // @ts-ignore
195
284
  formDispatch({
196
285
  type: 'SET_FIELD_VALUE',
197
286
  payload: {
@@ -200,20 +289,20 @@ var useForm = function useForm(_a) {
200
289
  }
201
290
  }); // touched 给外部控制展示,而不是当做参数暴露
202
291
 
203
- var shouldValidateField = // shouldValidate ?? (validateAfterTouched ? getNested(formState.touched, field) : true)
204
- validateAfterTouched ? getNested(formState.touched, field) && shouldValidate : shouldValidate;
292
+ var shouldValidateField = validateAfterTouched ? getNested(formState.touched, field) && shouldValidate : shouldValidate;
205
293
 
206
294
  if (shouldValidateField) {
207
- validateField(field, value);
295
+ validateField(field, value)["catch"](EMPTY_FUNC);
208
296
  }
209
297
  }, [validateField, validateAfterTouched, formState]);
210
- var setFieldsValue = useCallback(function (fields, shouldValidate) {
211
- Object.entries(fields).forEach(function (_ref) {
212
- var fieldName = _ref[0],
213
- value = _ref[1];
214
- setFieldValue(fieldName, value, shouldValidate);
298
+ var setFieldsValue = useCallback(function (fieldsState) {
299
+ formDispatch({
300
+ type: 'SET_VALUES',
301
+ payload: function payload(prevState) {
302
+ return isFunction(fieldsState) ? fieldsState(prevState) : mergeValues(prevState, fieldsState);
303
+ }
215
304
  });
216
- }, [setFieldValue]);
305
+ }, []);
217
306
  var normalizeValueFromChange = useCallback(function (eventOrValue, valuePropName) {
218
307
  var nextValue = eventOrValue;
219
308
 
@@ -258,7 +347,7 @@ var useForm = function useForm(_a) {
258
347
  var handleFieldBlur = useCallback(function (fieldName, shouldValidate) {
259
348
  return function (evt) {
260
349
  if (shouldValidate) {
261
- validateFieldState(fieldName);
350
+ validateFieldState(fieldName)["catch"](EMPTY_FUNC);
262
351
  }
263
352
 
264
353
  setFieldTouched(fieldName, true);
@@ -266,7 +355,7 @@ var useForm = function useForm(_a) {
266
355
  }, [setFieldTouched, validateFieldState]);
267
356
  var handleFieldTrigger = useCallback(function (fieldName) {
268
357
  return function (evt) {
269
- validateFieldState(fieldName);
358
+ validateFieldState(fieldName)["catch"](EMPTY_FUNC);
270
359
  };
271
360
  }, [validateFieldState]);
272
361
  /**
@@ -346,7 +435,7 @@ var useForm = function useForm(_a) {
346
435
  });
347
436
  return _context3.abrupt("return", validateAll().then(function (combinedErrors) {
348
437
  var isInstanceOfError = combinedErrors instanceof Error;
349
- var isActuallyValid = !isInstanceOfError;
438
+ var isActuallyValid = !!combinedErrors && !isInstanceOfError && Object.keys(combinedErrors).length === 0;
350
439
 
351
440
  if (isActuallyValid) {
352
441
  var promiseOrUndefined;
@@ -365,7 +454,6 @@ var useForm = function useForm(_a) {
365
454
  formDispatch({
366
455
  type: 'SUBMIT_DONE'
367
456
  }); // return combinedErrors
368
- // return combinedErrors
369
457
 
370
458
  return formState.values;
371
459
  }
@@ -375,8 +463,6 @@ var useForm = function useForm(_a) {
375
463
  type: 'SUBMIT_DONE'
376
464
  }); // return result
377
465
  // TODO: 满足promise 如果既给到values 又给到 errors
378
- // return result
379
- // TODO: 满足promise 如果既给到values 又给到 errors
380
466
 
381
467
  return formState.values;
382
468
  })["catch"](function (_errors) {
@@ -392,6 +478,8 @@ var useForm = function useForm(_a) {
392
478
 
393
479
  if (isInstanceOfError) {
394
480
  throw combinedErrors;
481
+ } else {
482
+ throw new TypeError('Validation Error');
395
483
  }
396
484
  }
397
485
  }, function (error) {
@@ -419,11 +507,13 @@ var useForm = function useForm(_a) {
419
507
  }, [resetForm]);
420
508
  var resetErrors = useCallback(function () {
421
509
  formDispatch({
422
- // TODO: reset errorMsg
423
510
  type: 'SET_ERRORS',
424
511
  payload: {}
425
512
  });
426
513
  }, []);
514
+ var resetFieldError = useCallback(function (field) {
515
+ setFieldError(field, '');
516
+ }, [setFieldError]);
427
517
  var setFormState = React.useCallback(function (stateOrFunc) {
428
518
  // @ts-ignore
429
519
  formDispatch({
@@ -437,17 +527,13 @@ var useForm = function useForm(_a) {
437
527
  onReset: handleReset
438
528
  });
439
529
  });
440
- var getFieldProps = useCallback(function (props, ref) {
530
+ var getFieldProps = useCallback(function (props) {
441
531
  var _returnProps;
442
532
 
443
533
  if (props === void 0) {
444
534
  props = {};
445
535
  }
446
536
 
447
- if (ref === void 0) {
448
- ref = null;
449
- }
450
-
451
537
  var _props = props,
452
538
  field = _props.field,
453
539
  _props$valuePropName = _props.valuePropName,
@@ -458,15 +544,16 @@ var useForm = function useForm(_a) {
458
544
  valueConnectTransform = _props.valueConnectTransform,
459
545
  _props$validateTrigge = _props.validateTrigger,
460
546
  validateTriggerProp = _props$validateTrigge === void 0 ? validateTriggersMemo : _props$validateTrigge,
461
- children = _props.children;
462
- var controlProps = children.props || {};
547
+ children = _props.children; // field 未设置,不进行收集管理
548
+
549
+ if (!isValidField(field)) return {}; // 控件的 props
550
+
551
+ var controlProps = children && children.props || {};
463
552
  var validateTrigger = isArray(validateTriggerProp) ? validateTriggerProp : [validateTriggerProp];
464
553
  var validateOnCollect = validateTrigger.includes(valueChangeFuncPropName);
465
554
  var validateOnBlur = validateTrigger.includes('onBlur');
466
555
  var controlledValue = getNested(formState.values, field);
467
- var returnProps = (_returnProps = {
468
- ref: ref
469
- }, _returnProps[valuePropName] = isFunction(valueConnectTransform) ? valueConnectTransform(controlledValue) : controlledValue, _returnProps[valueChangeFuncPropName] = callAllFuncs(controlProps[valueChangeFuncPropName], handleFieldChange(field, valuePropName, valueDispatchTransform, validateOnCollect)), _returnProps.onBlur = callAllFuncs(controlProps.onBlur, handleFieldBlur(field, validateOnBlur)), _returnProps.invalid = getFieldError(field), _returnProps);
556
+ var returnProps = (_returnProps = {}, _returnProps[valuePropName] = isFunction(valueConnectTransform) ? valueConnectTransform(controlledValue) : controlledValue, _returnProps[valueChangeFuncPropName] = callAllFuncs(controlProps[valueChangeFuncPropName], handleFieldChange(field, valuePropName, valueDispatchTransform, validateOnCollect)), _returnProps.onBlur = callAllFuncs(controlProps.onBlur, handleFieldBlur(field, validateOnBlur)), _returnProps.invalid = getFieldError(field), _returnProps);
470
557
  validateTrigger.forEach(function (triggerName) {
471
558
  if ([valueChangeFuncPropName, 'onBlur'].indexOf(triggerName) === -1) {
472
559
  returnProps[triggerName] = callAllFuncs(controlProps[triggerName], handleFieldTrigger(field));
@@ -492,14 +579,14 @@ var useForm = function useForm(_a) {
492
579
  submitForm: submitForm,
493
580
  resetForm: resetForm,
494
581
  resetErrors: resetErrors,
582
+ resetFieldError: resetFieldError,
495
583
  validateFieldState: validateFieldState,
496
584
  validateValue: validateField,
497
585
  getFieldsValue: getFieldsValue,
498
586
  setFieldsValue: setFieldsValue,
499
587
  getFieldsError: getFieldsError
500
588
  });
501
- }; // TODO: field 支持数组
502
-
589
+ };
503
590
 
504
591
  function formReducer(state, action) {
505
592
  switch (action.type) {
@@ -508,8 +595,9 @@ function formReducer(state, action) {
508
595
  return Object.assign(Object.assign({}, state), nextState);
509
596
 
510
597
  case 'SET_VALUES':
598
+ var nextValues = isFunction(action.payload) ? action.payload(state.values) : action.payload;
511
599
  return Object.assign(Object.assign({}, state), {
512
- values: action.payload
600
+ values: nextValues
513
601
  });
514
602
 
515
603
  case 'SET_ERRORS':
@@ -595,4 +683,3 @@ var useCollection = function useCollection() {
595
683
  };
596
684
 
597
685
  export { useForm };
598
- //# sourceMappingURL=use-form.js.map
@@ -2,11 +2,14 @@
2
2
  * @hi-ui/form
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/form#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
+ import { isNullish, isArray } from '@hi-ui/type-assertion';
11
+ import { clone, hasOwnProp } from '@hi-ui/object-utils';
12
+
10
13
  var stringify = function stringify(field) {
11
14
  return JSON.stringify(field);
12
15
  };
@@ -15,5 +18,26 @@ var parse = function parse(fieldStr) {
15
18
  return JSON.parse(fieldStr);
16
19
  };
17
20
 
18
- export { parse, stringify };
19
- //# sourceMappingURL=index.js.map
21
+ var isValidField = function isValidField(field) {
22
+ if (isNullish(field) || field === '') return false;
23
+ if (isArray(field) && field.every(function (item) {
24
+ return isNullish(item) || item === '';
25
+ })) return false;
26
+ return true;
27
+ };
28
+
29
+ var mergeValues = function mergeValues(source, override) {
30
+ if (!override) return source;
31
+ if (!source) return clone(override);
32
+ var target = clone(source);
33
+
34
+ for (var key in override) {
35
+ if (hasOwnProp(override, key)) {
36
+ target[key] = override[key];
37
+ }
38
+ }
39
+
40
+ return target;
41
+ };
42
+
43
+ export { isValidField, mergeValues, parse, stringify };
@@ -32,4 +32,8 @@ export interface FormProps<Values = Record<string, any>> extends Omit<HiBaseHTML
32
32
  * 配置是否展示冒号
33
33
  */
34
34
  showColon?: boolean;
35
+ /**
36
+ * FormItem 开启 filed 的 required 校验时,展示红色星号
37
+ */
38
+ showRequiredOnValidateRequired?: boolean;
35
39
  }
@@ -8,5 +8,9 @@ export interface FormFieldProps extends UseFormFieldProps {
8
8
  /**
9
9
  * 表单控件
10
10
  */
11
- children?: React.ReactElement;
11
+ children?: React.ReactNode;
12
+ /**
13
+ * 支持表单控件 render 渲染
14
+ */
15
+ render?: (props: Record<string, any>) => React.ReactNode;
12
16
  }
@@ -7,7 +7,11 @@ import { FormLabelProps } from './FormLabel';
7
7
  export declare const FormItem: React.FC<FormItemProps>;
8
8
  export interface FormItemProps extends UseFormFieldProps, FormLabelProps {
9
9
  /**
10
- * 表单控件
10
+ * 表单控件或其渲染函数
11
11
  */
12
- children?: React.ReactElement;
12
+ children?: React.ReactNode;
13
+ /**
14
+ * 支持表单控件 render 渲染
15
+ */
16
+ render?: (props: Record<string, any>) => any;
13
17
  }
@@ -10,7 +10,7 @@ export interface FormLabelProps extends HiBaseHTMLProps<'div'> {
10
10
  */
11
11
  labelPlacement?: 'right' | 'left' | 'top';
12
12
  /**
13
- * 标记是否必填
13
+ * 是否显示必填信号。这里不做校验处理,若需校验请使用 rules 进行设置
14
14
  */
15
15
  required?: boolean;
16
16
  /**
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
+ import { FormFieldPath, FormListChildrenAction } from './types';
2
3
  /**
3
4
  * TODO: What is FormList
4
5
  */
5
6
  export declare const FormList: React.FC<FormListProps>;
6
7
  export interface FormListProps {
7
8
  /**
8
- * 表单控件
9
+ * 表单控件渲染函数
9
10
  */
10
- children?: (fields: any[], action: any) => React.ReactElement | null;
11
+ children?: (fields: any[], action: FormListChildrenAction) => React.ReactElement;
11
12
  /**
12
13
  * 列表名称
13
14
  */
14
- name: string | string[];
15
+ name: FormFieldPath;
15
16
  }
@@ -5,5 +5,8 @@ import { ButtonProps } from '@hi-ui/button';
5
5
  */
6
6
  export declare const FormReset: React.ForwardRefExoticComponent<FormResetProps & React.RefAttributes<HTMLButtonElement | null>>;
7
7
  export interface FormResetProps extends ButtonProps {
8
+ /**
9
+ * 点击重置后触发
10
+ */
8
11
  onClick?: () => void;
9
12
  }
@@ -5,5 +5,8 @@ import { ButtonProps } from '@hi-ui/button';
5
5
  */
6
6
  export declare const FormSubmit: React.ForwardRefExoticComponent<FormSubmitProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | null>>;
7
7
  export interface FormSubmitProps extends Omit<ButtonProps, 'onClick'> {
8
- onClick?: (value: any, error: any) => void;
8
+ /**
9
+ * 点击提交后触发
10
+ */
11
+ onClick?: (result: any, error: any) => void;
9
12
  }
@@ -5,6 +5,8 @@ export interface FormContextProps extends UseFormReturn {
5
5
  labelPlacement: 'left' | 'right' | 'top';
6
6
  contentPosition: 'top' | 'center' | 'bottom';
7
7
  showColon: boolean;
8
+ showRequiredOnValidateRequired: boolean;
9
+ prefixCls: string;
8
10
  }
9
11
  export declare const FormProvider: React.Provider<Omit<FormContextProps, "rootProps"> | null>;
10
12
  export declare const useFormContext: () => Omit<FormContextProps, "rootProps">;