@arco-design/mobile-react 2.36.1 → 2.37.0

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 (233) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.en-US.md +2 -2
  3. package/README.md +2 -2
  4. package/cjs/_helpers/hooks.d.ts +1 -1
  5. package/cjs/_helpers/hooks.js +1 -1
  6. package/cjs/_helpers/react-dom.d.ts +5 -5
  7. package/cjs/_helpers/react-dom.js +49 -32
  8. package/cjs/_helpers/render.js +6 -3
  9. package/cjs/action-sheet/index.d.ts +3 -2
  10. package/cjs/action-sheet/index.js +2 -2
  11. package/cjs/carousel/index.js +8 -7
  12. package/cjs/checkbox/checkbox.d.ts +1 -1
  13. package/cjs/checkbox/group.d.ts +1 -1
  14. package/cjs/checkbox/hooks/useMergeProps.d.ts +1 -1
  15. package/cjs/checkbox/index.d.ts +2 -2
  16. package/cjs/context-provider/index.d.ts +8 -2
  17. package/cjs/count-down/hooks.js +2 -2
  18. package/cjs/dialog/index.d.ts +8 -3
  19. package/cjs/dialog/methods.d.ts +6 -2
  20. package/cjs/dropdown-menu/helper.d.ts +2 -2
  21. package/cjs/ellipsis/components/native-ellipsis.d.ts +2 -3
  22. package/cjs/ellipsis/components/native-ellipsis.js +1 -2
  23. package/cjs/form/form-item.d.ts +33 -2
  24. package/cjs/form/form-item.js +142 -121
  25. package/cjs/form/index.js +3 -1
  26. package/cjs/form/linked-container.d.ts +1 -1
  27. package/cjs/form/linked-container.js +4 -0
  28. package/cjs/form/style/css/index.css +4 -1
  29. package/cjs/form/style/index.less +6 -1
  30. package/cjs/form/type.d.ts +29 -6
  31. package/cjs/form/type.js +10 -2
  32. package/cjs/form/useForm.d.ts +2 -17
  33. package/cjs/form/useForm.js +98 -17
  34. package/cjs/form/utils.d.ts +2 -0
  35. package/cjs/form/utils.js +42 -2
  36. package/cjs/image-preview/index.d.ts +2 -2
  37. package/cjs/index-bar/group.js +3 -1
  38. package/cjs/index-bar/index.d.ts +2 -2
  39. package/cjs/index-bar/utils.d.ts +1 -1
  40. package/cjs/input/index.js +1 -1
  41. package/cjs/masking/index.d.ts +2 -2
  42. package/cjs/notify/index.d.ts +8 -8
  43. package/cjs/notify/index.js +2 -2
  44. package/cjs/picker-view/components/cascader.js +3 -1
  45. package/cjs/picker-view/components/picker-cell.js +1 -1
  46. package/cjs/picker-view/index.js +3 -1
  47. package/cjs/popup/index.d.ts +2 -2
  48. package/cjs/popup-swiper/index.d.ts +2 -2
  49. package/cjs/pull-refresh/hooks.d.ts +2 -2
  50. package/cjs/radio/group.d.ts +1 -1
  51. package/cjs/radio/group.js +1 -1
  52. package/cjs/radio/index.d.ts +2 -2
  53. package/cjs/radio/radio.d.ts +1 -1
  54. package/cjs/radio/type.d.ts +2 -2
  55. package/cjs/skeleton/elements.js +9 -3
  56. package/cjs/slider/hooks/index.d.ts +1 -1
  57. package/cjs/slider/hooks/useSliderEvents.d.ts +1 -1
  58. package/cjs/stepper/hooks/useValue.d.ts +2 -1
  59. package/cjs/steps/index.d.ts +1 -1
  60. package/cjs/tabs/type.d.ts +2 -2
  61. package/cjs/toast/index.d.ts +12 -12
  62. package/cjs/toast/index.js +1 -1
  63. package/dist/index.js +3070 -411
  64. package/dist/index.min.js +4 -4
  65. package/dist/style.css +4 -1
  66. package/dist/style.min.css +1 -1
  67. package/esm/_helpers/hooks.d.ts +1 -1
  68. package/esm/_helpers/hooks.js +1 -1
  69. package/esm/_helpers/react-dom.d.ts +5 -5
  70. package/esm/_helpers/react-dom.js +49 -30
  71. package/esm/_helpers/render.js +6 -3
  72. package/esm/action-sheet/index.d.ts +3 -2
  73. package/esm/action-sheet/index.js +2 -2
  74. package/esm/carousel/index.js +8 -7
  75. package/esm/checkbox/checkbox.d.ts +1 -1
  76. package/esm/checkbox/group.d.ts +1 -1
  77. package/esm/checkbox/hooks/useMergeProps.d.ts +1 -1
  78. package/esm/checkbox/index.d.ts +2 -2
  79. package/esm/context-provider/index.d.ts +8 -2
  80. package/esm/count-down/hooks.js +2 -2
  81. package/esm/dialog/index.d.ts +8 -3
  82. package/esm/dialog/methods.d.ts +6 -2
  83. package/esm/dropdown-menu/helper.d.ts +2 -2
  84. package/esm/ellipsis/components/native-ellipsis.d.ts +2 -3
  85. package/esm/ellipsis/components/native-ellipsis.js +1 -1
  86. package/esm/form/form-item.d.ts +33 -2
  87. package/esm/form/form-item.js +143 -122
  88. package/esm/form/index.js +3 -1
  89. package/esm/form/linked-container.d.ts +1 -1
  90. package/esm/form/linked-container.js +4 -0
  91. package/esm/form/style/css/index.css +4 -1
  92. package/esm/form/style/index.less +6 -1
  93. package/esm/form/type.d.ts +29 -6
  94. package/esm/form/type.js +8 -1
  95. package/esm/form/useForm.d.ts +2 -17
  96. package/esm/form/useForm.js +97 -17
  97. package/esm/form/utils.d.ts +2 -0
  98. package/esm/form/utils.js +31 -1
  99. package/esm/image-preview/index.d.ts +2 -2
  100. package/esm/index-bar/group.js +3 -1
  101. package/esm/index-bar/index.d.ts +2 -2
  102. package/esm/index-bar/utils.d.ts +1 -1
  103. package/esm/input/index.js +1 -1
  104. package/esm/masking/index.d.ts +2 -2
  105. package/esm/notify/index.d.ts +8 -8
  106. package/esm/notify/index.js +2 -2
  107. package/esm/picker-view/components/cascader.js +3 -1
  108. package/esm/picker-view/components/picker-cell.js +1 -1
  109. package/esm/picker-view/index.js +3 -1
  110. package/esm/popup/index.d.ts +2 -2
  111. package/esm/popup-swiper/index.d.ts +2 -2
  112. package/esm/pull-refresh/hooks.d.ts +2 -2
  113. package/esm/radio/group.d.ts +1 -1
  114. package/esm/radio/group.js +1 -1
  115. package/esm/radio/index.d.ts +2 -2
  116. package/esm/radio/radio.d.ts +1 -1
  117. package/esm/radio/type.d.ts +2 -2
  118. package/esm/skeleton/elements.js +9 -3
  119. package/esm/slider/hooks/index.d.ts +1 -1
  120. package/esm/slider/hooks/useSliderEvents.d.ts +1 -1
  121. package/esm/stepper/hooks/useValue.d.ts +2 -1
  122. package/esm/steps/index.d.ts +1 -1
  123. package/esm/tabs/type.d.ts +2 -2
  124. package/esm/toast/index.d.ts +12 -12
  125. package/esm/toast/index.js +1 -1
  126. package/esnext/_helpers/hooks.js +1 -1
  127. package/esnext/_helpers/react-dom.d.ts +5 -5
  128. package/esnext/_helpers/react-dom.js +47 -28
  129. package/esnext/_helpers/render.js +3 -2
  130. package/esnext/action-sheet/index.d.ts +3 -2
  131. package/esnext/action-sheet/index.js +1 -1
  132. package/esnext/carousel/index.js +7 -5
  133. package/esnext/context-provider/index.d.ts +8 -2
  134. package/esnext/context-provider/index.js +1 -1
  135. package/esnext/count-down/hooks.js +2 -2
  136. package/esnext/dialog/index.d.ts +8 -3
  137. package/esnext/dialog/methods.d.ts +6 -2
  138. package/esnext/dropdown-menu/helper.d.ts +1 -1
  139. package/esnext/ellipsis/components/native-ellipsis.d.ts +2 -3
  140. package/esnext/ellipsis/components/native-ellipsis.js +1 -1
  141. package/esnext/form/form-item.d.ts +33 -2
  142. package/esnext/form/form-item.js +85 -71
  143. package/esnext/form/index.js +2 -1
  144. package/esnext/form/linked-container.d.ts +1 -1
  145. package/esnext/form/linked-container.js +3 -0
  146. package/esnext/form/style/css/index.css +4 -1
  147. package/esnext/form/style/index.less +6 -1
  148. package/esnext/form/type.d.ts +29 -6
  149. package/esnext/form/type.js +7 -0
  150. package/esnext/form/useForm.d.ts +2 -17
  151. package/esnext/form/useForm.js +72 -13
  152. package/esnext/form/utils.d.ts +2 -0
  153. package/esnext/form/utils.js +26 -0
  154. package/esnext/image-preview/index.d.ts +2 -2
  155. package/esnext/index-bar/group.js +5 -1
  156. package/esnext/index-bar/index.d.ts +2 -2
  157. package/esnext/input/index.js +1 -1
  158. package/esnext/masking/index.d.ts +2 -2
  159. package/esnext/notify/index.d.ts +8 -8
  160. package/esnext/notify/index.js +2 -2
  161. package/esnext/picker-view/components/cascader.js +5 -1
  162. package/esnext/picker-view/components/picker-cell.js +1 -1
  163. package/esnext/picker-view/index.js +5 -1
  164. package/esnext/popup/index.d.ts +2 -2
  165. package/esnext/popup-swiper/index.d.ts +2 -2
  166. package/esnext/pull-refresh/hooks.d.ts +2 -2
  167. package/esnext/radio/group.js +3 -1
  168. package/esnext/radio/type.d.ts +2 -2
  169. package/esnext/skeleton/elements.js +15 -3
  170. package/esnext/slider/hooks/useSliderEvents.d.ts +1 -1
  171. package/esnext/tabs/type.d.ts +2 -2
  172. package/esnext/toast/index.d.ts +12 -12
  173. package/esnext/toast/index.js +1 -1
  174. package/package.json +3 -3
  175. package/umd/_helpers/hooks.d.ts +1 -1
  176. package/umd/_helpers/hooks.js +1 -1
  177. package/umd/_helpers/react-dom.d.ts +5 -5
  178. package/umd/_helpers/react-dom.js +53 -35
  179. package/umd/_helpers/render.js +6 -3
  180. package/umd/action-sheet/index.d.ts +3 -2
  181. package/umd/action-sheet/index.js +2 -2
  182. package/umd/carousel/index.js +8 -7
  183. package/umd/checkbox/checkbox.d.ts +1 -1
  184. package/umd/checkbox/group.d.ts +1 -1
  185. package/umd/checkbox/hooks/useMergeProps.d.ts +1 -1
  186. package/umd/checkbox/index.d.ts +2 -2
  187. package/umd/context-provider/index.d.ts +8 -2
  188. package/umd/count-down/hooks.js +2 -2
  189. package/umd/dialog/index.d.ts +8 -3
  190. package/umd/dialog/methods.d.ts +6 -2
  191. package/umd/dropdown-menu/helper.d.ts +2 -2
  192. package/umd/ellipsis/components/native-ellipsis.d.ts +2 -3
  193. package/umd/ellipsis/components/native-ellipsis.js +1 -2
  194. package/umd/form/form-item.d.ts +33 -2
  195. package/umd/form/form-item.js +142 -121
  196. package/umd/form/index.js +3 -1
  197. package/umd/form/linked-container.d.ts +1 -1
  198. package/umd/form/linked-container.js +4 -0
  199. package/umd/form/style/css/index.css +4 -1
  200. package/umd/form/style/index.less +6 -1
  201. package/umd/form/type.d.ts +29 -6
  202. package/umd/form/type.js +9 -1
  203. package/umd/form/useForm.d.ts +2 -17
  204. package/umd/form/useForm.js +98 -21
  205. package/umd/form/utils.d.ts +2 -0
  206. package/umd/form/utils.js +40 -5
  207. package/umd/image-preview/index.d.ts +2 -2
  208. package/umd/index-bar/group.js +3 -1
  209. package/umd/index-bar/index.d.ts +2 -2
  210. package/umd/index-bar/utils.d.ts +1 -1
  211. package/umd/input/index.js +1 -1
  212. package/umd/masking/index.d.ts +2 -2
  213. package/umd/notify/index.d.ts +8 -8
  214. package/umd/notify/index.js +2 -2
  215. package/umd/picker-view/components/cascader.js +3 -1
  216. package/umd/picker-view/components/picker-cell.js +1 -1
  217. package/umd/picker-view/index.js +3 -1
  218. package/umd/popup/index.d.ts +2 -2
  219. package/umd/popup-swiper/index.d.ts +2 -2
  220. package/umd/pull-refresh/hooks.d.ts +2 -2
  221. package/umd/radio/group.d.ts +1 -1
  222. package/umd/radio/group.js +1 -1
  223. package/umd/radio/index.d.ts +2 -2
  224. package/umd/radio/radio.d.ts +1 -1
  225. package/umd/radio/type.d.ts +2 -2
  226. package/umd/skeleton/elements.js +9 -3
  227. package/umd/slider/hooks/index.d.ts +1 -1
  228. package/umd/slider/hooks/useSliderEvents.d.ts +1 -1
  229. package/umd/stepper/hooks/useValue.d.ts +2 -1
  230. package/umd/steps/index.d.ts +1 -1
  231. package/umd/tabs/type.d.ts +2 -2
  232. package/umd/toast/index.d.ts +12 -12
  233. package/umd/toast/index.js +1 -1
@@ -4,37 +4,66 @@ import { cls, Validator, ValidatorType } from '@arco-design/mobile-utils';
4
4
  import { Promise } from 'es6-promise';
5
5
  import { FormItemContext } from './form-item-context';
6
6
  import { GlobalContext } from '../context-provider';
7
- import { FormInternalComponentType, } from './type';
8
- import { getErrorAndWarnings, isFieldRequired } from './utils';
7
+ import { FormInternalComponentType, ValueChangeType, } from './type';
8
+ import { getDefaultValueForInterComponent, getErrorAndWarnings, isFieldRequired } from './utils';
9
9
  import { DefaultDatePickerLinkedContainer, DefaultPickerLinkedContainer } from './linked-container';
10
10
  class FormItemInner extends PureComponent {
11
11
  constructor(props, context) {
12
12
  super(props);
13
13
  this._errors = [];
14
14
  this._touched = false;
15
- this.onValueChange = (curValue, preValue) => {
15
+ this.onValueChange = (curValue, preValue, info) => {
16
16
  this._touched = true;
17
17
  const { shouldUpdate } = this.props;
18
18
  if (typeof shouldUpdate === 'function') {
19
19
  shouldUpdate({ preValue, curValue }) && this.forceUpdate();
20
20
  return;
21
21
  }
22
+ if (info?.changeType === ValueChangeType.Reset) {
23
+ this.props.onValidateStatusChange({
24
+ errors: [],
25
+ warnings: [],
26
+ errorTypes: [],
27
+ });
28
+ this._errors = [];
29
+ }
22
30
  this.forceUpdate();
23
31
  };
32
+ this.getInitialValue = () => {
33
+ const { children, displayType } = this.props;
34
+ const { getInitialValue } = this.context.form.getInternalHooks();
35
+ const childrenType = displayType || children.type?.displayName;
36
+ // get user-defined initialValue or if not defined
37
+ return getInitialValue(this.props.field) ?? getDefaultValueForInterComponent(childrenType);
38
+ };
24
39
  this.getFieldError = () => {
25
40
  return this._errors;
26
41
  };
27
42
  this.isFieldTouched = () => {
28
43
  return this._touched;
29
44
  };
30
- this.validateField = () => {
45
+ this.getAllRuleValidateTriggers = () => {
46
+ return (this.props.rules
47
+ ?.map(rule => rule.validateTrigger)
48
+ .flat()
49
+ .filter(v => !!v) || []);
50
+ };
51
+ this.validateField = (validateTrigger) => {
31
52
  const { validateMessages } = this.context;
32
53
  const { getFieldValue } = this.context.form;
33
54
  const { field, rules, onValidateStatusChange } = this.props;
34
55
  const value = getFieldValue(field);
35
- if (rules?.length && field) {
56
+ // rules: if validateTrigger is not defined, all rules will be validated
57
+ // if validateTrigger is defined, only rules with validateTrigger or without rule.validateTrigger will be validated
58
+ const curRules = validateTrigger
59
+ ? rules?.filter(rule => {
60
+ const triggerList = [].concat(rule.validateTrigger || validateTrigger);
61
+ return triggerList.includes(validateTrigger);
62
+ })
63
+ : rules;
64
+ if (curRules?.length && field) {
36
65
  const fieldDom = this.props.getFormItemRef();
37
- const fieldValidator = new Validator({ [field]: rules }, { validateMessages });
66
+ const fieldValidator = new Validator({ [field]: curRules }, { validateMessages });
38
67
  return new Promise(resolve => {
39
68
  fieldValidator.validate({ [field]: value }, (errorsMap) => {
40
69
  const { errors, warnings, errorTypes } = getErrorAndWarnings(errorsMap?.[field] || []);
@@ -57,17 +86,10 @@ class FormItemInner extends PureComponent {
57
86
  return Promise.resolve({ errors: [], warnings: [], value, field, dom: null });
58
87
  };
59
88
  this.setFieldData = (value) => {
60
- const { field } = this.props;
61
- const { setFieldValue } = this.context.form;
62
- setFieldValue(field, value);
63
- this.validateField();
64
- };
65
- this.innerTriggerFunction = (_, value, ...args) => {
66
- this.setFieldData(value);
67
- const { children, trigger = 'onChange' } = this.props;
68
- if (trigger && children.props?.[trigger]) {
69
- children.props?.[trigger](_, value, ...args);
70
- }
89
+ const { field, trigger = 'onChange' } = this.props;
90
+ const { innerSetFieldValue } = this.context.form.getInternalHooks();
91
+ innerSetFieldValue(field, value);
92
+ this.validateField(trigger);
71
93
  };
72
94
  this.innerTriggerFunctionWithValueFirst = (value, ...args) => {
73
95
  this.setFieldData(value);
@@ -76,6 +98,11 @@ class FormItemInner extends PureComponent {
76
98
  children.props?.[trigger](value, ...args);
77
99
  }
78
100
  };
101
+ this.innerOnInputFunction = (_, value, ...args) => {
102
+ this.setFieldData(value);
103
+ const { children } = this.props;
104
+ children.props?.onInput?.(_, value, ...args);
105
+ };
79
106
  this.innerClearFunction = (...args) => {
80
107
  const { children } = this.props;
81
108
  this.setFieldData('');
@@ -85,8 +112,8 @@ class FormItemInner extends PureComponent {
85
112
  };
86
113
  this.destroyField = () => { };
87
114
  if (props?.initialValue && props.field) {
88
- const { setInitialValues } = context.form.getInternalHooks();
89
- setInitialValues({ [props.field]: props.initialValue });
115
+ const { setInitialValue } = context.form.getInternalHooks();
116
+ setInitialValue(props.field, props.initialValue);
90
117
  }
91
118
  }
92
119
  componentDidMount() {
@@ -97,82 +124,69 @@ class FormItemInner extends PureComponent {
97
124
  this.destroyField();
98
125
  }
99
126
  renderChildren() {
100
- const { children, field, trigger = 'onChange', triggerPropsField = 'value', displayType, } = this.props;
127
+ const { children, field, trigger = 'onChange', triggerPropsField = 'value', displayType, disabled, } = this.props;
101
128
  const { getFieldValue } = this.context.form;
102
- let props = {
103
- [triggerPropsField]: getFieldValue(field),
104
- disabled: this.props.disabled,
129
+ const childrenProps = {
130
+ disabled,
105
131
  };
132
+ // inject validateTriggers of rules
133
+ this.getAllRuleValidateTriggers().forEach(triggerName => {
134
+ childrenProps[triggerName] = e => {
135
+ this.validateField(triggerName);
136
+ children?.props?.[triggerName]?.(e);
137
+ };
138
+ });
106
139
  const childrenType = displayType || children.type?.displayName;
107
140
  switch (childrenType) {
108
141
  case FormInternalComponentType.Input:
109
142
  case FormInternalComponentType.Textarea:
110
- props = {
111
- value: getFieldValue(field) || '',
112
- onInput: this.innerTriggerFunction,
113
- onClear: this.innerClearFunction,
114
- disabled: this.props.disabled,
115
- };
116
- break;
117
- case FormInternalComponentType.Checkbox:
118
- case FormInternalComponentType.Radio:
119
- case FormInternalComponentType.Slider:
120
- case FormInternalComponentType.RadioGroup:
121
- case FormInternalComponentType.CheckboxGroup:
122
- props = {
123
- value: getFieldValue(field),
124
- onChange: this.innerTriggerFunctionWithValueFirst,
125
- disabled: this.props.disabled,
126
- };
143
+ childrenProps.value =
144
+ getFieldValue(field) || '';
145
+ childrenProps.onInput =
146
+ this.innerOnInputFunction;
147
+ childrenProps.onClear =
148
+ this.innerClearFunction;
127
149
  break;
128
150
  case FormInternalComponentType.DatePicker:
129
- props = {
130
- currentTs: getFieldValue(field),
131
- onChange: this.innerTriggerFunctionWithValueFirst,
132
- disabled: this.props.disabled,
133
- renderLinkedContainer: children.props?.renderLinkedContainer ||
134
- ((ts, types) => React.createElement(DefaultDatePickerLinkedContainer, { ts: ts, types: types })),
135
- };
151
+ childrenProps.currentTs = getFieldValue(field);
152
+ childrenProps.onChange =
153
+ this.innerTriggerFunctionWithValueFirst;
154
+ childrenProps.renderLinkedContainer =
155
+ children.props?.renderLinkedContainer ||
156
+ ((ts, types) => React.createElement(DefaultDatePickerLinkedContainer, { ts: ts, types: types }));
136
157
  break;
137
158
  case FormInternalComponentType.Picker:
138
- props = {
139
- value: getFieldValue(field),
140
- onChange: this.innerTriggerFunctionWithValueFirst,
141
- disabled: this.props.disabled,
142
- renderLinkedContainer: children.props?.renderLinkedContainer ||
143
- (val => React.createElement(DefaultPickerLinkedContainer, { value: val })),
144
- };
159
+ childrenProps.value = getFieldValue(field) || '';
160
+ childrenProps.onChange = this.innerTriggerFunctionWithValueFirst;
161
+ childrenProps.renderLinkedContainer =
162
+ children.props?.renderLinkedContainer ||
163
+ (val => React.createElement(DefaultPickerLinkedContainer, { value: val }));
145
164
  break;
146
165
  case FormInternalComponentType.Switch:
147
- props = {
148
- checked: Boolean(getFieldValue(field)),
149
- onChange: this.innerTriggerFunctionWithValueFirst,
150
- disabled: this.props.disabled,
151
- };
166
+ childrenProps.checked = Boolean(getFieldValue(field));
167
+ childrenProps.onChange = this.innerTriggerFunctionWithValueFirst;
152
168
  break;
153
169
  case FormInternalComponentType.ImagePicker:
154
- props = {
155
- images: getFieldValue(field),
156
- onChange: this.innerTriggerFunctionWithValueFirst,
157
- disabled: this.props.disabled,
158
- };
170
+ childrenProps.images = getFieldValue(field);
171
+ childrenProps.onChange =
172
+ this.innerTriggerFunctionWithValueFirst;
159
173
  break;
160
174
  default:
161
- const originTrigger = children.props[trigger];
175
+ if (triggerPropsField) {
176
+ childrenProps[triggerPropsField] = getFieldValue(field);
177
+ }
162
178
  // inject the validated result
163
- props.error = this._errors;
164
- props[trigger] = (newValue, ...args) => {
165
- this.setFieldData(newValue);
166
- originTrigger && originTrigger(newValue, ...args);
167
- };
179
+ childrenProps.error = this._errors;
180
+ childrenProps[trigger] = this.innerTriggerFunctionWithValueFirst;
168
181
  }
169
- return React.cloneElement(children, props);
182
+ return React.cloneElement(children, childrenProps);
170
183
  }
171
184
  render() {
172
185
  return this.renderChildren();
173
186
  }
174
187
  }
175
188
  FormItemInner.contextType = FormItemContext;
189
+ export { FormItemInner };
176
190
  export default forwardRef((props, ref) => {
177
191
  const { label, field, disabled = false, layout: itemLayout, style, extra, requiredIcon, rules, className = '', ...rest } = props;
178
192
  const { prefixCls } = useContext(GlobalContext);
@@ -7,7 +7,7 @@ import useForm from './useForm';
7
7
  export { default as useForm } from './useForm';
8
8
  export * from './type';
9
9
  const Form = forwardRef((props, ref) => {
10
- const { className = '', style, layout = 'horizontal', initialValues, form: formInstance, children, onValuesChange, onSubmit, onSubmitFailed, disabled, } = props;
10
+ const { className = '', style, layout = 'horizontal', initialValues, form: formInstance, children, onValuesChange, onChange, onSubmit, onSubmitFailed, disabled, } = props;
11
11
  const domRef = useRef(null);
12
12
  const initRef = useRef(false);
13
13
  const [form] = useForm(formInstance);
@@ -16,6 +16,7 @@ const Form = forwardRef((props, ref) => {
16
16
  onValuesChange,
17
17
  onSubmit,
18
18
  onSubmitFailed,
19
+ onChange,
19
20
  });
20
21
  if (!initRef.current) {
21
22
  setInitialValues(initialValues || {});
@@ -3,6 +3,6 @@ export declare function DefaultPickerLinkedContainer({ value }: {
3
3
  value: (string | number)[];
4
4
  }): JSX.Element;
5
5
  export declare function DefaultDatePickerLinkedContainer({ ts, types, }: {
6
- ts: number | [number, number];
6
+ ts?: number | [number, number];
7
7
  types: string[];
8
8
  }): JSX.Element;
@@ -11,6 +11,9 @@ export function DefaultDatePickerLinkedContainer({ ts, types, }) {
11
11
  const { prefixCls, locale } = useContext(GlobalContext);
12
12
  const className = `${prefixCls}-form-picker-link-container`;
13
13
  const dateTimeStr = useMemo(() => {
14
+ if (ts === undefined) {
15
+ return '';
16
+ }
14
17
  if (typeof ts === 'number') {
15
18
  return formatDateTimeStr(ts, types);
16
19
  }
@@ -567,6 +567,9 @@
567
567
  .arco-form-item-control .arco-input {
568
568
  padding: 0;
569
569
  }
570
+ .arco-form-item-control .arco-input-wrap.textarea {
571
+ padding: 0;
572
+ }
570
573
  .arco-form-item-control-wrapper {
571
574
  width: 100%;
572
575
  -webkit-box-flex: 1;
@@ -574,7 +577,7 @@
574
577
  flex: 1;
575
578
  position: relative;
576
579
  }
577
- .arco-form-item-control-wrapper .arco-input-wrap {
580
+ .arco-form-item-control-wrapper .arco-input-wrap.single-line {
578
581
  height: 0.44rem ;
579
582
  }
580
583
  .arco-form-item-message {
@@ -42,11 +42,16 @@
42
42
  .@{prefix}-input-wrap, .@{prefix}-input {
43
43
  padding: 0;
44
44
  }
45
+
46
+ .@{prefix}-input-wrap.textarea {
47
+ padding: 0;
48
+ }
49
+
45
50
  &-wrapper {
46
51
  width: 100%;
47
52
  flex: 1;
48
53
  position: relative;
49
- .@{prefix}-input-wrap {
54
+ .@{prefix}-input-wrap.single-line {
50
55
  .use-var(height, input-text-line-height);
51
56
  }
52
57
  }
@@ -1,8 +1,8 @@
1
1
  import { IRules } from '@arco-design/mobile-utils';
2
- import { ReactNode } from 'react';
2
+ import { ReactElement, ReactNode } from 'react';
3
3
  import { Promise } from 'es6-promise';
4
4
  export declare type FieldValue = any;
5
- export declare type FieldItem = Record<string, any>;
5
+ export declare type FieldItem = Record<string, FieldValue>;
6
6
  export declare type ILayout = 'horizontal' | 'vertical' | 'inline';
7
7
  export declare enum FormInternalComponentType {
8
8
  Input = "Input",
@@ -46,12 +46,17 @@ export interface FormProps {
46
46
  * @en Form initial value
47
47
  */
48
48
  initialValues?: FieldItem;
49
- children: React.ReactNodeArray | ReactNode;
49
+ children: ReactNode[] | ReactNode;
50
50
  /**
51
51
  * 表单项数据变化时的回调
52
52
  * @en Callback when the form item value changes
53
53
  */
54
54
  onValuesChange?: Callbacks['onValuesChange'];
55
+ /**
56
+ * 表单项数据变化时的回调(仅用户操作表单时触发)
57
+ * @en Callback when the form item value changes (Only trigger when user operate form)
58
+ */
59
+ onChange?: Callbacks['onChange'];
55
60
  /**
56
61
  * 表单项数据变化时的回调
57
62
  * @en Callback when the form is submitted
@@ -115,6 +120,11 @@ export interface Callbacks {
115
120
  * @en Callback when the form item value changes
116
121
  */
117
122
  onValuesChange?: (changedValues: FieldValue, values: FieldValue) => void;
123
+ /**
124
+ * 表单项数据变化时的回调(仅用户操作表单时触发)
125
+ * @en Callback when the form item value changes (Only trigger when user operate form)
126
+ */
127
+ onChange?: (changedValues: FieldValue, values: FieldValue) => void;
118
128
  /**
119
129
  * 表单项数据变化时的回调
120
130
  * @en Callback when the form is submitted
@@ -134,6 +144,10 @@ export interface InternalHooks {
134
144
  registerField: (name: string, self: any) => () => void;
135
145
  setInitialValues: (values: FieldItem) => void;
136
146
  setCallbacks: (callbacks: Callbacks) => void;
147
+ getInitialValue: (fieldName: string) => FieldValue;
148
+ setInitialValue: (fieldName: string, values: FieldItem) => void;
149
+ innerSetFieldsValue: (values: FieldItem) => boolean;
150
+ innerSetFieldValue: (name: string, value: FieldValue) => boolean;
137
151
  }
138
152
  export interface IFormInstance {
139
153
  /**
@@ -183,6 +197,11 @@ export declare type InternalFormInstance = IFormInstance & {
183
197
  * @en Get internal methods
184
198
  */
185
199
  getInternalHooks: () => InternalHooks;
200
+ /**
201
+ * 注册表单组件
202
+ * @en Register Form Item component
203
+ */
204
+ registerField: (name: string, self: any) => () => void;
186
205
  };
187
206
  export interface FormRef {
188
207
  /**
@@ -263,7 +282,7 @@ export interface FormItemProps {
263
282
  * 表单项子节点
264
283
  * @en Form item children
265
284
  */
266
- children: JSX.Element;
285
+ children: ReactElement;
267
286
  /**
268
287
  * 表单项是否刷新
269
288
  * @en Form item is updated
@@ -278,7 +297,7 @@ export interface FormItemProps {
278
297
  * 表单项下方节点
279
298
  * @en Form item extra node
280
299
  */
281
- extra?: JSX.Element;
300
+ extra?: ReactElement;
282
301
  /**
283
302
  * 触发事件更新事件名称
284
303
  * @en The function name when updating data
@@ -318,7 +337,7 @@ export interface IFormItemInnerProps {
318
337
  * 表单项子节点
319
338
  * @en Form item children
320
339
  */
321
- children: JSX.Element;
340
+ children: ReactElement<any, any>;
322
341
  /**
323
342
  * 表单项是否刷新
324
343
  * @en Form item is updated
@@ -371,3 +390,7 @@ export interface IFormItemInnerProps {
371
390
  */
372
391
  displayType?: FormInternalComponentType;
373
392
  }
393
+ export declare enum ValueChangeType {
394
+ Update = 0,
395
+ Reset = 1
396
+ }
@@ -24,3 +24,10 @@ export var ValidateStatus;
24
24
  ValidateStatus["Validating"] = "validating";
25
25
  ValidateStatus["Success"] = "success";
26
26
  })(ValidateStatus || (ValidateStatus = {}));
27
+ export var ValueChangeType;
28
+ (function (ValueChangeType) {
29
+ /* form update */
30
+ ValueChangeType[ValueChangeType["Update"] = 0] = "Update";
31
+ /* form clear */
32
+ ValueChangeType[ValueChangeType["Reset"] = 1] = "Reset";
33
+ })(ValueChangeType || (ValueChangeType = {}));
@@ -1,18 +1,3 @@
1
- import { IFormInstance } from './type';
2
- export declare const defaultFormDataMethods: {
3
- getFieldValue: (name: any) => any;
4
- getFieldsValue: (_names: any) => {};
5
- getFieldError: (_name: any) => never[];
6
- setFieldValue: (_name: any, _value: any) => boolean;
7
- setFieldsValue: (_values: any) => boolean;
8
- registerField: (_name: any, _self: any) => () => void;
9
- resetFields: any;
10
- validateFields: any;
11
- submit: any;
12
- getInternalHooks: () => {
13
- registerField: any;
14
- setInitialValues: any;
15
- setCallbacks: any;
16
- };
17
- };
1
+ import { IFormInstance, InternalFormInstance } from './type';
2
+ export declare const defaultFormDataMethods: InternalFormInstance;
18
3
  export default function useForm(form?: IFormInstance): IFormInstance[];
@@ -1,6 +1,8 @@
1
1
  /* eslint-disable no-console */
2
2
  import { useRef } from 'react';
3
3
  import { Promise } from 'es6-promise';
4
+ import { ValueChangeType, } from './type';
5
+ import { deepClone } from './utils';
4
6
  const defaultFunc = () => { };
5
7
  export const defaultFormDataMethods = {
6
8
  getFieldValue: name => name,
@@ -25,6 +27,10 @@ export const defaultFormDataMethods = {
25
27
  registerField: defaultFunc,
26
28
  setInitialValues: defaultFunc,
27
29
  setCallbacks: defaultFunc,
30
+ getInitialValue: defaultFunc,
31
+ setInitialValue: defaultFunc,
32
+ innerSetFieldsValue: defaultFunc,
33
+ innerSetFieldValue: defaultFunc,
28
34
  };
29
35
  },
30
36
  };
@@ -35,33 +41,61 @@ class FormData {
35
41
  this._fieldsList = {}; // 字段列表
36
42
  this._initialValues = {}; // 初始值
37
43
  this._callbacks = {};
38
- this.setFieldsValue = (values) => {
44
+ this.commonSetFieldsValue = (values, changeType) => {
39
45
  const oldValues = Object.keys(values).reduce((acc, key) => ({
40
46
  ...acc,
41
47
  [key]: this.getFieldValue(key),
42
48
  }), {});
43
49
  this._formData = { ...this._formData, ...values };
50
+ this.notifyField(values, oldValues, changeType);
51
+ };
52
+ this.setFieldsValue = (values) => {
53
+ this.commonSetFieldsValue(values);
44
54
  const { onValuesChange } = this._callbacks;
45
- onValuesChange && onValuesChange(values, this._formData);
46
- this.notifyField(values, oldValues);
55
+ onValuesChange?.(values, this._formData);
47
56
  return true;
48
57
  };
49
- this.setFieldValue = (name, value) => {
58
+ this.innerSetFieldsValue = (values, changeType) => {
59
+ this.commonSetFieldsValue(values, changeType);
60
+ const { onValuesChange, onChange } = this._callbacks;
61
+ onValuesChange?.(values, this._formData);
62
+ onChange?.(values, this._formData);
63
+ return true;
64
+ };
65
+ this.commonSetFieldValue = (name, value, changeType) => {
50
66
  const oldValues = { [name]: this.getFieldValue(name) };
51
67
  this._formData = { ...this._formData, [name]: value };
68
+ this.notifyField({ [name]: value }, oldValues, changeType);
69
+ };
70
+ this.setFieldValue = (name, value) => {
71
+ this.commonSetFieldValue(name, value);
52
72
  const { onValuesChange } = this._callbacks;
53
73
  onValuesChange &&
54
74
  onValuesChange({
55
75
  [name]: value,
76
+ }, this.getFieldsValue());
77
+ return true;
78
+ };
79
+ this.innerSetFieldValue = (name, value, changeType) => {
80
+ this.commonSetFieldValue(name, value, changeType);
81
+ const { onValuesChange, onChange } = this._callbacks;
82
+ onValuesChange &&
83
+ onValuesChange({
84
+ [name]: value,
85
+ }, this._formData);
86
+ onChange &&
87
+ onChange({
88
+ [name]: value,
56
89
  }, this._formData);
57
- this.notifyField({ [name]: value }, oldValues);
58
90
  return true;
59
91
  };
60
- this.notifyField = (values, oldValues) => {
92
+ this.notifyField = (values, oldValues, changeType = ValueChangeType.Update) => {
61
93
  Object.keys(values).map((fieldName) => {
62
94
  const fieldObj = this._fieldsList?.[fieldName] || null;
63
95
  if (fieldObj) {
64
- fieldObj.onValueChange(values[fieldName], oldValues[fieldName]);
96
+ fieldObj.onValueChange(values[fieldName], oldValues[fieldName], {
97
+ changeType,
98
+ });
65
99
  }
66
100
  });
67
101
  };
@@ -69,10 +103,10 @@ class FormData {
69
103
  if (names) {
70
104
  return names.map(name => this.getFieldValue(name));
71
105
  }
72
- return this._formData;
106
+ return deepClone(this._formData);
73
107
  };
74
108
  this.getFieldValue = (name) => {
75
- return this._formData?.[name];
109
+ return deepClone(this._formData?.[name]);
76
110
  };
77
111
  this.getFieldError = (name) => {
78
112
  const field = this._fieldsList?.[name] || null;
@@ -119,11 +153,32 @@ class FormData {
119
153
  };
120
154
  };
121
155
  this.setInitialValues = (initVal) => {
122
- this._initialValues = { ...(initVal || {}) };
156
+ this._initialValues = deepClone(initVal || {});
123
157
  this.setFieldsValue(initVal);
124
158
  };
159
+ this.setInitialValue = (fieldName, value) => {
160
+ if (!fieldName) {
161
+ return;
162
+ }
163
+ this._initialValues[fieldName] = value;
164
+ this.setFieldValue(fieldName, value);
165
+ };
166
+ this.getInitialValue = (fieldName) => {
167
+ return this._initialValues[fieldName];
168
+ };
125
169
  this.resetFields = () => {
126
- this.setFieldsValue(this._initialValues);
170
+ const oldValues = { ...this._formData };
171
+ const initialValues = {};
172
+ Object.keys(this._formData).forEach((fieldName) => {
173
+ const fieldObj = this._fieldsList?.[fieldName] || null;
174
+ if (fieldObj) {
175
+ initialValues[fieldName] = fieldObj.getInitialValue();
176
+ }
177
+ });
178
+ const { onValuesChange } = this._callbacks;
179
+ onValuesChange && onValuesChange(initialValues, this._formData);
180
+ this._formData = initialValues;
181
+ this.notifyField(initialValues, oldValues, ValueChangeType.Reset);
127
182
  };
128
183
  this.validateFields = () => {
129
184
  const promiseList = [];
@@ -148,14 +203,14 @@ class FormData {
148
203
  this.validateFields()
149
204
  .then(result => {
150
205
  const { onSubmit } = this._callbacks;
151
- onSubmit?.(this._formData, result);
206
+ onSubmit?.(this.getFieldsValue(), result);
152
207
  })
153
208
  .catch(e => {
154
209
  const { onSubmitFailed } = this._callbacks;
155
210
  if (!onSubmitFailed) {
156
211
  return;
157
212
  }
158
- onSubmitFailed(this._formData, e);
213
+ onSubmitFailed(this.getFieldsValue(), e);
159
214
  });
160
215
  };
161
216
  this.setCallbacks = (callbacks) => {
@@ -182,6 +237,10 @@ class FormData {
182
237
  registerField: this.registerField,
183
238
  setInitialValues: this.setInitialValues,
184
239
  setCallbacks: this.setCallbacks,
240
+ getInitialValue: this.getInitialValue,
241
+ setInitialValue: this.setInitialValue,
242
+ innerSetFieldsValue: this.innerSetFieldsValue,
243
+ innerSetFieldValue: this.innerSetFieldValue,
185
244
  };
186
245
  };
187
246
  }
@@ -5,3 +5,5 @@ export declare const getErrorAndWarnings: (result: ValidatorError[]) => {
5
5
  errors: string[];
6
6
  errorTypes: string[];
7
7
  };
8
+ export declare const getDefaultValueForInterComponent: (componentType: string) => 0 | never[] | null | undefined;
9
+ export declare function deepClone(value: any): any;
@@ -1,3 +1,6 @@
1
+ import { isObject, isArray } from '@arco-design/mobile-utils';
2
+ import cloneDeepWith from 'lodash/cloneDeepWith';
3
+ import { FormInternalComponentType } from './type';
1
4
  export const isFieldRequired = (rules = []) => {
2
5
  return (rules || []).some(rule => rule?.required);
3
6
  };
@@ -19,3 +22,26 @@ export const getErrorAndWarnings = (result) => {
19
22
  });
20
23
  return { warnings, errors, errorTypes };
21
24
  };
25
+ export const getDefaultValueForInterComponent = (componentType) => {
26
+ switch (componentType) {
27
+ case FormInternalComponentType.Input:
28
+ case FormInternalComponentType.Textarea:
29
+ return undefined;
30
+ case FormInternalComponentType.CheckboxGroup:
31
+ return [];
32
+ case FormInternalComponentType.RadioGroup:
33
+ return null;
34
+ case FormInternalComponentType.Slider:
35
+ case FormInternalComponentType.Rate:
36
+ return 0;
37
+ default:
38
+ return undefined;
39
+ }
40
+ };
41
+ export function deepClone(value) {
42
+ return cloneDeepWith(value, val => {
43
+ if (!isObject(val) && !isArray(val)) {
44
+ return val;
45
+ }
46
+ });
47
+ }