@arco-design/mobile-react 2.36.1 → 2.36.2

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 (76) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.en-US.md +2 -2
  3. package/README.md +2 -2
  4. package/cjs/carousel/index.js +8 -7
  5. package/cjs/form/form-item.d.ts +33 -2
  6. package/cjs/form/form-item.js +142 -121
  7. package/cjs/form/index.js +3 -1
  8. package/cjs/form/linked-container.d.ts +1 -1
  9. package/cjs/form/linked-container.js +4 -0
  10. package/cjs/form/style/css/index.css +4 -1
  11. package/cjs/form/style/index.less +6 -1
  12. package/cjs/form/type.d.ts +24 -1
  13. package/cjs/form/type.js +10 -2
  14. package/cjs/form/useForm.d.ts +2 -17
  15. package/cjs/form/useForm.js +98 -17
  16. package/cjs/form/utils.d.ts +2 -0
  17. package/cjs/form/utils.js +42 -2
  18. package/cjs/input/index.js +1 -1
  19. package/cjs/radio/group.js +1 -1
  20. package/cjs/radio/type.d.ts +2 -2
  21. package/dist/index.js +2993 -362
  22. package/dist/index.min.js +4 -4
  23. package/dist/style.css +4 -1
  24. package/dist/style.min.css +1 -1
  25. package/esm/carousel/index.js +8 -7
  26. package/esm/form/form-item.d.ts +33 -2
  27. package/esm/form/form-item.js +143 -122
  28. package/esm/form/index.js +3 -1
  29. package/esm/form/linked-container.d.ts +1 -1
  30. package/esm/form/linked-container.js +4 -0
  31. package/esm/form/style/css/index.css +4 -1
  32. package/esm/form/style/index.less +6 -1
  33. package/esm/form/type.d.ts +24 -1
  34. package/esm/form/type.js +8 -1
  35. package/esm/form/useForm.d.ts +2 -17
  36. package/esm/form/useForm.js +97 -17
  37. package/esm/form/utils.d.ts +2 -0
  38. package/esm/form/utils.js +31 -1
  39. package/esm/input/index.js +1 -1
  40. package/esm/radio/group.js +1 -1
  41. package/esm/radio/type.d.ts +2 -2
  42. package/esnext/carousel/index.js +7 -5
  43. package/esnext/form/form-item.d.ts +33 -2
  44. package/esnext/form/form-item.js +85 -71
  45. package/esnext/form/index.js +2 -1
  46. package/esnext/form/linked-container.d.ts +1 -1
  47. package/esnext/form/linked-container.js +3 -0
  48. package/esnext/form/style/css/index.css +4 -1
  49. package/esnext/form/style/index.less +6 -1
  50. package/esnext/form/type.d.ts +24 -1
  51. package/esnext/form/type.js +7 -0
  52. package/esnext/form/useForm.d.ts +2 -17
  53. package/esnext/form/useForm.js +72 -13
  54. package/esnext/form/utils.d.ts +2 -0
  55. package/esnext/form/utils.js +26 -0
  56. package/esnext/input/index.js +1 -1
  57. package/esnext/radio/group.js +3 -1
  58. package/esnext/radio/type.d.ts +2 -2
  59. package/package.json +3 -3
  60. package/umd/carousel/index.js +8 -7
  61. package/umd/form/form-item.d.ts +33 -2
  62. package/umd/form/form-item.js +142 -121
  63. package/umd/form/index.js +3 -1
  64. package/umd/form/linked-container.d.ts +1 -1
  65. package/umd/form/linked-container.js +4 -0
  66. package/umd/form/style/css/index.css +4 -1
  67. package/umd/form/style/index.less +6 -1
  68. package/umd/form/type.d.ts +24 -1
  69. package/umd/form/type.js +9 -1
  70. package/umd/form/useForm.d.ts +2 -17
  71. package/umd/form/useForm.js +98 -21
  72. package/umd/form/utils.d.ts +2 -0
  73. package/umd/form/utils.js +40 -5
  74. package/umd/input/index.js +1 -1
  75. package/umd/radio/group.js +1 -1
  76. package/umd/radio/type.d.ts +2 -2
@@ -2,7 +2,7 @@ import { IRules } from '@arco-design/mobile-utils';
2
2
  import { 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",
@@ -52,6 +52,11 @@ export interface FormProps {
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
  /**
@@ -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
+ }
@@ -12,7 +12,7 @@ const Input = forwardRef((props, ref) => {
12
12
  }));
13
13
  function renderInput({ prefixCls }) {
14
14
  const prefix = `${prefixCls}-input`;
15
- return renderWrapper(prefix, type, React.createElement("input", Object.assign({}, nativeProps, { id: id, name: name, maxLength: maxLength, placeholder: placeholder, readOnly: readOnly, onFocus: handleFocus, onBlur: handleBlur, onKeyUp: onKeyUp, onKeyPress: onKeyPress, ref: inputRef, className: cls(prefix, inputClass), style: inputStyle, value: inputValue, type: type, disabled: disabled, pattern: pattern, onChange: handleChange, onInput: handleInput, onKeyDown: handleKeyDown, onClick: handleClick, "aria-disabled": disabled, "aria-label": ariaLabel })));
15
+ return renderWrapper(prefix, `${type} single-line`, React.createElement("input", Object.assign({}, nativeProps, { id: id, name: name, maxLength: maxLength, placeholder: placeholder, readOnly: readOnly, onFocus: handleFocus, onBlur: handleBlur, onKeyUp: onKeyUp, onKeyPress: onKeyPress, ref: inputRef, className: cls(prefix, inputClass), style: inputStyle, value: inputValue, type: type, disabled: disabled, pattern: pattern, onChange: handleChange, onInput: handleInput, onKeyDown: handleKeyDown, onClick: handleClick, "aria-disabled": disabled, "aria-label": ariaLabel })));
16
16
  }
17
17
  return React.createElement(ContextLayout, null, renderInput);
18
18
  });
@@ -39,7 +39,9 @@ export function componentGenerator(Comp) {
39
39
  layout,
40
40
  disabled,
41
41
  icons,
42
- value: groupValue === void 0 ? [] : [groupValue],
42
+ value: groupValue === void 0 || groupValue === null
43
+ ? []
44
+ : [groupValue],
43
45
  onChange: handleChange,
44
46
  } },
45
47
  children,
@@ -8,10 +8,10 @@ export interface RadioGroupProps<T extends ValueType = ValueType, P extends Radi
8
8
  */
9
9
  options?: P[];
10
10
  /**
11
- * 受控模式,选中的选项
11
+ * 受控模式,选中的选项,传null表示取消选中
12
12
  * @en Checked option, controlled mode
13
13
  */
14
- value?: T;
14
+ value?: T | null;
15
15
  /**
16
16
  * 默认选中项
17
17
  * @en Default checked value
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arco-design/mobile-react",
3
- "version": "2.36.1",
3
+ "version": "2.36.2",
4
4
  "description": "",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -15,7 +15,7 @@
15
15
  "author": "taoyiyue@bytedance.com",
16
16
  "license": "ISC",
17
17
  "dependencies": {
18
- "@arco-design/mobile-utils": "2.21.1",
18
+ "@arco-design/mobile-utils": "2.21.2",
19
19
  "@arco-design/transformable": "^1.0.0",
20
20
  "@babel/runtime": "^7",
21
21
  "lodash.throttle": "^4.1.1",
@@ -47,5 +47,5 @@
47
47
  "publishConfig": {
48
48
  "access": "public"
49
49
  },
50
- "gitHead": "b7c3cd986250450f6433c906cf68bd550883fc7c"
50
+ "gitHead": "55380e688a52344b58e7bdc28bd3999b759386ba"
51
51
  }
@@ -704,12 +704,6 @@
704
704
 
705
705
  stopPropagation && e.stopPropagation();
706
706
 
707
- if (bouncingRef.current) {
708
- bouncingRef.current = false;
709
- jumpTo(index, false);
710
- return;
711
- }
712
-
713
707
  if (!touchStartedRef.current) {
714
708
  return;
715
709
  }
@@ -721,7 +715,14 @@
721
715
  return;
722
716
  }
723
717
 
724
- touchMovedRef.current = false;
718
+ touchMovedRef.current = false; // bugfix: 回弹判断逻辑需在touchMovedRef标识重置逻辑之后,否则会在触发回弹后导致标识无法重置引起滑动判断问题
719
+ // @en bugfix: The logic for the bounce judgment needs to be after the touchMovedRef reset logic, otherwise it will cause the problem of slide judgment after the bounce is triggered.
720
+
721
+ if (bouncingRef.current) {
722
+ bouncingRef.current = false;
723
+ jumpTo(index, false);
724
+ return;
725
+ }
725
726
 
726
727
  if (posAdjustingRef.current || touchStoppedRef.current) {
727
728
  return;
@@ -1,4 +1,35 @@
1
- import React from 'react';
2
- import { FormItemProps, FormItemRef } from './type';
1
+ import React, { PureComponent, ReactNode } from 'react';
2
+ import { Promise } from 'es6-promise';
3
+ import { FormItemContext } from './form-item-context';
4
+ import { IFieldError, FieldValue, IFormItemInnerProps, FormItemProps, ValidateStatus, FormItemRef, ValueChangeType, IFormItemContext } from './type';
5
+ interface IFormItemInnerState {
6
+ validateStatus: ValidateStatus;
7
+ errors?: ReactNode[];
8
+ _touched: boolean;
9
+ }
10
+ declare class FormItemInner extends PureComponent<IFormItemInnerProps, IFormItemInnerState> {
11
+ context: React.ContextType<typeof FormItemContext>;
12
+ destroyField: () => void;
13
+ private _errors;
14
+ private _touched;
15
+ constructor(props: IFormItemInnerProps, context: IFormItemContext);
16
+ componentDidMount(): void;
17
+ componentWillUnmount(): void;
18
+ onValueChange: (curValue: FieldValue, preValue: any, info?: {
19
+ changeType: ValueChangeType;
20
+ } | undefined) => void;
21
+ getInitialValue: () => any;
22
+ getFieldError: () => React.ReactNode[];
23
+ isFieldTouched: () => boolean;
24
+ getAllRuleValidateTriggers: () => string[];
25
+ validateField: (validateTrigger?: string | undefined) => Promise<IFieldError>;
26
+ setFieldData: (value: FieldValue) => void;
27
+ innerTriggerFunctionWithValueFirst: (value: any, ...args: any[]) => void;
28
+ innerOnInputFunction: (_: any, value: any, ...args: any[]) => void;
29
+ innerClearFunction: (...args: any[]) => void;
30
+ renderChildren(): React.FunctionComponentElement<any>;
31
+ render(): React.FunctionComponentElement<any>;
32
+ }
33
+ export { FormItemInner };
3
34
  declare const _default: React.ForwardRefExoticComponent<FormItemProps & React.RefAttributes<FormItemRef>>;
4
35
  export default _default;