@cloudbase/weda-ui 3.22.3 → 3.23.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 (40) hide show
  1. package/dist/configs/components/wd-tabbar.d.ts +16 -0
  2. package/dist/configs/components/wd-tabbar.js +6 -0
  3. package/dist/configs/components/wd-table.d.ts +1 -0
  4. package/dist/configs/components/wd-table.js +14 -1
  5. package/dist/configs/components/wd-upload-image.js +1 -1
  6. package/dist/configs/index.d.ts +34 -0
  7. package/dist/style/index.css +27 -0
  8. package/dist/style/index.scss +1 -1
  9. package/dist/style/weda-ui.min.css +2 -2
  10. package/dist/web/components/form-input-hooks/index.d.ts +0 -1
  11. package/dist/web/components/form-input-hooks/index.js +8 -14
  12. package/dist/web/components/wd-form/contexts/form-field-context.d.ts +6 -2
  13. package/dist/web/components/wd-form/contexts/form-field-context.js +18 -2
  14. package/dist/web/components/wd-form/contexts/form-field-obj-context.d.ts +2 -2
  15. package/dist/web/components/wd-form/contexts/form-field-obj-context.js +2 -2
  16. package/dist/web/components/wd-form/hoc/form-container-decorator.d.ts +11 -0
  17. package/dist/web/components/wd-form/hoc/form-container-decorator.js +61 -0
  18. package/dist/web/components/wd-form/index.d.ts +4 -49
  19. package/dist/web/components/wd-form/index.js +53 -70
  20. package/dist/web/components/wd-form-obj/base-form-obj.d.ts +5 -1
  21. package/dist/web/components/wd-form-obj/base-form-obj.js +19 -38
  22. package/dist/web/components/wd-input/wd-input.d.ts +2 -0
  23. package/dist/web/components/wd-input/wd-input.js +70 -18
  24. package/dist/web/components/wd-input-number/wd-input-number.js +15 -15
  25. package/dist/web/components/wd-tabbar/wd-tabbar.js +4 -6
  26. package/dist/web/components/wd-table/components/FieldRender/index.d.ts +9 -1
  27. package/dist/web/components/wd-table/components/FieldRender/index.js +33 -4
  28. package/dist/web/components/wd-table/components/FilterFieldsPanel/Fields.d.ts +3 -1
  29. package/dist/web/components/wd-table/components/FilterFieldsPanel/Fields.js +7 -3
  30. package/dist/web/components/wd-table/components/FilterFieldsPanel/FilterFieldItem.js +4 -1
  31. package/dist/web/components/wd-table/components/FilterFieldsPanel/filterFieldsGenerate.d.ts +6 -15
  32. package/dist/web/components/wd-table/components/FilterFieldsPanel/filterFieldsGenerate.js +47 -16
  33. package/dist/web/components/wd-table/components/FilterFieldsPanel/index.js +15 -5
  34. package/dist/web/components/wd-table/utils/index.d.ts +5 -2
  35. package/dist/web/components/wd-table/utils/index.js +12 -1
  36. package/dist/web/components/wd-table/wd-table.d.ts +5 -19
  37. package/dist/web/components/wd-table/wd-table.js +22 -2
  38. package/dist/web/components/wd-tree/utils.js +1 -1
  39. package/dist/web/utils/hooks/useFormLegacy.js +5 -12
  40. package/package.json +5 -5
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useState, useCallback } from 'react';
3
+ import lodashSet from 'lodash.set';
4
+ import lodashGet from 'lodash.get';
5
+ import { deepClone } from '../../../utils/tool';
6
+ import isObjectEqual from '../../../utils/isObjectEqual';
7
+ import { emptyObject, emptyArray, NOT_EXISTED_VALUE } from '../../../utils/constant';
8
+ import { FormFieldProvider, useFormField } from '../contexts/form-field-context';
9
+ /**
10
+ * 表单容器装饰器高阶组件
11
+ * 用于包装组件,提供表单容器上下文
12
+ * @param Component 需要包装的组件
13
+ * @returns 包装后的组件,支持透传ref
14
+ */
15
+ export function withFormContainer(Component) {
16
+ const WithFormContainer = React.forwardRef((props, ref) => {
17
+ var _a;
18
+ const { ...componentProps } = props;
19
+ const formField = useFormField();
20
+ const _formFieldValues = (_a = props.initialValues) !== null && _a !== void 0 ? _a : props.value;
21
+ const [formFieldsValue, setFormFieldsValue] = useState(_formFieldValues !== null && _formFieldValues !== void 0 ? _formFieldValues : ((props === null || props === void 0 ? void 0 : props.objType) === 'arr' ? emptyArray : emptyObject));
22
+ const [isReadyToCalculate, setIsReadyToCalculate] = useState(true);
23
+ const getFieldValue = useCallback(({ namePath, initialValue }) => {
24
+ const value = lodashGet(formFieldsValue, namePath, NOT_EXISTED_VALUE);
25
+ if (value !== NOT_EXISTED_VALUE) {
26
+ return value;
27
+ }
28
+ else {
29
+ // 设置初始值,兼容表单项变量绑定场景
30
+ // form的初始值>formArr/formObj/formDetail>field
31
+ if (initialValue !== undefined) {
32
+ return initialValue;
33
+ }
34
+ return null;
35
+ }
36
+ }, [formFieldsValue]);
37
+ const setFieldValue = useCallback(({ namePath, value }) => {
38
+ setFormFieldsValue((formData) => {
39
+ if (typeof formData !== 'object' || formData === null) {
40
+ console.warn('setValue data need expect a object but got null', formData);
41
+ return formData;
42
+ }
43
+ // 获取当前值并比较
44
+ const _value = lodashGet(formData, namePath, NOT_EXISTED_VALUE);
45
+ if (isObjectEqual(_value, value))
46
+ return formData;
47
+ const _formData = deepClone(formData);
48
+ lodashSet(_formData, namePath, value);
49
+ return _formData;
50
+ });
51
+ }, []);
52
+ // 在表单容器内直接渲染原始组件
53
+ if (formField) {
54
+ return _jsx(Component, { ...props, ref: ref, isInformContainer: true });
55
+ }
56
+ return (_jsx(FormFieldProvider, { setFieldValue: setFieldValue, getFieldValue: getFieldValue, isInformContainer: true, formFieldsValue: formFieldsValue, setFormFieldsValue: setFormFieldsValue, isReadyToCalculate: isReadyToCalculate, setIsReadyToCalculate: setIsReadyToCalculate, children: _jsx(Component, { ...componentProps, formFieldsValue: formFieldsValue, ref: ref }) }));
57
+ });
58
+ // 设置显示名称,方便调试
59
+ WithFormContainer.displayName = `withFormContainer(${Component.displayName || Component.name || 'Component'})`;
60
+ return WithFormContainer;
61
+ }
@@ -6,53 +6,8 @@ import '../style';
6
6
  export type WdFromProps = CommonPropsType & DataType & EventsType & {
7
7
  appCloud: typeof tcbAppCloud;
8
8
  };
9
- declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<CommonPropsType & {
10
- _id?: string;
11
- value: Record<string, any>;
12
- formType: "create" | "edit" | "read";
13
- contentSlot: React.ReactNode;
14
- layout: "vertical" | "horizontal";
15
- dataSourceName: string;
16
- labelAlign: "left" | "right";
17
- datasourceType: "connector" | "custom-connector" | "model" | "expression";
18
- methodGetItem: string;
19
- paramGetItem: Record<string, unknown>;
20
- methodCreate: string;
21
- methodUpdate: string;
22
- isDisabledSubmit: boolean;
23
- formType_bind: boolean;
24
- fields: {
25
- name: string;
26
- componentType: string;
27
- }[];
28
- colNum: never;
29
- lgWidth: "lg" | "sm" | "md" | "hundred";
30
- initialValues: Record<string, unknown>;
31
- } & {
32
- events: {
33
- submit: (eventDetail: unknown, ...args: unknown[]) => unknown;
34
- validateSuccess: (eventDetail: {
35
- errors: Record<string, string>;
36
- }, ...args: unknown[]) => unknown;
37
- validateFail: (eventDetail: {
38
- errors: Record<string, string>;
39
- }, ...args: unknown[]) => unknown;
40
- queryEmpty: (eventDetail: {
41
- data: Record<string, any>;
42
- }, ...args: unknown[]) => unknown;
43
- querySuccess: (eventDetail: {
44
- data: Record<string, any>;
45
- }, ...args: unknown[]) => unknown;
46
- queryFail: (eventDetail: {
47
- error: {
48
- requestid?: string;
49
- code: string;
50
- message: string;
51
- original: any;
52
- };
53
- }, ...args: unknown[]) => unknown;
54
- };
55
- } & {
56
- appCloud: typeof tcbAppCloud;
57
- } & React.RefAttributes<unknown>>>;
9
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<{
10
+ [key: string]: any;
11
+ initialValues?: any;
12
+ }, string | number> & React.RefAttributes<unknown>>>;
58
13
  export default _default;
@@ -19,7 +19,6 @@ import { useDataSource } from '../../utils/hooks/useDataSource';
19
19
  import { WdForm as FormUi } from './wd-form';
20
20
  import StatusContent from '../statusContent';
21
21
  import { deepClone } from '../../utils/tool';
22
- import isObjectEqual from '../../utils/isObjectEqual';
23
22
  import { convertMethodParam } from '../../utils/hooks/useFormLegacy';
24
23
  import '../style';
25
24
  import { getErrorObjectFromValidateResult, convertFormData } from './form-utils';
@@ -27,13 +26,15 @@ import { isNil } from '../../utils/lodash';
27
26
  import { FormTypeProvider } from './contexts/form-type-context';
28
27
  import { FormLayoutProvider } from './contexts/form-layout-context';
29
28
  import { FormWidgetProvider } from './contexts/form-widget-context';
30
- import { FormFieldProvider } from './contexts/form-field-context';
29
+ import { useFormField } from './contexts/form-field-context';
30
+ // eslint-disable-next-line tree-shaking/no-side-effects-in-initialization
31
+ import { withFormContainer } from './hoc/form-container-decorator';
31
32
  import { useSyncValue } from '../../utils/hooks/useSyncValue';
32
33
  import useDebouncedCallback from '../../utils/hooks/use-debounced-callback';
33
34
  const SET_VALUE_DEBOUNCE_TIMEOUT = 250;
34
35
  const logger = debug('wd-form');
35
- const WdForm = React.forwardRef(function WdForm(props, ref) {
36
- var _a, _b, _c;
36
+ const WdForm = withFormContainer(React.forwardRef(function WdForm(props, ref) {
37
+ var _a, _b;
37
38
  const { className, id, style, contentSlot: contentSlotEl, layout = 'horizontal', formType = 'create', _id, datasourceType = 'model', dataSourceName, methodGetItem, methodCreate, methodUpdate, paramGetItem, appCloud = tcbAppCloud, lgWidth, labelAlign = 'left', initialValues: _initialValues,
38
39
  // 兼容流程setValue调用,其他地方别用
39
40
  $node, $widget, } = props;
@@ -74,16 +75,32 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
74
75
  const [initialValues, setInitialValues] = useState((_b = deepClone(_initialValues)) !== null && _b !== void 0 ? _b : emptyObject);
75
76
  const [propsValue] = useSyncValue(props.value);
76
77
  // 表单值
77
- const [formData, setFormData] = useState((_c = deepClone(_initialValues)) !== null && _c !== void 0 ? _c : emptyObject);
78
+ // const [formData, setFormData] = useState<Record<string, unknown>>(deepClone(_initialValues) ?? emptyObject);
79
+ const formField = useFormField();
80
+ const { setFormFieldsValue, formFieldsValue, setIsReadyToCalculate } = formField || {};
78
81
  // 转换后表单值,仅保留已挂载表单项的值
79
- const formFieldsValue = useMemo(() => {
80
- return convertFormData(formData, formItemMapList, fieldInitValueCache);
81
- }, [formData, formItemMapList, fieldInitValueCache]);
82
+ const formFieldConvertValues = useMemo(() => {
83
+ return convertFormData(formFieldsValue, formItemMapList, fieldInitValueCache);
84
+ }, [formFieldsValue, formItemMapList, fieldInitValueCache]);
82
85
  useDebouncedEffect(() => {
83
86
  var _a, _b;
84
87
  // 表单容器上挂载的表单项的值
85
- (_b = (_a = eventsRef === null || eventsRef === void 0 ? void 0 : eventsRef.current) === null || _a === void 0 ? void 0 : _a.onDataChange) === null || _b === void 0 ? void 0 : _b.call(_a, { data: formFieldsValue });
86
- }, [formFieldsValue],
88
+ (_b = (_a = eventsRef === null || eventsRef === void 0 ? void 0 : eventsRef.current) === null || _a === void 0 ? void 0 : _a.onDataChange) === null || _b === void 0 ? void 0 : _b.call(_a, { data: formFieldConvertValues });
89
+ }, [formFieldConvertValues],
90
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
91
+ SET_VALUE_DEBOUNCE_TIMEOUT);
92
+ useEffect(() => {
93
+ if (['edit', 'read'].includes(formType) && !hasSetInitValueRef.current) {
94
+ // 表单容器编辑和只读状态下,接口返回数据后具备相应数据计算条件
95
+ setIsReadyToCalculate(false);
96
+ }
97
+ }, [formType, setIsReadyToCalculate]);
98
+ useDebouncedEffect(() => {
99
+ // 在编辑/只读场景下,当所有依赖表单数据全部完成时,允许触发计算逻辑
100
+ if (['edit', 'read'].includes(formType) && hasSetInitValueRef.current) {
101
+ setIsReadyToCalculate(true);
102
+ }
103
+ }, [hasSetInitValueRef.current, formType],
87
104
  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
88
105
  SET_VALUE_DEBOUNCE_TIMEOUT);
89
106
  const eventsRef = useSyncedRef(props.events);
@@ -182,9 +199,9 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
182
199
  if (Object.keys(errorObj !== null && errorObj !== void 0 ? errorObj : {}).length === 0) {
183
200
  validateSuccess({ errors: {} });
184
201
  const extra = ['read', 'edit'].includes(formType) && _id ? { _id } : {};
185
- submit && submit(deepClone({ ...extra, ...formFieldsValue }));
202
+ submit && submit(deepClone({ ...extra, ...formFieldConvertValues }));
186
203
  // 流程用了;
187
- return formFieldsValue;
204
+ return formFieldConvertValues;
188
205
  }
189
206
  else {
190
207
  setErrors(errorObj);
@@ -199,19 +216,30 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
199
216
  const r = await submitPromiseCache.current;
200
217
  submitPromiseCache.current = null;
201
218
  return r;
202
- }, [_id, eventsRef, formFieldsValue, formType, isDisabledSubmit, validate]);
219
+ }, [_id, eventsRef, formFieldConvertValues, formType, isDisabledSubmit, validate]);
203
220
  const submit = useDebouncedCallback(submitHandler, SET_VALUE_DEBOUNCE_TIMEOUT, {
204
221
  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
205
222
  maxWait: SET_VALUE_DEBOUNCE_TIMEOUT,
206
223
  trailing: true,
207
224
  });
208
- const setValue = useCallback((data) => {
225
+ const setValue = useCallback((data, notMerge = false) => {
226
+ // notMerge 默认false,表示与之前的表单值合并
209
227
  if (typeof data !== 'object' || data === null) {
210
228
  console.warn('setValue data need expect a object but got null', data);
211
229
  return;
212
230
  }
213
- setFormData(data);
214
- }, []);
231
+ if (notMerge) {
232
+ setFormFieldsValue(data);
233
+ }
234
+ else {
235
+ setFormFieldsValue((formFieldsValue) => ({ ...formFieldsValue, ...data }));
236
+ }
237
+ }, [setFormFieldsValue]);
238
+ const setValueDebounce = useDebouncedCallback(setValue, SET_VALUE_DEBOUNCE_TIMEOUT, {
239
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
240
+ maxWait: SET_VALUE_DEBOUNCE_TIMEOUT * 2,
241
+ trailing: true,
242
+ });
215
243
  const clearValidate = useCallback(() => {
216
244
  formsItemMap.forEach((items) => {
217
245
  items.forEach((item) => {
@@ -223,10 +251,6 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
223
251
  });
224
252
  });
225
253
  }, [formsItemMap]);
226
- const [isInformContainer, setIsInformContainer] = React.useState(false);
227
- React.useEffect(() => {
228
- setIsInformContainer(true);
229
- }, []);
230
254
  useMountEffect(() => {
231
255
  logger.debug('formItemMap', formsItemMap);
232
256
  });
@@ -291,19 +315,14 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
291
315
  // eslint-disable-next-line react-hooks/exhaustive-deps
292
316
  [formsItemMap]);
293
317
  const { data: formInitValueToSet } = useInitValueFromRemote(datasourceType, dataSourceProfile, fetchedInitialValues);
294
- const setValueDebounce = useDebouncedCallback(setValue, SET_VALUE_DEBOUNCE_TIMEOUT, {
295
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
296
- maxWait: SET_VALUE_DEBOUNCE_TIMEOUT * 2,
297
- trailing: true,
298
- });
299
318
  useEffect(() => {
300
319
  if (initValueLoadingStatus !== 'done' || !fetchedInitialValues)
301
320
  return;
302
321
  if (!initValueFetchError && formInitValueToSet) {
303
322
  /*
304
- 错误处理放在了 @link {onInitialValuesError}
305
- 下面是可以拿到data了
306
- */
323
+ 错误处理放在了 @link {onInitialValuesError}
324
+ 下面是可以拿到data了
325
+ */
307
326
  // TODO: 有哪些key可以暴露
308
327
  setInitialValues((original) => {
309
328
  if (hasSetInitValueRef.current) {
@@ -326,7 +345,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
326
345
  }, [authValue, isDataModel, initDataSourceFieldsWithAuth, formItemMapKey]);
327
346
  const submitParams = useRemoteParamsFromValue({
328
347
  dataSourceProfile,
329
- formData: formFieldsValue,
348
+ formData: formFieldConvertValues,
330
349
  formType,
331
350
  _id,
332
351
  });
@@ -378,13 +397,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
378
397
  setValue(val, opts = { notMerge: false }) {
379
398
  const value = convertMethodParam(val);
380
399
  // notMerge 默认false,表示与之前的表单值合并
381
- if (opts.notMerge) {
382
- setValueDebounce(value);
383
- }
384
- else {
385
- const _formData = deepClone(formData);
386
- setValueDebounce({ ..._formData, ...value });
387
- }
400
+ setValueDebounce(value, opts.notMerge);
388
401
  },
389
402
  reset() {
390
403
  setValueDebounce(initialValues);
@@ -427,7 +440,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
427
440
  authValue,
428
441
  layout,
429
442
  dataSourceName,
430
- value: formFieldsValue,
443
+ value: formFieldConvertValues,
431
444
  remoteValue: fetchedInitialValues,
432
445
  dataSourceProfile,
433
446
  errors,
@@ -449,7 +462,7 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
449
462
  authValue,
450
463
  layout,
451
464
  dataSourceName,
452
- formFieldsValue,
465
+ formFieldConvertValues,
453
466
  fetchedInitialValues,
454
467
  dataSourceProfile,
455
468
  errors,
@@ -464,7 +477,6 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
464
477
  fieldInitValueCache,
465
478
  formsItemMap,
466
479
  setValueDebounce,
467
- formData,
468
480
  formItemMapList,
469
481
  setValue,
470
482
  validate,
@@ -495,38 +507,9 @@ const WdForm = React.forwardRef(function WdForm(props, ref) {
495
507
  const labelPosition = useMemo(() => {
496
508
  return `${layout}-${labelAlign}`;
497
509
  }, [layout, labelAlign]);
498
- const getFieldValue = useCallback(({ namePath, initialValue }) => {
499
- const value = lodashGet(formData, namePath, NOT_EXISTED_VALUE);
500
- if (value !== NOT_EXISTED_VALUE) {
501
- return value;
502
- }
503
- else {
504
- // 设置初始值,兼容表单项变量绑定场景
505
- // form的初始值>formArr/formObj/formDetail>field
506
- if (initialValue !== undefined) {
507
- return initialValue;
508
- }
509
- return undefined;
510
- }
511
- }, [formData]);
512
- const setFieldValue = useCallback(({ namePath, value }) => {
513
- setFormData((formData) => {
514
- const _formData = deepClone(formData);
515
- const _value = lodashGet(_formData, namePath, NOT_EXISTED_VALUE);
516
- if (isObjectEqual(_value, value)) {
517
- return _formData;
518
- }
519
- lodashSet(_formData, namePath, value);
520
- if (typeof _formData !== 'object' || _formData === null) {
521
- console.warn('setValue data need expect a object but got null', _formData);
522
- return formData;
523
- }
524
- return _formData;
525
- });
526
- }, []);
527
510
  if (initValueLoadingStatus === 'loading' && !fetchedInitialValues) {
528
511
  return _jsx(StatusContent, { emptyText: '数据加载中,请稍候...', component: "table", icon: "loading" });
529
512
  }
530
- return (_jsx(FormWidgetProvider, { "$widget": $widget, children: _jsx(FormLayoutProvider, { layout: layout, children: _jsx(FormTypeProvider, { formType: formType, children: _jsx(FormFieldProvider, { setFieldValue: setFieldValue, isInformContainer: isInformContainer, getFieldValue: getFieldValue, children: _jsx(FormUi, { layout: layout, className: cls, style: style, id: id, lgWidth: lgWidth, labelPosition: labelPosition, children: initValueFetchError ? (_jsx(StatusContent, { emptyText: '数据加载失败', errorObj: initValueFetchError, icon: 'error', isH5: isH5 })) : (contentSlot) }) }) }) }) }));
531
- });
513
+ return (_jsx(FormWidgetProvider, { "$widget": $widget, children: _jsx(FormLayoutProvider, { layout: layout, children: _jsx(FormTypeProvider, { formType: formType, children: _jsx(FormUi, { layout: layout, className: cls, style: style, id: id, lgWidth: lgWidth, labelPosition: labelPosition, children: initValueFetchError ? (_jsx(StatusContent, { emptyText: '数据加载失败', errorObj: initValueFetchError, icon: 'error', isH5: isH5 })) : (contentSlot) }) }) }) }));
514
+ }));
532
515
  export default React.memo(WdForm);
@@ -3,12 +3,16 @@ import type { CommonPropsType } from '../../types';
3
3
  import type { DataType as ObjDataType } from '../../../configs/components/wd-form-obj';
4
4
  import type { DataType as ArrDataType } from '../../../configs/components/wd-form-arr';
5
5
  import '../style';
6
- export declare const BaseFormObj: React.ForwardRefExoticComponent<BaseFormObjProps & React.RefAttributes<any>>;
6
+ export declare const BaseFormObj: React.ForwardRefExoticComponent<Pick<{
7
+ [key: string]: any;
8
+ initialValues?: any;
9
+ }, string | number> & React.RefAttributes<unknown>>;
7
10
  type DataType = ObjDataType & ArrDataType;
8
11
  export interface BaseFormObjProps extends CommonPropsType, DataType {
9
12
  disabled: boolean;
10
13
  readOnly: boolean;
11
14
  objType: 'arr' | 'obj';
12
15
  isRoot?: boolean;
16
+ isInformContainer?: boolean;
13
17
  }
14
18
  export {};
@@ -1,23 +1,24 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  /* eslint-disable @typescript-eslint/no-magic-numbers */
3
- import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
+ import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState, useMemo } from 'react';
4
4
  import { useDeepCompareEffect } from '@react-hookz/web';
5
5
  import { useConfig } from '../../utils/config-context';
6
6
  import { WdFormItem } from '../wd-form-item';
7
7
  import { usePlatform } from '../../utils/platform';
8
8
  import classNames from '../../utils/classnames';
9
9
  import { FormFieldObjProvider } from '../wd-form/contexts/form-field-obj-context';
10
- import { FormFieldProvider } from '../wd-form/contexts/form-field-context';
11
- import { noop, NOT_EXISTED_VALUE } from '../../utils/constant';
10
+ import { useFormField } from '../wd-form/contexts/form-field-context';
11
+ import { noop } from '../../utils/constant';
12
12
  import lodashSet from 'lodash.set';
13
- import lodashGet from 'lodash.get';
14
13
  import { useFormInputTrait } from '../form-input-hooks';
15
14
  import { deepClone } from '../../utils/tool';
16
15
  import isObjectEqual from '../../utils/isObjectEqual';
16
+ // eslint-disable-next-line tree-shaking/no-side-effects-in-initialization
17
+ import { withFormContainer } from '../wd-form/hoc/form-container-decorator';
17
18
  import '../style';
18
19
  import useDebouncedCallback from '../../utils/hooks/use-debounced-callback';
19
20
  const classRoot = 'form-obj';
20
- export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
21
+ export const BaseFormObj = withFormContainer(forwardRef(function BaseFormObj(props, ref) {
21
22
  const { classPrefix } = useConfig();
22
23
  const platform = usePlatform();
23
24
  const cls = classNames({
@@ -34,8 +35,9 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
34
35
  const [status, updateStatus] = useState('edit');
35
36
  const [innerHandle, setInnerHandle] = useState({});
36
37
  const inputRef = useRef({});
37
- const [isInformObjContainer, setIsInformObjContainer] = useState(false);
38
- const { name, value: objValue, readOnly, disabled, visible, onChange: _onChange, namePath, isInformContainer: _isInformContainer, } = useFormInputTrait({
38
+ const formField = useFormField();
39
+ const { setFormFieldsValue, formFieldsValue } = formField || {};
40
+ const { name, value: _objValue, readOnly, disabled, visible, onChange: _onChange, namePath, } = useFormInputTrait({
39
41
  label: props.label,
40
42
  value: props.value,
41
43
  name: props.name,
@@ -47,9 +49,10 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
47
49
  requiredMsg: '',
48
50
  $widget: props.$widget,
49
51
  setInnerHandle,
50
- onChange: noop,
52
+ onChange: props.isInformContainer ? noop : setFormFieldsValue,
51
53
  $node: props.$node,
52
54
  });
55
+ const objValue = useMemo(() => (props.isInformContainer ? _objValue : formFieldsValue), [_objValue, formFieldsValue, props.isInformContainer]);
53
56
  const valueRef = useRef(props.value);
54
57
  useDeepCompareEffect(() => {
55
58
  if (isObjectEqual(valueRef.current, objValue)) {
@@ -57,9 +60,6 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
57
60
  }
58
61
  triggerOnDataChange(objValue);
59
62
  }, [objValue]);
60
- useEffect(() => {
61
- setIsInformObjContainer(true);
62
- }, []);
63
63
  useEffect(() => {
64
64
  if (readOnly) {
65
65
  updateStatus('readOnly');
@@ -78,7 +78,7 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
78
78
  var _a, _b;
79
79
  valueRef.current = value;
80
80
  (_b = (_a = props.events) === null || _a === void 0 ? void 0 : _a.onDataChange) === null || _b === void 0 ? void 0 : _b.call(_a, { data: value });
81
- }, [props.events]), 500);
81
+ }, [props.events]), 250);
82
82
  const dealArrChange = useCallback((params, objValue) => {
83
83
  let value;
84
84
  // 顶层为数组类型
@@ -138,12 +138,13 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
138
138
  if (isObjectEqual(value, objValue) || (value === null && isObjectEqual(initValue, objValue))) {
139
139
  return;
140
140
  }
141
- _onChange(value || initValue);
142
- triggerOnDataChange(value);
143
- }, [disabled, readOnly, props.objType, objValue, _onChange, triggerOnDataChange, dealArrChange]);
141
+ if (_onChange) {
142
+ _onChange(value || initValue);
143
+ }
144
+ }, [disabled, readOnly, props.objType, objValue, _onChange, dealArrChange]);
144
145
  const changeDebounce = useDebouncedCallback(useCallback((value) => {
145
146
  change(value);
146
- }, [change]), 300);
147
+ }, [change]), 250);
147
148
  useLayoutEffect(() => {
148
149
  if (!ref)
149
150
  return;
@@ -187,25 +188,5 @@ export const BaseFormObj = forwardRef(function BaseFormObj(props, ref) {
187
188
  readOnly,
188
189
  };
189
190
  }, [innerHandle, props.label, name, objValue, visible, disabled, readOnly, props.objType, change, ref, changeDebounce]);
190
- const setFieldValue = useCallback(({ namePath, value }) => {
191
- change({ name: namePath, value });
192
- }, [change]);
193
- const getFieldValue = useCallback(({ namePath, initialValue }) => {
194
- const value = lodashGet(objValue, namePath, NOT_EXISTED_VALUE);
195
- if (value !== NOT_EXISTED_VALUE) {
196
- return value;
197
- }
198
- else {
199
- // 设置初始值,兼容表单项变量绑定场景
200
- // form的初始值>formArr/formObj/formDetail>field
201
- if (initialValue !== undefined) {
202
- return initialValue;
203
- }
204
- return null;
205
- }
206
- }, [objValue]);
207
- if (_isInformContainer) {
208
- return (_jsx(FormFieldObjProvider, { namePath: namePath, status: status, objType: props.objType, children: _jsx(WdFormItem, { ...formItemProps, children: _jsx("fieldset", { className: cls, id: props.id, style: props.style, role: "container", "data-testid": "formObj", children: props.children }) }) }));
209
- }
210
- return (_jsx(FormFieldProvider, { setFieldValue: setFieldValue, isInformContainer: isInformObjContainer, getFieldValue: getFieldValue, children: _jsx(FormFieldObjProvider, { namePath: namePath, status: status, children: _jsx(WdFormItem, { ...formItemProps, children: _jsx("fieldset", { className: cls, id: props.id, style: props.style, role: "container", "data-testid": "formObj", children: props.children }) }) }) }));
211
- });
191
+ return (_jsx(FormFieldObjProvider, { namePath: namePath, status: status, isChildField: props.isInformContainer, children: _jsx(WdFormItem, { ...formItemProps, children: _jsx("fieldset", { className: cls, id: props.id, style: props.style, role: "container", "data-testid": "formObj", children: props.children }) }) }));
192
+ }));
@@ -67,9 +67,11 @@ export declare const WdInput: React.ForwardRefExoticComponent<CommonPropsType &
67
67
  wrapClassName?: string;
68
68
  classRoot?: string;
69
69
  inputPattern?: RegExp;
70
+ isTagInput?: boolean;
70
71
  } & React.RefAttributes<any>>;
71
72
  export type WdInputProps = CommonPropsType & DataType & EventsType & {
72
73
  wrapClassName?: string;
73
74
  classRoot?: string;
74
75
  inputPattern?: RegExp;
76
+ isTagInput?: boolean;
75
77
  };