@rainbow-oh/yee-c 0.8.20 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/cjs/Form/Field.js +6 -6
  2. package/dist/cjs/Form/demo/async-validate.js +2 -2
  3. package/dist/cjs/Form/demo/field-status.d.ts +3 -0
  4. package/dist/cjs/Form/demo/field-status.js +116 -0
  5. package/dist/cjs/Form/demo/validate.js +2 -2
  6. package/dist/cjs/Form/form-store.d.ts +6 -1
  7. package/dist/cjs/Form/form-store.js +93 -8
  8. package/dist/cjs/Form/index.d.ts +1 -1
  9. package/dist/cjs/Form/interface.d.ts +26 -3
  10. package/dist/cjs/Form/style/index.less +26 -0
  11. package/dist/cjs/Form/utils/path.js +1 -1
  12. package/dist/cjs/TreeSelect/tree-select.js +14 -4
  13. package/dist/cjs/style/themes.css +1 -1
  14. package/dist/cjs/style/variables.css +1 -1
  15. package/dist/cjs/version.d.ts +1 -1
  16. package/dist/cjs/version.js +1 -1
  17. package/dist/esm/Form/Field.js +6 -6
  18. package/dist/esm/Form/demo/async-validate.js +2 -2
  19. package/dist/esm/Form/demo/field-status.d.ts +3 -0
  20. package/dist/esm/Form/demo/field-status.js +104 -0
  21. package/dist/esm/Form/demo/validate.js +2 -2
  22. package/dist/esm/Form/form-store.d.ts +6 -1
  23. package/dist/esm/Form/form-store.js +118 -13
  24. package/dist/esm/Form/hooks/useForm.js +0 -175
  25. package/dist/esm/Form/index.d.ts +1 -1
  26. package/dist/esm/Form/interface.d.ts +26 -3
  27. package/dist/esm/Form/style/index.less +26 -0
  28. package/dist/esm/Form/utils/path.js +2 -1
  29. package/dist/esm/TreeSelect/tree-select.js +20 -6
  30. package/dist/esm/style/themes.css +1 -1
  31. package/dist/esm/style/variables.css +1 -1
  32. package/dist/esm/version.d.ts +1 -1
  33. package/dist/esm/version.js +1 -1
  34. package/dist/umd/yee-c.min.css +1 -1
  35. package/dist/umd/yee-c.min.js +1 -1
  36. package/package.json +1 -1
  37. package/src/Form/Field.tsx +7 -8
  38. package/src/Form/demo/async-validate.tsx +3 -2
  39. package/src/Form/demo/field-status.tsx +108 -0
  40. package/src/Form/demo/validate.tsx +3 -2
  41. package/src/Form/form-store.test.ts +156 -0
  42. package/src/Form/form-store.ts +117 -8
  43. package/src/Form/hooks/useForm.ts +0 -175
  44. package/src/Form/index.en-US.md +93 -88
  45. package/src/Form/index.ts +3 -0
  46. package/src/Form/index.zh-CN.md +56 -51
  47. package/src/Form/interface.ts +28 -3
  48. package/src/Form/style/index.less +26 -0
  49. package/src/Form/utils/path.ts +2 -1
  50. package/src/TreeSelect/tree-select.tsx +21 -4
  51. package/src/version.ts +1 -1
@@ -0,0 +1,104 @@
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
+ import { Button, Form, Input, Space } from "../..";
8
+ import React, { useState } from 'react';
9
+ export default (function () {
10
+ var _Form$useForm = Form.useForm(),
11
+ _Form$useForm2 = _slicedToArray(_Form$useForm, 1),
12
+ form = _Form$useForm2[0];
13
+ var _useState = useState(null),
14
+ _useState2 = _slicedToArray(_useState, 2),
15
+ currentStatus = _useState2[0],
16
+ setCurrentStatus = _useState2[1];
17
+ var _useState3 = useState(''),
18
+ _useState4 = _slicedToArray(_useState3, 2),
19
+ submitResult = _useState4[0],
20
+ setSubmitResult = _useState4[1];
21
+ var applyStatus = function applyStatus(status) {
22
+ form.setFieldStatus('username', status);
23
+ setCurrentStatus(form.getFieldStatus('username'));
24
+ setSubmitResult('');
25
+ };
26
+ return /*#__PURE__*/React.createElement(Form, {
27
+ form: form,
28
+ initialValues: {
29
+ username: 'demo-user'
30
+ },
31
+ onFinish: function onFinish() {
32
+ return setSubmitResult('Submit succeeded');
33
+ },
34
+ onFinishFailed: function onFinishFailed() {
35
+ return setSubmitResult('Submit blocked by the blocking error');
36
+ }
37
+ }, /*#__PURE__*/React.createElement(Form.Field, {
38
+ name: "username",
39
+ label: "Username",
40
+ rules: [{
41
+ required: true,
42
+ message: 'Please input your username!'
43
+ }]
44
+ }, /*#__PURE__*/React.createElement(Input, {
45
+ placeholder: "Please input your username"
46
+ })), /*#__PURE__*/React.createElement(Space, {
47
+ style: {
48
+ marginTop: 28,
49
+ flexWrap: 'wrap'
50
+ }
51
+ }, /*#__PURE__*/React.createElement(Button, {
52
+ onClick: function onClick() {
53
+ return applyStatus({
54
+ status: 'error',
55
+ message: 'This username is unavailable'
56
+ });
57
+ }
58
+ }, "Error"), /*#__PURE__*/React.createElement(Button, {
59
+ onClick: function onClick() {
60
+ return applyStatus({
61
+ status: 'error',
62
+ message: 'This error prevents submission',
63
+ blocking: true
64
+ });
65
+ }
66
+ }, "Blocking error"), /*#__PURE__*/React.createElement(Button, {
67
+ onClick: function onClick() {
68
+ return applyStatus({
69
+ status: 'warning',
70
+ message: 'This username is commonly used'
71
+ });
72
+ }
73
+ }, "Warning"), /*#__PURE__*/React.createElement(Button, {
74
+ onClick: function onClick() {
75
+ return applyStatus({
76
+ status: 'success',
77
+ message: 'This username is available'
78
+ });
79
+ }
80
+ }, "Success"), /*#__PURE__*/React.createElement(Button, {
81
+ onClick: function onClick() {
82
+ return applyStatus({
83
+ status: 'info',
84
+ message: 'The username can be changed later'
85
+ });
86
+ }
87
+ }, "Info"), /*#__PURE__*/React.createElement(Button, {
88
+ onClick: function onClick() {
89
+ return applyStatus(null);
90
+ }
91
+ }, "Clear"), /*#__PURE__*/React.createElement(Button, {
92
+ type: "primary",
93
+ htmlType: "submit"
94
+ }, "Submit")), /*#__PURE__*/React.createElement("pre", {
95
+ style: {
96
+ marginTop: 16
97
+ }
98
+ }, "Current status: ", JSON.stringify(currentStatus, null, 2)), submitResult ? /*#__PURE__*/React.createElement("div", null, submitResult) : null, /*#__PURE__*/React.createElement("div", {
99
+ style: {
100
+ marginTop: 8,
101
+ color: '#999'
102
+ }
103
+ }, "Tip: set Success, then clear the input \u2014 the rule error takes display precedence over the manually set status."));
104
+ });
@@ -13,8 +13,8 @@ export default (function () {
13
13
  var onFinish = function onFinish(values) {
14
14
  console.log('Received values:', values);
15
15
  };
16
- var onFinishFailed = function onFinishFailed(errorInfo) {
17
- console.log('Failed:', errorInfo);
16
+ var onFinishFailed = function onFinishFailed(errors) {
17
+ console.log('Failed:', errors);
18
18
  };
19
19
  return /*#__PURE__*/React.createElement(Form, {
20
20
  form: form,
@@ -1,10 +1,11 @@
1
- import type { Callbacks, FieldEntity, FormInstance, FormListField, FormListOperation, GroupEntity, Name, NamePath, Store, TRIGGER, ValidateMessage } from './interface';
1
+ import type { Callbacks, FieldEntity, FieldStatusData, FormInstance, FormListField, FormListOperation, GroupEntity, Name, NamePath, Store, TRIGGER, ValidateMessage } from './interface';
2
2
  export declare class FormStore {
3
3
  private store;
4
4
  private callbacks;
5
5
  private fieldEntities;
6
6
  private fieldMap;
7
7
  private validateMessages;
8
+ private fieldStatuses;
8
9
  private initialized;
9
10
  private initialValues;
10
11
  private listKeyManagers;
@@ -23,6 +24,10 @@ export declare class FormStore {
23
24
  private getValueByPath;
24
25
  getFieldValue: (name: Name) => any;
25
26
  getFieldValidate: (name: Name) => ValidateMessage | null;
27
+ getFieldStatus: (name: NamePath) => FieldStatusData | null;
28
+ setFieldStatus: (name: NamePath, status: FieldStatusData | null) => void;
29
+ private deleteRelatedEntries;
30
+ private clearFieldStatuses;
26
31
  setFieldsValue: (newStore: Store, trigger?: TRIGGER) => void;
27
32
  resetFields: (name?: Name[]) => void;
28
33
  clearFields: (name?: Name[]) => void;
@@ -46,6 +46,7 @@ export var FormStore = /*#__PURE__*/function () {
46
46
  _defineProperty(this, "fieldEntities", []);
47
47
  _defineProperty(this, "fieldMap", new Map());
48
48
  _defineProperty(this, "validateMessages", new Map());
49
+ _defineProperty(this, "fieldStatuses", new Map());
49
50
  _defineProperty(this, "initialized", false);
50
51
  _defineProperty(this, "initialValues", {});
51
52
  // List key manager
@@ -109,10 +110,72 @@ export var FormStore = /*#__PURE__*/function () {
109
110
  }
110
111
  return null;
111
112
  });
113
+ _defineProperty(this, "getFieldStatus", function (name) {
114
+ var _this$validateMessage;
115
+ var normalizedName = stringifyPath(getNamePath(name));
116
+ var manualStatus = _this.fieldStatuses.get(normalizedName);
117
+ var validateMessage = (_this$validateMessage = _this.validateMessages.get(normalizedName)) === null || _this$validateMessage === void 0 ? void 0 : _this$validateMessage[0];
118
+
119
+ // Rule errors reflect the current value and auto-clear once validation
120
+ // passes, so they always take display precedence — a stale manually set
121
+ // status must never hide why submission failed.
122
+ if ((validateMessage === null || validateMessage === void 0 ? void 0 : validateMessage.status) === 'error') {
123
+ return {
124
+ status: 'error',
125
+ message: validateMessage.message
126
+ };
127
+ }
128
+ if (manualStatus) {
129
+ return _objectSpread({}, manualStatus);
130
+ }
131
+ if (validateMessage) {
132
+ return {
133
+ status: validateMessage.status,
134
+ message: validateMessage.message
135
+ };
136
+ }
137
+ return null;
138
+ });
139
+ _defineProperty(this, "setFieldStatus", function (name, status) {
140
+ var _this$fieldMap$get;
141
+ var normalizedName = stringifyPath(getNamePath(name));
142
+ if (!normalizedName) return;
143
+ if (status) {
144
+ _this.fieldStatuses.set(normalizedName, _objectSpread({}, status));
145
+ } else {
146
+ _this.fieldStatuses.delete(normalizedName);
147
+ }
148
+ (_this$fieldMap$get = _this.fieldMap.get(normalizedName)) === null || _this$fieldMap$get === void 0 || _this$fieldMap$get.onStoreChange();
149
+ });
150
+ // Delete entries whose key equals or nests under one of `names`
151
+ // (no names = delete all). Keeps rule messages and manual statuses in
152
+ // sync with the fields that reset/clear actually touched.
153
+ _defineProperty(this, "deleteRelatedEntries", function (entries, names) {
154
+ if (!names) {
155
+ entries.clear();
156
+ return;
157
+ }
158
+ var normalizedNames = names.map(function (name) {
159
+ return stringifyPath(getNamePath(name));
160
+ });
161
+ Array.from(entries.keys()).forEach(function (fieldName) {
162
+ if (normalizedNames.some(function (name) {
163
+ return isRelatedNamePath(fieldName, name);
164
+ })) {
165
+ entries.delete(fieldName);
166
+ }
167
+ });
168
+ });
169
+ _defineProperty(this, "clearFieldStatuses", function (names) {
170
+ _this.deleteRelatedEntries(_this.fieldStatuses, names);
171
+ });
112
172
  _defineProperty(this, "setFieldsValue", function (newStore) {
113
173
  var trigger = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'onChange';
114
174
  if (trigger === 'reset' || trigger === 'clear') {
115
- _this.store = newStore;
175
+ // 'reset' replaces the whole store; 'clear' merges the given keys
176
+ // (typically undefined) over the store so a partial clear never
177
+ // wipes values of unrelated fields.
178
+ _this.store = trigger === 'reset' ? newStore : _objectSpread(_objectSpread({}, _this.store), newStore);
116
179
  if (trigger === 'reset') {
117
180
  var _this$callbacks, _this$callbacks$onRes;
118
181
  (_this$callbacks = _this.callbacks) === null || _this$callbacks === void 0 || (_this$callbacks$onRes = _this$callbacks.onReset) === null || _this$callbacks$onRes === void 0 || _this$callbacks$onRes.call(_this$callbacks);
@@ -189,19 +252,43 @@ export var FormStore = /*#__PURE__*/function () {
189
252
  });
190
253
  }
191
254
  (_this$callbacks4 = _this.callbacks) === null || _this$callbacks4 === void 0 || (_this$callbacks4$onRe = _this$callbacks4.onReset) === null || _this$callbacks4$onRe === void 0 || _this$callbacks4$onRe.call(_this$callbacks4);
192
- _this.validateMessages.clear();
255
+ // A named reset only clears rule messages of the fields it touched;
256
+ // unrelated fields keep their (still valid) validation state.
257
+ _this.deleteRelatedEntries(_this.validateMessages, name);
258
+ _this.clearFieldStatuses(name);
193
259
  _this.groupEntities.forEach(function (entity) {
194
260
  return entity.reset();
195
261
  });
196
262
  _this.refreshField();
197
263
  });
198
264
  _defineProperty(this, "clearFields", function (name) {
265
+ var _this$callbacks5, _this$callbacks5$onCl;
199
266
  var names = name || Object.keys(_this.store);
200
- var clearStore = names.reduce(function (acc, name) {
201
- acc[name] = undefined;
202
- return acc;
203
- }, {});
204
- _this.setFieldsValue(clearStore, 'clear');
267
+
268
+ // Merge undefined over the current store (nested paths included) —
269
+ // unrelated fields keep their values.
270
+ var clearStore = _objectSpread({}, _this.store);
271
+ names.forEach(function (n) {
272
+ var parsedPath = parsePath(n);
273
+ if (parsedPath.length > 1) {
274
+ clearStore = setValueByPath(clearStore, parsedPath, undefined);
275
+ } else {
276
+ clearStore[n] = undefined;
277
+ }
278
+ });
279
+ _this.deleteRelatedEntries(_this.validateMessages, name);
280
+ _this.clearFieldStatuses(name);
281
+ _this.store = clearStore;
282
+ (_this$callbacks5 = _this.callbacks) === null || _this$callbacks5 === void 0 || (_this$callbacks5$onCl = _this$callbacks5.onClear) === null || _this$callbacks5$onCl === void 0 || _this$callbacks5$onCl.call(_this$callbacks5);
283
+
284
+ // clearStore carries the whole store (nested paths must materialize
285
+ // it), so derive the refresh scope from `names` — only cleared
286
+ // fields re-render, not the entire form.
287
+ _this.getRelatedFieldNames(names).forEach(function (fieldName) {
288
+ var _this$fieldMap$get2;
289
+ (_this$fieldMap$get2 = _this.fieldMap.get(fieldName)) === null || _this$fieldMap$get2 === void 0 || _this$fieldMap$get2.onStoreChange();
290
+ });
291
+ _this.notifyWatchers(names);
205
292
  });
206
293
  _defineProperty(this, "validateField", /*#__PURE__*/function () {
207
294
  var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(name, trigger) {
@@ -347,8 +434,8 @@ export var FormStore = /*#__PURE__*/function () {
347
434
  var changedKeys = Object.keys(newStore);
348
435
  var fieldNames = relatedFieldNames !== null && relatedFieldNames !== void 0 ? relatedFieldNames : _this.getRelatedFieldNames(changedKeys);
349
436
  fieldNames.forEach(function (fieldName) {
350
- var _this$fieldMap$get;
351
- (_this$fieldMap$get = _this.fieldMap.get(fieldName)) === null || _this$fieldMap$get === void 0 || _this$fieldMap$get.onStoreChange();
437
+ var _this$fieldMap$get3;
438
+ (_this$fieldMap$get3 = _this.fieldMap.get(fieldName)) === null || _this$fieldMap$get3 === void 0 || _this$fieldMap$get3.onStoreChange();
352
439
  });
353
440
  _this.notifyWatchers(changedKeys);
354
441
  } else {
@@ -577,11 +664,11 @@ export var FormStore = /*#__PURE__*/function () {
577
664
  };
578
665
  });
579
666
  _defineProperty(this, "submit", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
580
- var _this$callbacks5, onFinish, onFinishFailed, fieldErrors, groupErrors, allErrors;
667
+ var _this$callbacks6, onFinish, onFinishFailed, fieldErrors, groupErrors, statusErrors, allErrors;
581
668
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
582
669
  while (1) switch (_context4.prev = _context4.next) {
583
670
  case 0:
584
- _this$callbacks5 = _this.callbacks, onFinish = _this$callbacks5.onFinish, onFinishFailed = _this$callbacks5.onFinishFailed;
671
+ _this$callbacks6 = _this.callbacks, onFinish = _this$callbacks6.onFinish, onFinishFailed = _this$callbacks6.onFinishFailed;
585
672
  _context4.next = 3;
586
673
  return _this.validateFields();
587
674
  case 3:
@@ -590,7 +677,23 @@ export var FormStore = /*#__PURE__*/function () {
590
677
  return _this.validateGroups(true);
591
678
  case 6:
592
679
  groupErrors = _context4.sent;
593
- allErrors = [].concat(_toConsumableArray(fieldErrors), _toConsumableArray(groupErrors));
680
+ statusErrors = Array.from(_this.fieldStatuses.entries()).filter(function (_ref9) {
681
+ var _ref10 = _slicedToArray(_ref9, 2),
682
+ status = _ref10[1];
683
+ return status.status === 'error' && status.blocking === true;
684
+ }).map(function (_ref11) {
685
+ var _status$message;
686
+ var _ref12 = _slicedToArray(_ref11, 2),
687
+ name = _ref12[0],
688
+ status = _ref12[1];
689
+ return {
690
+ name: name,
691
+ message: (_status$message = status.message) !== null && _status$message !== void 0 ? _status$message : '',
692
+ value: _this.getFieldValue(name),
693
+ status: 'error'
694
+ };
695
+ });
696
+ allErrors = [].concat(_toConsumableArray(fieldErrors), _toConsumableArray(groupErrors), _toConsumableArray(statusErrors));
594
697
  if (allErrors.length === 0) {
595
698
  onFinish === null || onFinish === void 0 || onFinish(_this.getFieldsValue());
596
699
  } else {
@@ -598,7 +701,7 @@ export var FormStore = /*#__PURE__*/function () {
598
701
  }
599
702
  _this.refreshField();
600
703
  return _context4.abrupt("return", allErrors);
601
- case 11:
704
+ case 12:
602
705
  case "end":
603
706
  return _context4.stop();
604
707
  }
@@ -647,6 +750,8 @@ export var FormStore = /*#__PURE__*/function () {
647
750
  value: function getForm() {
648
751
  return {
649
752
  getFieldValidate: this.getFieldValidate,
753
+ getFieldStatus: this.getFieldStatus,
754
+ setFieldStatus: this.setFieldStatus,
650
755
  getFieldsValue: this.getFieldsValue,
651
756
  getFieldValue: this.getFieldValue,
652
757
  setFieldsValue: this.setFieldsValue,
@@ -1,178 +1,3 @@
1
- // import { useRef } from 'react';
2
- // import type {
3
- // Callbacks,
4
- // FieldEntity,
5
- // FormInstance,
6
- // NamePath,
7
- // Store,
8
- // validateMessage,
9
- // } from './interface';
10
- // import validate from './utils/validate';
11
-
12
- // class FormStore {
13
- // private store: Store = {};
14
- // private callbacks: Callbacks = {};
15
- // private fieldEntities: FieldEntity[] = [];
16
- // private validateMessages: validateMessage[] = [];
17
- // private initialized = false;
18
- // // 初始化form实例
19
- // initialize = ({
20
- // initialValues,
21
- // callbacks,
22
- // }: {
23
- // initialValues?: Store;
24
- // callbacks?: Callbacks;
25
- // }) => {
26
- // if (!this.initialized) {
27
- // this.initialized = true;
28
-
29
- // if (initialValues) {
30
- // this.store = initialValues;
31
- // } else {
32
- // this.store = {};
33
- // }
34
-
35
- // if (callbacks) {
36
- // this.setCallbacks(callbacks);
37
- // }
38
- // }
39
- // };
40
-
41
- // getFieldsValue = () => {
42
- // return { ...this.store };
43
- // };
44
-
45
- // getFieldValue = (name: NamePath) => {
46
- // return this.store[name];
47
- // };
48
-
49
- // getFieldValidate = (name: NamePath) => {
50
- // return this.validateMessages?.find((item) => item.name === name);
51
- // };
52
-
53
- // resetFields = (name?: NamePath[]) => {
54
- // if (name) {
55
- // name.forEach((n) => {
56
- // this.setFieldsValue({ [n]: undefined });
57
- // });
58
- // } else {
59
- // Object.keys(this.store).forEach((key) => {
60
- // this.setFieldsValue({ [key]: undefined });
61
- // });
62
- // }
63
- // };
64
-
65
- // validateFields = () => {
66
- // const err: validateMessage[] = [];
67
- // this.fieldEntities.forEach((entity) => {
68
- // const { name, rules, required } = entity.props;
69
- // const value: NamePath = name && this.getFieldValue(name);
70
-
71
- // const mergedRules = rules || [];
72
-
73
- // if (required) {
74
- // mergedRules.push({
75
- // required: true,
76
- // message: 'This is required field.',
77
- // });
78
- // }
79
-
80
- // mergedRules.forEach((rule) => {
81
- // const mark = validate(rule, value);
82
- // if (name && !mark) {
83
- // err.push({
84
- // name: name,
85
- // status: 'error',
86
- // value,
87
- // ...rule
88
- // });
89
- // }
90
- // });
91
- // });
92
- // return err;
93
- // };
94
-
95
- // setFieldsValue = (newStore: Store, isChange?: boolean) => {
96
- // // const { onValuesChange } = this.callbacks;
97
- // this.store = {
98
- // ...this.store,
99
- // ...newStore,
100
- // };
101
- // // onValuesChange?.(newStore, this.store);
102
- // this.refreshField(newStore, isChange);
103
- // };
104
-
105
- // refreshField = (newStore?: Store, isChange?: boolean) => {
106
- // if (newStore) {
107
- // this.fieldEntities.forEach((entity) => {
108
- // Object.keys(newStore).forEach((k) => {
109
- // if (k === entity.props.name) {
110
- // if (isChange) {
111
- // this.validateMessages = this.validateFields();
112
- // }
113
- // entity.onStoreChange();
114
- // }
115
- // });
116
- // });
117
- // } else {
118
- // this.fieldEntities.forEach((entity) => {
119
- // if (entity.props.rules || entity.props.required) {
120
- // entity?.onStoreChange();
121
- // }
122
- // });
123
- // }
124
- // };
125
-
126
- // setCallbacks = (callbacks: Callbacks) => {
127
- // this.callbacks = { ...this.callbacks, ...callbacks };
128
- // };
129
-
130
- // getCallbacks = () => {
131
- // return this.callbacks;
132
- // };
133
-
134
- // // 订阅与取消订阅
135
- // registerFieldEntities = (entity: FieldEntity) => {
136
- // this.fieldEntities.push(entity);
137
- // if (entity.props.name) {
138
- // this.store = { ...this.store, [entity.props.name]: undefined };
139
- // }
140
- // return () => {
141
- // this.fieldEntities = this.fieldEntities.filter((item) => item !== entity);
142
- // const { name } = entity.props;
143
- // if (name) {
144
- // delete this.store[name];
145
- // }
146
- // };
147
- // };
148
-
149
- // submit = () => {
150
- // const { onFinish, onFinishFailed } = this.callbacks;
151
- // this.validateMessages = this.validateFields();
152
- // if (this.validateMessages.length === 0) {
153
- // onFinish?.(this.getFieldsValue());
154
- // } else {
155
- // onFinishFailed?.(this.validateMessages);
156
- // }
157
- // this.refreshField();
158
- // };
159
-
160
- // getForm(): FormInstance {
161
- // return {
162
- // getFieldValidate: this.getFieldValidate,
163
- // getFieldsValue: this.getFieldsValue,
164
- // getFieldValue: this.getFieldValue,
165
- // setFieldsValue: this.setFieldsValue,
166
- // resetFields: this.resetFields,
167
- // submit: this.submit,
168
- // setCallbacks: this.setCallbacks,
169
- // getCallbacks: this.getCallbacks,
170
- // registerFieldEntities: this.registerFieldEntities,
171
- // initialize: this.initialize,
172
- // };
173
- // }
174
- // }
175
-
176
1
  import { useRef } from 'react';
177
2
  import { useLocale } from "../../locale";
178
3
  import { FormStore } from "../form-store";
@@ -16,5 +16,5 @@ type FormInterface = typeof InternalForm & {
16
16
  List: typeof List;
17
17
  };
18
18
  declare const Form: FormInterface;
19
- export type { FieldGroupProps, FormInstance, FormListProps, FormProps, } from './interface';
19
+ export type { FieldGroupProps, FieldStatus, FieldStatusData, FormInstance, FormListProps, FormProps, ValidateMessage, } from './interface';
20
20
  export default Form;
@@ -2,6 +2,11 @@
2
2
  import type { TooltipProps } from '../Tooltip';
3
3
  import type { DataAttributeProps } from '../utils/types';
4
4
  export type StoreValue = any;
5
+ /**
6
+ * Form values keyed by field name. Nested-path fields (e.g.
7
+ * name="user.name") hold their values in nested objects:
8
+ * `{ user: { name: 'tom' } }`
9
+ */
5
10
  export type Store = Record<string, StoreValue>;
6
11
  export type Name = string;
7
12
  export type NamePath = string | string[] | number | (string | number)[];
@@ -37,7 +42,9 @@ export interface FormProps<Values = any> extends DataAttributeProps {
37
42
  */
38
43
  disabled?: boolean;
39
44
  /**
40
- * Initial values
45
+ * Initial values, keyed by field name. Nested-path fields (e.g.
46
+ * name="user.name") take their values from nested objects:
47
+ * `{ user: { name: 'tom' } }`
41
48
  */
42
49
  initialValues?: Store;
43
50
  /**
@@ -81,7 +88,7 @@ export interface Callbacks<Values = any> {
81
88
  /**
82
89
  * Triggered on failed form submit
83
90
  * */
84
- onFinishFailed?: (err: Values) => void;
91
+ onFinishFailed?: (errors: ValidateMessage[]) => void;
85
92
  /**
86
93
  * Triggered on form reset
87
94
  * */
@@ -96,6 +103,15 @@ export interface FormInstance<Values = any> {
96
103
  * Get field validation info
97
104
  */
98
105
  getFieldValidate: (name: Name) => ValidateMessage | null;
106
+ /**
107
+ * Get the displayed field status. Rule validation errors take display
108
+ * precedence; otherwise a manually set status overrides validation.
109
+ */
110
+ getFieldStatus: (name: NamePath) => FieldStatusData | null;
111
+ /**
112
+ * Set or clear a field's displayed status. Pass null to clear it.
113
+ */
114
+ setFieldStatus: (name: NamePath, status: FieldStatusData | null) => void;
99
115
  /**
100
116
  * Get field value
101
117
  */
@@ -225,11 +241,18 @@ export type Rule = {
225
241
  */
226
242
  validateTrigger?: 'onBlur' | 'onChange' | 'onSubmit' | 'reset' | Array<'onBlur' | 'onChange' | 'onSubmit'>;
227
243
  };
244
+ export type FieldStatus = 'error' | 'success' | 'warning' | 'info';
245
+ export type FieldStatusData = {
246
+ status: FieldStatus;
247
+ message?: string;
248
+ /** Whether an error status should prevent form submission. */
249
+ blocking?: boolean;
250
+ };
228
251
  export type ValidateMessage = {
229
252
  name: NamePath | NamePath[] | undefined;
230
253
  message: string;
231
254
  value: unknown;
232
- status: 'error' | 'success' | 'warning' | 'info';
255
+ status: FieldStatus;
233
256
  };
234
257
  export type FieldConfigurableTooltip = Omit<TooltipProps, 'children'> & {
235
258
  /**
@@ -79,6 +79,18 @@
79
79
  &-error {
80
80
  color: var(--yee-error-color);
81
81
  }
82
+
83
+ &-warning {
84
+ color: var(--yee-warning-color);
85
+ }
86
+
87
+ &-success {
88
+ color: var(--yee-success-color);
89
+ }
90
+
91
+ &-info {
92
+ color: var(--yee-info-color);
93
+ }
82
94
  }
83
95
 
84
96
  // 表单校验态:在此重定义控件读取的 border / box-shadow 变量,
@@ -97,5 +109,19 @@
97
109
  --yee-input-focus-bs-color: var(--yee-warning-color-border);
98
110
  --yee-checkbox-border-color: var(--yee-warning-color);
99
111
  }
112
+
113
+ &&-success {
114
+ --yee-input-border-color: var(--yee-success-color);
115
+ --yee-input-hover-border-color: var(--yee-success-color-hover);
116
+ --yee-input-focus-bs-color: var(--yee-success-color-border);
117
+ --yee-checkbox-border-color: var(--yee-success-color);
118
+ }
119
+
120
+ &&-info {
121
+ --yee-input-border-color: var(--yee-info-color);
122
+ --yee-input-hover-border-color: var(--yee-info-color-hover);
123
+ --yee-input-focus-bs-color: var(--yee-info-color-border);
124
+ --yee-checkbox-border-color: var(--yee-info-color);
125
+ }
100
126
  }
101
127
  }
@@ -73,7 +73,8 @@ export function setValueByPath(store, path, value) {
73
73
  var current = newStore;
74
74
  for (var i = 0; i < path.length - 1; i++) {
75
75
  var key = String(path[i]);
76
- if (!(key in current)) {
76
+ // eslint-disable-next-line eqeqeq
77
+ if (current[key] == null) {
77
78
  // 根据下一个键的类型创建容器
78
79
  current[key] = typeof path[i + 1] === 'number' ? [] : {};
79
80
  }