@chenzy-design/core 0.3.1 → 0.4.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 (283) hide show
  1. package/dist/ai-chat-dialogue.d.ts +300 -0
  2. package/dist/ai-chat-dialogue.d.ts.map +1 -0
  3. package/dist/ai-chat-dialogue.js +699 -0
  4. package/dist/ai-chat-dialogue.js.map +1 -0
  5. package/dist/ai-chat-dialogue.test.d.ts +2 -0
  6. package/dist/ai-chat-dialogue.test.d.ts.map +1 -0
  7. package/dist/ai-chat-dialogue.test.js +338 -0
  8. package/dist/ai-chat-dialogue.test.js.map +1 -0
  9. package/dist/ai-chat-input.d.ts +191 -0
  10. package/dist/ai-chat-input.d.ts.map +1 -0
  11. package/dist/ai-chat-input.js +274 -0
  12. package/dist/ai-chat-input.js.map +1 -0
  13. package/dist/ai-chat-input.test.d.ts +2 -0
  14. package/dist/ai-chat-input.test.d.ts.map +1 -0
  15. package/dist/ai-chat-input.test.js +339 -0
  16. package/dist/ai-chat-input.test.js.map +1 -0
  17. package/dist/audio-player.d.ts +154 -0
  18. package/dist/audio-player.d.ts.map +1 -0
  19. package/dist/audio-player.js +254 -0
  20. package/dist/audio-player.js.map +1 -0
  21. package/dist/audio-player.test.d.ts +2 -0
  22. package/dist/audio-player.test.d.ts.map +1 -0
  23. package/dist/audio-player.test.js +275 -0
  24. package/dist/audio-player.test.js.map +1 -0
  25. package/dist/back-top.d.ts +4 -1
  26. package/dist/back-top.d.ts.map +1 -1
  27. package/dist/back-top.js +5 -2
  28. package/dist/back-top.js.map +1 -1
  29. package/dist/back-top.test.js +3 -2
  30. package/dist/back-top.test.js.map +1 -1
  31. package/dist/calendar.d.ts +132 -44
  32. package/dist/calendar.d.ts.map +1 -1
  33. package/dist/calendar.js +413 -70
  34. package/dist/calendar.js.map +1 -1
  35. package/dist/calendar.test.js +160 -76
  36. package/dist/calendar.test.js.map +1 -1
  37. package/dist/chat.d.ts +172 -0
  38. package/dist/chat.d.ts.map +1 -0
  39. package/dist/chat.js +210 -0
  40. package/dist/chat.js.map +1 -0
  41. package/dist/chat.test.d.ts +2 -0
  42. package/dist/chat.test.d.ts.map +1 -0
  43. package/dist/chat.test.js +181 -0
  44. package/dist/chat.test.js.map +1 -0
  45. package/dist/code-highlight.d.ts +30 -0
  46. package/dist/code-highlight.d.ts.map +1 -0
  47. package/dist/code-highlight.js +37 -0
  48. package/dist/code-highlight.js.map +1 -0
  49. package/dist/code-highlight.test.d.ts +2 -0
  50. package/dist/code-highlight.test.d.ts.map +1 -0
  51. package/dist/code-highlight.test.js +36 -0
  52. package/dist/code-highlight.test.js.map +1 -0
  53. package/dist/collapsible.d.ts +41 -0
  54. package/dist/collapsible.d.ts.map +1 -0
  55. package/dist/collapsible.js +33 -0
  56. package/dist/collapsible.js.map +1 -0
  57. package/dist/collapsible.test.d.ts +2 -0
  58. package/dist/collapsible.test.d.ts.map +1 -0
  59. package/dist/collapsible.test.js +57 -0
  60. package/dist/collapsible.test.js.map +1 -0
  61. package/dist/color-value.d.ts +60 -0
  62. package/dist/color-value.d.ts.map +1 -0
  63. package/dist/color-value.js +165 -0
  64. package/dist/color-value.js.map +1 -0
  65. package/dist/color-value.test.d.ts +2 -0
  66. package/dist/color-value.test.d.ts.map +1 -0
  67. package/dist/color-value.test.js +104 -0
  68. package/dist/color-value.test.js.map +1 -0
  69. package/dist/config-provider.d.ts +76 -37
  70. package/dist/config-provider.d.ts.map +1 -1
  71. package/dist/config-provider.js +107 -32
  72. package/dist/config-provider.js.map +1 -1
  73. package/dist/config-provider.test.js +123 -60
  74. package/dist/config-provider.test.js.map +1 -1
  75. package/dist/cropper.d.ts +164 -0
  76. package/dist/cropper.d.ts.map +1 -0
  77. package/dist/cropper.js +841 -0
  78. package/dist/cropper.js.map +1 -0
  79. package/dist/cropper.test.d.ts +2 -0
  80. package/dist/cropper.test.d.ts.map +1 -0
  81. package/dist/cropper.test.js +259 -0
  82. package/dist/cropper.test.js.map +1 -0
  83. package/dist/drag-move.d.ts +119 -0
  84. package/dist/drag-move.d.ts.map +1 -0
  85. package/dist/drag-move.js +237 -0
  86. package/dist/drag-move.js.map +1 -0
  87. package/dist/drag-move.test.d.ts +2 -0
  88. package/dist/drag-move.test.d.ts.map +1 -0
  89. package/dist/drag-move.test.js +304 -0
  90. package/dist/drag-move.test.js.map +1 -0
  91. package/dist/editable.d.ts +24 -4
  92. package/dist/editable.d.ts.map +1 -1
  93. package/dist/editable.js +18 -0
  94. package/dist/editable.js.map +1 -1
  95. package/dist/editable.test.js +55 -2
  96. package/dist/editable.test.js.map +1 -1
  97. package/dist/ellipsis.d.ts +13 -0
  98. package/dist/ellipsis.d.ts.map +1 -1
  99. package/dist/ellipsis.js +36 -0
  100. package/dist/ellipsis.js.map +1 -1
  101. package/dist/ellipsis.test.js +37 -1
  102. package/dist/ellipsis.test.js.map +1 -1
  103. package/dist/form-path.d.ts +19 -0
  104. package/dist/form-path.d.ts.map +1 -0
  105. package/dist/form-path.js +97 -0
  106. package/dist/form-path.js.map +1 -0
  107. package/dist/form-path.test.d.ts +2 -0
  108. package/dist/form-path.test.d.ts.map +1 -0
  109. package/dist/form-path.test.js +57 -0
  110. package/dist/form-path.test.js.map +1 -0
  111. package/dist/form-validate.d.ts +13 -0
  112. package/dist/form-validate.d.ts.map +1 -0
  113. package/dist/form-validate.js +204 -0
  114. package/dist/form-validate.js.map +1 -0
  115. package/dist/form.d.ts +91 -18
  116. package/dist/form.d.ts.map +1 -1
  117. package/dist/form.js +170 -115
  118. package/dist/form.js.map +1 -1
  119. package/dist/form.test.js +349 -76
  120. package/dist/form.test.js.map +1 -1
  121. package/dist/highlight.d.ts +42 -32
  122. package/dist/highlight.d.ts.map +1 -1
  123. package/dist/highlight.js +67 -41
  124. package/dist/highlight.js.map +1 -1
  125. package/dist/highlight.test.js +73 -32
  126. package/dist/highlight.test.js.map +1 -1
  127. package/dist/hotkeys.d.ts +151 -0
  128. package/dist/hotkeys.d.ts.map +1 -0
  129. package/dist/hotkeys.js +188 -0
  130. package/dist/hotkeys.js.map +1 -0
  131. package/dist/hotkeys.test.d.ts +2 -0
  132. package/dist/hotkeys.test.d.ts.map +1 -0
  133. package/dist/hotkeys.test.js +170 -0
  134. package/dist/hotkeys.test.js.map +1 -0
  135. package/dist/index.d.ts +33 -17
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/index.js +32 -13
  138. package/dist/index.js.map +1 -1
  139. package/dist/input.d.ts +34 -0
  140. package/dist/input.d.ts.map +1 -0
  141. package/dist/input.js +54 -0
  142. package/dist/input.js.map +1 -0
  143. package/dist/input.test.d.ts +2 -0
  144. package/dist/input.test.d.ts.map +1 -0
  145. package/dist/input.test.js +56 -0
  146. package/dist/input.test.js.map +1 -0
  147. package/dist/markdown-render.d.ts +49 -0
  148. package/dist/markdown-render.d.ts.map +1 -0
  149. package/dist/markdown-render.js +61 -0
  150. package/dist/markdown-render.js.map +1 -0
  151. package/dist/markdown-render.test.d.ts +2 -0
  152. package/dist/markdown-render.test.d.ts.map +1 -0
  153. package/dist/markdown-render.test.js +106 -0
  154. package/dist/markdown-render.test.js.map +1 -0
  155. package/dist/notification.d.ts +40 -31
  156. package/dist/notification.d.ts.map +1 -1
  157. package/dist/notification.js +86 -70
  158. package/dist/notification.js.map +1 -1
  159. package/dist/notification.test.js +62 -39
  160. package/dist/notification.test.js.map +1 -1
  161. package/dist/numeral.d.ts +32 -0
  162. package/dist/numeral.d.ts.map +1 -0
  163. package/dist/numeral.js +67 -0
  164. package/dist/numeral.js.map +1 -0
  165. package/dist/numeral.test.d.ts +2 -0
  166. package/dist/numeral.test.d.ts.map +1 -0
  167. package/dist/numeral.test.js +59 -0
  168. package/dist/numeral.test.js.map +1 -0
  169. package/dist/overflow-list.d.ts +9 -40
  170. package/dist/overflow-list.d.ts.map +1 -1
  171. package/dist/overflow-list.js +9 -70
  172. package/dist/overflow-list.js.map +1 -1
  173. package/dist/overflow-list.test.js +1 -122
  174. package/dist/overflow-list.test.js.map +1 -1
  175. package/dist/pagination.d.ts +17 -0
  176. package/dist/pagination.d.ts.map +1 -1
  177. package/dist/pagination.js +48 -0
  178. package/dist/pagination.js.map +1 -1
  179. package/dist/pagination.test.js +40 -1
  180. package/dist/pagination.test.js.map +1 -1
  181. package/dist/pincode.d.ts +79 -0
  182. package/dist/pincode.d.ts.map +1 -0
  183. package/dist/pincode.js +119 -0
  184. package/dist/pincode.js.map +1 -0
  185. package/dist/pincode.test.d.ts +2 -0
  186. package/dist/pincode.test.d.ts.map +1 -0
  187. package/dist/pincode.test.js +151 -0
  188. package/dist/pincode.test.js.map +1 -0
  189. package/dist/progress.d.ts +32 -30
  190. package/dist/progress.d.ts.map +1 -1
  191. package/dist/progress.js +257 -64
  192. package/dist/progress.js.map +1 -1
  193. package/dist/progress.test.js +50 -47
  194. package/dist/progress.test.js.map +1 -1
  195. package/dist/resizable.d.ts +200 -0
  196. package/dist/resizable.d.ts.map +1 -0
  197. package/dist/resizable.js +329 -0
  198. package/dist/resizable.js.map +1 -0
  199. package/dist/resizable.test.d.ts +2 -0
  200. package/dist/resizable.test.d.ts.map +1 -0
  201. package/dist/resizable.test.js +302 -0
  202. package/dist/resizable.test.js.map +1 -0
  203. package/dist/scroll-list.d.ts +69 -62
  204. package/dist/scroll-list.d.ts.map +1 -1
  205. package/dist/scroll-list.js +103 -144
  206. package/dist/scroll-list.js.map +1 -1
  207. package/dist/scroll-list.test.js +100 -110
  208. package/dist/scroll-list.test.js.map +1 -1
  209. package/dist/sidebar.d.ts +46 -0
  210. package/dist/sidebar.d.ts.map +1 -0
  211. package/dist/sidebar.js +65 -0
  212. package/dist/sidebar.js.map +1 -0
  213. package/dist/sidebar.test.d.ts +2 -0
  214. package/dist/sidebar.test.d.ts.map +1 -0
  215. package/dist/sidebar.test.js +88 -0
  216. package/dist/sidebar.test.js.map +1 -0
  217. package/dist/spin.d.ts +5 -5
  218. package/dist/spin.d.ts.map +1 -1
  219. package/dist/spin.js +13 -39
  220. package/dist/spin.js.map +1 -1
  221. package/dist/spin.test.js +2 -26
  222. package/dist/spin.test.js.map +1 -1
  223. package/dist/toast.d.ts +33 -30
  224. package/dist/toast.d.ts.map +1 -1
  225. package/dist/toast.js +77 -72
  226. package/dist/toast.js.map +1 -1
  227. package/dist/toast.test.js +63 -37
  228. package/dist/toast.test.js.map +1 -1
  229. package/dist/tree.d.ts +22 -5
  230. package/dist/tree.d.ts.map +1 -1
  231. package/dist/tree.js +61 -9
  232. package/dist/tree.js.map +1 -1
  233. package/dist/tree.test.js +72 -1
  234. package/dist/tree.test.js.map +1 -1
  235. package/dist/user-guide.d.ts +73 -0
  236. package/dist/user-guide.d.ts.map +1 -0
  237. package/dist/user-guide.js +95 -0
  238. package/dist/user-guide.js.map +1 -0
  239. package/dist/user-guide.test.d.ts +2 -0
  240. package/dist/user-guide.test.d.ts.map +1 -0
  241. package/dist/user-guide.test.js +109 -0
  242. package/dist/user-guide.test.js.map +1 -0
  243. package/dist/video-player.d.ts +196 -0
  244. package/dist/video-player.d.ts.map +1 -0
  245. package/dist/video-player.js +461 -0
  246. package/dist/video-player.js.map +1 -0
  247. package/dist/video-player.test.d.ts +2 -0
  248. package/dist/video-player.test.d.ts.map +1 -0
  249. package/dist/video-player.test.js +435 -0
  250. package/dist/video-player.test.js.map +1 -0
  251. package/package.json +17 -1
  252. package/dist/banner.d.ts +0 -19
  253. package/dist/banner.d.ts.map +0 -1
  254. package/dist/banner.js +0 -20
  255. package/dist/banner.js.map +0 -1
  256. package/dist/banner.test.d.ts +0 -2
  257. package/dist/banner.test.d.ts.map +0 -1
  258. package/dist/banner.test.js +0 -29
  259. package/dist/banner.test.js.map +0 -1
  260. package/dist/breakpoints.d.ts +0 -30
  261. package/dist/breakpoints.d.ts.map +0 -1
  262. package/dist/breakpoints.js +0 -45
  263. package/dist/breakpoints.js.map +0 -1
  264. package/dist/breakpoints.test.d.ts +0 -2
  265. package/dist/breakpoints.test.d.ts.map +0 -1
  266. package/dist/breakpoints.test.js +0 -46
  267. package/dist/breakpoints.test.js.map +0 -1
  268. package/dist/lottie-icon.d.ts +0 -88
  269. package/dist/lottie-icon.d.ts.map +0 -1
  270. package/dist/lottie-icon.js +0 -84
  271. package/dist/lottie-icon.js.map +0 -1
  272. package/dist/lottie-icon.test.d.ts +0 -2
  273. package/dist/lottie-icon.test.d.ts.map +0 -1
  274. package/dist/lottie-icon.test.js +0 -88
  275. package/dist/lottie-icon.test.js.map +0 -1
  276. package/dist/sider.d.ts +0 -26
  277. package/dist/sider.d.ts.map +0 -1
  278. package/dist/sider.js +0 -55
  279. package/dist/sider.js.map +0 -1
  280. package/dist/sider.test.d.ts +0 -2
  281. package/dist/sider.test.d.ts.map +0 -1
  282. package/dist/sider.test.js +0 -29
  283. package/dist/sider.test.js.map +0 -1
package/dist/form.test.js CHANGED
@@ -4,31 +4,31 @@ describe('createForm', () => {
4
4
  it('registers fields and reads/writes values', () => {
5
5
  const f = createForm({ initialValues: { name: 'a' } });
6
6
  f.registerField('name', { label: 'Name' });
7
- expect(f.getFieldValue('name')).toBe('a');
8
- f.setFieldValue('name', 'b');
9
- expect(f.getFieldValue('name')).toBe('b');
7
+ expect(f.getValue('name')).toBe('a');
8
+ f.setValue('name', 'b');
9
+ expect(f.getValue('name')).toBe('b');
10
10
  });
11
11
  it('required rule fails on empty, passes when filled', async () => {
12
12
  const f = createForm();
13
13
  f.registerField('email', { label: 'Email', rules: [{ required: true }] });
14
14
  expect(await f.validateField('email')).toBeTruthy();
15
- f.setFieldValue('email', 'x@y.com');
15
+ f.setValue('email', 'x@y.com');
16
16
  expect(await f.validateField('email')).toBeUndefined();
17
17
  });
18
18
  it('email type rule rejects malformed input', async () => {
19
19
  const f = createForm();
20
20
  f.registerField('email', { rules: [{ type: 'email' }] });
21
- f.setFieldValue('email', 'nope');
21
+ f.setValue('email', 'nope');
22
22
  expect(await f.validateField('email')).toBeTruthy();
23
- f.setFieldValue('email', 'a@b.co');
23
+ f.setValue('email', 'a@b.co');
24
24
  expect(await f.validateField('email')).toBeUndefined();
25
25
  });
26
26
  it('min/max/length rules', async () => {
27
27
  const f = createForm();
28
28
  f.registerField('age', { rules: [{ min: 18, max: 60 }] });
29
- f.setFieldValue('age', 10);
29
+ f.setValue('age', 10);
30
30
  expect(await f.validateField('age')).toBeTruthy();
31
- f.setFieldValue('age', 30);
31
+ f.setValue('age', 30);
32
32
  expect(await f.validateField('age')).toBeUndefined();
33
33
  });
34
34
  it('async validator latest-wins (race token discard)', async () => {
@@ -47,32 +47,32 @@ describe('createForm', () => {
47
47
  },
48
48
  ],
49
49
  });
50
- f.setFieldValue('u', 'first');
50
+ f.setValue('u', 'first');
51
51
  const p1 = f.validateField('u');
52
52
  const p2 = f.validateField('u'); // supersedes
53
53
  await p2;
54
54
  resolveFirst?.('stale error'); // late first result must be discarded
55
55
  await p1;
56
- expect(f.getFieldError('u')).toBeUndefined();
56
+ expect(f.getError('u')).toBeUndefined();
57
57
  });
58
- it('resetFields restores initial values and clears errors', async () => {
58
+ it('reset restores initial values and clears errors', async () => {
59
59
  const f = createForm({ initialValues: { name: 'init' } });
60
60
  f.registerField('name', { rules: [{ required: true }] });
61
- f.setFieldValue('name', '');
61
+ f.setValue('name', '');
62
62
  await f.validateField('name');
63
- expect(f.getFieldError('name')).toBeTruthy();
64
- f.resetFields();
65
- expect(f.getFieldValue('name')).toBe('init');
66
- expect(f.getFieldError('name')).toBeUndefined();
63
+ expect(f.getError('name')).toBeTruthy();
64
+ f.reset();
65
+ expect(f.getValue('name')).toBe('init');
66
+ expect(f.getError('name')).toBeUndefined();
67
67
  });
68
68
  it('submit reports validity and increments submitCount', async () => {
69
69
  const f = createForm();
70
70
  f.registerField('name', { rules: [{ required: true }] });
71
- const r1 = await f.submit();
71
+ const r1 = await f.submitForm();
72
72
  expect(r1.valid).toBe(false);
73
- expect(f.getState().submitCount).toBe(1);
74
- f.setFieldValue('name', 'ok');
75
- const r2 = await f.submit();
73
+ expect(f.getFormState().submitCount).toBe(1);
74
+ f.setValue('name', 'ok');
75
+ const r2 = await f.submitForm();
76
76
  expect(r2.valid).toBe(true);
77
77
  expect(r2.values).toEqual({ name: 'ok' });
78
78
  });
@@ -87,18 +87,19 @@ describe('createForm', () => {
87
87
  },
88
88
  ],
89
89
  });
90
- f.setFieldValue('password', 'aaa');
91
- f.setFieldValue('confirm', 'bbb');
90
+ f.setValue('password', 'aaa');
91
+ f.setValue('confirm', 'bbb');
92
92
  await f.validateField('confirm');
93
- expect(f.getFieldError('confirm')).toBe('mismatch');
93
+ expect(f.getError('confirm')).toBe('mismatch');
94
94
  // changing password automatically re-validates the dependent confirm (which
95
95
  // is "active" because it already shows an error). The error clears once the
96
96
  // values match — note we do NOT validate the password field itself here.
97
- f.setFieldValue('password', 'bbb');
98
- // allow the scheduled (async) dependent validation to settle
99
- await Promise.resolve();
100
- await Promise.resolve();
101
- expect(f.getFieldError('confirm')).toBeUndefined();
97
+ f.setValue('password', 'bbb');
98
+ // allow the scheduled (async) dependent validation to settle. The engine now
99
+ // runs through async-validator (Promise-based), so it needs a real task tick
100
+ // rather than a couple of microtasks.
101
+ await new Promise((r) => setTimeout(r, 0));
102
+ expect(f.getError('confirm')).toBeUndefined();
102
103
  });
103
104
  it('dependencies: untouched/error-free dependent is not eagerly validated', async () => {
104
105
  const f = createForm();
@@ -108,33 +109,33 @@ describe('createForm', () => {
108
109
  rules: [{ validator: (v, values) => (v === values.password ? undefined : 'mismatch') }],
109
110
  });
110
111
  // confirm has neither been touched nor shows an error → must stay clean
111
- f.setFieldValue('password', 'x', { validate: true });
112
+ f.setValue('password', 'x', { validate: true });
112
113
  await Promise.resolve();
113
- expect(f.getFieldError('confirm')).toBeUndefined();
114
+ expect(f.getError('confirm')).toBeUndefined();
114
115
  });
115
116
  it('warningOnly rule produces a warning, not an error, and does not block submit', async () => {
116
117
  const f = createForm();
117
118
  f.registerField('name', {
118
119
  rules: [{ minLength: 5, warningOnly: true, message: 'too short' }],
119
120
  });
120
- f.setFieldValue('name', 'ab');
121
+ f.setValue('name', 'ab');
121
122
  const err = await f.validateField('name');
122
123
  // warningOnly never surfaces as a blocking error
123
124
  expect(err).toBeUndefined();
124
- expect(f.getFieldError('name')).toBeUndefined();
125
+ expect(f.getError('name')).toBeUndefined();
125
126
  expect(f.getFieldWarning('name')).toBe('too short');
126
127
  // submit must still be valid despite the standing warning
127
- const r = await f.submit();
128
+ const r = await f.submitForm();
128
129
  expect(r.valid).toBe(true);
129
130
  expect(f.getFieldWarning('name')).toBe('too short');
130
131
  });
131
132
  it('warning clears once the warningOnly rule passes', async () => {
132
133
  const f = createForm();
133
134
  f.registerField('name', { rules: [{ minLength: 5, warningOnly: true, message: 'w' }] });
134
- f.setFieldValue('name', 'ab');
135
+ f.setValue('name', 'ab');
135
136
  await f.validateField('name');
136
137
  expect(f.getFieldWarning('name')).toBe('w');
137
- f.setFieldValue('name', 'abcdef');
138
+ f.setValue('name', 'abcdef');
138
139
  await f.validateField('name');
139
140
  expect(f.getFieldWarning('name')).toBeUndefined();
140
141
  });
@@ -146,11 +147,11 @@ describe('createForm', () => {
146
147
  { required: true, message: 'err' },
147
148
  ],
148
149
  });
149
- f.setFieldValue('name', '');
150
+ f.setValue('name', '');
150
151
  const err = await f.validateField('name');
151
152
  expect(err).toBe('err');
152
- expect(f.getFieldError('name')).toBe('err');
153
- const r = await f.submit();
153
+ expect(f.getError('name')).toBe('err');
154
+ const r = await f.submitForm();
154
155
  expect(r.valid).toBe(false);
155
156
  });
156
157
  it('validating flag is set during async validation and cleared after', async () => {
@@ -159,21 +160,21 @@ describe('createForm', () => {
159
160
  f.registerField('u', {
160
161
  rules: [{ validator: () => new Promise((r) => (resolveV = r)) }],
161
162
  });
162
- f.setFieldValue('u', 'x');
163
+ f.setValue('u', 'x');
163
164
  const p = f.validateField('u');
164
165
  // synchronously after kicking off: the field is marked validating
165
- expect(f.getState().validating.u).toBe(true);
166
+ expect(f.getFormState().validating.u).toBe(true);
166
167
  resolveV?.(undefined);
167
168
  await p;
168
- expect(f.getState().validating.u).toBe(false);
169
+ expect(f.getFormState().validating.u).toBe(false);
169
170
  });
170
- it('resetFields clears warnings too', async () => {
171
+ it('reset clears warnings too', async () => {
171
172
  const f = createForm();
172
173
  f.registerField('name', { rules: [{ minLength: 5, warningOnly: true, message: 'w' }] });
173
- f.setFieldValue('name', 'ab');
174
+ f.setValue('name', 'ab');
174
175
  await f.validateField('name');
175
176
  expect(f.getFieldWarning('name')).toBe('w');
176
- f.resetFields();
177
+ f.reset();
177
178
  expect(f.getFieldWarning('name')).toBeUndefined();
178
179
  });
179
180
  // ---- validateTrigger (spec §4 L65 / L84) ----
@@ -207,7 +208,7 @@ describe('createForm', () => {
207
208
  { validator: () => (calls.push('r2'), 'second') },
208
209
  ],
209
210
  });
210
- f.setFieldValue('x', 'v');
211
+ f.setValue('x', 'v');
211
212
  const err = await f.validateField('x');
212
213
  expect(err).toBe('first');
213
214
  // both rules ran because we did NOT stop at the first error
@@ -222,7 +223,7 @@ describe('createForm', () => {
222
223
  { validator: () => (calls.push('r2'), 'second') },
223
224
  ],
224
225
  });
225
- f.setFieldValue('x', 'v');
226
+ f.setValue('x', 'v');
226
227
  const err = await f.validateField('x');
227
228
  expect(err).toBe('first');
228
229
  // second rule never ran
@@ -236,88 +237,360 @@ describe('createForm', () => {
236
237
  { minLength: 5, warningOnly: true, message: 'warn' },
237
238
  ],
238
239
  });
239
- f.setFieldValue('x', '');
240
+ f.setValue('x', '');
240
241
  await f.validateField('x');
241
- expect(f.getFieldError('x')).toBe('err');
242
+ expect(f.getError('x')).toBe('err');
242
243
  // empty value skips minLength, so no warning here — sanity that error wins
243
- f.setFieldValue('x', 'ab');
244
+ f.setValue('x', 'ab');
244
245
  await f.validateField('x');
245
246
  // 'ab' passes required, fails minLength → warning surfaces
246
- expect(f.getFieldError('x')).toBeUndefined();
247
+ expect(f.getError('x')).toBeUndefined();
247
248
  expect(f.getFieldWarning('x')).toBe('warn');
248
249
  });
249
250
  // ---- allowEmpty (spec §4 L70) ----
250
- it('allowEmpty:false (default) drops empty-value keys on submit/getFieldsValue', async () => {
251
+ it('allowEmpty:false (default) drops empty-value keys on submit/getValues', async () => {
251
252
  const f = createForm();
252
253
  f.registerField('name', {});
253
254
  f.registerField('bio', {});
254
- f.setFieldValue('name', 'jo');
255
- f.setFieldValue('bio', '');
256
- expect(f.getFieldsValue()).toEqual({ name: 'jo' });
257
- const r = await f.submit();
255
+ f.setValue('name', 'jo');
256
+ f.setValue('bio', '');
257
+ expect(f.getValues()).toEqual({ name: 'jo' });
258
+ const r = await f.submitForm();
258
259
  expect(r.values).toEqual({ name: 'jo' });
259
260
  });
260
261
  it('allowEmpty:true keeps empty-value keys', async () => {
261
262
  const f = createForm({ allowEmpty: true });
262
263
  f.registerField('name', {});
263
264
  f.registerField('bio', {});
264
- f.setFieldValue('name', 'jo');
265
- f.setFieldValue('bio', '');
266
- expect(f.getFieldsValue()).toEqual({ name: 'jo', bio: '' });
267
- const r = await f.submit();
265
+ f.setValue('name', 'jo');
266
+ f.setValue('bio', '');
267
+ expect(f.getValues()).toEqual({ name: 'jo', bio: '' });
268
+ const r = await f.submitForm();
268
269
  expect(r.values).toEqual({ name: 'jo', bio: '' });
269
270
  });
270
271
  // ---- field-level initialValue (spec §4.2 L79) ----
271
272
  it('registerField initialValue seeds the field value (field-level init)', () => {
272
273
  const f = createForm();
273
274
  f.registerField('plan', { initialValue: 'pro' });
274
- expect(f.getFieldValue('plan')).toBe('pro');
275
- expect(f.getFieldsValue()).toEqual({ plan: 'pro' });
275
+ expect(f.getValue('plan')).toBe('pro');
276
+ expect(f.getValues()).toEqual({ plan: 'pro' });
276
277
  });
277
278
  it('container initialValues take precedence over field initialValue', () => {
278
279
  const f = createForm({ initialValues: { plan: 'team' } });
279
280
  f.registerField('plan', { initialValue: 'pro' });
280
281
  // container already supplied a value → field init does not clobber it
281
- expect(f.getFieldValue('plan')).toBe('team');
282
+ expect(f.getValue('plan')).toBe('team');
282
283
  });
283
- it('resetFields restores the field-level initialValue', () => {
284
+ it('reset restores the field-level initialValue', () => {
284
285
  const f = createForm();
285
286
  f.registerField('plan', { initialValue: 'pro' });
286
- f.setFieldValue('plan', 'free');
287
- expect(f.getFieldValue('plan')).toBe('free');
288
- f.resetFields();
289
- expect(f.getFieldValue('plan')).toBe('pro');
287
+ f.setValue('plan', 'free');
288
+ expect(f.getValue('plan')).toBe('free');
289
+ f.reset();
290
+ expect(f.getValue('plan')).toBe('pro');
290
291
  });
291
292
  // ---- field-level transform (spec §4.2 L88) ----
292
293
  it('transform converts the value on collect/submit without mutating state', async () => {
293
294
  const f = createForm();
294
295
  f.registerField('tags', { transform: (v) => String(v).split(',').map((s) => s.trim()) });
295
- f.setFieldValue('tags', 'a, b , c');
296
+ f.setValue('tags', 'a, b , c');
296
297
  // live state keeps the raw string (red line #2: pure transform, no write-back)
297
- expect(f.getFieldValue('tags')).toBe('a, b , c');
298
- expect(f.getFieldsValue()).toEqual({ tags: ['a', 'b', 'c'] });
299
- const r = await f.submit();
298
+ expect(f.getValue('tags')).toBe('a, b , c');
299
+ expect(f.getValues()).toEqual({ tags: ['a', 'b', 'c'] });
300
+ const r = await f.submitForm();
300
301
  expect(r.values).toEqual({ tags: ['a', 'b', 'c'] });
301
302
  });
302
303
  it('transform receives sibling values and runs over emptiable input', async () => {
303
304
  const f = createForm({ allowEmpty: true });
304
305
  f.registerField('a', {});
305
306
  f.registerField('full', { transform: (_v, values) => `${values.a}!` });
306
- f.setFieldValue('a', 'hi');
307
- f.setFieldValue('full', '');
308
- expect(f.getFieldsValue()).toEqual({ a: 'hi', full: 'hi!' });
307
+ f.setValue('a', 'hi');
308
+ f.setValue('full', '');
309
+ expect(f.getValues()).toEqual({ a: 'hi', full: 'hi!' });
309
310
  });
310
311
  it('subscribe notifies on changes', () => {
311
312
  const f = createForm();
312
313
  f.registerField('x');
313
314
  let count = 0;
314
315
  const unsub = f.subscribe(() => (count += 1));
315
- f.setFieldValue('x', 1);
316
+ f.setValue('x', 1);
316
317
  expect(count).toBeGreaterThan(0);
317
318
  unsub();
318
319
  const before = count;
319
- f.setFieldValue('x', 2);
320
+ f.setValue('x', 2);
320
321
  expect(count).toBe(before);
321
322
  });
323
+ // ---- Semi bare-name additions (批C-A) ----
324
+ it('getValue() with no arg returns a snapshot of all values', () => {
325
+ const f = createForm({ initialValues: { a: 1, b: 2 } });
326
+ expect(f.getValue()).toEqual({ a: 1, b: 2 });
327
+ // snapshot is a copy — mutating it must not affect form state
328
+ f.getValue().a = 99;
329
+ expect(f.getValue('a')).toBe(1);
330
+ });
331
+ it('getError() with no arg returns the whole errors map', async () => {
332
+ const f = createForm();
333
+ f.registerField('name', { rules: [{ required: true }] });
334
+ await f.validateField('name');
335
+ expect(f.getError()).toEqual(f.getFormState().errors);
336
+ expect(f.getError('name')).toBeTruthy();
337
+ });
338
+ it('setError imperatively sets a field error', () => {
339
+ const f = createForm();
340
+ f.registerField('name', {});
341
+ f.setError('name', 'server says no');
342
+ expect(f.getError('name')).toBe('server says no');
343
+ f.setError('name', undefined);
344
+ expect(f.getError('name')).toBeUndefined();
345
+ });
346
+ it('getFieldExist reflects registration and cleanup', () => {
347
+ const f = createForm();
348
+ expect(f.getFieldExist('name')).toBe(false);
349
+ const unregister = f.registerField('name', {});
350
+ expect(f.getFieldExist('name')).toBe(true);
351
+ unregister();
352
+ expect(f.getFieldExist('name')).toBe(false);
353
+ });
354
+ it('getInitValue / getInitValues expose initial values', () => {
355
+ const f = createForm({ initialValues: { a: 1 } });
356
+ f.registerField('b', { initialValue: 2 });
357
+ expect(f.getInitValue('a')).toBe(1);
358
+ expect(f.getInitValue('b')).toBe(2);
359
+ expect(f.getInitValue('missing')).toBeUndefined();
360
+ expect(f.getInitValue()).toEqual({ a: 1, b: 2 });
361
+ expect(f.getInitValues()).toEqual({ a: 1, b: 2 });
362
+ // changing a live value must not affect the init snapshot
363
+ f.setValue('a', 9);
364
+ expect(f.getInitValue('a')).toBe(1);
365
+ });
366
+ it('reset(fields) resets only the targeted fields', async () => {
367
+ const f = createForm({ initialValues: { a: 'a0', b: 'b0' } });
368
+ f.registerField('a', { rules: [{ required: true }] });
369
+ f.registerField('b', { rules: [{ required: true }] });
370
+ f.setValue('a', '');
371
+ f.setValue('b', '');
372
+ await f.validate();
373
+ expect(f.getError('a')).toBeTruthy();
374
+ expect(f.getError('b')).toBeTruthy();
375
+ f.reset(['a']);
376
+ // only `a` fell back to its initial value and lost its error
377
+ expect(f.getValue('a')).toBe('a0');
378
+ expect(f.getError('a')).toBeUndefined();
379
+ // `b` is untouched by the partial reset
380
+ expect(f.getValue('b')).toBe('');
381
+ expect(f.getError('b')).toBeTruthy();
382
+ });
383
+ it('reset(fields) drops a field that has no initial value', () => {
384
+ const f = createForm();
385
+ f.registerField('a', {});
386
+ f.setValue('a', 'x');
387
+ f.reset(['a']);
388
+ expect(f.getValue('a')).toBeUndefined();
389
+ expect(Object.prototype.hasOwnProperty.call(f.getValue(), 'a')).toBe(false);
390
+ });
391
+ it('setValues merges by default, replaces with isOverride', () => {
392
+ const f = createForm({ initialValues: { a: 1, b: 2 } });
393
+ f.setValues({ b: 20 });
394
+ expect(f.getValue()).toEqual({ a: 1, b: 20 });
395
+ f.setValues({ c: 3 }, { isOverride: true });
396
+ expect(f.getValue()).toEqual({ c: 3 });
397
+ });
398
+ // ---- 批C-E: real nested-array paths (lodash path, Semi-aligned) ----
399
+ it('getValue/setValue address nested array paths (users[0].name)', () => {
400
+ const f = createForm();
401
+ f.setValue('users[0].name', 'ada');
402
+ f.setValue('users[0].age', 30);
403
+ f.setValue('users[1].name', 'bob');
404
+ // reads resolve nested paths
405
+ expect(f.getValue('users[0].name')).toBe('ada');
406
+ expect(f.getValue('users[1].name')).toBe('bob');
407
+ // the underlying tree is a REAL array of objects, not flat keys
408
+ expect(f.getValue('users')).toEqual([
409
+ { name: 'ada', age: 30 },
410
+ { name: 'bob' },
411
+ ]);
412
+ // no flat string keys leaked
413
+ const all = f.getValue();
414
+ expect(Object.keys(all)).toEqual(['users']);
415
+ expect(Array.isArray(all.users)).toBe(true);
416
+ });
417
+ it('setValue does not mutate the previous values tree (immutable)', () => {
418
+ const f = createForm();
419
+ f.setValue('a.b', 1);
420
+ const before = f.getFormState().values;
421
+ f.setValue('a.c', 2);
422
+ const after = f.getFormState().values;
423
+ // fresh root reference so Svelte subscribers see the change
424
+ expect(after).not.toBe(before);
425
+ expect(f.getValue('a')).toEqual({ b: 1, c: 2 });
426
+ });
427
+ it('collectValues rebuilds a nested array structure from registered fields', () => {
428
+ const f = createForm();
429
+ f.registerField('users[0].name', {});
430
+ f.registerField('users[0].age', {});
431
+ f.registerField('users[1].name', {});
432
+ f.setValue('users[0].name', 'ada');
433
+ f.setValue('users[0].age', 42);
434
+ f.setValue('users[1].name', 'bob');
435
+ // getValues returns a real nested array — the core Semi-alignment point
436
+ expect(f.getValues()).toEqual({
437
+ users: [
438
+ { name: 'ada', age: 42 },
439
+ { name: 'bob' },
440
+ ],
441
+ });
442
+ });
443
+ it('nested-path field validates and reads value by path', async () => {
444
+ const f = createForm();
445
+ f.registerField('users[0].name', { label: 'Name', rules: [{ required: true }] });
446
+ expect(await f.validateField('users[0].name')).toBeTruthy();
447
+ f.setValue('users[0].name', 'ada');
448
+ expect(await f.validateField('users[0].name')).toBeUndefined();
449
+ });
450
+ it('nested initialValues seed nested reads and reset restores them', () => {
451
+ const f = createForm({ initialValues: { users: [{ name: 'seed' }] } });
452
+ expect(f.getValue('users[0].name')).toBe('seed');
453
+ f.setValue('users[0].name', 'changed');
454
+ expect(f.getValue('users[0].name')).toBe('changed');
455
+ f.reset();
456
+ expect(f.getValue('users[0].name')).toBe('seed');
457
+ // initial snapshot never aliased the mutated live tree
458
+ expect(f.getInitValue('users[0].name')).toBe('seed');
459
+ });
460
+ // ---- 批C-E: async-validator-specific rules ----
461
+ it('type=array rule (async-validator) rejects non-arrays', async () => {
462
+ const f = createForm();
463
+ f.registerField('tags', { rules: [{ type: 'array', message: 'must be array' }] });
464
+ f.setValue('tags', 'nope');
465
+ expect(await f.validateField('tags')).toBe('must be array');
466
+ f.setValue('tags', ['a', 'b']);
467
+ expect(await f.validateField('tags')).toBeUndefined();
468
+ });
469
+ it('type=enum rule (async-validator) restricts to allowed values', async () => {
470
+ const f = createForm();
471
+ f.registerField('plan', {
472
+ rules: [{ type: 'enum', enum: ['free', 'pro'], message: 'bad plan' }],
473
+ });
474
+ f.setValue('plan', 'gold');
475
+ expect(await f.validateField('plan')).toBe('bad plan');
476
+ f.setValue('plan', 'pro');
477
+ expect(await f.validateField('plan')).toBeUndefined();
478
+ });
479
+ it('len rule (async-validator) enforces exact length', async () => {
480
+ const f = createForm();
481
+ f.registerField('code', { rules: [{ len: 4, message: 'need 4 chars' }] });
482
+ f.setValue('code', 'ab');
483
+ expect(await f.validateField('code')).toBe('need 4 chars');
484
+ f.setValue('code', 'abcd');
485
+ expect(await f.validateField('code')).toBeUndefined();
486
+ });
487
+ it('whitespace rule (async-validator) rejects whitespace-only strings', async () => {
488
+ const f = createForm();
489
+ f.registerField('title', {
490
+ rules: [{ type: 'string', whitespace: true, message: 'blank' }],
491
+ });
492
+ f.setValue('title', ' ');
493
+ expect(await f.validateField('title')).toBe('blank');
494
+ f.setValue('title', 'hi');
495
+ expect(await f.validateField('title')).toBeUndefined();
496
+ });
497
+ it('type=integer rule (async-validator) rejects floats', async () => {
498
+ const f = createForm();
499
+ f.registerField('n', { rules: [{ type: 'integer', message: 'not int' }] });
500
+ f.setValue('n', 3.5);
501
+ expect(await f.validateField('n')).toBe('not int');
502
+ f.setValue('n', 3);
503
+ expect(await f.validateField('n')).toBeUndefined();
504
+ });
505
+ it('warningOnly still layers on top of async-validator (soft warning)', async () => {
506
+ const f = createForm();
507
+ f.registerField('bio', {
508
+ rules: [
509
+ { required: true, message: 'required' },
510
+ { minLength: 10, warningOnly: true, message: 'longer is better' },
511
+ ],
512
+ });
513
+ f.setValue('bio', 'short');
514
+ const err = await f.validateField('bio');
515
+ // required passes (non-empty); minLength is warningOnly → warning, not error
516
+ expect(err).toBeUndefined();
517
+ expect(f.getFieldWarning('bio')).toBe('longer is better');
518
+ const r = await f.submitForm();
519
+ expect(r.valid).toBe(true);
520
+ });
521
+ it('getTouched reflects setTouched', () => {
522
+ const f = createForm();
523
+ f.registerField('a');
524
+ expect(f.getTouched('a')).toBe(false);
525
+ f.setTouched('a', true);
526
+ expect(f.getTouched('a')).toBe(true);
527
+ f.setTouched('a', false);
528
+ expect(f.getTouched('a')).toBe(false);
529
+ });
530
+ it('silent validate computes result without mutating state', async () => {
531
+ const f = createForm();
532
+ f.registerField('email', { rules: [{ required: true, message: 'required' }] });
533
+ // invalid but silent → returns false, yet no error is surfaced in state
534
+ const ok = await f.validate({ silent: true });
535
+ expect(ok).toBe(false);
536
+ expect(f.getError('email')).toBeUndefined();
537
+ expect(f.getFormState().touched.email).toBeUndefined();
538
+ // non-silent validate DOES surface the error
539
+ await f.validate();
540
+ expect(f.getError('email')).toBeTruthy();
541
+ });
542
+ it('silent validate can target specific fields', async () => {
543
+ const f = createForm();
544
+ f.registerField('a', { rules: [{ required: true }] });
545
+ f.registerField('b', { rules: [{ required: true }] });
546
+ f.setValue('b', 'filled');
547
+ expect(await f.validate({ fields: ['b'], silent: true })).toBe(true);
548
+ expect(await f.validate({ fields: ['a'], silent: true })).toBe(false);
549
+ // still no state mutation
550
+ expect(f.getError('a')).toBeUndefined();
551
+ });
552
+ it('form-level validator replaces per-field rules on validate', async () => {
553
+ const f = createForm({
554
+ validator: (values) => {
555
+ const errors = {};
556
+ if (values.name !== 'mike')
557
+ errors.name = 'you must name mike';
558
+ return errors;
559
+ },
560
+ });
561
+ // per-field rule would pass, but form-level validator fails it
562
+ f.registerField('name', { rules: [] });
563
+ f.setValue('name', 'bob');
564
+ expect(await f.validate()).toBe(false);
565
+ expect(f.getError('name')).toBe('you must name mike');
566
+ f.setValue('name', 'mike');
567
+ expect(await f.validate()).toBe(true);
568
+ expect(f.getError('name')).toBeFalsy();
569
+ });
570
+ it('form-level validator runs on submitForm', async () => {
571
+ const f = createForm({
572
+ validator: (values) => (values.age >= 18 ? {} : { age: 'must be adult' }),
573
+ });
574
+ f.registerField('age');
575
+ f.setValue('age', 10);
576
+ let r = await f.submitForm();
577
+ expect(r.valid).toBe(false);
578
+ expect(r.errors.age).toBe('must be adult');
579
+ f.setValue('age', 20);
580
+ r = await f.submitForm();
581
+ expect(r.valid).toBe(true);
582
+ });
583
+ it('async form-level validator is awaited', async () => {
584
+ const f = createForm({
585
+ validator: async (values) => {
586
+ await new Promise((res) => setTimeout(res, 10));
587
+ return values.name ? {} : { name: 'required' };
588
+ },
589
+ });
590
+ f.registerField('name');
591
+ expect(await f.validate()).toBe(false);
592
+ f.setValue('name', 'x');
593
+ expect(await f.validate()).toBe(true);
594
+ });
322
595
  });
323
596
  //# sourceMappingURL=form.test.js.map