pdyform 1.1.0 → 2.0.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 (175) hide show
  1. package/README.md +28 -1
  2. package/example/README.md +36 -0
  3. package/example/react-demo/dist/assets/index-BBU9cJqy.css +1 -0
  4. package/example/react-demo/dist/assets/index-DeJS8UcQ.js +105 -0
  5. package/example/react-demo/dist/index.html +13 -0
  6. package/example/react-demo/index.html +12 -0
  7. package/example/react-demo/node_modules/.bin/browserslist +17 -0
  8. package/example/react-demo/node_modules/.bin/tsc +17 -0
  9. package/example/react-demo/node_modules/.bin/tsserver +17 -0
  10. package/example/react-demo/node_modules/.bin/vite +17 -0
  11. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js +300 -0
  12. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js.map +7 -0
  13. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js +194 -0
  14. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js.map +7 -0
  15. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js +530 -0
  16. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js.map +7 -0
  17. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js +4808 -0
  18. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js.map +7 -0
  19. package/example/react-demo/node_modules/.vite/deps/_metadata.json +115 -0
  20. package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js +49 -0
  21. package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js.map +7 -0
  22. package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js +127 -0
  23. package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js.map +7 -0
  24. package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js +36 -0
  25. package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js.map +7 -0
  26. package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js +370 -0
  27. package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js.map +7 -0
  28. package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js +928 -0
  29. package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js.map +7 -0
  30. package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js +21 -0
  31. package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js.map +7 -0
  32. package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js +1906 -0
  33. package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js.map +7 -0
  34. package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js +21628 -0
  35. package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js.map +7 -0
  36. package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js +144 -0
  37. package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js.map +7 -0
  38. package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js +51 -0
  39. package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js.map +7 -0
  40. package/example/react-demo/node_modules/.vite/deps/clsx.js +10 -0
  41. package/example/react-demo/node_modules/.vite/deps/clsx.js.map +7 -0
  42. package/example/react-demo/node_modules/.vite/deps/lucide-react.js +29725 -0
  43. package/example/react-demo/node_modules/.vite/deps/lucide-react.js.map +7 -0
  44. package/example/react-demo/node_modules/.vite/deps/package.json +3 -0
  45. package/example/react-demo/node_modules/.vite/deps/react-dom.js +7 -0
  46. package/example/react-demo/node_modules/.vite/deps/react-dom.js.map +7 -0
  47. package/example/react-demo/node_modules/.vite/deps/react-dom_client.js +39 -0
  48. package/example/react-demo/node_modules/.vite/deps/react-dom_client.js.map +7 -0
  49. package/example/react-demo/node_modules/.vite/deps/react.js +6 -0
  50. package/example/react-demo/node_modules/.vite/deps/react.js.map +7 -0
  51. package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +913 -0
  52. package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
  53. package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js +7 -0
  54. package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
  55. package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js +2534 -0
  56. package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js.map +7 -0
  57. package/example/react-demo/package.json +23 -0
  58. package/example/react-demo/postcss.config.mjs +6 -0
  59. package/example/react-demo/src/App.tsx +64 -0
  60. package/example/react-demo/src/main.tsx +10 -0
  61. package/example/react-demo/src/styles.css +102 -0
  62. package/example/react-demo/tailwind.config.mjs +50 -0
  63. package/example/react-demo/tsconfig.json +16 -0
  64. package/example/react-demo/vite.config.ts +14 -0
  65. package/example/shared/defaultSchema.ts +68 -0
  66. package/example/vue-demo/dist/assets/index-BhWj3D5x.css +1 -0
  67. package/example/vue-demo/dist/assets/index-Bw3THsrD.js +44 -0
  68. package/example/vue-demo/dist/index.html +13 -0
  69. package/example/vue-demo/index.html +12 -0
  70. package/example/vue-demo/node_modules/.bin/tsc +17 -0
  71. package/example/vue-demo/node_modules/.bin/tsserver +17 -0
  72. package/example/vue-demo/node_modules/.bin/vite +17 -0
  73. package/example/vue-demo/node_modules/.vite/deps/_metadata.json +46 -0
  74. package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js +10 -0
  75. package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js.map +7 -0
  76. package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js +12877 -0
  77. package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js.map +7 -0
  78. package/example/vue-demo/node_modules/.vite/deps/clsx.js +22 -0
  79. package/example/vue-demo/node_modules/.vite/deps/clsx.js.map +7 -0
  80. package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js +29720 -0
  81. package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js.map +7 -0
  82. package/example/vue-demo/node_modules/.vite/deps/package.json +3 -0
  83. package/example/vue-demo/node_modules/.vite/deps/radix-vue.js +24321 -0
  84. package/example/vue-demo/node_modules/.vite/deps/radix-vue.js.map +7 -0
  85. package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js +2534 -0
  86. package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js.map +7 -0
  87. package/example/vue-demo/node_modules/.vite/deps/vue.js +348 -0
  88. package/example/vue-demo/node_modules/.vite/deps/vue.js.map +7 -0
  89. package/example/vue-demo/package.json +20 -0
  90. package/example/vue-demo/postcss.config.mjs +6 -0
  91. package/example/vue-demo/src/App.vue +61 -0
  92. package/example/vue-demo/src/env.d.ts +1 -0
  93. package/example/vue-demo/src/main.ts +5 -0
  94. package/example/vue-demo/src/style.css +102 -0
  95. package/example/vue-demo/tailwind.config.mjs +50 -0
  96. package/example/vue-demo/tsconfig.json +15 -0
  97. package/example/vue-demo/vite.config.ts +14 -0
  98. package/package.json +10 -2
  99. package/packages/core/dist/{chunk-KQR3LFND.js → chunk-GQASS6PM.js} +20 -0
  100. package/packages/core/dist/index.cjs +20 -0
  101. package/packages/core/dist/index.js +1 -1
  102. package/packages/core/dist/utils.cjs +20 -0
  103. package/packages/core/dist/utils.js +1 -1
  104. package/packages/core/node_modules/.bin/jiti +17 -0
  105. package/packages/core/node_modules/.bin/tsup +2 -2
  106. package/packages/core/node_modules/.bin/tsup-node +2 -2
  107. package/packages/core/node_modules/.vite/vitest/results.json +1 -1
  108. package/packages/core/src/utils.ts +21 -0
  109. package/packages/core/test/utils.test.ts +99 -0
  110. package/packages/react/dist/index.cjs +383 -110
  111. package/packages/react/dist/index.d.cts +80 -4
  112. package/packages/react/dist/index.d.ts +80 -4
  113. package/packages/react/dist/index.js +355 -110
  114. package/packages/react/node_modules/.bin/jiti +17 -0
  115. package/packages/react/node_modules/.bin/tsup +2 -2
  116. package/packages/react/node_modules/.bin/tsup-node +2 -2
  117. package/packages/react/node_modules/.bin/vite +4 -4
  118. package/packages/react/node_modules/.vite/vitest/results.json +1 -1
  119. package/packages/react/package.json +7 -2
  120. package/packages/react/postcss.config.mjs +6 -0
  121. package/packages/react/src/FormFieldRenderer.tsx +32 -112
  122. package/packages/react/src/components/Checkbox.tsx +28 -0
  123. package/packages/react/src/components/CheckboxRenderer.tsx +37 -0
  124. package/packages/react/src/components/Input.tsx +24 -0
  125. package/packages/react/src/components/InputRenderer.tsx +29 -0
  126. package/packages/react/src/components/Label.tsx +24 -0
  127. package/packages/react/src/components/RadioGroup.tsx +42 -0
  128. package/packages/react/src/components/RadioRenderer.tsx +29 -0
  129. package/packages/react/src/components/Select.tsx +93 -0
  130. package/packages/react/src/components/SelectRenderer.tsx +27 -0
  131. package/packages/react/src/components/Textarea.tsx +23 -0
  132. package/packages/react/src/components/TextareaRenderer.tsx +17 -0
  133. package/packages/react/src/components/index.ts +55 -0
  134. package/packages/react/src/components/types.ts +17 -0
  135. package/packages/react/src/index.tsx +1 -0
  136. package/packages/react/src/utils.ts +7 -0
  137. package/packages/react/tailwind.config.mjs +10 -0
  138. package/packages/react/test/FormFieldRenderer.test.tsx +127 -0
  139. package/packages/vue/dist/index.d.ts +33 -0
  140. package/packages/vue/dist/index.js +28 -1
  141. package/packages/vue/dist/index.mjs +6798 -142
  142. package/packages/vue/node_modules/.bin/tsc +2 -2
  143. package/packages/vue/node_modules/.bin/tsserver +2 -2
  144. package/packages/vue/node_modules/.bin/vite +2 -2
  145. package/packages/vue/node_modules/.bin/vitest +2 -2
  146. package/packages/vue/node_modules/.bin/vue-tsc +2 -2
  147. package/packages/vue/node_modules/.vite/vitest/results.json +1 -1
  148. package/packages/vue/package.json +4 -2
  149. package/packages/vue/postcss.config.mjs +6 -0
  150. package/packages/vue/src/FormFieldRenderer.vue +46 -90
  151. package/packages/vue/src/components/Checkbox.vue +28 -0
  152. package/packages/vue/src/components/CheckboxRenderer.vue +35 -0
  153. package/packages/vue/src/components/Input.vue +21 -0
  154. package/packages/vue/src/components/InputRenderer.vue +28 -0
  155. package/packages/vue/src/components/Label.vue +21 -0
  156. package/packages/vue/src/components/RadioGroup.vue +30 -0
  157. package/packages/vue/src/components/RadioGroupItem.vue +26 -0
  158. package/packages/vue/src/components/RadioRenderer.vue +24 -0
  159. package/packages/vue/src/components/Select.vue +40 -0
  160. package/packages/vue/src/components/SelectContent.vue +38 -0
  161. package/packages/vue/src/components/SelectItem.vue +43 -0
  162. package/packages/vue/src/components/SelectRenderer.vue +30 -0
  163. package/packages/vue/src/components/SelectTrigger.vue +27 -0
  164. package/packages/vue/src/components/Textarea.vue +19 -0
  165. package/packages/vue/src/components/TextareaRenderer.vue +18 -0
  166. package/packages/vue/src/components/index.ts +24 -0
  167. package/packages/vue/src/fieldComponentMap.ts +34 -0
  168. package/packages/vue/src/index.ts +2 -0
  169. package/packages/vue/src/utils.ts +6 -0
  170. package/packages/vue/tailwind.config.mjs +10 -0
  171. package/packages/vue/test/FormFieldRenderer.test.ts +133 -0
  172. package/pnpm-workspace.yaml +1 -1
  173. package/packages/core/src/index.test.ts +0 -37
  174. /package/packages/react/{src → test}/DynamicForm.test.tsx +0 -0
  175. /package/packages/vue/{src → test}/DynamicForm.test.ts +0 -0
@@ -26,6 +26,12 @@ __export(index_exports, {
26
26
  module.exports = __toCommonJS(index_exports);
27
27
 
28
28
  // src/utils.ts
29
+ function parseNumberish(value) {
30
+ if (typeof value === "number") return Number.isNaN(value) ? null : value;
31
+ if (typeof value !== "string" || value.trim() === "") return null;
32
+ const parsed = Number(value);
33
+ return Number.isNaN(parsed) ? null : parsed;
34
+ }
29
35
  function validateField(value, field) {
30
36
  if (!field.validations) return null;
31
37
  for (const rule of field.validations) {
@@ -36,6 +42,13 @@ function validateField(value, field) {
36
42
  }
37
43
  break;
38
44
  case "min":
45
+ if (field.type === "number") {
46
+ const numericValue = parseNumberish(value);
47
+ if (numericValue !== null && numericValue < rule.value) {
48
+ return rule.message || `${field.label} must be at least ${rule.value}`;
49
+ }
50
+ break;
51
+ }
39
52
  if (typeof value === "number" && value < rule.value) {
40
53
  return rule.message || `${field.label} must be at least ${rule.value}`;
41
54
  }
@@ -44,6 +57,13 @@ function validateField(value, field) {
44
57
  }
45
58
  break;
46
59
  case "max":
60
+ if (field.type === "number") {
61
+ const numericValue = parseNumberish(value);
62
+ if (numericValue !== null && numericValue > rule.value) {
63
+ return rule.message || `${field.label} must be at most ${rule.value}`;
64
+ }
65
+ break;
66
+ }
47
67
  if (typeof value === "number" && value > rule.value) {
48
68
  return rule.message || `${field.label} must be at most ${rule.value}`;
49
69
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDefaultValues,
3
3
  validateField
4
- } from "./chunk-KQR3LFND.js";
4
+ } from "./chunk-GQASS6PM.js";
5
5
  export {
6
6
  getDefaultValues,
7
7
  validateField
@@ -24,6 +24,12 @@ __export(utils_exports, {
24
24
  validateField: () => validateField
25
25
  });
26
26
  module.exports = __toCommonJS(utils_exports);
27
+ function parseNumberish(value) {
28
+ if (typeof value === "number") return Number.isNaN(value) ? null : value;
29
+ if (typeof value !== "string" || value.trim() === "") return null;
30
+ const parsed = Number(value);
31
+ return Number.isNaN(parsed) ? null : parsed;
32
+ }
27
33
  function validateField(value, field) {
28
34
  if (!field.validations) return null;
29
35
  for (const rule of field.validations) {
@@ -34,6 +40,13 @@ function validateField(value, field) {
34
40
  }
35
41
  break;
36
42
  case "min":
43
+ if (field.type === "number") {
44
+ const numericValue = parseNumberish(value);
45
+ if (numericValue !== null && numericValue < rule.value) {
46
+ return rule.message || `${field.label} must be at least ${rule.value}`;
47
+ }
48
+ break;
49
+ }
37
50
  if (typeof value === "number" && value < rule.value) {
38
51
  return rule.message || `${field.label} must be at least ${rule.value}`;
39
52
  }
@@ -42,6 +55,13 @@ function validateField(value, field) {
42
55
  }
43
56
  break;
44
57
  case "max":
58
+ if (field.type === "number") {
59
+ const numericValue = parseNumberish(value);
60
+ if (numericValue !== null && numericValue > rule.value) {
61
+ return rule.message || `${field.label} must be at most ${rule.value}`;
62
+ }
63
+ break;
64
+ }
45
65
  if (typeof value === "number" && value > rule.value) {
46
66
  return rule.message || `${field.label} must be at most ${rule.value}`;
47
67
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDefaultValues,
3
3
  validateField
4
- } from "./chunk-KQR3LFND.js";
4
+ } from "./chunk-GQASS6PM.js";
5
5
  export {
6
6
  getDefaultValues,
7
7
  validateField
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/jiti@1.21.7/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/jiti@1.21.7/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/jiti.js" "$@"
15
+ else
16
+ exec node "$basedir/../../../../node_modules/.pnpm/jiti@1.21.7/node_modules/jiti/bin/jiti.js" "$@"
17
+ fi
@@ -6,9 +6,9 @@ case `uname` in
6
6
  esac
7
7
 
8
8
  if [ -z "$NODE_PATH" ]; then
9
- export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules"
10
10
  else
11
- export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules:$NODE_PATH"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
14
  exec "$basedir/node" "$basedir/../tsup/dist/cli-default.js" "$@"
@@ -6,9 +6,9 @@ case `uname` in
6
6
  esac
7
7
 
8
8
  if [ -z "$NODE_PATH" ]; then
9
- export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules"
10
10
  else
11
- export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/dist/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.57.6_@types+node@20.19.35__jiti@1.21.7_postcss@8.5.8_typescript@5.9.3/node_modules:/Users/pidan/Work/Learn/dynamic-form/node_modules/.pnpm/node_modules:$NODE_PATH"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
14
  exec "$basedir/node" "$basedir/../tsup/dist/cli-node.js" "$@"
@@ -1 +1 @@
1
- {"version":"1.6.1","results":[[":src/index.test.ts",{"duration":2,"failed":false}]]}
1
+ {"version":"1.6.1","results":[[":test/utils.test.ts",{"duration":3,"failed":false}]]}
@@ -1,5 +1,12 @@
1
1
  import type { FormField } from './types';
2
2
 
3
+ function parseNumberish(value: unknown): number | null {
4
+ if (typeof value === 'number') return Number.isNaN(value) ? null : value;
5
+ if (typeof value !== 'string' || value.trim() === '') return null;
6
+ const parsed = Number(value);
7
+ return Number.isNaN(parsed) ? null : parsed;
8
+ }
9
+
3
10
  export function validateField(value: any, field: FormField): string | null {
4
11
  if (!field.validations) return null;
5
12
 
@@ -11,6 +18,13 @@ export function validateField(value: any, field: FormField): string | null {
11
18
  }
12
19
  break;
13
20
  case 'min':
21
+ if (field.type === 'number') {
22
+ const numericValue = parseNumberish(value);
23
+ if (numericValue !== null && numericValue < rule.value) {
24
+ return rule.message || `${field.label} must be at least ${rule.value}`;
25
+ }
26
+ break;
27
+ }
14
28
  if (typeof value === 'number' && value < rule.value) {
15
29
  return rule.message || `${field.label} must be at least ${rule.value}`;
16
30
  }
@@ -19,6 +33,13 @@ export function validateField(value: any, field: FormField): string | null {
19
33
  }
20
34
  break;
21
35
  case 'max':
36
+ if (field.type === 'number') {
37
+ const numericValue = parseNumberish(value);
38
+ if (numericValue !== null && numericValue > rule.value) {
39
+ return rule.message || `${field.label} must be at most ${rule.value}`;
40
+ }
41
+ break;
42
+ }
22
43
  if (typeof value === 'number' && value > rule.value) {
23
44
  return rule.message || `${field.label} must be at most ${rule.value}`;
24
45
  }
@@ -0,0 +1,99 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { validateField, getDefaultValues } from '../src';
3
+ import { FormField } from '../src/types';
4
+
5
+ describe('core utils - validateField', () => {
6
+ it('returns null if there are no validations', () => {
7
+ const field: FormField = { name: 'f1', label: 'Field 1', type: 'text' };
8
+ expect(validateField('any value', field)).toBeNull();
9
+ });
10
+
11
+ describe('required', () => {
12
+ const field: FormField = { name: 'f1', label: 'Field 1', type: 'text', validations: [{ type: 'required', message: 'req' }] };
13
+
14
+ it('fails on undefined, null, empty string, or empty array', () => {
15
+ expect(validateField(undefined, field)).toBe('req');
16
+ expect(validateField(null, field)).toBe('req');
17
+ expect(validateField('', field)).toBe('req');
18
+ expect(validateField([], field)).toBe('req');
19
+ });
20
+
21
+ it('passes on valid values', () => {
22
+ expect(validateField('test', field)).toBeNull();
23
+ expect(validateField(0, field)).toBeNull();
24
+ expect(validateField(['a'], field)).toBeNull();
25
+ });
26
+ });
27
+
28
+ describe('min/max', () => {
29
+ const fieldStr: FormField = { name: 'f1', label: 'F1', type: 'text', validations: [{ type: 'min', value: 3 }, { type: 'max', value: 5 }] };
30
+ const fieldNum: FormField = { name: 'f2', label: 'F2', type: 'number', validations: [{ type: 'min', value: 10 }, { type: 'max', value: 20 }] };
31
+
32
+ it('validates string length', () => {
33
+ expect(validateField('ab', fieldStr)).toBe('F1 must be at least 3 characters');
34
+ expect(validateField('abc', fieldStr)).toBeNull();
35
+ expect(validateField('abcdef', fieldStr)).toBe('F1 must be at most 5 characters');
36
+ });
37
+
38
+ it('validates number value', () => {
39
+ expect(validateField(9, fieldNum)).toBe('F2 must be at least 10');
40
+ expect(validateField(10, fieldNum)).toBeNull();
41
+ expect(validateField(21, fieldNum)).toBe('F2 must be at most 20');
42
+ });
43
+
44
+ it('treats numeric strings as numbers for number fields', () => {
45
+ expect(validateField('9', fieldNum)).toBe('F2 must be at least 10');
46
+ expect(validateField('10', fieldNum)).toBeNull();
47
+ expect(validateField('22', fieldNum)).toBe('F2 must be at most 20');
48
+ });
49
+ });
50
+
51
+ describe('email', () => {
52
+ const field: FormField = { name: 'e', label: 'E', type: 'text', validations: [{ type: 'email' }] };
53
+
54
+ it('validates email format', () => {
55
+ expect(validateField('invalid', field)).toBe('Invalid email address');
56
+ expect(validateField('test@test.com', field)).toBeNull();
57
+ expect(validateField(undefined, field)).toBeNull(); // Empty check is for required
58
+ });
59
+ });
60
+
61
+ describe('pattern', () => {
62
+ const field: FormField = { name: 'p', label: 'P', type: 'text', validations: [{ type: 'pattern', value: '^[0-9]+$' }] };
63
+
64
+ it('validates regex', () => {
65
+ expect(validateField('abc', field)).toBe('Invalid format');
66
+ expect(validateField('123', field)).toBeNull();
67
+ });
68
+ });
69
+
70
+ describe('custom', () => {
71
+ const field: FormField = {
72
+ name: 'c', label: 'C', type: 'text',
73
+ validations: [{ type: 'custom', validator: (val) => val === 'magic' ? true : 'Not magic' }]
74
+ };
75
+
76
+ it('uses custom validator', () => {
77
+ expect(validateField('test', field)).toBe('Not magic');
78
+ expect(validateField('magic', field)).toBeNull();
79
+ });
80
+ });
81
+ });
82
+
83
+ describe('core utils - getDefaultValues', () => {
84
+ it('returns correctly mapped default values', () => {
85
+ const fields: FormField[] = [
86
+ { name: 't1', label: 'T1', type: 'text', defaultValue: 'default' },
87
+ { name: 't2', label: 'T2', type: 'text' },
88
+ { name: 'cb1', label: 'CB1', type: 'checkbox' },
89
+ { name: 'cb2', label: 'CB2', type: 'checkbox', defaultValue: ['opt1'] }
90
+ ] as any;
91
+
92
+ expect(getDefaultValues(fields)).toEqual({
93
+ t1: 'default',
94
+ t2: '',
95
+ cb1: [],
96
+ cb2: ['opt1']
97
+ });
98
+ });
99
+ });