pdyform 2.0.2 → 2.2.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.
- package/README.md +98 -74
- package/package.json +9 -3
- package/packages/core/dist/chunk-6F4PWJZI.js +0 -0
- package/packages/core/dist/chunk-KA6QUMVR.js +158 -0
- package/packages/core/dist/chunk-REHKL5VH.js +76 -0
- package/packages/core/dist/formState.cjs +132 -78
- package/packages/core/dist/formState.d.cts +14 -10
- package/packages/core/dist/formState.d.ts +14 -10
- package/packages/core/dist/formState.js +4 -12
- package/packages/core/dist/index.cjs +138 -78
- package/packages/core/dist/index.d.cts +4 -3
- package/packages/core/dist/index.d.ts +4 -3
- package/packages/core/dist/index.js +11 -12
- package/packages/core/dist/types.d.cts +17 -5
- package/packages/core/dist/types.d.ts +17 -5
- package/packages/core/dist/types.js +1 -0
- package/packages/core/dist/utils.cjs +78 -19
- package/packages/core/dist/utils.d.cts +17 -5
- package/packages/core/dist/utils.d.ts +17 -5
- package/packages/core/dist/utils.js +7 -1
- package/packages/react/dist/index.cjs +1 -461
- package/packages/react/dist/index.d.cts +33 -2
- package/packages/react/dist/index.d.ts +33 -2
- package/packages/react/dist/index.js +1 -411
- package/packages/vue/dist/index.d.ts +51 -39
- package/packages/vue/dist/index.js +1 -28
- package/packages/vue/dist/index.mjs +630 -6527
- package/eslint.config.mjs +0 -53
- package/example/README.md +0 -36
- package/example/react-demo/index.html +0 -12
- package/example/react-demo/node_modules/.bin/browserslist +0 -17
- package/example/react-demo/node_modules/.bin/tsc +0 -17
- package/example/react-demo/node_modules/.bin/tsserver +0 -17
- package/example/react-demo/node_modules/.bin/vite +0 -17
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js +0 -300
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js +0 -194
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js +0 -530
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js +0 -4808
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/_metadata.json +0 -115
- package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js +0 -49
- package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js +0 -127
- package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js +0 -36
- package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js +0 -370
- package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js +0 -928
- package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js +0 -21
- package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js +0 -1906
- package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js +0 -21628
- package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js +0 -144
- package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js +0 -51
- package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/clsx.js +0 -10
- package/example/react-demo/node_modules/.vite/deps/clsx.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/lucide-react.js +0 -29725
- package/example/react-demo/node_modules/.vite/deps/lucide-react.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/package.json +0 -3
- package/example/react-demo/node_modules/.vite/deps/react-dom.js +0 -7
- package/example/react-demo/node_modules/.vite/deps/react-dom.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/react-dom_client.js +0 -39
- package/example/react-demo/node_modules/.vite/deps/react-dom_client.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/react.js +0 -6
- package/example/react-demo/node_modules/.vite/deps/react.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +0 -913
- package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js +0 -7
- package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js.map +0 -7
- package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js +0 -2534
- package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js.map +0 -7
- package/example/react-demo/package.json +0 -23
- package/example/react-demo/postcss.config.mjs +0 -6
- package/example/react-demo/src/App.tsx +0 -64
- package/example/react-demo/src/main.tsx +0 -10
- package/example/react-demo/src/styles.css +0 -102
- package/example/react-demo/tailwind.config.mjs +0 -50
- package/example/react-demo/tsconfig.json +0 -16
- package/example/react-demo/vite.config.ts +0 -14
- package/example/shared/defaultSchema.ts +0 -68
- package/example/vue-demo/index.html +0 -12
- package/example/vue-demo/node_modules/.bin/tsc +0 -17
- package/example/vue-demo/node_modules/.bin/tsserver +0 -17
- package/example/vue-demo/node_modules/.bin/vite +0 -17
- package/example/vue-demo/node_modules/.vite/deps/_metadata.json +0 -46
- package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js +0 -10
- package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js.map +0 -7
- package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js +0 -12877
- package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js.map +0 -7
- package/example/vue-demo/node_modules/.vite/deps/clsx.js +0 -22
- package/example/vue-demo/node_modules/.vite/deps/clsx.js.map +0 -7
- package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js +0 -29720
- package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js.map +0 -7
- package/example/vue-demo/node_modules/.vite/deps/package.json +0 -3
- package/example/vue-demo/node_modules/.vite/deps/radix-vue.js +0 -24321
- package/example/vue-demo/node_modules/.vite/deps/radix-vue.js.map +0 -7
- package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js +0 -2534
- package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js.map +0 -7
- package/example/vue-demo/node_modules/.vite/deps/vue.js +0 -348
- package/example/vue-demo/node_modules/.vite/deps/vue.js.map +0 -7
- package/example/vue-demo/package.json +0 -20
- package/example/vue-demo/postcss.config.mjs +0 -6
- package/example/vue-demo/src/App.vue +0 -61
- package/example/vue-demo/src/env.d.ts +0 -1
- package/example/vue-demo/src/main.ts +0 -5
- package/example/vue-demo/src/style.css +0 -102
- package/example/vue-demo/tailwind.config.mjs +0 -50
- package/example/vue-demo/tsconfig.json +0 -15
- package/example/vue-demo/vite.config.ts +0 -14
- package/packages/core/dist/chunk-TP3IHKWV.js +0 -69
- package/packages/core/dist/chunk-WEDHXOHH.js +0 -102
- package/packages/core/node_modules/.bin/api-extractor +0 -17
- package/packages/core/node_modules/.bin/esbuild +0 -14
- package/packages/core/node_modules/.bin/jiti +0 -17
- package/packages/core/node_modules/.bin/tsc +0 -17
- package/packages/core/node_modules/.bin/tsserver +0 -17
- package/packages/core/node_modules/.bin/tsup +0 -17
- package/packages/core/node_modules/.bin/tsup-node +0 -17
- package/packages/core/node_modules/.bin/vitest +0 -17
- package/packages/core/node_modules/.vite/vitest/results.json +0 -1
- package/packages/core/package.json +0 -37
- package/packages/core/src/formState.ts +0 -79
- package/packages/core/src/index.ts +0 -3
- package/packages/core/src/types.ts +0 -42
- package/packages/core/src/utils.ts +0 -104
- package/packages/core/test/formState.test.ts +0 -71
- package/packages/core/test/utils.test.ts +0 -178
- package/packages/core/tsconfig.json +0 -15
- package/packages/core/tsup.config.ts +0 -9
- package/packages/react/node_modules/.bin/api-extractor +0 -17
- package/packages/react/node_modules/.bin/browserslist +0 -17
- package/packages/react/node_modules/.bin/esbuild +0 -14
- package/packages/react/node_modules/.bin/jiti +0 -17
- package/packages/react/node_modules/.bin/tsc +0 -17
- package/packages/react/node_modules/.bin/tsserver +0 -17
- package/packages/react/node_modules/.bin/tsup +0 -17
- package/packages/react/node_modules/.bin/tsup-node +0 -17
- package/packages/react/node_modules/.bin/vite +0 -17
- package/packages/react/node_modules/.bin/vitest +0 -17
- package/packages/react/node_modules/.vite/vitest/results.json +0 -1
- package/packages/react/package.json +0 -57
- package/packages/react/postcss.config.mjs +0 -6
- package/packages/react/src/DynamicForm.tsx +0 -69
- package/packages/react/src/FormFieldRenderer.tsx +0 -50
- package/packages/react/src/components/Checkbox.tsx +0 -28
- package/packages/react/src/components/CheckboxRenderer.tsx +0 -37
- package/packages/react/src/components/Input.tsx +0 -24
- package/packages/react/src/components/InputRenderer.tsx +0 -25
- package/packages/react/src/components/Label.tsx +0 -24
- package/packages/react/src/components/RadioGroup.tsx +0 -42
- package/packages/react/src/components/RadioRenderer.tsx +0 -29
- package/packages/react/src/components/Select.tsx +0 -93
- package/packages/react/src/components/SelectRenderer.tsx +0 -27
- package/packages/react/src/components/Textarea.tsx +0 -23
- package/packages/react/src/components/TextareaRenderer.tsx +0 -17
- package/packages/react/src/components/index.ts +0 -55
- package/packages/react/src/components/types.ts +0 -17
- package/packages/react/src/index.tsx +0 -3
- package/packages/react/src/utils.ts +0 -7
- package/packages/react/tailwind.config.mjs +0 -10
- package/packages/react/test/DynamicForm.test.tsx +0 -25
- package/packages/react/test/FormFieldRenderer.test.tsx +0 -127
- package/packages/react/tsconfig.json +0 -15
- package/packages/react/vitest.config.ts +0 -16
- package/packages/vue/node_modules/.bin/rollup +0 -17
- package/packages/vue/node_modules/.bin/tsc +0 -17
- package/packages/vue/node_modules/.bin/tsserver +0 -17
- package/packages/vue/node_modules/.bin/vite +0 -17
- package/packages/vue/node_modules/.bin/vitest +0 -17
- package/packages/vue/node_modules/.bin/vue-tsc +0 -17
- package/packages/vue/node_modules/.vite/vitest/results.json +0 -1
- package/packages/vue/node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts +0 -118
- package/packages/vue/node_modules/.vue-global-types/vue_3.5_false.d.ts +0 -128
- package/packages/vue/package.json +0 -53
- package/packages/vue/postcss.config.mjs +0 -6
- package/packages/vue/src/DynamicForm.vue +0 -63
- package/packages/vue/src/FormFieldRenderer.vue +0 -70
- package/packages/vue/src/components/Checkbox.vue +0 -28
- package/packages/vue/src/components/CheckboxRenderer.vue +0 -35
- package/packages/vue/src/components/Input.vue +0 -21
- package/packages/vue/src/components/InputRenderer.vue +0 -24
- package/packages/vue/src/components/Label.vue +0 -21
- package/packages/vue/src/components/RadioGroup.vue +0 -30
- package/packages/vue/src/components/RadioGroupItem.vue +0 -26
- package/packages/vue/src/components/RadioRenderer.vue +0 -24
- package/packages/vue/src/components/Select.vue +0 -40
- package/packages/vue/src/components/SelectContent.vue +0 -38
- package/packages/vue/src/components/SelectItem.vue +0 -43
- package/packages/vue/src/components/SelectRenderer.vue +0 -30
- package/packages/vue/src/components/SelectTrigger.vue +0 -27
- package/packages/vue/src/components/Textarea.vue +0 -19
- package/packages/vue/src/components/TextareaRenderer.vue +0 -18
- package/packages/vue/src/components/index.ts +0 -24
- package/packages/vue/src/env.d.ts +0 -7
- package/packages/vue/src/fieldComponentMap.ts +0 -34
- package/packages/vue/src/index.ts +0 -4
- package/packages/vue/src/utils.ts +0 -6
- package/packages/vue/tailwind.config.mjs +0 -10
- package/packages/vue/test/DynamicForm.test.ts +0 -19
- package/packages/vue/test/FormFieldRenderer.test.ts +0 -133
- package/packages/vue/tsconfig.json +0 -16
- package/packages/vue/vite.config.ts +0 -29
- package/packages/vue/vitest.config.ts +0 -16
- package/pnpm-workspace.yaml +0 -4
- package/tsconfig.json +0 -21
- package/turbo.json +0 -25
|
@@ -20,13 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
createFormStore: () => createFormStore,
|
|
24
|
+
defaultErrorMessages: () => defaultErrorMessages,
|
|
25
|
+
get: () => get,
|
|
26
26
|
getDefaultValues: () => getDefaultValues,
|
|
27
27
|
normalizeFieldValue: () => normalizeFieldValue,
|
|
28
|
-
|
|
29
|
-
setSubmitting: () => setSubmitting,
|
|
28
|
+
set: () => set,
|
|
30
29
|
validateField: () => validateField,
|
|
31
30
|
validateFieldByName: () => validateFieldByName,
|
|
32
31
|
validateForm: () => validateForm
|
|
@@ -40,85 +39,138 @@ function parseNumberish(value) {
|
|
|
40
39
|
const parsed = Number(value);
|
|
41
40
|
return Number.isNaN(parsed) ? null : parsed;
|
|
42
41
|
}
|
|
42
|
+
var defaultErrorMessages = {
|
|
43
|
+
required: "{label} is required",
|
|
44
|
+
min: "{label} must be at least {value}",
|
|
45
|
+
max: "{label} must be at most {value}",
|
|
46
|
+
email: "Invalid email address",
|
|
47
|
+
pattern: "Invalid format",
|
|
48
|
+
custom: "Invalid value"
|
|
49
|
+
};
|
|
50
|
+
function formatMessage(template, field, rule) {
|
|
51
|
+
return template.replace("{label}", field.label).replace("{value}", String(rule.value || ""));
|
|
52
|
+
}
|
|
53
|
+
function get(obj, path, defaultValue) {
|
|
54
|
+
if (!path) return defaultValue;
|
|
55
|
+
const keys = path.split(/[.[\]]/).filter(Boolean);
|
|
56
|
+
let result = obj;
|
|
57
|
+
for (const key of keys) {
|
|
58
|
+
if (result === null || result === void 0) return defaultValue;
|
|
59
|
+
result = result[key];
|
|
60
|
+
}
|
|
61
|
+
return result === void 0 ? defaultValue : result;
|
|
62
|
+
}
|
|
63
|
+
function set(obj, path, value) {
|
|
64
|
+
if (Object(obj) !== obj) return obj;
|
|
65
|
+
const keys = path.split(/[.[\]]/).filter(Boolean);
|
|
66
|
+
const newObj = { ...obj };
|
|
67
|
+
let current = newObj;
|
|
68
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
69
|
+
const key = keys[i];
|
|
70
|
+
const nextKey = keys[i + 1];
|
|
71
|
+
const isNextKeyIndex = /^\d+$/.test(nextKey);
|
|
72
|
+
if (!(key in current) || current[key] === null || typeof current[key] !== "object") {
|
|
73
|
+
current[key] = isNextKeyIndex ? [] : {};
|
|
74
|
+
} else {
|
|
75
|
+
current[key] = Array.isArray(current[key]) ? [...current[key]] : { ...current[key] };
|
|
76
|
+
}
|
|
77
|
+
current = current[key];
|
|
78
|
+
}
|
|
79
|
+
current[keys[keys.length - 1]] = value;
|
|
80
|
+
return newObj;
|
|
81
|
+
}
|
|
43
82
|
function normalizeFieldValue(field, value) {
|
|
44
83
|
if (field.type !== "number") return value;
|
|
45
84
|
if (value === "" || value === void 0 || value === null) return "";
|
|
46
85
|
const numericValue = parseNumberish(value);
|
|
47
86
|
return numericValue === null ? value : numericValue;
|
|
48
87
|
}
|
|
49
|
-
function validateField(value, field) {
|
|
88
|
+
async function validateField(value, field, customMessages) {
|
|
50
89
|
if (!field.validations) return null;
|
|
90
|
+
const messages = { ...defaultErrorMessages, ...customMessages };
|
|
51
91
|
for (const rule of field.validations) {
|
|
52
92
|
switch (rule.type) {
|
|
53
93
|
case "required":
|
|
54
94
|
if (value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0) {
|
|
55
|
-
return rule.message ||
|
|
95
|
+
return rule.message || formatMessage(messages.required, field, rule);
|
|
56
96
|
}
|
|
57
97
|
break;
|
|
58
98
|
case "min":
|
|
59
99
|
if (field.type === "number") {
|
|
60
100
|
const numericValue = parseNumberish(value);
|
|
61
101
|
if (numericValue !== null && numericValue < rule.value) {
|
|
62
|
-
|
|
102
|
+
const template = field.type === "number" ? messages.min : typeof value === "string" ? "{label} must be at least {value} characters" : messages.min;
|
|
103
|
+
return rule.message || formatMessage(template, field, rule);
|
|
63
104
|
}
|
|
64
105
|
break;
|
|
65
106
|
}
|
|
66
107
|
if (typeof value === "number" && value < rule.value) {
|
|
67
|
-
return rule.message ||
|
|
108
|
+
return rule.message || formatMessage(messages.min, field, rule);
|
|
68
109
|
}
|
|
69
110
|
if (typeof value === "string" && value.length < rule.value) {
|
|
70
|
-
|
|
111
|
+
const template = "{label} must be at least {value} characters";
|
|
112
|
+
return rule.message || formatMessage(template, field, rule);
|
|
71
113
|
}
|
|
72
114
|
break;
|
|
73
115
|
case "max":
|
|
74
116
|
if (field.type === "number") {
|
|
75
117
|
const numericValue = parseNumberish(value);
|
|
76
118
|
if (numericValue !== null && numericValue > rule.value) {
|
|
77
|
-
return rule.message ||
|
|
119
|
+
return rule.message || formatMessage(messages.max, field, rule);
|
|
78
120
|
}
|
|
79
121
|
break;
|
|
80
122
|
}
|
|
81
123
|
if (typeof value === "number" && value > rule.value) {
|
|
82
|
-
return rule.message ||
|
|
124
|
+
return rule.message || formatMessage(messages.max, field, rule);
|
|
83
125
|
}
|
|
84
126
|
if (typeof value === "string" && value.length > rule.value) {
|
|
85
|
-
|
|
127
|
+
const template = "{label} must be at most {value} characters";
|
|
128
|
+
return rule.message || formatMessage(template, field, rule);
|
|
86
129
|
}
|
|
87
130
|
break;
|
|
88
131
|
case "email": {
|
|
89
132
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
90
133
|
if (value && !emailRegex.test(value)) {
|
|
91
|
-
return rule.message ||
|
|
134
|
+
return rule.message || formatMessage(messages.email, field, rule);
|
|
92
135
|
}
|
|
93
136
|
break;
|
|
94
137
|
}
|
|
95
138
|
case "pattern":
|
|
96
139
|
if (value && rule.value && !new RegExp(rule.value).test(value)) {
|
|
97
|
-
return rule.message ||
|
|
140
|
+
return rule.message || formatMessage(messages.pattern, field, rule);
|
|
98
141
|
}
|
|
99
142
|
break;
|
|
100
143
|
case "custom":
|
|
101
144
|
if (rule.validator) {
|
|
102
|
-
const result = rule.validator(value);
|
|
145
|
+
const result = await rule.validator(value);
|
|
103
146
|
if (typeof result === "string") return result;
|
|
104
|
-
if (
|
|
147
|
+
if (result === false) return rule.message || formatMessage(messages.custom, field, rule);
|
|
105
148
|
}
|
|
106
149
|
break;
|
|
107
150
|
}
|
|
108
151
|
}
|
|
109
152
|
return null;
|
|
110
153
|
}
|
|
111
|
-
function validateFieldByName(fields, name, value) {
|
|
154
|
+
async function validateFieldByName(fields, name, value, resolver, allValues, customMessages) {
|
|
155
|
+
if (resolver && allValues) {
|
|
156
|
+
const resolverErrors = await resolver(allValues);
|
|
157
|
+
if (resolverErrors[name]) return resolverErrors[name];
|
|
158
|
+
}
|
|
112
159
|
const field = fields.find((f) => f.name === name);
|
|
113
160
|
if (!field) return null;
|
|
114
|
-
return validateField(value, field);
|
|
161
|
+
return await validateField(value, field, customMessages);
|
|
115
162
|
}
|
|
116
|
-
function validateForm(fields, values) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (error) errors[field.name] = error;
|
|
163
|
+
async function validateForm(fields, values, resolver, customMessages) {
|
|
164
|
+
let errors = {};
|
|
165
|
+
if (resolver) {
|
|
166
|
+
errors = await resolver(values);
|
|
121
167
|
}
|
|
168
|
+
const validationPromises = fields.map(async (field) => {
|
|
169
|
+
if (errors[field.name]) return;
|
|
170
|
+
const error = await validateField(get(values, field.name), field, customMessages);
|
|
171
|
+
if (error) errors[field.name] = error;
|
|
172
|
+
});
|
|
173
|
+
await Promise.all(validationPromises);
|
|
122
174
|
return errors;
|
|
123
175
|
}
|
|
124
176
|
function getDefaultValues(fields) {
|
|
@@ -129,68 +181,76 @@ function getDefaultValues(fields) {
|
|
|
129
181
|
}
|
|
130
182
|
|
|
131
183
|
// src/formState.ts
|
|
132
|
-
|
|
133
|
-
|
|
184
|
+
var import_vanilla = require("zustand/vanilla");
|
|
185
|
+
function createFormStore(fields, resolver, errorMessages) {
|
|
186
|
+
return (0, import_vanilla.createStore)()((set2, getStore) => ({
|
|
134
187
|
values: getDefaultValues(fields),
|
|
135
188
|
errors: {},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
...state,
|
|
159
|
-
values,
|
|
160
|
-
errors
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
function applyFieldBlur(fields, state, name) {
|
|
164
|
-
const error = validateFieldByName(fields, name, state.values[name]);
|
|
165
|
-
return {
|
|
166
|
-
...state,
|
|
167
|
-
errors: {
|
|
168
|
-
...state.errors,
|
|
169
|
-
[name]: error || ""
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
function runSubmitValidation(fields, state) {
|
|
174
|
-
const errors = validateForm(fields, state.values);
|
|
175
|
-
const hasError = Object.keys(errors).length > 0;
|
|
176
|
-
return {
|
|
177
|
-
state: {
|
|
178
|
-
...state,
|
|
179
|
-
errors,
|
|
180
|
-
isSubmitting: false
|
|
189
|
+
validatingFields: [],
|
|
190
|
+
isSubmitting: false,
|
|
191
|
+
setFieldValue: async (name, rawValue) => {
|
|
192
|
+
const field = fields.find((f) => f.name === name);
|
|
193
|
+
const normalizedValue = field ? normalizeFieldValue(field, rawValue) : rawValue;
|
|
194
|
+
set2((state) => ({
|
|
195
|
+
values: set(state.values, name, normalizedValue),
|
|
196
|
+
validatingFields: [...state.validatingFields, name]
|
|
197
|
+
}));
|
|
198
|
+
try {
|
|
199
|
+
const currentValues = getStore().values;
|
|
200
|
+
const error = await validateFieldByName(fields, name, normalizedValue, resolver, currentValues, errorMessages);
|
|
201
|
+
set2((state) => ({
|
|
202
|
+
errors: { ...state.errors, [name]: error || "" },
|
|
203
|
+
validatingFields: state.validatingFields.filter((f) => f !== name)
|
|
204
|
+
}));
|
|
205
|
+
} catch (err) {
|
|
206
|
+
set2((state) => ({
|
|
207
|
+
validatingFields: state.validatingFields.filter((f) => f !== name)
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
181
210
|
},
|
|
182
|
-
|
|
183
|
-
|
|
211
|
+
setFieldBlur: async (name) => {
|
|
212
|
+
set2((state) => ({
|
|
213
|
+
validatingFields: [...state.validatingFields, name]
|
|
214
|
+
}));
|
|
215
|
+
try {
|
|
216
|
+
const currentValues = getStore().values;
|
|
217
|
+
const value = get(currentValues, name);
|
|
218
|
+
const error = await validateFieldByName(fields, name, value, resolver, currentValues, errorMessages);
|
|
219
|
+
set2((state) => ({
|
|
220
|
+
errors: { ...state.errors, [name]: error || "" },
|
|
221
|
+
validatingFields: state.validatingFields.filter((f) => f !== name)
|
|
222
|
+
}));
|
|
223
|
+
} catch (err) {
|
|
224
|
+
set2((state) => ({
|
|
225
|
+
validatingFields: state.validatingFields.filter((f) => f !== name)
|
|
226
|
+
}));
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
setSubmitting: (isSubmitting) => set2({ isSubmitting }),
|
|
230
|
+
runSubmitValidation: async () => {
|
|
231
|
+
set2({ isSubmitting: true });
|
|
232
|
+
const state = getStore();
|
|
233
|
+
const errors = await validateForm(fields, state.values, resolver, errorMessages);
|
|
234
|
+
const hasError = Object.keys(errors).length > 0;
|
|
235
|
+
set2({
|
|
236
|
+
errors,
|
|
237
|
+
isSubmitting: false
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
state: getStore(),
|
|
241
|
+
hasError
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}));
|
|
184
245
|
}
|
|
185
246
|
// Annotate the CommonJS export names for ESM import in node:
|
|
186
247
|
0 && (module.exports = {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
248
|
+
createFormStore,
|
|
249
|
+
defaultErrorMessages,
|
|
250
|
+
get,
|
|
190
251
|
getDefaultValues,
|
|
191
252
|
normalizeFieldValue,
|
|
192
|
-
|
|
193
|
-
setSubmitting,
|
|
253
|
+
set,
|
|
194
254
|
validateField,
|
|
195
255
|
validateFieldByName,
|
|
196
256
|
validateForm
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { FieldType, FormField, FormSchema, FormState, Option, ValidationRule } from './types.cjs';
|
|
2
|
-
export { getDefaultValues, normalizeFieldValue, validateField, validateFieldByName, validateForm } from './utils.cjs';
|
|
3
|
-
export { FormRuntimeState,
|
|
1
|
+
export { ErrorMessageTemplates, FieldType, FormField, FormResolver, FormSchema, FormState, Option, ValidationRule } from './types.cjs';
|
|
2
|
+
export { defaultErrorMessages, get, getDefaultValues, normalizeFieldValue, set, validateField, validateFieldByName, validateForm } from './utils.cjs';
|
|
3
|
+
export { FormRuntimeState, FormStore, createFormStore } from './formState.cjs';
|
|
4
|
+
import 'zustand/vanilla';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { FieldType, FormField, FormSchema, FormState, Option, ValidationRule } from './types.js';
|
|
2
|
-
export { getDefaultValues, normalizeFieldValue, validateField, validateFieldByName, validateForm } from './utils.js';
|
|
3
|
-
export { FormRuntimeState,
|
|
1
|
+
export { ErrorMessageTemplates, FieldType, FormField, FormResolver, FormSchema, FormState, Option, ValidationRule } from './types.js';
|
|
2
|
+
export { defaultErrorMessages, get, getDefaultValues, normalizeFieldValue, set, validateField, validateFieldByName, validateForm } from './utils.js';
|
|
3
|
+
export { FormRuntimeState, FormStore, createFormStore } from './formState.js';
|
|
4
|
+
import 'zustand/vanilla';
|
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
runSubmitValidation,
|
|
6
|
-
setSubmitting
|
|
7
|
-
} from "./chunk-TP3IHKWV.js";
|
|
2
|
+
createFormStore
|
|
3
|
+
} from "./chunk-REHKL5VH.js";
|
|
4
|
+
import "./chunk-6F4PWJZI.js";
|
|
8
5
|
import {
|
|
6
|
+
defaultErrorMessages,
|
|
7
|
+
get,
|
|
9
8
|
getDefaultValues,
|
|
10
9
|
normalizeFieldValue,
|
|
10
|
+
set,
|
|
11
11
|
validateField,
|
|
12
12
|
validateFieldByName,
|
|
13
13
|
validateForm
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KA6QUMVR.js";
|
|
15
15
|
export {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
createFormStore,
|
|
17
|
+
defaultErrorMessages,
|
|
18
|
+
get,
|
|
19
19
|
getDefaultValues,
|
|
20
20
|
normalizeFieldValue,
|
|
21
|
-
|
|
22
|
-
setSubmitting,
|
|
21
|
+
set,
|
|
23
22
|
validateField,
|
|
24
23
|
validateFieldByName,
|
|
25
24
|
validateForm
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
type FieldType = 'text' | 'number' | 'email' | 'password' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date';
|
|
1
|
+
type FieldType = 'text' | 'number' | 'email' | 'password' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date' | 'switch';
|
|
2
2
|
interface ValidationRule {
|
|
3
3
|
type: 'required' | 'min' | 'max' | 'pattern' | 'email' | 'custom';
|
|
4
4
|
value?: any;
|
|
5
5
|
message?: string;
|
|
6
|
-
validator?: (value: any) => boolean | string
|
|
6
|
+
validator?: (value: any) => boolean | string | Promise<boolean | string>;
|
|
7
7
|
}
|
|
8
8
|
interface Option {
|
|
9
9
|
label: string;
|
|
@@ -19,21 +19,33 @@ interface FormField {
|
|
|
19
19
|
defaultValue?: any;
|
|
20
20
|
options?: Option[];
|
|
21
21
|
validations?: ValidationRule[];
|
|
22
|
-
hidden?: boolean;
|
|
23
|
-
disabled?: boolean;
|
|
22
|
+
hidden?: boolean | ((values: any) => boolean);
|
|
23
|
+
disabled?: boolean | ((values: any) => boolean);
|
|
24
24
|
className?: string;
|
|
25
25
|
}
|
|
26
|
+
type FormResolver = (values: any) => Record<string, string> | Promise<Record<string, string>>;
|
|
27
|
+
type ErrorMessageTemplates = {
|
|
28
|
+
required?: string;
|
|
29
|
+
min?: string;
|
|
30
|
+
max?: string;
|
|
31
|
+
email?: string;
|
|
32
|
+
pattern?: string;
|
|
33
|
+
custom?: string;
|
|
34
|
+
};
|
|
26
35
|
interface FormSchema {
|
|
27
36
|
title?: string;
|
|
28
37
|
description?: string;
|
|
29
38
|
fields: FormField[];
|
|
30
39
|
submitButtonText?: string;
|
|
40
|
+
resolver?: FormResolver;
|
|
41
|
+
errorMessages?: ErrorMessageTemplates;
|
|
31
42
|
}
|
|
32
43
|
interface FormState {
|
|
33
44
|
values: Record<string, any>;
|
|
34
45
|
errors: Record<string, string>;
|
|
46
|
+
validatingFields: string[];
|
|
35
47
|
isSubmitting: boolean;
|
|
36
48
|
isValid: boolean;
|
|
37
49
|
}
|
|
38
50
|
|
|
39
|
-
export type { FieldType, FormField, FormSchema, FormState, Option, ValidationRule };
|
|
51
|
+
export type { ErrorMessageTemplates, FieldType, FormField, FormResolver, FormSchema, FormState, Option, ValidationRule };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
type FieldType = 'text' | 'number' | 'email' | 'password' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date';
|
|
1
|
+
type FieldType = 'text' | 'number' | 'email' | 'password' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date' | 'switch';
|
|
2
2
|
interface ValidationRule {
|
|
3
3
|
type: 'required' | 'min' | 'max' | 'pattern' | 'email' | 'custom';
|
|
4
4
|
value?: any;
|
|
5
5
|
message?: string;
|
|
6
|
-
validator?: (value: any) => boolean | string
|
|
6
|
+
validator?: (value: any) => boolean | string | Promise<boolean | string>;
|
|
7
7
|
}
|
|
8
8
|
interface Option {
|
|
9
9
|
label: string;
|
|
@@ -19,21 +19,33 @@ interface FormField {
|
|
|
19
19
|
defaultValue?: any;
|
|
20
20
|
options?: Option[];
|
|
21
21
|
validations?: ValidationRule[];
|
|
22
|
-
hidden?: boolean;
|
|
23
|
-
disabled?: boolean;
|
|
22
|
+
hidden?: boolean | ((values: any) => boolean);
|
|
23
|
+
disabled?: boolean | ((values: any) => boolean);
|
|
24
24
|
className?: string;
|
|
25
25
|
}
|
|
26
|
+
type FormResolver = (values: any) => Record<string, string> | Promise<Record<string, string>>;
|
|
27
|
+
type ErrorMessageTemplates = {
|
|
28
|
+
required?: string;
|
|
29
|
+
min?: string;
|
|
30
|
+
max?: string;
|
|
31
|
+
email?: string;
|
|
32
|
+
pattern?: string;
|
|
33
|
+
custom?: string;
|
|
34
|
+
};
|
|
26
35
|
interface FormSchema {
|
|
27
36
|
title?: string;
|
|
28
37
|
description?: string;
|
|
29
38
|
fields: FormField[];
|
|
30
39
|
submitButtonText?: string;
|
|
40
|
+
resolver?: FormResolver;
|
|
41
|
+
errorMessages?: ErrorMessageTemplates;
|
|
31
42
|
}
|
|
32
43
|
interface FormState {
|
|
33
44
|
values: Record<string, any>;
|
|
34
45
|
errors: Record<string, string>;
|
|
46
|
+
validatingFields: string[];
|
|
35
47
|
isSubmitting: boolean;
|
|
36
48
|
isValid: boolean;
|
|
37
49
|
}
|
|
38
50
|
|
|
39
|
-
export type { FieldType, FormField, FormSchema, FormState, Option, ValidationRule };
|
|
51
|
+
export type { ErrorMessageTemplates, FieldType, FormField, FormResolver, FormSchema, FormState, Option, ValidationRule };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./chunk-6F4PWJZI.js";
|
|
@@ -20,8 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/utils.ts
|
|
21
21
|
var utils_exports = {};
|
|
22
22
|
__export(utils_exports, {
|
|
23
|
+
defaultErrorMessages: () => defaultErrorMessages,
|
|
24
|
+
get: () => get,
|
|
23
25
|
getDefaultValues: () => getDefaultValues,
|
|
24
26
|
normalizeFieldValue: () => normalizeFieldValue,
|
|
27
|
+
set: () => set,
|
|
25
28
|
validateField: () => validateField,
|
|
26
29
|
validateFieldByName: () => validateFieldByName,
|
|
27
30
|
validateForm: () => validateForm
|
|
@@ -33,85 +36,138 @@ function parseNumberish(value) {
|
|
|
33
36
|
const parsed = Number(value);
|
|
34
37
|
return Number.isNaN(parsed) ? null : parsed;
|
|
35
38
|
}
|
|
39
|
+
var defaultErrorMessages = {
|
|
40
|
+
required: "{label} is required",
|
|
41
|
+
min: "{label} must be at least {value}",
|
|
42
|
+
max: "{label} must be at most {value}",
|
|
43
|
+
email: "Invalid email address",
|
|
44
|
+
pattern: "Invalid format",
|
|
45
|
+
custom: "Invalid value"
|
|
46
|
+
};
|
|
47
|
+
function formatMessage(template, field, rule) {
|
|
48
|
+
return template.replace("{label}", field.label).replace("{value}", String(rule.value || ""));
|
|
49
|
+
}
|
|
50
|
+
function get(obj, path, defaultValue) {
|
|
51
|
+
if (!path) return defaultValue;
|
|
52
|
+
const keys = path.split(/[.[\]]/).filter(Boolean);
|
|
53
|
+
let result = obj;
|
|
54
|
+
for (const key of keys) {
|
|
55
|
+
if (result === null || result === void 0) return defaultValue;
|
|
56
|
+
result = result[key];
|
|
57
|
+
}
|
|
58
|
+
return result === void 0 ? defaultValue : result;
|
|
59
|
+
}
|
|
60
|
+
function set(obj, path, value) {
|
|
61
|
+
if (Object(obj) !== obj) return obj;
|
|
62
|
+
const keys = path.split(/[.[\]]/).filter(Boolean);
|
|
63
|
+
const newObj = { ...obj };
|
|
64
|
+
let current = newObj;
|
|
65
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
66
|
+
const key = keys[i];
|
|
67
|
+
const nextKey = keys[i + 1];
|
|
68
|
+
const isNextKeyIndex = /^\d+$/.test(nextKey);
|
|
69
|
+
if (!(key in current) || current[key] === null || typeof current[key] !== "object") {
|
|
70
|
+
current[key] = isNextKeyIndex ? [] : {};
|
|
71
|
+
} else {
|
|
72
|
+
current[key] = Array.isArray(current[key]) ? [...current[key]] : { ...current[key] };
|
|
73
|
+
}
|
|
74
|
+
current = current[key];
|
|
75
|
+
}
|
|
76
|
+
current[keys[keys.length - 1]] = value;
|
|
77
|
+
return newObj;
|
|
78
|
+
}
|
|
36
79
|
function normalizeFieldValue(field, value) {
|
|
37
80
|
if (field.type !== "number") return value;
|
|
38
81
|
if (value === "" || value === void 0 || value === null) return "";
|
|
39
82
|
const numericValue = parseNumberish(value);
|
|
40
83
|
return numericValue === null ? value : numericValue;
|
|
41
84
|
}
|
|
42
|
-
function validateField(value, field) {
|
|
85
|
+
async function validateField(value, field, customMessages) {
|
|
43
86
|
if (!field.validations) return null;
|
|
87
|
+
const messages = { ...defaultErrorMessages, ...customMessages };
|
|
44
88
|
for (const rule of field.validations) {
|
|
45
89
|
switch (rule.type) {
|
|
46
90
|
case "required":
|
|
47
91
|
if (value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0) {
|
|
48
|
-
return rule.message ||
|
|
92
|
+
return rule.message || formatMessage(messages.required, field, rule);
|
|
49
93
|
}
|
|
50
94
|
break;
|
|
51
95
|
case "min":
|
|
52
96
|
if (field.type === "number") {
|
|
53
97
|
const numericValue = parseNumberish(value);
|
|
54
98
|
if (numericValue !== null && numericValue < rule.value) {
|
|
55
|
-
|
|
99
|
+
const template = field.type === "number" ? messages.min : typeof value === "string" ? "{label} must be at least {value} characters" : messages.min;
|
|
100
|
+
return rule.message || formatMessage(template, field, rule);
|
|
56
101
|
}
|
|
57
102
|
break;
|
|
58
103
|
}
|
|
59
104
|
if (typeof value === "number" && value < rule.value) {
|
|
60
|
-
return rule.message ||
|
|
105
|
+
return rule.message || formatMessage(messages.min, field, rule);
|
|
61
106
|
}
|
|
62
107
|
if (typeof value === "string" && value.length < rule.value) {
|
|
63
|
-
|
|
108
|
+
const template = "{label} must be at least {value} characters";
|
|
109
|
+
return rule.message || formatMessage(template, field, rule);
|
|
64
110
|
}
|
|
65
111
|
break;
|
|
66
112
|
case "max":
|
|
67
113
|
if (field.type === "number") {
|
|
68
114
|
const numericValue = parseNumberish(value);
|
|
69
115
|
if (numericValue !== null && numericValue > rule.value) {
|
|
70
|
-
return rule.message ||
|
|
116
|
+
return rule.message || formatMessage(messages.max, field, rule);
|
|
71
117
|
}
|
|
72
118
|
break;
|
|
73
119
|
}
|
|
74
120
|
if (typeof value === "number" && value > rule.value) {
|
|
75
|
-
return rule.message ||
|
|
121
|
+
return rule.message || formatMessage(messages.max, field, rule);
|
|
76
122
|
}
|
|
77
123
|
if (typeof value === "string" && value.length > rule.value) {
|
|
78
|
-
|
|
124
|
+
const template = "{label} must be at most {value} characters";
|
|
125
|
+
return rule.message || formatMessage(template, field, rule);
|
|
79
126
|
}
|
|
80
127
|
break;
|
|
81
128
|
case "email": {
|
|
82
129
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
83
130
|
if (value && !emailRegex.test(value)) {
|
|
84
|
-
return rule.message ||
|
|
131
|
+
return rule.message || formatMessage(messages.email, field, rule);
|
|
85
132
|
}
|
|
86
133
|
break;
|
|
87
134
|
}
|
|
88
135
|
case "pattern":
|
|
89
136
|
if (value && rule.value && !new RegExp(rule.value).test(value)) {
|
|
90
|
-
return rule.message ||
|
|
137
|
+
return rule.message || formatMessage(messages.pattern, field, rule);
|
|
91
138
|
}
|
|
92
139
|
break;
|
|
93
140
|
case "custom":
|
|
94
141
|
if (rule.validator) {
|
|
95
|
-
const result = rule.validator(value);
|
|
142
|
+
const result = await rule.validator(value);
|
|
96
143
|
if (typeof result === "string") return result;
|
|
97
|
-
if (
|
|
144
|
+
if (result === false) return rule.message || formatMessage(messages.custom, field, rule);
|
|
98
145
|
}
|
|
99
146
|
break;
|
|
100
147
|
}
|
|
101
148
|
}
|
|
102
149
|
return null;
|
|
103
150
|
}
|
|
104
|
-
function validateFieldByName(fields, name, value) {
|
|
151
|
+
async function validateFieldByName(fields, name, value, resolver, allValues, customMessages) {
|
|
152
|
+
if (resolver && allValues) {
|
|
153
|
+
const resolverErrors = await resolver(allValues);
|
|
154
|
+
if (resolverErrors[name]) return resolverErrors[name];
|
|
155
|
+
}
|
|
105
156
|
const field = fields.find((f) => f.name === name);
|
|
106
157
|
if (!field) return null;
|
|
107
|
-
return validateField(value, field);
|
|
158
|
+
return await validateField(value, field, customMessages);
|
|
108
159
|
}
|
|
109
|
-
function validateForm(fields, values) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (error) errors[field.name] = error;
|
|
160
|
+
async function validateForm(fields, values, resolver, customMessages) {
|
|
161
|
+
let errors = {};
|
|
162
|
+
if (resolver) {
|
|
163
|
+
errors = await resolver(values);
|
|
114
164
|
}
|
|
165
|
+
const validationPromises = fields.map(async (field) => {
|
|
166
|
+
if (errors[field.name]) return;
|
|
167
|
+
const error = await validateField(get(values, field.name), field, customMessages);
|
|
168
|
+
if (error) errors[field.name] = error;
|
|
169
|
+
});
|
|
170
|
+
await Promise.all(validationPromises);
|
|
115
171
|
return errors;
|
|
116
172
|
}
|
|
117
173
|
function getDefaultValues(fields) {
|
|
@@ -122,8 +178,11 @@ function getDefaultValues(fields) {
|
|
|
122
178
|
}
|
|
123
179
|
// Annotate the CommonJS export names for ESM import in node:
|
|
124
180
|
0 && (module.exports = {
|
|
181
|
+
defaultErrorMessages,
|
|
182
|
+
get,
|
|
125
183
|
getDefaultValues,
|
|
126
184
|
normalizeFieldValue,
|
|
185
|
+
set,
|
|
127
186
|
validateField,
|
|
128
187
|
validateFieldByName,
|
|
129
188
|
validateForm
|