@axenstudio/axen-form 0.1.17 → 0.1.19

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 (132) hide show
  1. package/README.md +34 -3
  2. package/dist/adapters/yupAdapter.cjs +29 -10
  3. package/dist/adapters/yupAdapter.d.ts +1 -2
  4. package/dist/adapters/yupAdapter.js +29 -10
  5. package/dist/adapters/zodAdapter.cjs +29 -10
  6. package/dist/adapters/zodAdapter.d.ts +1 -2
  7. package/dist/adapters/zodAdapter.js +29 -10
  8. package/dist/core/dateUtils.d.ts +0 -1
  9. package/dist/core/formStore.cjs +214 -47
  10. package/dist/core/formStore.d.ts +5 -2
  11. package/dist/core/formStore.js +214 -47
  12. package/dist/core/numberUtils.d.ts +0 -1
  13. package/dist/core/pathUtils.d.ts +0 -1
  14. package/dist/core/payloadUtils.d.ts +0 -1
  15. package/dist/core/semanticValidation.cjs +82 -0
  16. package/dist/core/semanticValidation.d.ts +5 -0
  17. package/dist/core/semanticValidation.js +82 -0
  18. package/dist/core/validation.cjs +4 -3
  19. package/dist/core/validation.d.ts +0 -1
  20. package/dist/core/validation.js +4 -3
  21. package/dist/fields/AutocompleteField/AutocompleteField.d.ts +1 -2
  22. package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.d.ts +1 -2
  23. package/dist/fields/AutocompletePredictField/AutocompletePredictField.d.ts +1 -2
  24. package/dist/fields/CheckboxField/CheckboxField.d.ts +1 -2
  25. package/dist/fields/ColorField/ColorField.d.ts +1 -2
  26. package/dist/fields/CurrencyField/CurrencyField.d.ts +1 -2
  27. package/dist/fields/DateField/DateField.d.ts +1 -2
  28. package/dist/fields/DateField/DatePicker.d.ts +1 -2
  29. package/dist/fields/DateTimeField/DateTimeField.d.ts +1 -2
  30. package/dist/fields/EmailField/EmailField.d.ts +1 -2
  31. package/dist/fields/NumberField/NumberField.d.ts +1 -2
  32. package/dist/fields/PasswordField/PasswordField.d.ts +1 -2
  33. package/dist/fields/PhoneField/PhoneField.d.ts +1 -2
  34. package/dist/fields/RadioField/RadioField.d.ts +1 -2
  35. package/dist/fields/SelectField/SelectField.d.ts +1 -2
  36. package/dist/fields/SliderField/SliderField.d.ts +1 -2
  37. package/dist/fields/SwitchField/SwitchField.d.ts +1 -2
  38. package/dist/fields/TextField/TextField.d.ts +1 -2
  39. package/dist/fields/TextareaField/TextareaField.d.ts +1 -2
  40. package/dist/fields/TimeField/TimeField.d.ts +1 -2
  41. package/dist/fields/TimeField/TimePicker.d.ts +1 -2
  42. package/dist/fields/defaultComponentMap.cjs +3 -0
  43. package/dist/fields/defaultComponentMap.d.ts +0 -1
  44. package/dist/fields/defaultComponentMap.js +3 -0
  45. package/dist/fields/defaultPlaceholders.d.ts +0 -1
  46. package/dist/fields/fieldBase.module.css.cjs +92 -70
  47. package/dist/fields/fieldBase.module.css.js +92 -70
  48. package/dist/fields/fieldUtils.d.ts +0 -1
  49. package/dist/fields/iconUtils.d.ts +0 -1
  50. package/dist/fields/icons.d.ts +3 -4
  51. package/dist/index.cjs +31 -22
  52. package/dist/index.d.ts +3 -2
  53. package/dist/index.js +32 -23
  54. package/dist/layout/Box/Box.d.ts +1 -2
  55. package/dist/layout/Divider/Divider.d.ts +1 -2
  56. package/dist/layout/Grid/Grid.d.ts +1 -2
  57. package/dist/layout/Spacer/Spacer.d.ts +1 -2
  58. package/dist/layout/Stack/Stack.d.ts +1 -2
  59. package/dist/layout/index.d.ts +0 -1
  60. package/dist/react/AxenArrayField.cjs +2 -0
  61. package/dist/react/AxenArrayField.d.ts +1 -2
  62. package/dist/react/AxenArrayField.js +2 -0
  63. package/dist/react/AxenField.cjs +2 -0
  64. package/dist/react/AxenField.d.ts +1 -2
  65. package/dist/react/AxenField.js +2 -0
  66. package/dist/react/AxenForm.cjs +29 -23
  67. package/dist/react/AxenForm.d.ts +0 -1
  68. package/dist/react/AxenForm.js +30 -24
  69. package/dist/react/FormContext.d.ts +0 -1
  70. package/dist/react/useAxenForm.cjs +17 -4
  71. package/dist/react/useAxenForm.d.ts +1 -2
  72. package/dist/react/useAxenForm.js +17 -4
  73. package/dist/react/useField.cjs +3 -0
  74. package/dist/react/useField.d.ts +0 -1
  75. package/dist/react/useField.js +3 -0
  76. package/dist/react/useFieldArray.cjs +19 -13
  77. package/dist/react/useFieldArray.d.ts +0 -1
  78. package/dist/react/useFieldArray.js +19 -13
  79. package/dist/react/useFormState.cjs +18 -0
  80. package/dist/react/useFormState.d.ts +5 -0
  81. package/dist/react/useFormState.js +18 -0
  82. package/dist/types.d.ts +28 -3
  83. package/package.json +5 -2
  84. package/dist/adapters/yupAdapter.d.ts.map +0 -1
  85. package/dist/adapters/zodAdapter.d.ts.map +0 -1
  86. package/dist/core/dateUtils.d.ts.map +0 -1
  87. package/dist/core/formStore.d.ts.map +0 -1
  88. package/dist/core/numberUtils.d.ts.map +0 -1
  89. package/dist/core/pathUtils.d.ts.map +0 -1
  90. package/dist/core/payloadUtils.d.ts.map +0 -1
  91. package/dist/core/validation.d.ts.map +0 -1
  92. package/dist/fields/AutocompleteField/AutocompleteField.d.ts.map +0 -1
  93. package/dist/fields/AutocompleteMultiField/AutocompleteMultiField.d.ts.map +0 -1
  94. package/dist/fields/AutocompletePredictField/AutocompletePredictField.d.ts.map +0 -1
  95. package/dist/fields/CheckboxField/CheckboxField.d.ts.map +0 -1
  96. package/dist/fields/ColorField/ColorField.d.ts.map +0 -1
  97. package/dist/fields/CurrencyField/CurrencyField.d.ts.map +0 -1
  98. package/dist/fields/DateField/DateField.d.ts.map +0 -1
  99. package/dist/fields/DateField/DatePicker.d.ts.map +0 -1
  100. package/dist/fields/DateTimeField/DateTimeField.d.ts.map +0 -1
  101. package/dist/fields/EmailField/EmailField.d.ts.map +0 -1
  102. package/dist/fields/NumberField/NumberField.d.ts.map +0 -1
  103. package/dist/fields/PasswordField/PasswordField.d.ts.map +0 -1
  104. package/dist/fields/PhoneField/PhoneField.d.ts.map +0 -1
  105. package/dist/fields/RadioField/RadioField.d.ts.map +0 -1
  106. package/dist/fields/SelectField/SelectField.d.ts.map +0 -1
  107. package/dist/fields/SliderField/SliderField.d.ts.map +0 -1
  108. package/dist/fields/SwitchField/SwitchField.d.ts.map +0 -1
  109. package/dist/fields/TextField/TextField.d.ts.map +0 -1
  110. package/dist/fields/TextareaField/TextareaField.d.ts.map +0 -1
  111. package/dist/fields/TimeField/TimeField.d.ts.map +0 -1
  112. package/dist/fields/TimeField/TimePicker.d.ts.map +0 -1
  113. package/dist/fields/defaultComponentMap.d.ts.map +0 -1
  114. package/dist/fields/defaultPlaceholders.d.ts.map +0 -1
  115. package/dist/fields/fieldUtils.d.ts.map +0 -1
  116. package/dist/fields/iconUtils.d.ts.map +0 -1
  117. package/dist/fields/icons.d.ts.map +0 -1
  118. package/dist/index.d.ts.map +0 -1
  119. package/dist/layout/Box/Box.d.ts.map +0 -1
  120. package/dist/layout/Divider/Divider.d.ts.map +0 -1
  121. package/dist/layout/Grid/Grid.d.ts.map +0 -1
  122. package/dist/layout/Spacer/Spacer.d.ts.map +0 -1
  123. package/dist/layout/Stack/Stack.d.ts.map +0 -1
  124. package/dist/layout/index.d.ts.map +0 -1
  125. package/dist/react/AxenArrayField.d.ts.map +0 -1
  126. package/dist/react/AxenField.d.ts.map +0 -1
  127. package/dist/react/AxenForm.d.ts.map +0 -1
  128. package/dist/react/FormContext.d.ts.map +0 -1
  129. package/dist/react/useAxenForm.d.ts.map +0 -1
  130. package/dist/react/useField.d.ts.map +0 -1
  131. package/dist/react/useFieldArray.d.ts.map +0 -1
  132. package/dist/types.d.ts.map +0 -1
package/README.md CHANGED
@@ -324,7 +324,7 @@ const config = {
324
324
  <AxenForm
325
325
  config={config}
326
326
  components={defaultComponentMap}
327
- validationAdapter={yupAdapter}
327
+ validationAdapter={yupAdapter(yup)}
328
328
  onSubmit={handleSubmit}
329
329
  />;
330
330
  ```
@@ -333,11 +333,12 @@ const config = {
333
333
 
334
334
  ```tsx
335
335
  import { zodAdapter } from '@axenstudio/axen-form/adapters/zod';
336
+ import { z } from 'zod';
336
337
 
337
338
  <AxenForm
338
339
  config={config}
339
340
  components={defaultComponentMap}
340
- validationAdapter={zodAdapter}
341
+ validationAdapter={zodAdapter(z)}
341
342
  onSubmit={handleSubmit}
342
343
  />;
343
344
  ```
@@ -964,7 +965,7 @@ Plug in any validation library:
964
965
  | `zodAdapter` | `@axenstudio/axen-form/adapters/zod` | Zod |
965
966
  | `simpleValidator` | Built-in (default) | None |
966
967
 
967
- Both adapters auto-generate schemas from `FieldConfig` (required, min, max, type-aware schema). You can also provide custom `validation` on individual fields.
968
+ Both adapters are factories: call `yupAdapter(yup)` or `zodAdapter(z)` with your installed validation library. They generate type-aware schemas for required fields. Put additional rules such as min/max on the field's custom `validation` schema; the adapters do not infer those rules from display props. The packed-consumer suite verifies Yup 1 and Zod 3.
968
969
 
969
970
  ---
970
971
 
@@ -1138,6 +1139,13 @@ src/
1138
1139
 
1139
1140
  axen-form uses CSS Custom Properties (design tokens) for fine-grained theming.
1140
1141
 
1142
+ Published JS injects the compiled styles automatically; no separate CSS import is needed.
1143
+ Form resets and the default light color scheme apply inside `AxenForm` (or an explicit
1144
+ `data-axen-theme` wrapper). Standalone fields keep their own scoped base styles.
1145
+ Importing the package does not reset unrelated application controls or change the
1146
+ document's color scheme. The namespaced `--axen-*` token defaults remain available
1147
+ on `:root` for standalone layout components.
1148
+
1141
1149
  **Key token categories:**
1142
1150
 
1143
1151
  | Category | Example Tokens |
@@ -1173,6 +1181,29 @@ Requires React 19+ and ES2022+ environment.
1173
1181
 
1174
1182
  ---
1175
1183
 
1184
+ ## Development validation
1185
+
1186
+ From `libs/axen-form`, using the tested Linux/WSL Node 24 and pnpm 10 toolchain:
1187
+
1188
+ ```bash
1189
+ pnpm install --frozen-lockfile
1190
+ pnpm typecheck
1191
+ pnpm test
1192
+ pnpm test:consumer
1193
+ ```
1194
+
1195
+ `test:consumer` builds and packs the library, installs the tarball into a fresh
1196
+ temporary React application, checks public ESM/CJS/types exports and server
1197
+ rendering, then builds that application and runs Chromium desktop/mobile tests.
1198
+ It covers required-field validation, submission and reset with the built-in,
1199
+ Yup 1 and Zod 3 adapters, CSS isolation, and standalone static named imports.
1200
+ It requires npm and network access to install the fixture dependencies and
1201
+ Chromium. The evidence directory is printed and retained under the system temp
1202
+ directory, including browser failure screenshots. The preview uses local port
1203
+ 4179 and fails if that port is already occupied.
1204
+
1205
+ ---
1206
+
1176
1207
  ## License
1177
1208
 
1178
1209
  MIT © [Axen Studio](https://github.com/axenstudio)
@@ -1,33 +1,50 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const pathUtils = require("../core/pathUtils.cjs");
3
4
  function yupAdapter(yup) {
4
5
  return {
5
6
  buildSchema(fields) {
6
7
  const shape = {};
7
8
  for (const field of fields) {
9
+ let rule;
8
10
  if (field.validation) {
9
- shape[field.name] = field.validation;
11
+ rule = field.validation;
10
12
  } else if (field.required) {
11
13
  const msg = field.requiredMessage ?? `${field.label ?? field.name} is required`;
12
14
  switch (field.type) {
13
15
  case "checkbox":
14
16
  case "switch":
15
- shape[field.name] = yup.boolean().oneOf([true], msg).required(msg);
17
+ rule = yup.boolean().oneOf([true], msg).required(msg);
16
18
  break;
17
19
  case "number":
18
20
  case "currency":
19
21
  case "slider":
20
- shape[field.name] = yup.number().required(msg).typeError(msg);
22
+ rule = yup.number().required(msg).typeError(msg);
21
23
  break;
22
24
  case "autocomplete-multi":
23
- shape[field.name] = yup.array().min(1, msg).required(msg);
25
+ rule = yup.array().min(1, msg).required(msg);
24
26
  break;
25
27
  default:
26
- shape[field.name] = yup.string().required(msg);
28
+ rule = yup.string().required(msg);
27
29
  }
28
30
  }
31
+ if (!rule) continue;
32
+ const path = field.name.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
33
+ let node = shape;
34
+ for (const segment of path.slice(0, -1)) {
35
+ node[segment] ?? (node[segment] = {});
36
+ node = node[segment];
37
+ }
38
+ const leaf = path.at(-1);
39
+ if (leaf) node[leaf] = rule;
29
40
  }
30
- return yup.object(shape);
41
+ const nested = (node) => yup.object(Object.fromEntries(
42
+ Object.entries(node).map(([key, value]) => [
43
+ key,
44
+ value && Object.getPrototypeOf(value) === Object.prototype ? nested(value) : value
45
+ ])
46
+ ));
47
+ return nested(shape);
31
48
  },
32
49
  async validate(schema, values) {
33
50
  const yupSchema = schema;
@@ -39,10 +56,12 @@ function yupAdapter(yup) {
39
56
  const errors = {};
40
57
  if (validationError.inner) {
41
58
  for (const e of validationError.inner) {
42
- if (e.path && !errors[e.path]) {
43
- errors[e.path] = e.message;
44
- }
59
+ if (e.path && !errors[e.path]) errors[e.path] = e.message;
45
60
  }
61
+ } else if ("path" in validationError && typeof validationError.path === "string") {
62
+ errors[validationError.path] = validationError.message;
63
+ } else {
64
+ throw err;
46
65
  }
47
66
  return errors;
48
67
  }
@@ -50,7 +69,7 @@ function yupAdapter(yup) {
50
69
  async validateField(schema, name, value) {
51
70
  const yupSchema = schema;
52
71
  try {
53
- await yupSchema.validateAt(name, { [name]: value });
72
+ await yupSchema.validateAt(name, pathUtils.set({}, name, value));
54
73
  return void 0;
55
74
  } catch (err) {
56
75
  return err.message;
@@ -5,7 +5,7 @@ import { ValidationAdapter } from '../types';
5
5
  *
6
6
  * Usage:
7
7
  * import * as yup from 'yup';
8
- * import { yupAdapter } from '@axenstudio/axen-form/yupAdapter';
8
+ * import { yupAdapter } from '@axenstudio/axen-form/adapters/yup';
9
9
  *
10
10
  * const adapter = yupAdapter(yup);
11
11
  */
@@ -18,4 +18,3 @@ interface YupLike {
18
18
  }
19
19
  export declare function yupAdapter(yup: YupLike): ValidationAdapter;
20
20
  export {};
21
- //# sourceMappingURL=yupAdapter.d.ts.map
@@ -1,31 +1,48 @@
1
+ import { set } from "../core/pathUtils.js";
1
2
  function yupAdapter(yup) {
2
3
  return {
3
4
  buildSchema(fields) {
4
5
  const shape = {};
5
6
  for (const field of fields) {
7
+ let rule;
6
8
  if (field.validation) {
7
- shape[field.name] = field.validation;
9
+ rule = field.validation;
8
10
  } else if (field.required) {
9
11
  const msg = field.requiredMessage ?? `${field.label ?? field.name} is required`;
10
12
  switch (field.type) {
11
13
  case "checkbox":
12
14
  case "switch":
13
- shape[field.name] = yup.boolean().oneOf([true], msg).required(msg);
15
+ rule = yup.boolean().oneOf([true], msg).required(msg);
14
16
  break;
15
17
  case "number":
16
18
  case "currency":
17
19
  case "slider":
18
- shape[field.name] = yup.number().required(msg).typeError(msg);
20
+ rule = yup.number().required(msg).typeError(msg);
19
21
  break;
20
22
  case "autocomplete-multi":
21
- shape[field.name] = yup.array().min(1, msg).required(msg);
23
+ rule = yup.array().min(1, msg).required(msg);
22
24
  break;
23
25
  default:
24
- shape[field.name] = yup.string().required(msg);
26
+ rule = yup.string().required(msg);
25
27
  }
26
28
  }
29
+ if (!rule) continue;
30
+ const path = field.name.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
31
+ let node = shape;
32
+ for (const segment of path.slice(0, -1)) {
33
+ node[segment] ?? (node[segment] = {});
34
+ node = node[segment];
35
+ }
36
+ const leaf = path.at(-1);
37
+ if (leaf) node[leaf] = rule;
27
38
  }
28
- return yup.object(shape);
39
+ const nested = (node) => yup.object(Object.fromEntries(
40
+ Object.entries(node).map(([key, value]) => [
41
+ key,
42
+ value && Object.getPrototypeOf(value) === Object.prototype ? nested(value) : value
43
+ ])
44
+ ));
45
+ return nested(shape);
29
46
  },
30
47
  async validate(schema, values) {
31
48
  const yupSchema = schema;
@@ -37,10 +54,12 @@ function yupAdapter(yup) {
37
54
  const errors = {};
38
55
  if (validationError.inner) {
39
56
  for (const e of validationError.inner) {
40
- if (e.path && !errors[e.path]) {
41
- errors[e.path] = e.message;
42
- }
57
+ if (e.path && !errors[e.path]) errors[e.path] = e.message;
43
58
  }
59
+ } else if ("path" in validationError && typeof validationError.path === "string") {
60
+ errors[validationError.path] = validationError.message;
61
+ } else {
62
+ throw err;
44
63
  }
45
64
  return errors;
46
65
  }
@@ -48,7 +67,7 @@ function yupAdapter(yup) {
48
67
  async validateField(schema, name, value) {
49
68
  const yupSchema = schema;
50
69
  try {
51
- await yupSchema.validateAt(name, { [name]: value });
70
+ await yupSchema.validateAt(name, set({}, name, value));
52
71
  return void 0;
53
72
  } catch (err) {
54
73
  return err.message;
@@ -5,29 +5,45 @@ function zodAdapter(z) {
5
5
  buildSchema(fields) {
6
6
  const shape = {};
7
7
  for (const field of fields) {
8
+ let rule;
8
9
  if (field.validation) {
9
- shape[field.name] = field.validation;
10
+ rule = field.validation;
10
11
  } else if (field.required) {
11
12
  const msg = field.requiredMessage ?? `${field.label ?? field.name} is required`;
12
13
  switch (field.type) {
13
14
  case "checkbox":
14
15
  case "switch":
15
- shape[field.name] = z.literal(true, { errorMap: () => ({ message: msg }) });
16
+ rule = z.literal(true, { errorMap: () => ({ message: msg }) });
16
17
  break;
17
18
  case "number":
18
19
  case "currency":
19
20
  case "slider":
20
- shape[field.name] = z.number({ required_error: msg, invalid_type_error: msg });
21
+ rule = z.number({ required_error: msg, invalid_type_error: msg });
21
22
  break;
22
23
  case "autocomplete-multi":
23
- shape[field.name] = z.array(z.unknown()).min(1, msg);
24
+ rule = z.array(z.unknown()).min(1, msg);
24
25
  break;
25
26
  default:
26
- shape[field.name] = z.string({ required_error: msg }).min(1, msg);
27
+ rule = z.string({ required_error: msg }).min(1, msg);
27
28
  }
28
29
  }
30
+ if (!rule) continue;
31
+ const path = field.name.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
32
+ let node = shape;
33
+ for (const segment of path.slice(0, -1)) {
34
+ node[segment] ?? (node[segment] = {});
35
+ node = node[segment];
36
+ }
37
+ const leaf = path.at(-1);
38
+ if (leaf) node[leaf] = rule;
29
39
  }
30
- return z.object(shape);
40
+ const nested = (node) => z.object(Object.fromEntries(
41
+ Object.entries(node).map(([key, value]) => [
42
+ key,
43
+ value && Object.getPrototypeOf(value) === Object.prototype ? nested(value) : value
44
+ ])
45
+ ));
46
+ return nested(shape);
31
47
  },
32
48
  async validate(schema, values) {
33
49
  var _a;
@@ -46,13 +62,16 @@ function zodAdapter(z) {
46
62
  return errors;
47
63
  },
48
64
  async validateField(schema, name, value) {
49
- var _a, _b;
65
+ var _a, _b, _c;
50
66
  const zodSchema = schema;
51
- const fieldSchema = zodSchema.shape[name];
52
- if (!fieldSchema) return void 0;
67
+ let fieldSchema = zodSchema;
68
+ for (const segment of name.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean)) {
69
+ fieldSchema = (_a = fieldSchema.shape) == null ? void 0 : _a[segment];
70
+ if (!fieldSchema) return void 0;
71
+ }
53
72
  const result = fieldSchema.safeParse(value);
54
73
  if (result.success) return void 0;
55
- return (_b = (_a = result.error) == null ? void 0 : _a.issues[0]) == null ? void 0 : _b.message;
74
+ return (_c = (_b = result.error) == null ? void 0 : _b.issues[0]) == null ? void 0 : _c.message;
56
75
  }
57
76
  };
58
77
  }
@@ -5,7 +5,7 @@ import { ValidationAdapter } from '../types';
5
5
  *
6
6
  * Usage:
7
7
  * import { z } from 'zod';
8
- * import { zodAdapter } from '@axenstudio/axen-form/zodAdapter';
8
+ * import { zodAdapter } from '@axenstudio/axen-form/adapters/zod';
9
9
  *
10
10
  * const adapter = zodAdapter(z);
11
11
  */
@@ -19,4 +19,3 @@ interface ZodLike {
19
19
  }
20
20
  export declare function zodAdapter(z: ZodLike): ValidationAdapter;
21
21
  export {};
22
- //# sourceMappingURL=zodAdapter.d.ts.map
@@ -3,29 +3,45 @@ function zodAdapter(z) {
3
3
  buildSchema(fields) {
4
4
  const shape = {};
5
5
  for (const field of fields) {
6
+ let rule;
6
7
  if (field.validation) {
7
- shape[field.name] = field.validation;
8
+ rule = field.validation;
8
9
  } else if (field.required) {
9
10
  const msg = field.requiredMessage ?? `${field.label ?? field.name} is required`;
10
11
  switch (field.type) {
11
12
  case "checkbox":
12
13
  case "switch":
13
- shape[field.name] = z.literal(true, { errorMap: () => ({ message: msg }) });
14
+ rule = z.literal(true, { errorMap: () => ({ message: msg }) });
14
15
  break;
15
16
  case "number":
16
17
  case "currency":
17
18
  case "slider":
18
- shape[field.name] = z.number({ required_error: msg, invalid_type_error: msg });
19
+ rule = z.number({ required_error: msg, invalid_type_error: msg });
19
20
  break;
20
21
  case "autocomplete-multi":
21
- shape[field.name] = z.array(z.unknown()).min(1, msg);
22
+ rule = z.array(z.unknown()).min(1, msg);
22
23
  break;
23
24
  default:
24
- shape[field.name] = z.string({ required_error: msg }).min(1, msg);
25
+ rule = z.string({ required_error: msg }).min(1, msg);
25
26
  }
26
27
  }
28
+ if (!rule) continue;
29
+ const path = field.name.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
30
+ let node = shape;
31
+ for (const segment of path.slice(0, -1)) {
32
+ node[segment] ?? (node[segment] = {});
33
+ node = node[segment];
34
+ }
35
+ const leaf = path.at(-1);
36
+ if (leaf) node[leaf] = rule;
27
37
  }
28
- return z.object(shape);
38
+ const nested = (node) => z.object(Object.fromEntries(
39
+ Object.entries(node).map(([key, value]) => [
40
+ key,
41
+ value && Object.getPrototypeOf(value) === Object.prototype ? nested(value) : value
42
+ ])
43
+ ));
44
+ return nested(shape);
29
45
  },
30
46
  async validate(schema, values) {
31
47
  var _a;
@@ -44,13 +60,16 @@ function zodAdapter(z) {
44
60
  return errors;
45
61
  },
46
62
  async validateField(schema, name, value) {
47
- var _a, _b;
63
+ var _a, _b, _c;
48
64
  const zodSchema = schema;
49
- const fieldSchema = zodSchema.shape[name];
50
- if (!fieldSchema) return void 0;
65
+ let fieldSchema = zodSchema;
66
+ for (const segment of name.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean)) {
67
+ fieldSchema = (_a = fieldSchema.shape) == null ? void 0 : _a[segment];
68
+ if (!fieldSchema) return void 0;
69
+ }
51
70
  const result = fieldSchema.safeParse(value);
52
71
  if (result.success) return void 0;
53
- return (_b = (_a = result.error) == null ? void 0 : _a.issues[0]) == null ? void 0 : _b.message;
72
+ return (_c = (_b = result.error) == null ? void 0 : _b.issues[0]) == null ? void 0 : _c.message;
54
73
  }
55
74
  };
56
75
  }
@@ -25,4 +25,3 @@ export declare function toISOTimeString(date: Date): string;
25
25
  * Falls back to 'en-US' in non-browser environments (SSR/tests).
26
26
  */
27
27
  export declare function getDefaultLocale(): string;
28
- //# sourceMappingURL=dateUtils.d.ts.map