pdyform 2.1.0 → 2.2.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.
- package/README.md +98 -74
- package/package.json +1 -1
- package/packages/core/dist/chunk-6F4PWJZI.js +0 -0
- package/packages/core/dist/chunk-B7OMM2UC.js +160 -0
- package/packages/core/dist/chunk-J6ESJZ4U.js +82 -0
- package/packages/core/dist/formState.cjs +140 -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 +146 -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 +80 -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 +55 -9
- package/packages/vue/dist/index.js +1 -1
- package/packages/vue/dist/index.mjs +600 -247
- package/packages/core/dist/chunk-TP3IHKWV.js +0 -69
- package/packages/core/dist/chunk-WEDHXOHH.js +0 -102
|
@@ -20,13 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/formState.ts
|
|
21
21
|
var formState_exports = {};
|
|
22
22
|
__export(formState_exports, {
|
|
23
|
-
|
|
24
|
-
applyFieldChange: () => applyFieldChange,
|
|
25
|
-
createFormRuntimeState: () => createFormRuntimeState,
|
|
26
|
-
runSubmitValidation: () => runSubmitValidation,
|
|
27
|
-
setSubmitting: () => setSubmitting
|
|
23
|
+
createFormStore: () => createFormStore
|
|
28
24
|
});
|
|
29
25
|
module.exports = __toCommonJS(formState_exports);
|
|
26
|
+
var import_vanilla = require("zustand/vanilla");
|
|
30
27
|
|
|
31
28
|
// src/utils.ts
|
|
32
29
|
function parseNumberish(value) {
|
|
@@ -35,85 +32,140 @@ function parseNumberish(value) {
|
|
|
35
32
|
const parsed = Number(value);
|
|
36
33
|
return Number.isNaN(parsed) ? null : parsed;
|
|
37
34
|
}
|
|
35
|
+
var defaultErrorMessages = {
|
|
36
|
+
required: "{label} is required",
|
|
37
|
+
min: "{label} must be at least {value}",
|
|
38
|
+
max: "{label} must be at most {value}",
|
|
39
|
+
email: "Invalid email address",
|
|
40
|
+
pattern: "Invalid format",
|
|
41
|
+
custom: "Invalid value"
|
|
42
|
+
};
|
|
43
|
+
function formatMessage(template, field, rule) {
|
|
44
|
+
return template.replace("{label}", field.label).replace("{value}", String(rule.value || ""));
|
|
45
|
+
}
|
|
46
|
+
function get(obj, path, defaultValue) {
|
|
47
|
+
if (!path) return defaultValue;
|
|
48
|
+
const keys = path.split(/[.[\]]/).filter(Boolean);
|
|
49
|
+
let result = obj;
|
|
50
|
+
for (const key of keys) {
|
|
51
|
+
if (result === null || result === void 0) return defaultValue;
|
|
52
|
+
result = result[key];
|
|
53
|
+
}
|
|
54
|
+
return result === void 0 ? defaultValue : result;
|
|
55
|
+
}
|
|
56
|
+
function set(obj, path, value) {
|
|
57
|
+
if (Object(obj) !== obj) return obj;
|
|
58
|
+
const keys = path.split(/[.[\]]/).filter(Boolean);
|
|
59
|
+
const newObj = { ...obj };
|
|
60
|
+
let current = newObj;
|
|
61
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
62
|
+
const key = keys[i];
|
|
63
|
+
const nextKey = keys[i + 1];
|
|
64
|
+
const isNextKeyIndex = /^\d+$/.test(nextKey);
|
|
65
|
+
if (!(key in current) || current[key] === null || typeof current[key] !== "object") {
|
|
66
|
+
current[key] = isNextKeyIndex ? [] : {};
|
|
67
|
+
} else {
|
|
68
|
+
current[key] = Array.isArray(current[key]) ? [...current[key]] : { ...current[key] };
|
|
69
|
+
}
|
|
70
|
+
current = current[key];
|
|
71
|
+
}
|
|
72
|
+
current[keys[keys.length - 1]] = value;
|
|
73
|
+
return newObj;
|
|
74
|
+
}
|
|
38
75
|
function normalizeFieldValue(field, value) {
|
|
39
76
|
if (field.type !== "number") return value;
|
|
40
77
|
if (value === "" || value === void 0 || value === null) return "";
|
|
41
78
|
const numericValue = parseNumberish(value);
|
|
42
79
|
return numericValue === null ? value : numericValue;
|
|
43
80
|
}
|
|
44
|
-
function validateField(value, field) {
|
|
81
|
+
async function validateField(value, field, customMessages) {
|
|
45
82
|
if (!field.validations) return null;
|
|
83
|
+
const messages = { ...defaultErrorMessages, ...customMessages };
|
|
46
84
|
for (const rule of field.validations) {
|
|
47
85
|
switch (rule.type) {
|
|
48
86
|
case "required":
|
|
49
87
|
if (value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0) {
|
|
50
|
-
return rule.message ||
|
|
88
|
+
return rule.message || formatMessage(messages.required, field, rule);
|
|
51
89
|
}
|
|
52
90
|
break;
|
|
53
91
|
case "min":
|
|
54
92
|
if (field.type === "number") {
|
|
55
93
|
const numericValue = parseNumberish(value);
|
|
56
94
|
if (numericValue !== null && numericValue < rule.value) {
|
|
57
|
-
|
|
95
|
+
const template = field.type === "number" ? messages.min : typeof value === "string" ? "{label} must be at least {value} characters" : messages.min;
|
|
96
|
+
return rule.message || formatMessage(template, field, rule);
|
|
58
97
|
}
|
|
59
98
|
break;
|
|
60
99
|
}
|
|
61
100
|
if (typeof value === "number" && value < rule.value) {
|
|
62
|
-
return rule.message ||
|
|
101
|
+
return rule.message || formatMessage(messages.min, field, rule);
|
|
63
102
|
}
|
|
64
103
|
if (typeof value === "string" && value.length < rule.value) {
|
|
65
|
-
|
|
104
|
+
const template = "{label} must be at least {value} characters";
|
|
105
|
+
return rule.message || formatMessage(template, field, rule);
|
|
66
106
|
}
|
|
67
107
|
break;
|
|
68
108
|
case "max":
|
|
69
109
|
if (field.type === "number") {
|
|
70
110
|
const numericValue = parseNumberish(value);
|
|
71
111
|
if (numericValue !== null && numericValue > rule.value) {
|
|
72
|
-
return rule.message ||
|
|
112
|
+
return rule.message || formatMessage(messages.max, field, rule);
|
|
73
113
|
}
|
|
74
114
|
break;
|
|
75
115
|
}
|
|
76
116
|
if (typeof value === "number" && value > rule.value) {
|
|
77
|
-
return rule.message ||
|
|
117
|
+
return rule.message || formatMessage(messages.max, field, rule);
|
|
78
118
|
}
|
|
79
119
|
if (typeof value === "string" && value.length > rule.value) {
|
|
80
|
-
|
|
120
|
+
const template = "{label} must be at most {value} characters";
|
|
121
|
+
return rule.message || formatMessage(template, field, rule);
|
|
81
122
|
}
|
|
82
123
|
break;
|
|
83
124
|
case "email": {
|
|
84
125
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
85
126
|
if (value && !emailRegex.test(value)) {
|
|
86
|
-
return rule.message ||
|
|
127
|
+
return rule.message || formatMessage(messages.email, field, rule);
|
|
87
128
|
}
|
|
88
129
|
break;
|
|
89
130
|
}
|
|
90
131
|
case "pattern":
|
|
91
132
|
if (value && rule.value && !new RegExp(rule.value).test(value)) {
|
|
92
|
-
return rule.message ||
|
|
133
|
+
return rule.message || formatMessage(messages.pattern, field, rule);
|
|
93
134
|
}
|
|
94
135
|
break;
|
|
95
136
|
case "custom":
|
|
96
137
|
if (rule.validator) {
|
|
97
|
-
const result = rule.validator(value);
|
|
138
|
+
const result = await rule.validator(value);
|
|
98
139
|
if (typeof result === "string") return result;
|
|
99
|
-
if (
|
|
140
|
+
if (result === false) return rule.message || formatMessage(messages.custom, field, rule);
|
|
100
141
|
}
|
|
101
142
|
break;
|
|
102
143
|
}
|
|
103
144
|
}
|
|
104
145
|
return null;
|
|
105
146
|
}
|
|
106
|
-
function validateFieldByName(fields, name, value) {
|
|
147
|
+
async function validateFieldByName(fields, name, value, resolver, allValues, customMessages) {
|
|
148
|
+
if (resolver && allValues) {
|
|
149
|
+
const resolverErrors = await resolver(allValues);
|
|
150
|
+
if (resolverErrors[name]) return resolverErrors[name];
|
|
151
|
+
}
|
|
107
152
|
const field = fields.find((f) => f.name === name);
|
|
108
153
|
if (!field) return null;
|
|
109
|
-
return validateField(value, field);
|
|
154
|
+
return await validateField(value, field, customMessages);
|
|
110
155
|
}
|
|
111
|
-
function validateForm(fields, values) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (error) errors[field.name] = error;
|
|
156
|
+
async function validateForm(fields, values, resolver, customMessages) {
|
|
157
|
+
let errors = {};
|
|
158
|
+
if (resolver) {
|
|
159
|
+
errors = await resolver(values);
|
|
116
160
|
}
|
|
161
|
+
const validationPromises = fields.map(async (field) => {
|
|
162
|
+
if (errors[field.name]) return;
|
|
163
|
+
const isHidden = typeof field.hidden === "function" ? field.hidden(values) : field.hidden;
|
|
164
|
+
if (isHidden) return;
|
|
165
|
+
const error = await validateField(get(values, field.name), field, customMessages);
|
|
166
|
+
if (error) errors[field.name] = error;
|
|
167
|
+
});
|
|
168
|
+
await Promise.all(validationPromises);
|
|
117
169
|
return errors;
|
|
118
170
|
}
|
|
119
171
|
function getDefaultValues(fields) {
|
|
@@ -124,64 +176,74 @@ function getDefaultValues(fields) {
|
|
|
124
176
|
}
|
|
125
177
|
|
|
126
178
|
// src/formState.ts
|
|
127
|
-
function
|
|
128
|
-
return {
|
|
179
|
+
function createFormStore(fields, resolver, errorMessages) {
|
|
180
|
+
return (0, import_vanilla.createStore)()((set2, getStore) => ({
|
|
129
181
|
values: getDefaultValues(fields),
|
|
130
182
|
errors: {},
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
function applyFieldBlur(fields, state, name) {
|
|
159
|
-
const error = validateFieldByName(fields, name, state.values[name]);
|
|
160
|
-
return {
|
|
161
|
-
...state,
|
|
162
|
-
errors: {
|
|
163
|
-
...state.errors,
|
|
164
|
-
[name]: error || ""
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
function runSubmitValidation(fields, state) {
|
|
169
|
-
const errors = validateForm(fields, state.values);
|
|
170
|
-
const hasError = Object.keys(errors).length > 0;
|
|
171
|
-
return {
|
|
172
|
-
state: {
|
|
173
|
-
...state,
|
|
174
|
-
errors,
|
|
175
|
-
isSubmitting: false
|
|
183
|
+
validatingFields: [],
|
|
184
|
+
isSubmitting: false,
|
|
185
|
+
setFieldValue: async (name, rawValue) => {
|
|
186
|
+
const field = fields.find((f) => f.name === name);
|
|
187
|
+
const normalizedValue = field ? normalizeFieldValue(field, rawValue) : rawValue;
|
|
188
|
+
set2((state) => ({
|
|
189
|
+
values: set(state.values, name, normalizedValue)
|
|
190
|
+
}));
|
|
191
|
+
const hasExistingError = !!getStore().errors[name];
|
|
192
|
+
const shouldValidateImmediately = field && ["select", "checkbox", "radio", "switch", "date"].includes(field.type);
|
|
193
|
+
if (shouldValidateImmediately || hasExistingError) {
|
|
194
|
+
set2((state) => ({
|
|
195
|
+
validatingFields: [...state.validatingFields, name]
|
|
196
|
+
}));
|
|
197
|
+
try {
|
|
198
|
+
const currentValues = getStore().values;
|
|
199
|
+
const error = await validateFieldByName(fields, name, normalizedValue, resolver, currentValues, errorMessages);
|
|
200
|
+
set2((state) => ({
|
|
201
|
+
errors: { ...state.errors, [name]: error || "" },
|
|
202
|
+
validatingFields: state.validatingFields.filter((f) => f !== name)
|
|
203
|
+
}));
|
|
204
|
+
} catch (err) {
|
|
205
|
+
set2((state) => ({
|
|
206
|
+
validatingFields: state.validatingFields.filter((f) => f !== name)
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
176
210
|
},
|
|
177
|
-
|
|
178
|
-
|
|
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
|
+
}));
|
|
179
245
|
}
|
|
180
246
|
// Annotate the CommonJS export names for ESM import in node:
|
|
181
247
|
0 && (module.exports = {
|
|
182
|
-
|
|
183
|
-
applyFieldChange,
|
|
184
|
-
createFormRuntimeState,
|
|
185
|
-
runSubmitValidation,
|
|
186
|
-
setSubmitting
|
|
248
|
+
createFormStore
|
|
187
249
|
});
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as zustand_vanilla from 'zustand/vanilla';
|
|
2
|
+
import { FormField, FormResolver, ErrorMessageTemplates } from './types.cjs';
|
|
2
3
|
|
|
3
4
|
interface FormRuntimeState {
|
|
4
5
|
values: Record<string, any>;
|
|
5
6
|
errors: Record<string, string>;
|
|
7
|
+
validatingFields: string[];
|
|
6
8
|
isSubmitting: boolean;
|
|
7
9
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
10
|
+
interface FormStore extends FormRuntimeState {
|
|
11
|
+
setFieldValue: (name: string, rawValue: unknown) => Promise<void>;
|
|
12
|
+
setFieldBlur: (name: string) => Promise<void>;
|
|
13
|
+
setSubmitting: (isSubmitting: boolean) => void;
|
|
14
|
+
runSubmitValidation: () => Promise<{
|
|
15
|
+
state: FormRuntimeState;
|
|
16
|
+
hasError: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
declare function createFormStore(fields: FormField[], resolver?: FormResolver, errorMessages?: ErrorMessageTemplates): zustand_vanilla.StoreApi<FormStore>;
|
|
16
20
|
|
|
17
|
-
export { type FormRuntimeState,
|
|
21
|
+
export { type FormRuntimeState, type FormStore, createFormStore };
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as zustand_vanilla from 'zustand/vanilla';
|
|
2
|
+
import { FormField, FormResolver, ErrorMessageTemplates } from './types.js';
|
|
2
3
|
|
|
3
4
|
interface FormRuntimeState {
|
|
4
5
|
values: Record<string, any>;
|
|
5
6
|
errors: Record<string, string>;
|
|
7
|
+
validatingFields: string[];
|
|
6
8
|
isSubmitting: boolean;
|
|
7
9
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
10
|
+
interface FormStore extends FormRuntimeState {
|
|
11
|
+
setFieldValue: (name: string, rawValue: unknown) => Promise<void>;
|
|
12
|
+
setFieldBlur: (name: string) => Promise<void>;
|
|
13
|
+
setSubmitting: (isSubmitting: boolean) => void;
|
|
14
|
+
runSubmitValidation: () => Promise<{
|
|
15
|
+
state: FormRuntimeState;
|
|
16
|
+
hasError: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
declare function createFormStore(fields: FormField[], resolver?: FormResolver, errorMessages?: ErrorMessageTemplates): zustand_vanilla.StoreApi<FormStore>;
|
|
16
20
|
|
|
17
|
-
export { type FormRuntimeState,
|
|
21
|
+
export { type FormRuntimeState, type FormStore, createFormStore };
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
runSubmitValidation,
|
|
6
|
-
setSubmitting
|
|
7
|
-
} from "./chunk-TP3IHKWV.js";
|
|
8
|
-
import "./chunk-WEDHXOHH.js";
|
|
2
|
+
createFormStore
|
|
3
|
+
} from "./chunk-J6ESJZ4U.js";
|
|
4
|
+
import "./chunk-B7OMM2UC.js";
|
|
9
5
|
export {
|
|
10
|
-
|
|
11
|
-
applyFieldChange,
|
|
12
|
-
createFormRuntimeState,
|
|
13
|
-
runSubmitValidation,
|
|
14
|
-
setSubmitting
|
|
6
|
+
createFormStore
|
|
15
7
|
};
|