x-ui-design 1.0.30 → 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 (219) 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/components/Input/Input.d.ts +11 -0
  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 -56
  18. package/dist/index.d.ts +1 -150
  19. package/dist/index.esm.js +3433 -3863
  20. package/dist/index.esm.js.map +1 -1
  21. package/dist/index.js +3395 -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/dist/esm/types/components/Input/Input.d.ts +0 -16
  28. package/eslint.config.mjs +0 -16
  29. package/lib/components/Button/Button.tsx +0 -136
  30. package/lib/components/Button/index.ts +0 -1
  31. package/lib/components/Button/style.css +0 -197
  32. package/lib/components/Checkbox/Checkbox.tsx +0 -131
  33. package/lib/components/Checkbox/index.ts +0 -1
  34. package/lib/components/Checkbox/style.css +0 -95
  35. package/lib/components/ConditionalWrapper/index.tsx +0 -12
  36. package/lib/components/DatePicker/DatePicker.tsx +0 -526
  37. package/lib/components/DatePicker/RangePicker/RangePicker.tsx +0 -500
  38. package/lib/components/DatePicker/RangePicker/index.ts +0 -1
  39. package/lib/components/DatePicker/RangePicker/style.css +0 -434
  40. package/lib/components/DatePicker/TimePicker/TimePicker.tsx +0 -497
  41. package/lib/components/DatePicker/TimePicker/index.ts +0 -1
  42. package/lib/components/DatePicker/TimePicker/style.css +0 -197
  43. package/lib/components/DatePicker/index.ts +0 -1
  44. package/lib/components/DatePicker/style.css +0 -318
  45. package/lib/components/Dropdown/Dropdown.tsx +0 -234
  46. package/lib/components/Dropdown/index.ts +0 -1
  47. package/lib/components/Dropdown/style.css +0 -124
  48. package/lib/components/Empty/Empty.tsx +0 -45
  49. package/lib/components/Empty/index.ts +0 -1
  50. package/lib/components/Empty/style.css +0 -13
  51. package/lib/components/Form/Form.tsx +0 -130
  52. package/lib/components/Form/Item/Item.tsx +0 -294
  53. package/lib/components/Form/Item/index.ts +0 -1
  54. package/lib/components/Form/Item/style.css +0 -61
  55. package/lib/components/Form/index.ts +0 -1
  56. package/lib/components/Icons/Icons.tsx +0 -433
  57. package/lib/components/Icons/index.ts +0 -15
  58. package/lib/components/Input/Input.tsx +0 -228
  59. package/lib/components/Input/Textarea/Textarea.tsx +0 -110
  60. package/lib/components/Input/Textarea/index.ts +0 -1
  61. package/lib/components/Input/Textarea/style.css +0 -104
  62. package/lib/components/Input/index.ts +0 -1
  63. package/lib/components/Input/style.css +0 -137
  64. package/lib/components/Menu/Item/Item.tsx +0 -65
  65. package/lib/components/Menu/Menu.tsx +0 -261
  66. package/lib/components/Menu/SubMenu/SubMenu.tsx +0 -68
  67. package/lib/components/Menu/index.css +0 -145
  68. package/lib/components/Menu/index.ts +0 -1
  69. package/lib/components/Popover/Popover.tsx +0 -135
  70. package/lib/components/Popover/index.ts +0 -1
  71. package/lib/components/Popover/style.css +0 -82
  72. package/lib/components/Radio/Button/Button.tsx +0 -42
  73. package/lib/components/Radio/Button/index.ts +0 -1
  74. package/lib/components/Radio/Button/style.css +0 -43
  75. package/lib/components/Radio/Group/Group.tsx +0 -105
  76. package/lib/components/Radio/Group/index.ts +0 -1
  77. package/lib/components/Radio/Group/style.css +0 -53
  78. package/lib/components/Radio/Radio.tsx +0 -83
  79. package/lib/components/Radio/index.ts +0 -1
  80. package/lib/components/Radio/style.css +0 -73
  81. package/lib/components/Result/Result.tsx +0 -39
  82. package/lib/components/Result/index.ts +0 -1
  83. package/lib/components/Result/style.css +0 -173
  84. package/lib/components/Select/Option/Option.tsx +0 -49
  85. package/lib/components/Select/Option/index.ts +0 -1
  86. package/lib/components/Select/Option/style.css +0 -50
  87. package/lib/components/Select/Select.tsx +0 -935
  88. package/lib/components/Select/Tag/Tag.tsx +0 -43
  89. package/lib/components/Select/Tag/index.ts +0 -1
  90. package/lib/components/Select/Tag/style.css +0 -87
  91. package/lib/components/Select/index.ts +0 -1
  92. package/lib/components/Select/style.css +0 -186
  93. package/lib/components/Skeleton/Avatar/Avatar.tsx +0 -61
  94. package/lib/components/Skeleton/Avatar/index.ts +0 -1
  95. package/lib/components/Skeleton/Avatar/style.css +0 -27
  96. package/lib/components/Skeleton/Button/Button.tsx +0 -44
  97. package/lib/components/Skeleton/Button/index.ts +0 -1
  98. package/lib/components/Skeleton/Button/style.css +0 -50
  99. package/lib/components/Skeleton/Image/Image.tsx +0 -45
  100. package/lib/components/Skeleton/Image/index.ts +0 -1
  101. package/lib/components/Skeleton/Image/style.css +0 -23
  102. package/lib/components/Skeleton/Input/Input.tsx +0 -42
  103. package/lib/components/Skeleton/Input/index.ts +0 -1
  104. package/lib/components/Skeleton/Input/style.css +0 -56
  105. package/lib/components/Skeleton/Skeleton.tsx +0 -97
  106. package/lib/components/Skeleton/index.ts +0 -1
  107. package/lib/components/Skeleton/style.css +0 -84
  108. package/lib/components/Switch/Switch.tsx +0 -68
  109. package/lib/components/Switch/index.css +0 -50
  110. package/lib/components/Switch/index.ts +0 -1
  111. package/lib/components/Upload/Upload.tsx +0 -291
  112. package/lib/components/Upload/index.ts +0 -1
  113. package/lib/components/Upload/style.css +0 -151
  114. package/lib/global.d.ts +0 -1
  115. package/lib/helpers/flatten.ts +0 -26
  116. package/lib/helpers/index.ts +0 -52
  117. package/lib/helpers/mask.ts +0 -52
  118. package/lib/hooks/useForm.ts +0 -548
  119. package/lib/hooks/usePosition.ts +0 -206
  120. package/lib/hooks/useWatch.ts +0 -41
  121. package/lib/hooks/useWatchError.ts +0 -20
  122. package/lib/index.ts +0 -184
  123. package/lib/styles/global.css +0 -57
  124. package/lib/types/button.ts +0 -83
  125. package/lib/types/checkbox.ts +0 -32
  126. package/lib/types/datepicker.ts +0 -165
  127. package/lib/types/dropdown.ts +0 -41
  128. package/lib/types/empty.ts +0 -8
  129. package/lib/types/form.ts +0 -179
  130. package/lib/types/index.ts +0 -38
  131. package/lib/types/input.ts +0 -72
  132. package/lib/types/menu.ts +0 -55
  133. package/lib/types/popover.ts +0 -16
  134. package/lib/types/radio.ts +0 -69
  135. package/lib/types/result.ts +0 -22
  136. package/lib/types/select.ts +0 -126
  137. package/lib/types/skeleton.ts +0 -62
  138. package/lib/types/switch.ts +0 -22
  139. package/lib/types/upload.ts +0 -67
  140. package/lib/utils/index.ts +0 -37
  141. package/lib/utils/lazy.ts +0 -17
  142. package/next.config.ts +0 -7
  143. package/rollup.config.js +0 -71
  144. package/src/app/favicon.ico +0 -0
  145. package/src/app/globals.css +0 -48
  146. package/src/app/layout.d.ts +0 -5
  147. package/src/app/layout.tsx +0 -16
  148. package/src/app/page.d.ts +0 -1
  149. package/src/app/page.tsx +0 -21
  150. package/tsconfig.json +0 -46
  151. /package/dist/{esm/types/components → components}/Button/Button.d.ts +0 -0
  152. /package/dist/{esm/types/components → components}/Button/index.d.ts +0 -0
  153. /package/dist/{esm/types/components → components}/Checkbox/Checkbox.d.ts +0 -0
  154. /package/dist/{esm/types/components → components}/Checkbox/index.d.ts +0 -0
  155. /package/dist/{esm/types/components → components}/ConditionalWrapper/index.d.ts +0 -0
  156. /package/dist/{esm/types/components → components}/DatePicker/RangePicker/index.d.ts +0 -0
  157. /package/dist/{esm/types/components → components}/DatePicker/TimePicker/TimePicker.d.ts +0 -0
  158. /package/dist/{esm/types/components → components}/DatePicker/TimePicker/index.d.ts +0 -0
  159. /package/dist/{esm/types/components → components}/DatePicker/index.d.ts +0 -0
  160. /package/dist/{esm/types/components → components}/Dropdown/index.d.ts +0 -0
  161. /package/dist/{esm/types/components → components}/Empty/index.d.ts +0 -0
  162. /package/dist/{esm/types/components → components}/Form/Form.d.ts +0 -0
  163. /package/dist/{esm/types/components → components}/Form/Item/index.d.ts +0 -0
  164. /package/dist/{esm/types/components → components}/Form/index.d.ts +0 -0
  165. /package/dist/{esm/types/components → components}/Icons/index.d.ts +0 -0
  166. /package/dist/{esm/types/components → components}/Input/Textarea/index.d.ts +0 -0
  167. /package/dist/{esm/types/components → components}/Input/index.d.ts +0 -0
  168. /package/dist/{esm/types/components → components}/Menu/Item/Item.d.ts +0 -0
  169. /package/dist/{esm/types/components → components}/Menu/Menu.d.ts +0 -0
  170. /package/dist/{esm/types/components → components}/Menu/SubMenu/SubMenu.d.ts +0 -0
  171. /package/dist/{esm/types/components → components}/Menu/index.d.ts +0 -0
  172. /package/dist/{esm/types/components → components}/Popover/index.d.ts +0 -0
  173. /package/dist/{esm/types/components → components}/Radio/Button/index.d.ts +0 -0
  174. /package/dist/{esm/types/components → components}/Radio/Group/index.d.ts +0 -0
  175. /package/dist/{esm/types/components → components}/Radio/index.d.ts +0 -0
  176. /package/dist/{esm/types/components → components}/Result/index.d.ts +0 -0
  177. /package/dist/{esm/types/components → components}/Select/Option/Option.d.ts +0 -0
  178. /package/dist/{esm/types/components → components}/Select/Option/index.d.ts +0 -0
  179. /package/dist/{esm/types/components → components}/Select/Select.d.ts +0 -0
  180. /package/dist/{esm/types/components → components}/Select/Tag/Tag.d.ts +0 -0
  181. /package/dist/{esm/types/components → components}/Select/Tag/index.d.ts +0 -0
  182. /package/dist/{esm/types/components → components}/Select/index.d.ts +0 -0
  183. /package/dist/{esm/types/components → components}/Skeleton/Avatar/Avatar.d.ts +0 -0
  184. /package/dist/{esm/types/components → components}/Skeleton/Avatar/index.d.ts +0 -0
  185. /package/dist/{esm/types/components → components}/Skeleton/Button/Button.d.ts +0 -0
  186. /package/dist/{esm/types/components → components}/Skeleton/Button/index.d.ts +0 -0
  187. /package/dist/{esm/types/components → components}/Skeleton/Image/Image.d.ts +0 -0
  188. /package/dist/{esm/types/components → components}/Skeleton/Image/index.d.ts +0 -0
  189. /package/dist/{esm/types/components → components}/Skeleton/Input/Input.d.ts +0 -0
  190. /package/dist/{esm/types/components → components}/Skeleton/Input/index.d.ts +0 -0
  191. /package/dist/{esm/types/components → components}/Skeleton/Skeleton.d.ts +0 -0
  192. /package/dist/{esm/types/components → components}/Skeleton/index.d.ts +0 -0
  193. /package/dist/{esm/types/components → components}/Switch/index.d.ts +0 -0
  194. /package/dist/{esm/types/components → components}/Upload/index.d.ts +0 -0
  195. /package/dist/{esm/types/helpers → helpers}/flatten.d.ts +0 -0
  196. /package/dist/{esm/types/helpers → helpers}/index.d.ts +0 -0
  197. /package/dist/{esm/types/helpers → helpers}/mask.d.ts +0 -0
  198. /package/dist/{esm/types/hooks → hooks}/useForm.d.ts +0 -0
  199. /package/dist/{esm/types/hooks → hooks}/usePosition.d.ts +0 -0
  200. /package/dist/{esm/types/hooks → hooks}/useWatch.d.ts +0 -0
  201. /package/dist/{esm/types/hooks → hooks}/useWatchError.d.ts +0 -0
  202. /package/dist/{esm/types/types → types}/button.d.ts +0 -0
  203. /package/dist/{esm/types/types → types}/checkbox.d.ts +0 -0
  204. /package/dist/{esm/types/types → types}/datepicker.d.ts +0 -0
  205. /package/dist/{esm/types/types → types}/dropdown.d.ts +0 -0
  206. /package/dist/{esm/types/types → types}/empty.d.ts +0 -0
  207. /package/dist/{esm/types/types → types}/form.d.ts +0 -0
  208. /package/dist/{esm/types/types → types}/index.d.ts +0 -0
  209. /package/dist/{esm/types/types → types}/input.d.ts +0 -0
  210. /package/dist/{esm/types/types → types}/menu.d.ts +0 -0
  211. /package/dist/{esm/types/types → types}/popover.d.ts +0 -0
  212. /package/dist/{esm/types/types → types}/radio.d.ts +0 -0
  213. /package/dist/{esm/types/types → types}/result.d.ts +0 -0
  214. /package/dist/{esm/types/types → types}/select.d.ts +0 -0
  215. /package/dist/{esm/types/types → types}/skeleton.d.ts +0 -0
  216. /package/dist/{esm/types/types → types}/switch.d.ts +0 -0
  217. /package/dist/{esm/types/types → types}/upload.d.ts +0 -0
  218. /package/dist/{esm/types/utils → utils}/index.d.ts +0 -0
  219. /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 };