@fjyueke/arco-mcp 1.0.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 (191) hide show
  1. package/README.md +85 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +244 -0
  4. package/metaData/components/action-sheet/doc.md +102 -0
  5. package/metaData/components/action-sheet/example/index.tsx +199 -0
  6. package/metaData/components/action-sheet/example/methods.tsx +6 -0
  7. package/metaData/components/avatar/doc.md +57 -0
  8. package/metaData/components/avatar/example/group.tsx +69 -0
  9. package/metaData/components/avatar/example/index.tsx +196 -0
  10. package/metaData/components/badge/doc.md +28 -0
  11. package/metaData/components/badge/example/index.tsx +128 -0
  12. package/metaData/components/button/doc.md +45 -0
  13. package/metaData/components/button/example/index.tsx +264 -0
  14. package/metaData/components/carousel/doc.md +89 -0
  15. package/metaData/components/carousel/example/index.tsx +1481 -0
  16. package/metaData/components/cell/doc.md +68 -0
  17. package/metaData/components/cell/example/arrow.tsx +13 -0
  18. package/metaData/components/cell/example/cell.tsx +71 -0
  19. package/metaData/components/cell/example/group.tsx +63 -0
  20. package/metaData/components/cell/example/index.tsx +19 -0
  21. package/metaData/components/checkbox/doc.md +91 -0
  22. package/metaData/components/checkbox/example/checkbox.tsx +158 -0
  23. package/metaData/components/checkbox/example/group.tsx +103 -0
  24. package/metaData/components/checkbox/example/index.tsx +25 -0
  25. package/metaData/components/circle-progress/doc.md +40 -0
  26. package/metaData/components/circle-progress/example/index.tsx +323 -0
  27. package/metaData/components/collapse/doc.md +74 -0
  28. package/metaData/components/collapse/example/collapse.tsx +183 -0
  29. package/metaData/components/collapse/example/group.tsx +136 -0
  30. package/metaData/components/collapse/example/index.tsx +16 -0
  31. package/metaData/components/collapse/example/utils.tsx +20 -0
  32. package/metaData/components/context-provider/doc.md +44 -0
  33. package/metaData/components/context-provider/example/index.tsx +208 -0
  34. package/metaData/components/count-down/doc.md +40 -0
  35. package/metaData/components/count-down/example/hooks.tsx +118 -0
  36. package/metaData/components/count-down/example/index.tsx +63 -0
  37. package/metaData/components/date-picker/doc.md +102 -0
  38. package/metaData/components/date-picker/example/index.tsx +545 -0
  39. package/metaData/components/dialog/doc.md +200 -0
  40. package/metaData/components/dialog/example/index.tsx +328 -0
  41. package/metaData/components/dialog/example/methods.tsx +56 -0
  42. package/metaData/components/divider/doc.md +25 -0
  43. package/metaData/components/divider/example/index.tsx +87 -0
  44. package/metaData/components/dropdown/doc.md +80 -0
  45. package/metaData/components/dropdown/example/dropdown.tsx +308 -0
  46. package/metaData/components/dropdown/example/index.tsx +19 -0
  47. package/metaData/components/dropdown/example/options.tsx +103 -0
  48. package/metaData/components/dropdown-menu/doc.md +91 -0
  49. package/metaData/components/dropdown-menu/example/dropdown-menu.tsx +270 -0
  50. package/metaData/components/dropdown-menu/example/index.tsx +16 -0
  51. package/metaData/components/ellipsis/doc.md +33 -0
  52. package/metaData/components/ellipsis/example/index.tsx +93 -0
  53. package/metaData/components/ellipsis/example/js-ellipsis.tsx +229 -0
  54. package/metaData/components/ellipsis/example/native-ellipsis.tsx +48 -0
  55. package/metaData/components/form/doc.md +90 -0
  56. package/metaData/components/form/example/form-item-context.tsx +8 -0
  57. package/metaData/components/form/example/form-item.tsx +378 -0
  58. package/metaData/components/form/example/index.tsx +87 -0
  59. package/metaData/components/form/example/linked-container.tsx +66 -0
  60. package/metaData/components/grid/doc.md +39 -0
  61. package/metaData/components/grid/example/index.tsx +252 -0
  62. package/metaData/components/icon/doc.md +15 -0
  63. package/metaData/components/icon/example/index.tsx +32 -0
  64. package/metaData/components/image/doc.md +62 -0
  65. package/metaData/components/image/example/index.tsx +528 -0
  66. package/metaData/components/image-picker/doc.md +116 -0
  67. package/metaData/components/image-picker/example/add-icon.tsx +14 -0
  68. package/metaData/components/image-picker/example/index.tsx +175 -0
  69. package/metaData/components/image-preview/doc.md +119 -0
  70. package/metaData/components/image-preview/example/index.tsx +1290 -0
  71. package/metaData/components/image-preview/example/methods.tsx +72 -0
  72. package/metaData/components/index-bar/doc.md +83 -0
  73. package/metaData/components/index-bar/example/group.tsx +93 -0
  74. package/metaData/components/index-bar/example/index.tsx +271 -0
  75. package/metaData/components/index-bar/example/side-bar.tsx +82 -0
  76. package/metaData/components/input/doc.md +60 -0
  77. package/metaData/components/input/example/hooks.tsx +259 -0
  78. package/metaData/components/input/example/index.tsx +134 -0
  79. package/metaData/components/input/example/props.tsx +183 -0
  80. package/metaData/components/keyboard/doc.md +73 -0
  81. package/metaData/components/keyboard/example/index.tsx +238 -0
  82. package/metaData/components/load-more/doc.md +48 -0
  83. package/metaData/components/load-more/example/index.tsx +395 -0
  84. package/metaData/components/loading/doc.md +34 -0
  85. package/metaData/components/loading/example/index.tsx +312 -0
  86. package/metaData/components/masking/doc.md +93 -0
  87. package/metaData/components/masking/example/index.tsx +410 -0
  88. package/metaData/components/masking/example/methods.tsx +88 -0
  89. package/metaData/components/nav-bar/doc.md +40 -0
  90. package/metaData/components/nav-bar/example/back-icon.tsx +28 -0
  91. package/metaData/components/nav-bar/example/index.tsx +305 -0
  92. package/metaData/components/notice-bar/doc.md +34 -0
  93. package/metaData/components/notice-bar/example/index.tsx +294 -0
  94. package/metaData/components/notify/doc.md +81 -0
  95. package/metaData/components/notify/example/index.tsx +171 -0
  96. package/metaData/components/notify/example/methods.tsx +83 -0
  97. package/metaData/components/pagination/doc.md +41 -0
  98. package/metaData/components/pagination/example/arrow.tsx +14 -0
  99. package/metaData/components/pagination/example/index.tsx +292 -0
  100. package/metaData/components/picker/doc.md +89 -0
  101. package/metaData/components/picker/example/index.tsx +217 -0
  102. package/metaData/components/picker-view/doc.md +57 -0
  103. package/metaData/components/picker-view/example/cascader.tsx +141 -0
  104. package/metaData/components/picker-view/example/index.tsx +297 -0
  105. package/metaData/components/picker-view/example/multi-picker.tsx +66 -0
  106. package/metaData/components/picker-view/example/picker-cell.tsx +416 -0
  107. package/metaData/components/popover/doc.md +144 -0
  108. package/metaData/components/popover/example/index.tsx +23 -0
  109. package/metaData/components/popover/example/menu.tsx +145 -0
  110. package/metaData/components/popover/example/popover-inner.tsx +147 -0
  111. package/metaData/components/popover/example/popover.tsx +268 -0
  112. package/metaData/components/popup/doc.md +101 -0
  113. package/metaData/components/popup/example/index.tsx +125 -0
  114. package/metaData/components/popup/example/methods.tsx +6 -0
  115. package/metaData/components/popup-swiper/doc.md +108 -0
  116. package/metaData/components/popup-swiper/example/index.tsx +332 -0
  117. package/metaData/components/popup-swiper/example/methods.tsx +6 -0
  118. package/metaData/components/portal/doc.md +14 -0
  119. package/metaData/components/portal/example/index.tsx +35 -0
  120. package/metaData/components/progress/doc.md +42 -0
  121. package/metaData/components/progress/example/index.tsx +256 -0
  122. package/metaData/components/pull-refresh/doc.md +37 -0
  123. package/metaData/components/pull-refresh/example/android-pull-refresh.tsx +260 -0
  124. package/metaData/components/pull-refresh/example/index.tsx +44 -0
  125. package/metaData/components/pull-refresh/example/ios-pull-refresh.tsx +216 -0
  126. package/metaData/components/radio/doc.md +89 -0
  127. package/metaData/components/radio/example/group.tsx +92 -0
  128. package/metaData/components/radio/example/index.tsx +25 -0
  129. package/metaData/components/radio/example/radio.tsx +22 -0
  130. package/metaData/components/rate/doc.md +33 -0
  131. package/metaData/components/rate/example/index.tsx +281 -0
  132. package/metaData/components/search-bar/doc.md +97 -0
  133. package/metaData/components/search-bar/example/association.tsx +89 -0
  134. package/metaData/components/search-bar/example/cancel-button.tsx +34 -0
  135. package/metaData/components/search-bar/example/highlight.tsx +66 -0
  136. package/metaData/components/search-bar/example/index.tsx +251 -0
  137. package/metaData/components/show-monitor/doc.md +34 -0
  138. package/metaData/components/show-monitor/example/index.tsx +646 -0
  139. package/metaData/components/skeleton/doc.md +101 -0
  140. package/metaData/components/skeleton/example/elements.tsx +290 -0
  141. package/metaData/components/skeleton/example/index.tsx +96 -0
  142. package/metaData/components/skeleton/example/skeleton-context.tsx +7 -0
  143. package/metaData/components/slider/doc.md +42 -0
  144. package/metaData/components/slider/example/index.tsx +326 -0
  145. package/metaData/components/slider/example/marks.tsx +50 -0
  146. package/metaData/components/slider/example/popover.tsx +38 -0
  147. package/metaData/components/slider/example/thumb.tsx +48 -0
  148. package/metaData/components/slider/example/useSliderIcon.tsx +38 -0
  149. package/metaData/components/slider/example/useSliderInit.tsx +170 -0
  150. package/metaData/components/stepper/doc.md +46 -0
  151. package/metaData/components/stepper/example/index.tsx +166 -0
  152. package/metaData/components/stepper/example/useButtonClick.tsx +74 -0
  153. package/metaData/components/stepper/example/useInputEvent.tsx +65 -0
  154. package/metaData/components/stepper/example/useValue.tsx +43 -0
  155. package/metaData/components/steps/doc.md +57 -0
  156. package/metaData/components/steps/example/index.tsx +123 -0
  157. package/metaData/components/steps/example/step.tsx +126 -0
  158. package/metaData/components/sticky/doc.md +45 -0
  159. package/metaData/components/sticky/example/index.tsx +430 -0
  160. package/metaData/components/swipe-action/doc.md +44 -0
  161. package/metaData/components/swipe-action/example/index.tsx +338 -0
  162. package/metaData/components/swipe-action/example/item.tsx +40 -0
  163. package/metaData/components/swipe-load/doc.md +43 -0
  164. package/metaData/components/swipe-load/example/index.tsx +339 -0
  165. package/metaData/components/swipe-load/example/type.tsx +153 -0
  166. package/metaData/components/switch/doc.md +38 -0
  167. package/metaData/components/switch/example/index.tsx +237 -0
  168. package/metaData/components/tab-bar/doc.md +57 -0
  169. package/metaData/components/tab-bar/example/index.tsx +18 -0
  170. package/metaData/components/tab-bar/example/item.tsx +74 -0
  171. package/metaData/components/tab-bar/example/tab-bar.tsx +105 -0
  172. package/metaData/components/tabs/doc.md +187 -0
  173. package/metaData/components/tabs/example/index.tsx +514 -0
  174. package/metaData/components/tabs/example/tab-cell-underline.tsx +320 -0
  175. package/metaData/components/tabs/example/tab-cell.tsx +433 -0
  176. package/metaData/components/tabs/example/tab-pane.tsx +349 -0
  177. package/metaData/components/tag/doc.md +80 -0
  178. package/metaData/components/tag/example/index.tsx +23 -0
  179. package/metaData/components/tag/example/list.tsx +97 -0
  180. package/metaData/components/tag/example/tag.tsx +85 -0
  181. package/metaData/components/textarea/doc.md +67 -0
  182. package/metaData/components/textarea/example/index.tsx +258 -0
  183. package/metaData/components/toast/doc.md +90 -0
  184. package/metaData/components/toast/example/index.tsx +335 -0
  185. package/metaData/components/toast/example/methods.tsx +87 -0
  186. package/metaData/components/transition/doc.md +19 -0
  187. package/metaData/components/transition/example/index.tsx +113 -0
  188. package/metaData/components/uploader/doc.md +82 -0
  189. package/metaData/components/uploader/example/index.tsx +208 -0
  190. package/metaData/components-index.json +242 -0
  191. package/package.json +56 -0
@@ -0,0 +1,378 @@
1
+ /* eslint-disable react/no-unused-class-component-methods */
2
+ import React, {
3
+ forwardRef,
4
+ PureComponent,
5
+ ReactNode,
6
+ Ref,
7
+ useContext,
8
+ useImperativeHandle,
9
+ useRef,
10
+ useState,
11
+ } from 'react';
12
+ import { cls, Validator, ValidatorType, ValidatorError } from '@arco-design/mobile-utils';
13
+ import { Promise } from 'es6-promise';
14
+ import { FormItemContext } from './form-item-context';
15
+ import { GlobalContext } from '../context-provider';
16
+ import {
17
+ IFieldError,
18
+ FieldValue,
19
+ IFormItemInnerProps,
20
+ FormItemProps,
21
+ ValidateStatus,
22
+ FormItemRef,
23
+ FormInternalComponentType,
24
+ ValueChangeType,
25
+ IFormItemContext,
26
+ } from './type';
27
+ import { getDefaultValueForInterComponent, getErrorAndWarnings, isFieldRequired } from './utils';
28
+ import { DefaultDatePickerLinkedContainer, DefaultPickerLinkedContainer } from './linked-container';
29
+ import { BasicInputProps } from '../input/props';
30
+ import { DatePickerProps } from '../date-picker/type';
31
+ import { PickerProps } from '../picker/type';
32
+ import { SwitchProps } from '../switch';
33
+ import { ImagePickerProps } from '../image-picker/type';
34
+
35
+ interface IFormItemInnerState {
36
+ validateStatus: ValidateStatus;
37
+ errors?: ReactNode[];
38
+ _touched: boolean;
39
+ }
40
+
41
+ class FormItemInner extends PureComponent<IFormItemInnerProps, IFormItemInnerState> {
42
+ // eslint-disable-next-line react/static-property-placement
43
+ context!: React.ContextType<typeof FormItemContext>;
44
+
45
+ destroyField: () => void;
46
+
47
+ private _errors: ReactNode[] = [];
48
+
49
+ private _touched = false;
50
+
51
+ constructor(props: IFormItemInnerProps, context: IFormItemContext) {
52
+ super(props);
53
+ this.destroyField = () => {};
54
+ if (props?.initialValue && props.field) {
55
+ const { setInitialValue } = context.form.getInternalHooks();
56
+ setInitialValue(props.field, props.initialValue);
57
+ }
58
+ }
59
+
60
+ componentDidMount() {
61
+ const { registerField } = this.context.form.getInternalHooks();
62
+ this.destroyField = registerField(this.props.field, this);
63
+ }
64
+
65
+ componentWillUnmount() {
66
+ this.destroyField();
67
+ }
68
+
69
+ onValueChange = (
70
+ curValue: FieldValue,
71
+ preValue: any,
72
+ info?: { changeType: ValueChangeType },
73
+ ) => {
74
+ this._touched = true;
75
+ const { shouldUpdate } = this.props;
76
+ if (typeof shouldUpdate === 'function') {
77
+ shouldUpdate({ preValue, curValue }) && this.forceUpdate();
78
+ return;
79
+ }
80
+
81
+ if (info?.changeType === ValueChangeType.Reset) {
82
+ this.props.onValidateStatusChange({
83
+ errors: [],
84
+ warnings: [],
85
+ errorTypes: [],
86
+ });
87
+ this._errors = [];
88
+ }
89
+ this.forceUpdate();
90
+ };
91
+
92
+ getInitialValue = () => {
93
+ const { children, displayType } = this.props;
94
+ const { getInitialValue } = this.context.form.getInternalHooks();
95
+ const childrenType = displayType || children.type?.displayName;
96
+ // get user-defined initialValue or if not defined
97
+ return getInitialValue(this.props.field) ?? getDefaultValueForInterComponent(childrenType);
98
+ };
99
+
100
+ getFieldError = () => {
101
+ return this._errors;
102
+ };
103
+
104
+ isFieldTouched = () => {
105
+ return this._touched;
106
+ };
107
+
108
+ getAllRuleValidateTriggers = (): string[] => {
109
+ return (
110
+ (this.props.rules
111
+ ?.map(rule => rule.validateTrigger)
112
+ .flat()
113
+ .filter(v => !!v) as string[]) || []
114
+ );
115
+ };
116
+
117
+ validateField = (validateTrigger?: string): Promise<IFieldError> => {
118
+ const { validateMessages } = this.context;
119
+ const { getFieldValue } = this.context.form;
120
+ const { field, rules, onValidateStatusChange } = this.props;
121
+ const value = getFieldValue(field);
122
+ // rules: if validateTrigger is not defined, all rules will be validated
123
+ // if validateTrigger is defined, only rules with validateTrigger or without rule.validateTrigger will be validated
124
+ const curRules = validateTrigger
125
+ ? rules?.filter(rule => {
126
+ const triggerList: string[] = ([] as string[]).concat(
127
+ rule.validateTrigger || validateTrigger,
128
+ );
129
+ return triggerList.includes(validateTrigger);
130
+ })
131
+ : rules;
132
+
133
+ if (curRules?.length && field) {
134
+ const fieldDom = this.props.getFormItemRef();
135
+ const fieldValidator = new Validator({ [field]: curRules }, { validateMessages });
136
+ return new Promise(resolve => {
137
+ fieldValidator.validate(
138
+ { [field]: value },
139
+ (errorsMap: Record<string, ValidatorError[]>) => {
140
+ const { errors, warnings, errorTypes } = getErrorAndWarnings(
141
+ errorsMap?.[field] || [],
142
+ );
143
+ this._errors = errors;
144
+ onValidateStatusChange({
145
+ errors: this._errors,
146
+ warnings,
147
+ errorTypes,
148
+ });
149
+ return resolve({
150
+ errors: this._errors,
151
+ warnings,
152
+ value,
153
+ field,
154
+ dom: fieldDom,
155
+ });
156
+ },
157
+ );
158
+ });
159
+ }
160
+ return Promise.resolve({ errors: [], warnings: [], value, field, dom: null });
161
+ };
162
+
163
+ setFieldData = (value: FieldValue) => {
164
+ const { field, trigger = 'onChange' } = this.props;
165
+ const { innerSetFieldValue } = this.context.form.getInternalHooks();
166
+ innerSetFieldValue(field, value);
167
+ this.validateField(trigger);
168
+ };
169
+
170
+ innerTriggerFunctionWithValueFirst = (value, ...args) => {
171
+ this.setFieldData(value);
172
+ const { children, trigger = 'onChange' } = this.props;
173
+ if (trigger && children.props?.[trigger]) {
174
+ children.props?.[trigger](value, ...args);
175
+ }
176
+ };
177
+
178
+ innerOnInputFunction = (_, value, ...args) => {
179
+ this.setFieldData(value);
180
+ const { children } = this.props;
181
+ children.props?.onInput?.(_, value, ...args);
182
+ };
183
+
184
+ innerClearFunction = (...args) => {
185
+ const { children } = this.props;
186
+ this.setFieldData('');
187
+ if (children.props?.onClear) {
188
+ children.props?.onClear(...args);
189
+ }
190
+ };
191
+
192
+ renderChildren() {
193
+ const {
194
+ children,
195
+ field,
196
+ trigger = 'onChange',
197
+ triggerPropsField = 'value',
198
+ displayType,
199
+ disabled,
200
+ } = this.props;
201
+ const { getFieldValue } = this.context.form;
202
+ const childrenProps: {
203
+ disabled?: boolean;
204
+ error?: ReactNode[];
205
+ } = {
206
+ disabled,
207
+ };
208
+ // inject validateTriggers of rules
209
+ this.getAllRuleValidateTriggers().forEach(triggerName => {
210
+ childrenProps[triggerName] = e => {
211
+ this.validateField(triggerName);
212
+ children?.props?.[triggerName]?.(e);
213
+ };
214
+ });
215
+ const childrenType = displayType || children.type?.displayName;
216
+ switch (childrenType) {
217
+ case FormInternalComponentType.Input:
218
+ case FormInternalComponentType.Textarea:
219
+ (childrenProps as BasicInputProps<HTMLInputElement>).value =
220
+ getFieldValue(field) || '';
221
+ (childrenProps as BasicInputProps<HTMLInputElement>).onInput =
222
+ this.innerOnInputFunction;
223
+ (childrenProps as BasicInputProps<HTMLInputElement>).onClear =
224
+ this.innerClearFunction;
225
+ break;
226
+ case FormInternalComponentType.DatePicker:
227
+ (childrenProps as DatePickerProps).currentTs = getFieldValue(field);
228
+ (childrenProps as DatePickerProps).onChange =
229
+ this.innerTriggerFunctionWithValueFirst;
230
+ (childrenProps as DatePickerProps).renderLinkedContainer =
231
+ children.props?.renderLinkedContainer ||
232
+ ((ts, types) => <DefaultDatePickerLinkedContainer ts={ts} types={types} />);
233
+ break;
234
+ case FormInternalComponentType.Picker:
235
+ (childrenProps as PickerProps).value = getFieldValue(field) || '';
236
+ (childrenProps as PickerProps).onChange = this.innerTriggerFunctionWithValueFirst;
237
+ (childrenProps as PickerProps).renderLinkedContainer =
238
+ children.props?.renderLinkedContainer ||
239
+ (val => <DefaultPickerLinkedContainer value={val} />);
240
+ break;
241
+
242
+ case FormInternalComponentType.Switch:
243
+ (childrenProps as SwitchProps).checked = Boolean(getFieldValue(field));
244
+ (childrenProps as SwitchProps).onChange = this.innerTriggerFunctionWithValueFirst;
245
+ break;
246
+ case FormInternalComponentType.ImagePicker:
247
+ (childrenProps as ImagePickerProps).images = getFieldValue(field);
248
+ (childrenProps as ImagePickerProps).onChange =
249
+ this.innerTriggerFunctionWithValueFirst;
250
+ break;
251
+ default:
252
+ if (triggerPropsField) {
253
+ childrenProps[triggerPropsField] = getFieldValue(field);
254
+ }
255
+ // inject the validated result
256
+ childrenProps.error = this._errors;
257
+ childrenProps[trigger] = this.innerTriggerFunctionWithValueFirst;
258
+ }
259
+
260
+ return React.cloneElement(children, childrenProps);
261
+ }
262
+
263
+ render() {
264
+ return this.renderChildren();
265
+ }
266
+ }
267
+ FormItemInner.contextType = FormItemContext;
268
+
269
+ export { FormItemInner };
270
+
271
+ export default forwardRef((props: FormItemProps, ref: Ref<FormItemRef>) => {
272
+ const {
273
+ label,
274
+ field,
275
+ disabled = false,
276
+ layout: itemLayout,
277
+ style,
278
+ extra,
279
+ requiredIcon,
280
+ rules,
281
+ className = '',
282
+ ...rest
283
+ } = props;
284
+ const { prefixCls } = useContext(GlobalContext);
285
+ const { layout, disabled: propsDisabled } = useContext(FormItemContext);
286
+ const [errors, setErrors] = useState<ReactNode | null>(null);
287
+ const [errorTypes, setErrorTypes] = useState<string | null>(null);
288
+ const [warnings, setWarnings] = useState<ReactNode[]>([]);
289
+ const formItemRef = useRef<HTMLDivElement | null>(null);
290
+
291
+ const onValidateStatusChange = (validateResult: {
292
+ errors: ReactNode[];
293
+ warnings: ReactNode[];
294
+ errorTypes: string[];
295
+ }) => {
296
+ const { errors: _errors, warnings: _warnings, errorTypes: _errorTypes } = validateResult;
297
+ setErrors(_errors.length ? _errors[0] : null);
298
+ setErrorTypes(_errorTypes.length ? _errorTypes[0] : null);
299
+ setWarnings(_warnings);
300
+ };
301
+ const getFormItemRef = () => {
302
+ return formItemRef.current;
303
+ };
304
+ const fieldDisabled = disabled || propsDisabled;
305
+
306
+ const fieldRules = rest?.required
307
+ ? [{ type: ValidatorType.String, required: true }, ...(rules || [])]
308
+ : rules;
309
+ const isRequired = isFieldRequired(rules) || rest?.required;
310
+
311
+ useImperativeHandle(ref, () => ({
312
+ dom: formItemRef.current,
313
+ }));
314
+ return (
315
+ <div
316
+ className={cls(
317
+ `${prefixCls}-form-item`,
318
+ `${prefixCls}-form-item-${itemLayout || layout}`,
319
+ className,
320
+ {
321
+ disabled: fieldDisabled,
322
+ [`${prefixCls}-form-item-error`]: !!errors,
323
+ [`${prefixCls}-form-item-warning`]: Boolean(!errors && warnings),
324
+ [`${prefixCls}-form-item-error-${errorTypes}`]: errorTypes,
325
+ },
326
+ )}
327
+ style={style}
328
+ ref={formItemRef}
329
+ >
330
+ <div className={cls(`${prefixCls}-form-label-item`)}>
331
+ {isRequired
332
+ ? requiredIcon || (
333
+ <span className={cls(`${prefixCls}-form-label-item-required-asterisk`)}>
334
+ *
335
+ </span>
336
+ )
337
+ : null}
338
+ {label}
339
+ </div>
340
+ <div className={cls(`${prefixCls}-form-item-control-wrapper`)}>
341
+ <div className={cls(`${prefixCls}-form-item-control`)}>
342
+ <FormItemInner
343
+ {...rest}
344
+ rules={fieldRules}
345
+ disabled={fieldDisabled}
346
+ field={field}
347
+ onValidateStatusChange={onValidateStatusChange}
348
+ getFormItemRef={getFormItemRef}
349
+ />
350
+ </div>
351
+ {errors && (
352
+ <div
353
+ className={cls(
354
+ `${prefixCls}-form-item-message ${prefixCls}-form-item-error-message`,
355
+ )}
356
+ >
357
+ {errors}
358
+ </div>
359
+ )}
360
+ {(warnings || []).map((node, key) =>
361
+ typeof node === 'string' ? (
362
+ <div
363
+ className={cls(
364
+ `${prefixCls}-form-item-message ${prefixCls}-form-item-warning-message`,
365
+ )}
366
+ key={key}
367
+ >
368
+ {node}
369
+ </div>
370
+ ) : (
371
+ node
372
+ ),
373
+ )}
374
+ </div>
375
+ {extra}
376
+ </div>
377
+ );
378
+ });
@@ -0,0 +1,87 @@
1
+ import { componentWrapper, defaultLocale } from '@arco-design/mobile-utils';
2
+ import React, { useRef, forwardRef, Ref, useImperativeHandle } from 'react';
3
+ import { ContextLayout } from '../context-provider';
4
+ import Item from './form-item';
5
+ import { FormItemContext } from './form-item-context';
6
+ import { FormProps, FormRef, InternalFormInstance } from './type';
7
+ import useForm from './useForm';
8
+
9
+ export { default as useForm } from './useForm';
10
+ export * from './type';
11
+
12
+ const Form = forwardRef((props: FormProps, ref: Ref<FormRef>) => {
13
+ const {
14
+ className = '',
15
+ style,
16
+ layout = 'horizontal',
17
+ initialValues,
18
+ form: formInstance,
19
+ children,
20
+ onValuesChange,
21
+ onChange,
22
+ onSubmit,
23
+ onSubmitFailed,
24
+ disabled,
25
+ } = props;
26
+ const domRef = useRef<HTMLFormElement | null>(null);
27
+ const initRef = useRef(false);
28
+ const [form] = useForm(formInstance);
29
+ const { setCallbacks, setInitialValues } = (form as InternalFormInstance).getInternalHooks();
30
+ setCallbacks({
31
+ onValuesChange,
32
+ onSubmit,
33
+ onSubmitFailed,
34
+ onChange,
35
+ });
36
+
37
+ if (!initRef.current) {
38
+ setInitialValues(initialValues || {});
39
+ initRef.current = true;
40
+ }
41
+
42
+ useImperativeHandle(ref, () => ({
43
+ dom: domRef.current,
44
+ form,
45
+ }));
46
+
47
+ const contextValue = {
48
+ form: form as InternalFormInstance,
49
+ layout,
50
+ disabled,
51
+ };
52
+
53
+ return (
54
+ <ContextLayout>
55
+ {({ prefixCls, locale = defaultLocale }) => (
56
+ <form
57
+ className={`${prefixCls}-form ${className}`}
58
+ style={style}
59
+ ref={domRef}
60
+ onSubmit={e => {
61
+ e.preventDefault();
62
+ e.stopPropagation();
63
+ form.submit();
64
+ }}
65
+ >
66
+ <FormItemContext.Provider
67
+ value={{ ...contextValue, validateMessages: locale?.Form || {} }}
68
+ >
69
+ {children}
70
+ </FormItemContext.Provider>
71
+ </form>
72
+ )}
73
+ </ContextLayout>
74
+ );
75
+ });
76
+
77
+ /**
78
+ * 表单组件用于集合数据录入
79
+ * @en Form, Form for collecting data input
80
+ * @type 数据录入
81
+ * @type_en Data Entry
82
+ * @name 表单
83
+ * @name_en Form
84
+ */
85
+ export default componentWrapper(Form, {
86
+ Item,
87
+ });
@@ -0,0 +1,66 @@
1
+ import React, { useContext, useMemo } from 'react';
2
+ import { formatDateNumber } from '@arco-design/mobile-utils';
3
+ import { convertTsToDateObj } from '../date-picker/helper';
4
+ import { GlobalContext } from '../context-provider';
5
+
6
+ export function DefaultPickerLinkedContainer({ value }: { value: (string | number)[] }) {
7
+ const { prefixCls, locale } = useContext(GlobalContext);
8
+ const className = `${prefixCls}-form-picker-link-container`;
9
+ return (
10
+ <div className={className}>
11
+ {value && value.length ? (
12
+ value.join('-')
13
+ ) : (
14
+ <span className={`${className}-placeholder`}>{locale?.Form.pickerDefaultHint}</span>
15
+ )}
16
+ </div>
17
+ );
18
+ }
19
+
20
+ export function DefaultDatePickerLinkedContainer({
21
+ ts,
22
+ types,
23
+ }: {
24
+ ts?: number | [number, number];
25
+ types: string[];
26
+ }) {
27
+ const { prefixCls, locale } = useContext(GlobalContext);
28
+ const className = `${prefixCls}-form-picker-link-container`;
29
+ const dateTimeStr = useMemo(() => {
30
+ if (ts === undefined) {
31
+ return '';
32
+ }
33
+ if (typeof ts === 'number') {
34
+ return formatDateTimeStr(ts, types);
35
+ }
36
+ return `${formatDateTimeStr(ts[0], types)} ~ ${formatDateTimeStr(ts[1], types)}`;
37
+ }, [ts, types]);
38
+
39
+ function formatDateTimeStr(timestamp: number, itemTypes: string[]) {
40
+ const dateObj = convertTsToDateObj(timestamp);
41
+ const validDateObj: Record<string, string> = Object.keys(dateObj).reduce(
42
+ (acc, key) => ({
43
+ ...acc,
44
+ ...(itemTypes.includes(key) ? { [key]: formatDateNumber(dateObj[key]) } : {}),
45
+ }),
46
+ {},
47
+ );
48
+ const dateStr = [validDateObj.year, validDateObj.month, validDateObj.date]
49
+ .filter(v => v)
50
+ .join('-');
51
+ const timeStr = [validDateObj.hour, validDateObj.minute, validDateObj.second]
52
+ .filter(v => v)
53
+ .join(':');
54
+ return `${dateStr} ${timeStr}`;
55
+ }
56
+
57
+ return (
58
+ <div className={className}>
59
+ {ts ? (
60
+ dateTimeStr
61
+ ) : (
62
+ <span className={`${className}-placeholder`}>{locale?.Form.pickerDefaultHint}</span>
63
+ )}
64
+ </div>
65
+ );
66
+ }
@@ -0,0 +1,39 @@
1
+ ### 布局
2
+
3
+ # 宫格 Grid
4
+
5
+ 宫格可以在水平方向上把页面分隔成等宽度的区块,用于展示内容或进行页面导航。
6
+
7
+ ======
8
+
9
+ > 属性/Props
10
+
11
+ |参数|描述|类型|默认值|
12
+ |----------|-------------|------|------|
13
+ |className|自定义类名|string|-|
14
+ |style|自定义样式|CSSProperties|-|
15
+ |data|传入的数据|GridData\[\]|必填|
16
+ |columns|一行的列数|number|3|
17
+ |border|是否有边框|boolean|false|
18
+ |gutter|格子间的间距|number \| \{ x: number; y: number; \}|0|
19
+ |shape|格子的形状,可选值为 circle|string|"square"|
20
+ |isSliding|溢出时是否支持滑动|boolean|false|
21
+ |direction|格子内容排列的方向,可选值为 horizontal|string|"vertical"|
22
+
23
+ > 引用/Refs
24
+
25
+ |参数|描述|类型|
26
+ |----------|-------------|------|
27
+ |dom|最外层元素 DOM|HTMLDivElement|
28
+
29
+ > GridData
30
+
31
+ |参数|描述|类型|
32
+ |----------|-------------|------|
33
+ |img|传入图标的资源地址|ReactNode|
34
+ |title|传入的标题文字内容|ReactNode|
35
+ |content|传入的描述文字内容|ReactNode|
36
+ |className|自定义样式|string|
37
+ |onClick|点击后的回调函数|(item: GridData) =\> void|
38
+ |itemStyle|每个格子自定义样式|CSSProperties|
39
+ |renderGrid|自定义单个 grid 的创建函数|(item: GridData, colIndex: number, rowIndex: number) =\> ReactNode|