x-ui-design 1.0.29 → 1.0.31-gamma.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 (218) hide show
  1. package/README.md +1 -22
  2. package/dist/{esm/types/components → components}/DatePicker/DatePicker.d.ts +1 -2
  3. package/dist/{esm/types/components → components}/DatePicker/RangePicker/RangePicker.d.ts +1 -2
  4. package/dist/{esm/types/components → components}/Dropdown/Dropdown.d.ts +1 -2
  5. package/dist/{esm/types/components → components}/Empty/Empty.d.ts +1 -2
  6. package/dist/{esm/types/components → components}/Form/Item/Item.d.ts +1 -2
  7. package/dist/components/Icons/Icons.d.ts +18 -0
  8. package/dist/{esm/types/components → components}/Input/Input.d.ts +1 -2
  9. package/dist/{esm/types/components → components}/Input/Textarea/Textarea.d.ts +1 -2
  10. package/dist/{esm/types/components → components}/Popover/Popover.d.ts +1 -2
  11. package/dist/{esm/types/components → components}/Radio/Button/Button.d.ts +1 -2
  12. package/dist/{esm/types/components → components}/Radio/Group/Group.d.ts +1 -2
  13. package/dist/{esm/types/components → components}/Radio/Radio.d.ts +1 -2
  14. package/dist/{esm/types/components → components}/Result/Result.d.ts +1 -2
  15. package/dist/{esm/types/components → components}/Switch/Switch.d.ts +1 -2
  16. package/dist/{esm/types/components → components}/Upload/Upload.d.ts +1 -2
  17. package/dist/esm/types/index.d.ts +0 -50
  18. package/dist/index.d.ts +1 -144
  19. package/dist/index.esm.js +3436 -3863
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/index.js +3398 -3825
  22. package/dist/index.js.map +1 -1
  23. package/package.json +22 -20
  24. package/.github/workflows/x-ui-design.yml +0 -14
  25. package/compile.sh +0 -15
  26. package/dist/esm/types/components/Icons/Icons.d.ts +0 -19
  27. package/eslint.config.mjs +0 -16
  28. package/lib/components/Button/Button.tsx +0 -136
  29. package/lib/components/Button/index.ts +0 -1
  30. package/lib/components/Button/style.css +0 -197
  31. package/lib/components/Checkbox/Checkbox.tsx +0 -131
  32. package/lib/components/Checkbox/index.ts +0 -1
  33. package/lib/components/Checkbox/style.css +0 -95
  34. package/lib/components/ConditionalWrapper/index.tsx +0 -12
  35. package/lib/components/DatePicker/DatePicker.tsx +0 -526
  36. package/lib/components/DatePicker/RangePicker/RangePicker.tsx +0 -500
  37. package/lib/components/DatePicker/RangePicker/index.ts +0 -1
  38. package/lib/components/DatePicker/RangePicker/style.css +0 -434
  39. package/lib/components/DatePicker/TimePicker/TimePicker.tsx +0 -497
  40. package/lib/components/DatePicker/TimePicker/index.ts +0 -1
  41. package/lib/components/DatePicker/TimePicker/style.css +0 -197
  42. package/lib/components/DatePicker/index.ts +0 -1
  43. package/lib/components/DatePicker/style.css +0 -318
  44. package/lib/components/Dropdown/Dropdown.tsx +0 -234
  45. package/lib/components/Dropdown/index.ts +0 -1
  46. package/lib/components/Dropdown/style.css +0 -124
  47. package/lib/components/Empty/Empty.tsx +0 -45
  48. package/lib/components/Empty/index.ts +0 -1
  49. package/lib/components/Empty/style.css +0 -13
  50. package/lib/components/Form/Form.tsx +0 -130
  51. package/lib/components/Form/Item/Item.tsx +0 -294
  52. package/lib/components/Form/Item/index.ts +0 -1
  53. package/lib/components/Form/Item/style.css +0 -61
  54. package/lib/components/Form/index.ts +0 -1
  55. package/lib/components/Icons/Icons.tsx +0 -433
  56. package/lib/components/Icons/index.ts +0 -15
  57. package/lib/components/Input/Input.tsx +0 -216
  58. package/lib/components/Input/Textarea/Textarea.tsx +0 -110
  59. package/lib/components/Input/Textarea/index.ts +0 -1
  60. package/lib/components/Input/Textarea/style.css +0 -104
  61. package/lib/components/Input/index.ts +0 -1
  62. package/lib/components/Input/style.css +0 -137
  63. package/lib/components/Menu/Item/Item.tsx +0 -65
  64. package/lib/components/Menu/Menu.tsx +0 -261
  65. package/lib/components/Menu/SubMenu/SubMenu.tsx +0 -68
  66. package/lib/components/Menu/index.css +0 -145
  67. package/lib/components/Menu/index.ts +0 -1
  68. package/lib/components/Popover/Popover.tsx +0 -135
  69. package/lib/components/Popover/index.ts +0 -1
  70. package/lib/components/Popover/style.css +0 -82
  71. package/lib/components/Radio/Button/Button.tsx +0 -42
  72. package/lib/components/Radio/Button/index.ts +0 -1
  73. package/lib/components/Radio/Button/style.css +0 -43
  74. package/lib/components/Radio/Group/Group.tsx +0 -105
  75. package/lib/components/Radio/Group/index.ts +0 -1
  76. package/lib/components/Radio/Group/style.css +0 -53
  77. package/lib/components/Radio/Radio.tsx +0 -83
  78. package/lib/components/Radio/index.ts +0 -1
  79. package/lib/components/Radio/style.css +0 -73
  80. package/lib/components/Result/Result.tsx +0 -39
  81. package/lib/components/Result/index.ts +0 -1
  82. package/lib/components/Result/style.css +0 -173
  83. package/lib/components/Select/Option/Option.tsx +0 -49
  84. package/lib/components/Select/Option/index.ts +0 -1
  85. package/lib/components/Select/Option/style.css +0 -50
  86. package/lib/components/Select/Select.tsx +0 -935
  87. package/lib/components/Select/Tag/Tag.tsx +0 -43
  88. package/lib/components/Select/Tag/index.ts +0 -1
  89. package/lib/components/Select/Tag/style.css +0 -87
  90. package/lib/components/Select/index.ts +0 -1
  91. package/lib/components/Select/style.css +0 -186
  92. package/lib/components/Skeleton/Avatar/Avatar.tsx +0 -61
  93. package/lib/components/Skeleton/Avatar/index.ts +0 -1
  94. package/lib/components/Skeleton/Avatar/style.css +0 -27
  95. package/lib/components/Skeleton/Button/Button.tsx +0 -44
  96. package/lib/components/Skeleton/Button/index.ts +0 -1
  97. package/lib/components/Skeleton/Button/style.css +0 -50
  98. package/lib/components/Skeleton/Image/Image.tsx +0 -45
  99. package/lib/components/Skeleton/Image/index.ts +0 -1
  100. package/lib/components/Skeleton/Image/style.css +0 -23
  101. package/lib/components/Skeleton/Input/Input.tsx +0 -42
  102. package/lib/components/Skeleton/Input/index.ts +0 -1
  103. package/lib/components/Skeleton/Input/style.css +0 -56
  104. package/lib/components/Skeleton/Skeleton.tsx +0 -97
  105. package/lib/components/Skeleton/index.ts +0 -1
  106. package/lib/components/Skeleton/style.css +0 -84
  107. package/lib/components/Switch/Switch.tsx +0 -68
  108. package/lib/components/Switch/index.css +0 -50
  109. package/lib/components/Switch/index.ts +0 -1
  110. package/lib/components/Upload/Upload.tsx +0 -291
  111. package/lib/components/Upload/index.ts +0 -1
  112. package/lib/components/Upload/style.css +0 -151
  113. package/lib/global.d.ts +0 -1
  114. package/lib/helpers/flatten.ts +0 -26
  115. package/lib/helpers/index.ts +0 -52
  116. package/lib/helpers/mask.ts +0 -52
  117. package/lib/hooks/useForm.ts +0 -548
  118. package/lib/hooks/usePosition.ts +0 -206
  119. package/lib/hooks/useWatch.ts +0 -41
  120. package/lib/hooks/useWatchError.ts +0 -20
  121. package/lib/index.ts +0 -184
  122. package/lib/styles/global.css +0 -57
  123. package/lib/types/button.ts +0 -83
  124. package/lib/types/checkbox.ts +0 -32
  125. package/lib/types/datepicker.ts +0 -165
  126. package/lib/types/dropdown.ts +0 -41
  127. package/lib/types/empty.ts +0 -8
  128. package/lib/types/form.ts +0 -179
  129. package/lib/types/index.ts +0 -38
  130. package/lib/types/input.ts +0 -72
  131. package/lib/types/menu.ts +0 -55
  132. package/lib/types/popover.ts +0 -16
  133. package/lib/types/radio.ts +0 -69
  134. package/lib/types/result.ts +0 -22
  135. package/lib/types/select.ts +0 -126
  136. package/lib/types/skeleton.ts +0 -62
  137. package/lib/types/switch.ts +0 -22
  138. package/lib/types/upload.ts +0 -67
  139. package/lib/utils/index.ts +0 -37
  140. package/lib/utils/lazy.ts +0 -17
  141. package/next.config.ts +0 -7
  142. package/rollup.config.js +0 -71
  143. package/src/app/favicon.ico +0 -0
  144. package/src/app/globals.css +0 -48
  145. package/src/app/layout.d.ts +0 -5
  146. package/src/app/layout.tsx +0 -16
  147. package/src/app/page.d.ts +0 -1
  148. package/src/app/page.tsx +0 -21
  149. package/tsconfig.json +0 -46
  150. /package/dist/{esm/types/components → components}/Button/Button.d.ts +0 -0
  151. /package/dist/{esm/types/components → components}/Button/index.d.ts +0 -0
  152. /package/dist/{esm/types/components → components}/Checkbox/Checkbox.d.ts +0 -0
  153. /package/dist/{esm/types/components → components}/Checkbox/index.d.ts +0 -0
  154. /package/dist/{esm/types/components → components}/ConditionalWrapper/index.d.ts +0 -0
  155. /package/dist/{esm/types/components → components}/DatePicker/RangePicker/index.d.ts +0 -0
  156. /package/dist/{esm/types/components → components}/DatePicker/TimePicker/TimePicker.d.ts +0 -0
  157. /package/dist/{esm/types/components → components}/DatePicker/TimePicker/index.d.ts +0 -0
  158. /package/dist/{esm/types/components → components}/DatePicker/index.d.ts +0 -0
  159. /package/dist/{esm/types/components → components}/Dropdown/index.d.ts +0 -0
  160. /package/dist/{esm/types/components → components}/Empty/index.d.ts +0 -0
  161. /package/dist/{esm/types/components → components}/Form/Form.d.ts +0 -0
  162. /package/dist/{esm/types/components → components}/Form/Item/index.d.ts +0 -0
  163. /package/dist/{esm/types/components → components}/Form/index.d.ts +0 -0
  164. /package/dist/{esm/types/components → components}/Icons/index.d.ts +0 -0
  165. /package/dist/{esm/types/components → components}/Input/Textarea/index.d.ts +0 -0
  166. /package/dist/{esm/types/components → components}/Input/index.d.ts +0 -0
  167. /package/dist/{esm/types/components → components}/Menu/Item/Item.d.ts +0 -0
  168. /package/dist/{esm/types/components → components}/Menu/Menu.d.ts +0 -0
  169. /package/dist/{esm/types/components → components}/Menu/SubMenu/SubMenu.d.ts +0 -0
  170. /package/dist/{esm/types/components → components}/Menu/index.d.ts +0 -0
  171. /package/dist/{esm/types/components → components}/Popover/index.d.ts +0 -0
  172. /package/dist/{esm/types/components → components}/Radio/Button/index.d.ts +0 -0
  173. /package/dist/{esm/types/components → components}/Radio/Group/index.d.ts +0 -0
  174. /package/dist/{esm/types/components → components}/Radio/index.d.ts +0 -0
  175. /package/dist/{esm/types/components → components}/Result/index.d.ts +0 -0
  176. /package/dist/{esm/types/components → components}/Select/Option/Option.d.ts +0 -0
  177. /package/dist/{esm/types/components → components}/Select/Option/index.d.ts +0 -0
  178. /package/dist/{esm/types/components → components}/Select/Select.d.ts +0 -0
  179. /package/dist/{esm/types/components → components}/Select/Tag/Tag.d.ts +0 -0
  180. /package/dist/{esm/types/components → components}/Select/Tag/index.d.ts +0 -0
  181. /package/dist/{esm/types/components → components}/Select/index.d.ts +0 -0
  182. /package/dist/{esm/types/components → components}/Skeleton/Avatar/Avatar.d.ts +0 -0
  183. /package/dist/{esm/types/components → components}/Skeleton/Avatar/index.d.ts +0 -0
  184. /package/dist/{esm/types/components → components}/Skeleton/Button/Button.d.ts +0 -0
  185. /package/dist/{esm/types/components → components}/Skeleton/Button/index.d.ts +0 -0
  186. /package/dist/{esm/types/components → components}/Skeleton/Image/Image.d.ts +0 -0
  187. /package/dist/{esm/types/components → components}/Skeleton/Image/index.d.ts +0 -0
  188. /package/dist/{esm/types/components → components}/Skeleton/Input/Input.d.ts +0 -0
  189. /package/dist/{esm/types/components → components}/Skeleton/Input/index.d.ts +0 -0
  190. /package/dist/{esm/types/components → components}/Skeleton/Skeleton.d.ts +0 -0
  191. /package/dist/{esm/types/components → components}/Skeleton/index.d.ts +0 -0
  192. /package/dist/{esm/types/components → components}/Switch/index.d.ts +0 -0
  193. /package/dist/{esm/types/components → components}/Upload/index.d.ts +0 -0
  194. /package/dist/{esm/types/helpers → helpers}/flatten.d.ts +0 -0
  195. /package/dist/{esm/types/helpers → helpers}/index.d.ts +0 -0
  196. /package/dist/{esm/types/helpers → helpers}/mask.d.ts +0 -0
  197. /package/dist/{esm/types/hooks → hooks}/useForm.d.ts +0 -0
  198. /package/dist/{esm/types/hooks → hooks}/usePosition.d.ts +0 -0
  199. /package/dist/{esm/types/hooks → hooks}/useWatch.d.ts +0 -0
  200. /package/dist/{esm/types/hooks → hooks}/useWatchError.d.ts +0 -0
  201. /package/dist/{esm/types/types → types}/button.d.ts +0 -0
  202. /package/dist/{esm/types/types → types}/checkbox.d.ts +0 -0
  203. /package/dist/{esm/types/types → types}/datepicker.d.ts +0 -0
  204. /package/dist/{esm/types/types → types}/dropdown.d.ts +0 -0
  205. /package/dist/{esm/types/types → types}/empty.d.ts +0 -0
  206. /package/dist/{esm/types/types → types}/form.d.ts +0 -0
  207. /package/dist/{esm/types/types → types}/index.d.ts +0 -0
  208. /package/dist/{esm/types/types → types}/input.d.ts +0 -0
  209. /package/dist/{esm/types/types → types}/menu.d.ts +0 -0
  210. /package/dist/{esm/types/types → types}/popover.d.ts +0 -0
  211. /package/dist/{esm/types/types → types}/radio.d.ts +0 -0
  212. /package/dist/{esm/types/types → types}/result.d.ts +0 -0
  213. /package/dist/{esm/types/types → types}/select.d.ts +0 -0
  214. /package/dist/{esm/types/types → types}/skeleton.d.ts +0 -0
  215. /package/dist/{esm/types/types → types}/switch.d.ts +0 -0
  216. /package/dist/{esm/types/types → types}/upload.d.ts +0 -0
  217. /package/dist/{esm/types/utils → utils}/index.d.ts +0 -0
  218. /package/dist/{esm/types/utils → utils}/lazy.d.ts +0 -0
@@ -1,548 +0,0 @@
1
- 'use client';
2
-
3
- import { useRef, useState } from 'react';
4
- import { RuleType, RuleTypes } from '../types';
5
- import type {
6
- FieldData,
7
- FieldError,
8
- FieldInstancesRef,
9
- FormInstance,
10
- RuleObject,
11
- RuleRender
12
- } from '../types/form';
13
-
14
- const useForm = (
15
- initialValues: Record<string, RuleTypes> = {},
16
- onFieldsChange?: (changedFields: FieldData[]) => void,
17
- onValuesChange?: (
18
- changedValues: Record<string, RuleTypes>,
19
- allValues: Record<string, RuleTypes>
20
- ) => void,
21
- scrollToFirstError?: boolean,
22
- onFinish?: ((values: Record<string, RuleTypes>) => void) | undefined,
23
- onFinishFailed?: (errorInfo: {
24
- values: Record<string, RuleTypes>;
25
- errorFields: Pick<FieldError, 'errors' | 'name'>[];
26
- }) => void
27
- ): FormInstance => {
28
- const touchedFieldsRef = useRef(new Set<string>());
29
- const rulesRef = useRef<Record<string, RuleObject[] | RuleRender>>({});
30
- const warningsRef = useRef<Record<string, string[]>>({});
31
- const _scrollToFirstError = useRef<boolean>(scrollToFirstError);
32
- const stepRef = useRef<number>(0);
33
- const formHandlersRef = useRef<{
34
- onFinish?: ((values: Record<string, RuleTypes>) => void) | undefined,
35
- onValuesChange?: (
36
- changedValues: Record<string, RuleTypes>,
37
- allValues: Record<string, RuleTypes>
38
- ) => void
39
- onFieldsChange?: (changedFields: FieldData[]) => void;
40
- onFinishFailed?: (errorInfo: {
41
- values: Record<string, RuleTypes>;
42
- errorFields: Pick<FieldError, 'errors' | 'name'>[];
43
- }) => void;
44
- }>({
45
- onFinish,
46
- onValuesChange,
47
- onFieldsChange,
48
- onFinishFailed
49
- })
50
-
51
- const formRef = useRef<Record<number, Record<string, RuleTypes>>>({ [stepRef.current]: { ...initialValues } });
52
- const trashFormRef = useRef<Record<string, RuleTypes>>({ ...initialValues });
53
- const fieldInstancesRef = useRef<Record<string, FieldInstancesRef | null>>({});
54
-
55
- const [isReseting, setIsReseting] = useState(false);
56
-
57
- const errorsRef = useRef<Record<string, string[]>>({});
58
- const errorSubscribers = useRef<
59
- Record<string, ((errors: string[]) => void)[]>
60
- >({});
61
-
62
- const fieldSubscribers = useRef<
63
- Record<string, ((value: RuleTypes) => void)[]>
64
- >({});
65
-
66
- const formSubscribers = useRef<
67
- ((values: Record<string, RuleTypes>) => void)[]
68
- >([]);
69
-
70
- function getFormFields() {
71
- return Object.assign({}, ...Object.values(formRef.current));
72
- }
73
-
74
- function getFieldInstance(name?: string) {
75
- return name ? fieldInstancesRef.current[name] : fieldInstancesRef.current;
76
- }
77
-
78
- function getFieldValue(name: string) {
79
- const formData = getFormFields();
80
-
81
- return formData[name]
82
- }
83
-
84
- function getFieldsValue(nameList?: string[]) {
85
- const formData = getFormFields();
86
-
87
- if (!nameList) {
88
- return formData;
89
- }
90
-
91
- return nameList.reduce((acc, key) => {
92
- acc[key] = formData[key];
93
-
94
- return acc;
95
- }, {} as Record<string, RuleTypes>);
96
- }
97
-
98
- function getFieldError(name: string) {
99
- return errorsRef.current[name] || [];
100
- }
101
-
102
- function getFieldWarning(name: string): string[] {
103
- return warningsRef.current[name] || [];
104
- }
105
-
106
- function getFieldsError(): Pick<FieldError, 'errors' | 'name'>[] {
107
- return Object.entries(errorsRef.current).map(([name, err]) => ({ name, errors: err }));
108
- }
109
-
110
- function setFieldValue(
111
- name: string,
112
- value: RuleTypes,
113
- errors?: string[],
114
- reset: boolean | null | -1 | undefined = undefined,
115
- touch?: boolean
116
- ) {
117
- if (
118
- !reset && reset !== null &&
119
- ([undefined, null].includes(value) || formRef.current[stepRef.current][name] === value)
120
- ) {
121
- return;
122
- }
123
-
124
- let isFieldExist = false;
125
-
126
- Object.values(formRef.current).forEach((_, step) => {
127
- if (formRef.current[step].hasOwnProperty(name)) {
128
- formRef.current[step][name] = value;
129
-
130
- isFieldExist = true;
131
-
132
- return;
133
- }
134
- })
135
-
136
- if (!isFieldExist) {
137
- formRef.current[stepRef.current][name] = value;
138
- }
139
-
140
- if (touch) {
141
- touchedFieldsRef.current.add(name);
142
- }
143
-
144
- if (reset === null) {
145
- errorsRef.current[name] = []
146
- notifyErrorSubscribers(name);
147
-
148
- return
149
- }
150
-
151
- if (!errors?.length) {
152
- validateField(name).then(() => {
153
- const allValues = getFieldsValue();
154
- fieldSubscribers.current[name]?.forEach(callback => callback(value));
155
- formSubscribers.current.forEach(callback => callback(allValues));
156
-
157
- if (formHandlersRef.current.onValuesChange) {
158
- formHandlersRef.current.onValuesChange({ [name]: value }, allValues);
159
- }
160
-
161
- if (formHandlersRef.current.onFieldsChange) {
162
- formHandlersRef.current.onFieldsChange([{ name, value }]);
163
- }
164
- });
165
- } else {
166
- if (reset === -1) {
167
- setTimeout(() => {
168
- errorsRef.current[name] = errors;
169
- notifyErrorSubscribers(name);
170
- }, 0);
171
- } else {
172
- errorsRef.current[name] = errors;
173
- notifyErrorSubscribers(name);
174
- }
175
- }
176
- }
177
-
178
- function setFieldsValue(values: Partial<Record<string, RuleTypes>>, reset?: boolean | null | undefined) {
179
- Object.entries(values).forEach(([name, value]) =>
180
- setFieldValue(name, value as RuleTypes, undefined, reset)
181
- );
182
- }
183
-
184
- function setFields(fields: FieldData[]) {
185
- fields.forEach(({ name, value, errors }) =>
186
- setFieldValue(
187
- Array.isArray(name) ? name[0] : name,
188
- value ?? getFieldValue(Array.isArray(name) ? name[0] : name),
189
- errors,
190
- -1
191
- )
192
- );
193
- }
194
-
195
- function setFieldInstance(fieldName: string, fieldRef: FieldInstancesRef | null) {
196
- fieldInstancesRef.current[fieldName] = fieldRef;
197
- }
198
-
199
- function isFieldTouched(name: string) {
200
- return touchedFieldsRef.current.has(name);
201
- }
202
-
203
- function isFieldsTouched(nameList?: string[], allFieldsTouched = false) {
204
- if (!nameList) {
205
- return touchedFieldsRef.current.size > 0;
206
- }
207
-
208
- return allFieldsTouched
209
- ? nameList.every(name => touchedFieldsRef.current.has(name))
210
- : nameList.some(name => touchedFieldsRef.current.has(name));
211
- }
212
-
213
- function isFieldValidating(name: string): boolean {
214
- return !!name;
215
- }
216
-
217
- function registerField(name: string, rules: RuleObject[] = [], remove: boolean = false) {
218
- if (remove) {
219
- trashFormRef.current[name] = formRef.current[stepRef.current]?.[name];
220
-
221
- delete formRef.current[stepRef.current]?.[name];
222
- delete rulesRef.current[name];
223
- delete fieldInstancesRef.current[name];
224
- } else {
225
- if (!(name in formRef.current[stepRef.current])) {
226
- if (trashFormRef.current.hasOwnProperty(name)) {
227
- formRef.current[stepRef.current][name] = trashFormRef.current[name];
228
-
229
- delete trashFormRef.current[name];
230
- } else {
231
- const existFields: Record<string, RuleType> = {};
232
-
233
- Object.values(formRef.current).forEach((_, step) => {
234
- if (formRef.current[step].hasOwnProperty(name)) {
235
- existFields[name] = formRef.current[step][name]
236
-
237
- delete formRef.current[step][name];
238
- }
239
- })
240
-
241
- formRef.current[stepRef.current][name] = initialValues?.[name];
242
-
243
- if (Object.keys(existFields).length) {
244
- Object.entries(existFields).forEach(([_key, _value]) => {
245
- formRef.current[stepRef.current][_key] = _value
246
- })
247
- }
248
- }
249
- }
250
-
251
- rulesRef.current[name] = rules;
252
- }
253
- }
254
-
255
- async function validateField(name: string) {
256
- const value = formRef.current[stepRef.current][name];
257
- const rules = rulesRef.current[name] || [];
258
- const fieldErrors: string[] = [];
259
- const fieldWarnings: string[] = [];
260
-
261
- await Promise.all(
262
- [rules].flat(1).map(async (rule: RuleTypes) => {
263
- rule = typeof rule === 'function' ? rule(formInstance) : rule;
264
-
265
- if (
266
- rule.required &&
267
- ((rule.validateBooleanFalse && !value) ||
268
- value === undefined ||
269
- value === null ||
270
- value === '' ||
271
- (Array.isArray(value) && !value.length))
272
- ) {
273
- fieldErrors.push(rule.message || 'This field is required');
274
- }
275
-
276
- if (
277
- (typeof value === 'string' ||
278
- typeof value === 'number' ||
279
- Array.isArray(value)) &&
280
- rule.min !== undefined &&
281
- String(value).length < rule.min
282
- ) {
283
- fieldErrors.push(
284
- rule.message || `Must be at least ${rule.min} characters`
285
- );
286
- }
287
-
288
- if (
289
- (typeof value === 'string' ||
290
- typeof value === 'number' ||
291
- Array.isArray(value)) &&
292
- rule.max !== undefined &&
293
- String(value).length > rule.max
294
- ) {
295
- fieldErrors.push(
296
- rule.message || `Must be at most ${rule.max} characters`
297
- );
298
- }
299
-
300
- if (value !== undefined && rule.pattern && !rule.pattern.test(String(value))) {
301
- fieldErrors.push(rule.message || 'Invalid format');
302
- }
303
-
304
- if (rule.warningPattern && !rule.warningPattern.test(String(value))) {
305
- fieldWarnings.push(rule.warningMessage || 'Invalid format');
306
- }
307
-
308
- if (rule.validator) {
309
- try {
310
- await rule.validator(
311
- rule,
312
- value,
313
- (error?: string) => error && fieldErrors.push(error)
314
- );
315
- } catch (error) {
316
- fieldErrors.push(
317
- error instanceof Error ? error.message : String(error)
318
- );
319
- }
320
- }
321
- })
322
- );
323
-
324
- errorsRef.current[name] = fieldErrors
325
- warningsRef.current[name] = fieldWarnings;
326
-
327
- notifyErrorSubscribers(name);
328
-
329
- return fieldErrors.length === 0;
330
- }
331
-
332
- async function validateFields(nameList?: string[]) {
333
- const fieldsToValidate = nameList || Object.keys(formRef.current[stepRef.current]);
334
-
335
- const results = await Promise.all(
336
- fieldsToValidate.map(name => validateField(name))
337
- );
338
-
339
- const errorFields = formInstance.getFieldsError().filter(e => e.errors.length);
340
-
341
- if (errorFields.length) {
342
- formHandlersRef.current.onFinishFailed?.({ values: formInstance.getFieldsValue(), errorFields })
343
- }
344
-
345
- if (_scrollToFirstError.current) {
346
- const firstErrorContent = document.querySelectorAll('.xUi-form-item-has-error')?.[0];
347
-
348
- if (firstErrorContent) {
349
- firstErrorContent.closest('.xUi-form-item')?.scrollIntoView({
350
- behavior: 'smooth'
351
- });
352
- }
353
- }
354
-
355
- fieldsToValidate.forEach(name => notifyErrorSubscribers(name));
356
-
357
- return results.every(valid => valid);
358
- }
359
-
360
- function resetFields(nameList?: string[], showError: boolean | null = true) {
361
- const formData = getFormFields();
362
-
363
- if (nameList?.length) {
364
- nameList.forEach((name: string) => {
365
- formData[name] = initialValues[name];
366
- trashFormRef.current[name] = initialValues[name]
367
-
368
- touchedFieldsRef.current.delete(name);
369
- delete warningsRef.current[name];
370
-
371
- errorsRef.current[name] = [];
372
- notifyErrorSubscribers(name);
373
-
374
- setFieldValue(name, initialValues[name], undefined, showError);
375
- });
376
- } else {
377
- touchedFieldsRef.current.clear();
378
- warningsRef.current = {};
379
-
380
- Object.keys({
381
- ...formData,
382
- }).forEach(name => {
383
- setFieldValue(name, initialValues[name], undefined, showError);
384
- });
385
- }
386
-
387
- formSubscribers.current.forEach(callback => callback(getFieldsValue()));
388
- setIsReseting(prev => !prev);
389
- }
390
-
391
- async function submit() {
392
- const formData = getFormFields();
393
-
394
- return (await validateFields()) ? (() => {
395
- formHandlersRef.current.onFinish?.(formData)
396
-
397
- return formData
398
- })() : undefined;
399
- }
400
-
401
- function subscribeToField(
402
- name: string,
403
- callback: (value: RuleTypes) => void
404
- ) {
405
- if (!fieldSubscribers.current[name]) {
406
- fieldSubscribers.current[name] = [];
407
- }
408
-
409
- fieldSubscribers.current[name].push(callback);
410
-
411
- return () => {
412
- fieldSubscribers.current[name] = fieldSubscribers.current[name].filter(
413
- cb => cb !== callback
414
- );
415
- };
416
- }
417
-
418
- function subscribeToForm(
419
- callback: (values: Record<string, RuleTypes>) => void
420
- ) {
421
- formSubscribers.current.push(callback);
422
-
423
- return () => {
424
- formSubscribers.current = formSubscribers.current.filter(
425
- cb => cb !== callback
426
- );
427
- };
428
- }
429
-
430
- function subscribeToFields(
431
- names: string[],
432
- callback: (values: Record<string, RuleTypes>) => void
433
- ) {
434
- const fieldCallbacks = names.map(name =>
435
- subscribeToField(name, () => {
436
- const updatedValues = getFieldsValue(names);
437
- callback(updatedValues);
438
- })
439
- );
440
-
441
- return () => {
442
- fieldCallbacks.forEach(unsubscribe => unsubscribe());
443
- };
444
- }
445
-
446
- function subscribeToError(name: string, callback: (errors: string[]) => void) {
447
- if (!errorSubscribers.current[name]) {
448
- errorSubscribers.current[name] = [];
449
- }
450
-
451
- errorSubscribers.current[name].push(callback);
452
-
453
- return () => {
454
- errorSubscribers.current[name] = errorSubscribers.current[name].filter(
455
- cb => cb !== callback
456
- );
457
- };
458
- }
459
-
460
- function notifyErrorSubscribers(name: string) {
461
- const errors = getFieldError(name);
462
- errorSubscribers.current[name]?.forEach(cb => cb(errors));
463
- }
464
-
465
- function setScrollToFirstError(value: boolean) {
466
- _scrollToFirstError.current = value;
467
- }
468
-
469
- function setOnFieldsChange(
470
- onFieldsChange?: (changedFields: FieldData[]) => void
471
- ) {
472
- formHandlersRef.current.onFieldsChange = onFieldsChange
473
- }
474
-
475
- function setOnValuesChange(
476
- onValuesChange?: (changedValues: Record<string, RuleTypes>, allValues: Record<string, RuleTypes>) => void
477
- ) {
478
- formHandlersRef.current.onValuesChange = onValuesChange
479
- }
480
-
481
- function setOnFinish(
482
- onFinish?: ((values: Record<string, RuleTypes>) => void) | undefined
483
- ) {
484
- formHandlersRef.current.onFinish = onFinish;
485
- }
486
-
487
- function setOnFinishFailed(
488
- onFinishFailed?: ((errorInfo: {
489
- values: Record<string, RuleType>;
490
- errorFields: Pick<FieldError, "errors" | "name">[];
491
- }) => void) | undefined
492
- ) {
493
- formHandlersRef.current.onFinishFailed = onFinishFailed
494
- }
495
-
496
- function changeStep(step: number) {
497
- stepRef.current = step ?? 0;
498
-
499
- if (!formRef.current[stepRef.current]) {
500
- formRef.current[stepRef.current] = {};
501
- }
502
- }
503
-
504
- const formInstanceRef = useRef<FormInstance>(null);
505
- const formInstance: FormInstance = {
506
- submit,
507
- setFields,
508
- resetFields,
509
- getFieldError,
510
- registerField,
511
- setFieldValue,
512
- getFieldValue,
513
- validateFields,
514
- setFieldsValue,
515
- getFieldsValue,
516
- isFieldTouched,
517
- getFieldsError,
518
- setOnFinishFailed,
519
- isFieldsTouched,
520
- getFieldWarning,
521
- isFieldValidating,
522
- subscribeToField,
523
- subscribeToForm,
524
- onFieldsChange,
525
- onValuesChange,
526
- getFieldInstance,
527
- setFieldInstance,
528
- subscribeToFields,
529
- setScrollToFirstError,
530
- subscribeToError,
531
- scrollToFirstError,
532
- isReseting,
533
- setOnFinish,
534
- setOnFieldsChange,
535
- setOnValuesChange,
536
- changeStep,
537
- };
538
-
539
- if (formInstanceRef.current) {
540
- return formInstanceRef.current
541
- } else {
542
- formInstanceRef.current = formInstance;
543
-
544
- return formInstanceRef.current
545
- }
546
- };
547
-
548
- export { useForm };