@buildnbuzz/buzzform 0.1.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/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/adapter-BT9v2OVg.d.mts +1136 -0
- package/dist/adapter-BT9v2OVg.d.ts +1136 -0
- package/dist/chunk-DDDGBPVU.mjs +273 -0
- package/dist/chunk-DDDGBPVU.mjs.map +1 -0
- package/dist/chunk-K42S5YX3.mjs +599 -0
- package/dist/chunk-K42S5YX3.mjs.map +1 -0
- package/dist/index.d.mts +270 -0
- package/dist/index.d.ts +270 -0
- package/dist/index.js +1028 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +194 -0
- package/dist/index.mjs.map +1 -0
- package/dist/rhf.d.mts +70 -0
- package/dist/rhf.d.ts +70 -0
- package/dist/rhf.js +293 -0
- package/dist/rhf.js.map +1 -0
- package/dist/rhf.mjs +175 -0
- package/dist/rhf.mjs.map +1 -0
- package/dist/schema.d.mts +72 -0
- package/dist/schema.d.ts +72 -0
- package/dist/schema.js +768 -0
- package/dist/schema.js.map +1 -0
- package/dist/schema.mjs +63 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/utils-BgwyUFGB.d.mts +233 -0
- package/dist/utils-DVLpbOoW.d.ts +233 -0
- package/dist/zod.d.mts +32 -0
- package/dist/zod.d.ts +32 -0
- package/dist/zod.js +88 -0
- package/dist/zod.js.map +1 -0
- package/dist/zod.mjs +62 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +109 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1028 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
FormConfigContext: () => FormConfigContext,
|
|
24
|
+
FormProvider: () => FormProvider,
|
|
25
|
+
applyCustomValidation: () => applyCustomValidation,
|
|
26
|
+
applyNumericPrecision: () => applyNumericPrecision,
|
|
27
|
+
clampNumber: () => clampNumber,
|
|
28
|
+
coerceToDate: () => coerceToDate,
|
|
29
|
+
coerceToNumber: () => coerceToNumber,
|
|
30
|
+
countNestedErrors: () => countNestedErrors,
|
|
31
|
+
createArrayHelpers: () => createArrayHelpers,
|
|
32
|
+
createSchema: () => createSchema,
|
|
33
|
+
extractValidationConfig: () => extractValidationConfig,
|
|
34
|
+
fieldsToZodSchema: () => fieldsToZodSchema,
|
|
35
|
+
formatBytes: () => formatBytes,
|
|
36
|
+
formatNumberWithSeparator: () => formatNumberWithSeparator,
|
|
37
|
+
generateFieldId: () => generateFieldId,
|
|
38
|
+
getArrayRowLabel: () => getArrayRowLabel,
|
|
39
|
+
getFieldWidthStyle: () => getFieldWidthStyle,
|
|
40
|
+
getNestedFieldPaths: () => getNestedFieldPaths,
|
|
41
|
+
getNestedValue: () => getNestedValue,
|
|
42
|
+
getPatternErrorMessage: () => getPatternErrorMessage,
|
|
43
|
+
getSelectOptionLabel: () => getSelectOptionLabel,
|
|
44
|
+
getSelectOptionLabelString: () => getSelectOptionLabelString,
|
|
45
|
+
getSelectOptionValue: () => getSelectOptionValue,
|
|
46
|
+
isFileLike: () => isFileLike,
|
|
47
|
+
isFileTypeAccepted: () => isFileTypeAccepted,
|
|
48
|
+
isSelectOptionDisabled: () => isSelectOptionDisabled,
|
|
49
|
+
makeOptional: () => makeOptional,
|
|
50
|
+
normalizeSelectOption: () => normalizeSelectOption,
|
|
51
|
+
parseFormattedNumber: () => parseFormattedNumber,
|
|
52
|
+
parseToDate: () => parseToDate,
|
|
53
|
+
resolveFieldState: () => resolveFieldState,
|
|
54
|
+
setNestedValue: () => setNestedValue,
|
|
55
|
+
useForm: () => useForm,
|
|
56
|
+
validateAdapter: () => validateAdapter
|
|
57
|
+
});
|
|
58
|
+
module.exports = __toCommonJS(src_exports);
|
|
59
|
+
|
|
60
|
+
// src/types/adapter.ts
|
|
61
|
+
function validateAdapter(adapter, adapterName = "adapter") {
|
|
62
|
+
const required = [
|
|
63
|
+
"control",
|
|
64
|
+
"formState",
|
|
65
|
+
"handleSubmit",
|
|
66
|
+
"getValues",
|
|
67
|
+
"setValue",
|
|
68
|
+
"reset",
|
|
69
|
+
"watch",
|
|
70
|
+
"validate",
|
|
71
|
+
"setError",
|
|
72
|
+
"clearErrors",
|
|
73
|
+
"array"
|
|
74
|
+
];
|
|
75
|
+
for (const key of required) {
|
|
76
|
+
if (adapter[key] === void 0) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Invalid FormAdapter: "${adapterName}" is missing required property "${key}". See FormAdapter interface for implementation requirements.`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const arrayMethods = [
|
|
83
|
+
"fields",
|
|
84
|
+
"append",
|
|
85
|
+
"prepend",
|
|
86
|
+
"insert",
|
|
87
|
+
"remove",
|
|
88
|
+
"move",
|
|
89
|
+
"swap",
|
|
90
|
+
"replace",
|
|
91
|
+
"update"
|
|
92
|
+
];
|
|
93
|
+
for (const method of arrayMethods) {
|
|
94
|
+
if (typeof adapter.array[method] !== "function") {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Invalid FormAdapter: "${adapterName}.array.${method}" must be a function.`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/schema/fields-to-schema.ts
|
|
103
|
+
var import_zod10 = require("zod");
|
|
104
|
+
|
|
105
|
+
// src/schema/builders/text.ts
|
|
106
|
+
var import_zod2 = require("zod");
|
|
107
|
+
|
|
108
|
+
// src/schema/helpers.ts
|
|
109
|
+
var import_zod = require("zod");
|
|
110
|
+
function extractValidationConfig(validate) {
|
|
111
|
+
if (!validate) {
|
|
112
|
+
return { fn: void 0, isLive: false };
|
|
113
|
+
}
|
|
114
|
+
if (typeof validate === "function") {
|
|
115
|
+
return { fn: validate, isLive: false };
|
|
116
|
+
}
|
|
117
|
+
if (typeof validate === "object" && "fn" in validate) {
|
|
118
|
+
const obj = validate;
|
|
119
|
+
const fn = typeof obj.fn === "function" ? obj.fn : void 0;
|
|
120
|
+
if (!obj.live) {
|
|
121
|
+
return { fn, isLive: false };
|
|
122
|
+
}
|
|
123
|
+
const debounceMs = typeof obj.live === "object" ? obj.live.debounceMs : void 0;
|
|
124
|
+
return { fn, isLive: true, debounceMs };
|
|
125
|
+
}
|
|
126
|
+
return { fn: void 0, isLive: false };
|
|
127
|
+
}
|
|
128
|
+
function applyCustomValidation(schema, field, fieldPath = "") {
|
|
129
|
+
if (!("validate" in field)) {
|
|
130
|
+
return schema;
|
|
131
|
+
}
|
|
132
|
+
const fieldWithValidate = field;
|
|
133
|
+
if (!fieldWithValidate.validate) {
|
|
134
|
+
return schema;
|
|
135
|
+
}
|
|
136
|
+
const config = extractValidationConfig(fieldWithValidate.validate);
|
|
137
|
+
if (!config.fn) {
|
|
138
|
+
return schema;
|
|
139
|
+
}
|
|
140
|
+
return schema.superRefine(async (val, ctx) => {
|
|
141
|
+
const result = await config.fn(val, {
|
|
142
|
+
data: {},
|
|
143
|
+
siblingData: {},
|
|
144
|
+
path: fieldPath.split(".")
|
|
145
|
+
});
|
|
146
|
+
if (result !== true) {
|
|
147
|
+
ctx.addIssue({
|
|
148
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
149
|
+
message: typeof result === "string" ? result : "Validation failed"
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function makeOptional(schema, fieldType) {
|
|
155
|
+
switch (fieldType) {
|
|
156
|
+
// String types: allow empty string
|
|
157
|
+
case "text":
|
|
158
|
+
case "textarea":
|
|
159
|
+
case "email":
|
|
160
|
+
case "password":
|
|
161
|
+
return schema.optional().or(import_zod.z.literal(""));
|
|
162
|
+
// Nullable types
|
|
163
|
+
case "number":
|
|
164
|
+
case "date":
|
|
165
|
+
case "select":
|
|
166
|
+
case "radio":
|
|
167
|
+
return schema.optional().nullable();
|
|
168
|
+
// Boolean types: always have a value
|
|
169
|
+
case "checkbox":
|
|
170
|
+
case "switch":
|
|
171
|
+
return schema;
|
|
172
|
+
// Booleans are never "optional" in the traditional sense
|
|
173
|
+
// Array types
|
|
174
|
+
case "tags":
|
|
175
|
+
case "array":
|
|
176
|
+
return schema.optional().default([]);
|
|
177
|
+
// Upload
|
|
178
|
+
case "upload":
|
|
179
|
+
return schema.optional().nullable();
|
|
180
|
+
// Default
|
|
181
|
+
default:
|
|
182
|
+
return schema.optional();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function coerceToNumber(val) {
|
|
186
|
+
if (val === "" || val === null || val === void 0) {
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
const num = Number(val);
|
|
190
|
+
return isNaN(num) ? void 0 : num;
|
|
191
|
+
}
|
|
192
|
+
function coerceToDate(val) {
|
|
193
|
+
if (val === "" || val === null || val === void 0) {
|
|
194
|
+
return void 0;
|
|
195
|
+
}
|
|
196
|
+
if (val instanceof Date) {
|
|
197
|
+
return isNaN(val.getTime()) ? void 0 : val;
|
|
198
|
+
}
|
|
199
|
+
if (typeof val === "string" || typeof val === "number") {
|
|
200
|
+
const d = new Date(val);
|
|
201
|
+
return isNaN(d.getTime()) ? void 0 : d;
|
|
202
|
+
}
|
|
203
|
+
return void 0;
|
|
204
|
+
}
|
|
205
|
+
var PATTERN_MESSAGES = {
|
|
206
|
+
"^[a-zA-Z0-9_]+$": "Only letters, numbers, and underscores allowed",
|
|
207
|
+
"^[a-z0-9-]+$": "Only lowercase letters, numbers, and hyphens allowed",
|
|
208
|
+
"^\\S+@\\S+\\.\\S+$": "Invalid email format",
|
|
209
|
+
"^https?://": "Must start with http:// or https://"
|
|
210
|
+
};
|
|
211
|
+
function getPatternErrorMessage(pattern) {
|
|
212
|
+
const patternStr = typeof pattern === "string" ? pattern : pattern.source;
|
|
213
|
+
return PATTERN_MESSAGES[patternStr] || `Must match pattern: ${patternStr}`;
|
|
214
|
+
}
|
|
215
|
+
function isFileLike(value) {
|
|
216
|
+
return typeof value === "object" && value !== null && "name" in value && "size" in value && "type" in value;
|
|
217
|
+
}
|
|
218
|
+
function isFileTypeAccepted(file, accept) {
|
|
219
|
+
if (accept === "*" || !accept) return true;
|
|
220
|
+
const acceptTypes = accept.split(",").map((t) => t.trim().toLowerCase());
|
|
221
|
+
const fileType = file.type.toLowerCase();
|
|
222
|
+
const fileName = file.name.toLowerCase();
|
|
223
|
+
return acceptTypes.some((acceptType) => {
|
|
224
|
+
if (acceptType.endsWith("/*")) {
|
|
225
|
+
const category = acceptType.replace("/*", "");
|
|
226
|
+
return fileType.startsWith(category + "/");
|
|
227
|
+
}
|
|
228
|
+
if (acceptType.startsWith(".")) {
|
|
229
|
+
return fileName.endsWith(acceptType);
|
|
230
|
+
}
|
|
231
|
+
return fileType === acceptType;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/schema/builders/text.ts
|
|
236
|
+
function createTextFieldSchema(field) {
|
|
237
|
+
let schema = import_zod2.z.string();
|
|
238
|
+
if ("pattern" in field && field.pattern) {
|
|
239
|
+
const pattern = typeof field.pattern === "string" ? new RegExp(field.pattern) : field.pattern;
|
|
240
|
+
schema = schema.regex(pattern, {
|
|
241
|
+
message: getPatternErrorMessage(field.pattern)
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
if (field.minLength) {
|
|
245
|
+
schema = schema.min(field.minLength, {
|
|
246
|
+
message: `Must be at least ${field.minLength} characters`
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
if (field.maxLength) {
|
|
250
|
+
schema = schema.max(field.maxLength, {
|
|
251
|
+
message: `Must be no more than ${field.maxLength} characters`
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
if (field.required) {
|
|
255
|
+
schema = schema.min(1, { message: "This field is required" });
|
|
256
|
+
}
|
|
257
|
+
let finalSchema = schema;
|
|
258
|
+
if ("trim" in field && field.trim) {
|
|
259
|
+
finalSchema = import_zod2.z.preprocess((val) => {
|
|
260
|
+
return typeof val === "string" ? val.trim() : val;
|
|
261
|
+
}, schema);
|
|
262
|
+
}
|
|
263
|
+
finalSchema = applyCustomValidation(finalSchema, field, field.name);
|
|
264
|
+
if (!field.required) {
|
|
265
|
+
return makeOptional(finalSchema, field.type);
|
|
266
|
+
}
|
|
267
|
+
return finalSchema;
|
|
268
|
+
}
|
|
269
|
+
function createEmailFieldSchema(field) {
|
|
270
|
+
let schema = import_zod2.z.string().email({ message: "Invalid email address" });
|
|
271
|
+
if (field.minLength) {
|
|
272
|
+
schema = schema.min(field.minLength, {
|
|
273
|
+
message: `Must be at least ${field.minLength} characters`
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
if (field.maxLength) {
|
|
277
|
+
schema = schema.max(field.maxLength, {
|
|
278
|
+
message: `Must be no more than ${field.maxLength} characters`
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
if (field.required) {
|
|
282
|
+
schema = schema.min(1, { message: "Email is required" });
|
|
283
|
+
}
|
|
284
|
+
const finalSchema = applyCustomValidation(schema, field, field.name);
|
|
285
|
+
if (!field.required) {
|
|
286
|
+
return makeOptional(finalSchema, "email");
|
|
287
|
+
}
|
|
288
|
+
return finalSchema;
|
|
289
|
+
}
|
|
290
|
+
function createPasswordFieldSchema(field) {
|
|
291
|
+
let schema = import_zod2.z.string();
|
|
292
|
+
if (field.minLength) {
|
|
293
|
+
schema = schema.min(field.minLength, {
|
|
294
|
+
message: `Password must be at least ${field.minLength} characters`
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (field.maxLength) {
|
|
298
|
+
schema = schema.max(field.maxLength, {
|
|
299
|
+
message: `Password must be no more than ${field.maxLength} characters`
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
if (field.required) {
|
|
303
|
+
schema = schema.min(1, { message: "Password is required" });
|
|
304
|
+
}
|
|
305
|
+
const finalSchema = applyCustomValidation(schema, field, field.name);
|
|
306
|
+
if (!field.required) {
|
|
307
|
+
return makeOptional(finalSchema, "password");
|
|
308
|
+
}
|
|
309
|
+
return finalSchema;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/schema/builders/number.ts
|
|
313
|
+
var import_zod3 = require("zod");
|
|
314
|
+
function createNumberFieldSchema(field) {
|
|
315
|
+
let numSchema = import_zod3.z.number({ invalid_type_error: "Must be a number" });
|
|
316
|
+
if (field.min !== void 0) {
|
|
317
|
+
numSchema = numSchema.min(field.min, `Must be at least ${field.min}`);
|
|
318
|
+
}
|
|
319
|
+
if (field.max !== void 0) {
|
|
320
|
+
numSchema = numSchema.max(field.max, `Must be at most ${field.max}`);
|
|
321
|
+
}
|
|
322
|
+
let schema = import_zod3.z.preprocess(coerceToNumber, numSchema);
|
|
323
|
+
schema = applyCustomValidation(schema, field, field.name);
|
|
324
|
+
if (field.required) {
|
|
325
|
+
return schema;
|
|
326
|
+
}
|
|
327
|
+
return makeOptional(schema, "number");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// src/schema/builders/date.ts
|
|
331
|
+
var import_zod4 = require("zod");
|
|
332
|
+
function toDate(value) {
|
|
333
|
+
if (!value) return void 0;
|
|
334
|
+
if (value instanceof Date) return isNaN(value.getTime()) ? void 0 : value;
|
|
335
|
+
const parsed = new Date(value);
|
|
336
|
+
return isNaN(parsed.getTime()) ? void 0 : parsed;
|
|
337
|
+
}
|
|
338
|
+
function createDateFieldSchema(field) {
|
|
339
|
+
const isDatetime = field.type === "datetime";
|
|
340
|
+
const minDate = toDate(field.minDate);
|
|
341
|
+
const maxDate = toDate(field.maxDate);
|
|
342
|
+
let dateSchema = import_zod4.z.date({ invalid_type_error: "Please enter a valid date" });
|
|
343
|
+
if (minDate) {
|
|
344
|
+
const formattedDate = isDatetime ? minDate.toLocaleString() : minDate.toDateString();
|
|
345
|
+
dateSchema = dateSchema.min(minDate, {
|
|
346
|
+
message: `Date must be on or after ${formattedDate}`
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
if (maxDate) {
|
|
350
|
+
const formattedDate = isDatetime ? maxDate.toLocaleString() : maxDate.toDateString();
|
|
351
|
+
dateSchema = dateSchema.max(maxDate, {
|
|
352
|
+
message: `Date must be on or before ${formattedDate}`
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
let schema = import_zod4.z.preprocess(coerceToDate, dateSchema);
|
|
356
|
+
schema = applyCustomValidation(schema, field, field.name);
|
|
357
|
+
if (field.required) {
|
|
358
|
+
return schema.refine(
|
|
359
|
+
(val) => val instanceof Date && !isNaN(val.getTime()),
|
|
360
|
+
"Date is required"
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
return makeOptional(schema, "date");
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// src/schema/builders/select.ts
|
|
367
|
+
var import_zod5 = require("zod");
|
|
368
|
+
var selectValueSchema = import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number(), import_zod5.z.boolean()]);
|
|
369
|
+
function createSelectFieldSchema(field) {
|
|
370
|
+
if (field.hasMany) {
|
|
371
|
+
let arraySchema = import_zod5.z.array(selectValueSchema);
|
|
372
|
+
if (field.required) {
|
|
373
|
+
arraySchema = arraySchema.min(1, "Select at least one option");
|
|
374
|
+
}
|
|
375
|
+
const schema2 = applyCustomValidation(arraySchema, field, field.name);
|
|
376
|
+
if (!field.required) {
|
|
377
|
+
return schema2.optional().default([]);
|
|
378
|
+
}
|
|
379
|
+
return schema2;
|
|
380
|
+
}
|
|
381
|
+
let schema = selectValueSchema;
|
|
382
|
+
if (field.required) {
|
|
383
|
+
schema = selectValueSchema.refine(
|
|
384
|
+
(val) => val !== "" && val !== null && val !== void 0,
|
|
385
|
+
"Please select an option"
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
schema = applyCustomValidation(schema, field, field.name);
|
|
389
|
+
if (!field.required) {
|
|
390
|
+
return makeOptional(schema, "select");
|
|
391
|
+
}
|
|
392
|
+
return schema;
|
|
393
|
+
}
|
|
394
|
+
function createRadioFieldSchema(field) {
|
|
395
|
+
let schema = selectValueSchema;
|
|
396
|
+
if (field.required) {
|
|
397
|
+
schema = selectValueSchema.refine(
|
|
398
|
+
(val) => val !== "" && val !== null && val !== void 0,
|
|
399
|
+
"Please select an option"
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
schema = applyCustomValidation(schema, field, field.name);
|
|
403
|
+
if (!field.required) {
|
|
404
|
+
return makeOptional(schema, "radio");
|
|
405
|
+
}
|
|
406
|
+
return schema;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/schema/builders/boolean.ts
|
|
410
|
+
var import_zod6 = require("zod");
|
|
411
|
+
function createCheckboxFieldSchema(field) {
|
|
412
|
+
let schema = import_zod6.z.boolean();
|
|
413
|
+
if (field.required) {
|
|
414
|
+
schema = import_zod6.z.boolean().refine((val) => val === true, {
|
|
415
|
+
message: "This field is required"
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
return applyCustomValidation(schema, field, field.name);
|
|
419
|
+
}
|
|
420
|
+
function createSwitchFieldSchema(field) {
|
|
421
|
+
let schema = import_zod6.z.boolean();
|
|
422
|
+
if (field.required) {
|
|
423
|
+
schema = import_zod6.z.boolean().refine((val) => val === true, {
|
|
424
|
+
message: "This field is required"
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
return applyCustomValidation(schema, field, field.name);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/schema/builders/upload.ts
|
|
431
|
+
var import_zod7 = require("zod");
|
|
432
|
+
function validateSingleFile(value, field) {
|
|
433
|
+
if (value === null || value === void 0 || value === "") {
|
|
434
|
+
return { valid: true };
|
|
435
|
+
}
|
|
436
|
+
if (typeof value === "string") {
|
|
437
|
+
return { valid: true };
|
|
438
|
+
}
|
|
439
|
+
if (!isFileLike(value)) {
|
|
440
|
+
return { valid: false, message: "Invalid file" };
|
|
441
|
+
}
|
|
442
|
+
if (field.maxSize && value.size > field.maxSize) {
|
|
443
|
+
const sizeMB = (field.maxSize / 1024 / 1024).toFixed(1);
|
|
444
|
+
return {
|
|
445
|
+
valid: false,
|
|
446
|
+
message: `File must be smaller than ${sizeMB}MB`
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
const accept = field.ui?.accept;
|
|
450
|
+
if (accept && accept !== "*") {
|
|
451
|
+
if (!isFileTypeAccepted(value, accept)) {
|
|
452
|
+
return {
|
|
453
|
+
valid: false,
|
|
454
|
+
message: `File type not allowed. Accepted: ${accept}`
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return { valid: true };
|
|
459
|
+
}
|
|
460
|
+
function createUploadFieldSchema(field) {
|
|
461
|
+
if (field.hasMany) {
|
|
462
|
+
const schema2 = import_zod7.z.array(import_zod7.z.any()).superRefine((files, ctx) => {
|
|
463
|
+
for (let i = 0; i < files.length; i++) {
|
|
464
|
+
const file = files[i];
|
|
465
|
+
const result = validateSingleFile(file, field);
|
|
466
|
+
if (!result.valid) {
|
|
467
|
+
ctx.addIssue({
|
|
468
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
469
|
+
message: result.message || "Invalid file",
|
|
470
|
+
path: [i]
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (field.required) {
|
|
475
|
+
const validFiles = files.filter((f) => f !== null && f !== void 0);
|
|
476
|
+
if (validFiles.length === 0) {
|
|
477
|
+
ctx.addIssue({
|
|
478
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
479
|
+
message: "At least one file is required"
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (field.minFiles !== void 0 && field.minFiles > 0) {
|
|
484
|
+
const validFiles = files.filter((f) => f !== null && f !== void 0);
|
|
485
|
+
if (validFiles.length < field.minFiles) {
|
|
486
|
+
ctx.addIssue({
|
|
487
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
488
|
+
message: `At least ${field.minFiles} file(s) required`
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if (field.maxFiles !== void 0) {
|
|
493
|
+
const validFiles = files.filter((f) => f !== null && f !== void 0);
|
|
494
|
+
if (validFiles.length > field.maxFiles) {
|
|
495
|
+
ctx.addIssue({
|
|
496
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
497
|
+
message: `Maximum ${field.maxFiles} file(s) allowed`
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
if (!field.required) {
|
|
503
|
+
return schema2.optional().default([]);
|
|
504
|
+
}
|
|
505
|
+
return schema2;
|
|
506
|
+
}
|
|
507
|
+
const schema = import_zod7.z.any().superRefine((value, ctx) => {
|
|
508
|
+
if (field.required && (value === null || value === void 0 || value === "")) {
|
|
509
|
+
ctx.addIssue({
|
|
510
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
511
|
+
message: "File is required"
|
|
512
|
+
});
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (value === null || value === void 0 || value === "") {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const result = validateSingleFile(value, field);
|
|
519
|
+
if (!result.valid) {
|
|
520
|
+
ctx.addIssue({
|
|
521
|
+
code: import_zod7.z.ZodIssueCode.custom,
|
|
522
|
+
message: result.message || "Invalid file"
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
if (!field.required) {
|
|
527
|
+
return schema.optional().nullable();
|
|
528
|
+
}
|
|
529
|
+
return schema;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// src/schema/builders/tags.ts
|
|
533
|
+
var import_zod8 = require("zod");
|
|
534
|
+
function createTagsFieldSchema(field) {
|
|
535
|
+
const tagSchema = import_zod8.z.string();
|
|
536
|
+
let schema = import_zod8.z.array(tagSchema);
|
|
537
|
+
if (field.minTags !== void 0) {
|
|
538
|
+
schema = schema.min(field.minTags, `At least ${field.minTags} tag(s) required`);
|
|
539
|
+
}
|
|
540
|
+
if (field.maxTags !== void 0) {
|
|
541
|
+
schema = schema.max(field.maxTags, `Maximum ${field.maxTags} tag(s) allowed`);
|
|
542
|
+
}
|
|
543
|
+
let finalSchema = applyCustomValidation(schema, field, field.name);
|
|
544
|
+
if (field.required) {
|
|
545
|
+
finalSchema = finalSchema.refine(
|
|
546
|
+
(arr) => Array.isArray(arr) && arr.length > 0,
|
|
547
|
+
"At least one tag is required"
|
|
548
|
+
);
|
|
549
|
+
return finalSchema;
|
|
550
|
+
}
|
|
551
|
+
return finalSchema.optional().default([]);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// src/schema/builders/composite.ts
|
|
555
|
+
var import_zod9 = require("zod");
|
|
556
|
+
function createArrayFieldSchema(field, fieldsToZodSchema2) {
|
|
557
|
+
const itemSchema = fieldsToZodSchema2(field.fields);
|
|
558
|
+
let schema = import_zod9.z.array(itemSchema);
|
|
559
|
+
if (field.minRows !== void 0) {
|
|
560
|
+
schema = schema.min(
|
|
561
|
+
field.minRows,
|
|
562
|
+
`At least ${field.minRows} row${field.minRows !== 1 ? "s" : ""} required`
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
if (field.maxRows !== void 0) {
|
|
566
|
+
schema = schema.max(
|
|
567
|
+
field.maxRows,
|
|
568
|
+
`Maximum ${field.maxRows} row${field.maxRows !== 1 ? "s" : ""} allowed`
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
if (field.required) {
|
|
572
|
+
return schema;
|
|
573
|
+
}
|
|
574
|
+
return schema.optional().default([]);
|
|
575
|
+
}
|
|
576
|
+
function createGroupFieldSchema(field, fieldsToZodSchema2) {
|
|
577
|
+
const schema = fieldsToZodSchema2(field.fields);
|
|
578
|
+
if (!field.required) {
|
|
579
|
+
return schema.optional();
|
|
580
|
+
}
|
|
581
|
+
return schema;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// src/schema/fields-to-schema.ts
|
|
585
|
+
function fieldToZod(field) {
|
|
586
|
+
if ("schema" in field && field.schema) {
|
|
587
|
+
return field.schema;
|
|
588
|
+
}
|
|
589
|
+
switch (field.type) {
|
|
590
|
+
// Text-based fields
|
|
591
|
+
case "text":
|
|
592
|
+
return createTextFieldSchema(field);
|
|
593
|
+
case "email":
|
|
594
|
+
return createEmailFieldSchema(field);
|
|
595
|
+
case "password":
|
|
596
|
+
return createPasswordFieldSchema(field);
|
|
597
|
+
case "textarea":
|
|
598
|
+
return createTextFieldSchema(field);
|
|
599
|
+
// Number
|
|
600
|
+
case "number":
|
|
601
|
+
return createNumberFieldSchema(field);
|
|
602
|
+
// Date
|
|
603
|
+
case "date":
|
|
604
|
+
case "datetime":
|
|
605
|
+
return createDateFieldSchema(field);
|
|
606
|
+
// Selection
|
|
607
|
+
case "select":
|
|
608
|
+
return createSelectFieldSchema(field);
|
|
609
|
+
case "radio":
|
|
610
|
+
return createRadioFieldSchema(field);
|
|
611
|
+
// Boolean
|
|
612
|
+
case "checkbox":
|
|
613
|
+
return createCheckboxFieldSchema(field);
|
|
614
|
+
case "switch":
|
|
615
|
+
return createSwitchFieldSchema(field);
|
|
616
|
+
// Upload
|
|
617
|
+
case "upload":
|
|
618
|
+
return createUploadFieldSchema(field);
|
|
619
|
+
// Tags
|
|
620
|
+
case "tags":
|
|
621
|
+
return createTagsFieldSchema(field);
|
|
622
|
+
// Composite (recursive)
|
|
623
|
+
case "array":
|
|
624
|
+
return createArrayFieldSchema(field, fieldsToZodSchema);
|
|
625
|
+
case "group":
|
|
626
|
+
return createGroupFieldSchema(field, fieldsToZodSchema);
|
|
627
|
+
// Layout fields don't produce schemas directly
|
|
628
|
+
case "row":
|
|
629
|
+
case "collapsible":
|
|
630
|
+
case "tabs":
|
|
631
|
+
return import_zod10.z.any();
|
|
632
|
+
default:
|
|
633
|
+
return import_zod10.z.any();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
function processTabsField(field) {
|
|
637
|
+
const shape = {};
|
|
638
|
+
for (const tab of field.tabs) {
|
|
639
|
+
if (tab.name) {
|
|
640
|
+
const tabSchema = fieldsToZodSchema(tab.fields);
|
|
641
|
+
shape[tab.name] = tabSchema;
|
|
642
|
+
} else {
|
|
643
|
+
const tabFieldsSchema = fieldsToZodSchema(tab.fields);
|
|
644
|
+
if (tabFieldsSchema instanceof import_zod10.z.ZodObject) {
|
|
645
|
+
Object.assign(shape, tabFieldsSchema.shape);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return shape;
|
|
650
|
+
}
|
|
651
|
+
function fieldsToZodSchema(fields) {
|
|
652
|
+
const shape = {};
|
|
653
|
+
for (const field of fields) {
|
|
654
|
+
if ("name" in field && field.name) {
|
|
655
|
+
shape[field.name] = fieldToZod(field);
|
|
656
|
+
} else if (field.type === "tabs") {
|
|
657
|
+
const tabsShape = processTabsField(field);
|
|
658
|
+
Object.assign(shape, tabsShape);
|
|
659
|
+
} else if (field.type === "row" || field.type === "collapsible") {
|
|
660
|
+
const nestedSchema = fieldsToZodSchema(field.fields);
|
|
661
|
+
if (nestedSchema instanceof import_zod10.z.ZodObject) {
|
|
662
|
+
Object.assign(shape, nestedSchema.shape);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return import_zod10.z.object(shape);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// src/schema/create-schema.ts
|
|
670
|
+
function createSchema(fields) {
|
|
671
|
+
const schema = fieldsToZodSchema(fields);
|
|
672
|
+
return Object.assign(schema, { fields });
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// src/utils/array.ts
|
|
676
|
+
var import_nanoid = require("nanoid");
|
|
677
|
+
function createArrayHelpers(getArray, setArray) {
|
|
678
|
+
return {
|
|
679
|
+
fields: (path) => {
|
|
680
|
+
const arr = getArray(path);
|
|
681
|
+
if (!Array.isArray(arr)) return [];
|
|
682
|
+
return arr.map((item, index) => ({
|
|
683
|
+
id: item?.id || `${path}-${index}`,
|
|
684
|
+
...item
|
|
685
|
+
}));
|
|
686
|
+
},
|
|
687
|
+
append: (path, value) => {
|
|
688
|
+
const current = getArray(path) || [];
|
|
689
|
+
const itemWithId = ensureId(value);
|
|
690
|
+
setArray(path, [...current, itemWithId]);
|
|
691
|
+
},
|
|
692
|
+
prepend: (path, value) => {
|
|
693
|
+
const current = getArray(path) || [];
|
|
694
|
+
const itemWithId = ensureId(value);
|
|
695
|
+
setArray(path, [itemWithId, ...current]);
|
|
696
|
+
},
|
|
697
|
+
insert: (path, index, value) => {
|
|
698
|
+
const current = [...getArray(path) || []];
|
|
699
|
+
const itemWithId = ensureId(value);
|
|
700
|
+
current.splice(index, 0, itemWithId);
|
|
701
|
+
setArray(path, current);
|
|
702
|
+
},
|
|
703
|
+
remove: (path, index) => {
|
|
704
|
+
const current = [...getArray(path) || []];
|
|
705
|
+
current.splice(index, 1);
|
|
706
|
+
setArray(path, current);
|
|
707
|
+
},
|
|
708
|
+
move: (path, from, to) => {
|
|
709
|
+
const current = [...getArray(path) || []];
|
|
710
|
+
const [item] = current.splice(from, 1);
|
|
711
|
+
current.splice(to, 0, item);
|
|
712
|
+
setArray(path, current);
|
|
713
|
+
},
|
|
714
|
+
swap: (path, indexA, indexB) => {
|
|
715
|
+
const current = [...getArray(path) || []];
|
|
716
|
+
const temp = current[indexA];
|
|
717
|
+
current[indexA] = current[indexB];
|
|
718
|
+
current[indexB] = temp;
|
|
719
|
+
setArray(path, current);
|
|
720
|
+
},
|
|
721
|
+
replace: (path, values) => {
|
|
722
|
+
const itemsWithIds = values.map(ensureId);
|
|
723
|
+
setArray(path, itemsWithIds);
|
|
724
|
+
},
|
|
725
|
+
update: (path, index, value) => {
|
|
726
|
+
const current = [...getArray(path) || []];
|
|
727
|
+
const existingId = current[index]?.id;
|
|
728
|
+
current[index] = {
|
|
729
|
+
...typeof value === "object" && value !== null ? value : {},
|
|
730
|
+
id: existingId || (0, import_nanoid.nanoid)()
|
|
731
|
+
};
|
|
732
|
+
setArray(path, current);
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
function ensureId(value) {
|
|
737
|
+
if (typeof value === "object" && value !== null) {
|
|
738
|
+
const obj = value;
|
|
739
|
+
if (!obj.id) {
|
|
740
|
+
return { ...obj, id: (0, import_nanoid.nanoid)() };
|
|
741
|
+
}
|
|
742
|
+
return obj;
|
|
743
|
+
}
|
|
744
|
+
return { value, id: (0, import_nanoid.nanoid)() };
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/lib/utils.ts
|
|
748
|
+
function generateFieldId(path) {
|
|
749
|
+
return `field-${path.replace(/\./g, "-").replace(/\[/g, "-").replace(/\]/g, "")}`;
|
|
750
|
+
}
|
|
751
|
+
function getNestedValue(obj, path) {
|
|
752
|
+
if (!obj || !path) return void 0;
|
|
753
|
+
return path.split(".").reduce((acc, key) => {
|
|
754
|
+
if (acc && typeof acc === "object" && acc !== null) {
|
|
755
|
+
return acc[key];
|
|
756
|
+
}
|
|
757
|
+
return void 0;
|
|
758
|
+
}, obj);
|
|
759
|
+
}
|
|
760
|
+
function setNestedValue(obj, path, value) {
|
|
761
|
+
const keys = path.split(".");
|
|
762
|
+
const result = { ...obj };
|
|
763
|
+
let current = result;
|
|
764
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
765
|
+
const key = keys[i];
|
|
766
|
+
if (!(key in current) || typeof current[key] !== "object") {
|
|
767
|
+
const nextKey = keys[i + 1];
|
|
768
|
+
current[key] = /^\d+$/.test(nextKey) ? [] : {};
|
|
769
|
+
} else {
|
|
770
|
+
current[key] = Array.isArray(current[key]) ? [...current[key]] : { ...current[key] };
|
|
771
|
+
}
|
|
772
|
+
current = current[key];
|
|
773
|
+
}
|
|
774
|
+
current[keys[keys.length - 1]] = value;
|
|
775
|
+
return result;
|
|
776
|
+
}
|
|
777
|
+
function formatBytes(bytes, decimals = 2) {
|
|
778
|
+
if (bytes === 0) return "0 Bytes";
|
|
779
|
+
const k = 1024;
|
|
780
|
+
const dm = decimals < 0 ? 0 : decimals;
|
|
781
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
|
782
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
783
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// src/lib/field.ts
|
|
787
|
+
function getNestedFieldPaths(fields, basePath) {
|
|
788
|
+
const paths = [];
|
|
789
|
+
for (const field of fields) {
|
|
790
|
+
if ("name" in field && field.name) {
|
|
791
|
+
const fieldPath = basePath ? `${basePath}.${field.name}` : field.name;
|
|
792
|
+
paths.push(fieldPath);
|
|
793
|
+
if (field.type === "group" && "fields" in field) {
|
|
794
|
+
paths.push(...getNestedFieldPaths(field.fields, fieldPath));
|
|
795
|
+
}
|
|
796
|
+
if (field.type === "array" && "fields" in field) {
|
|
797
|
+
paths.push(...getNestedFieldPaths(field.fields, fieldPath));
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if ("fields" in field && field.type !== "group" && field.type !== "array") {
|
|
801
|
+
const layoutField = field;
|
|
802
|
+
paths.push(...getNestedFieldPaths(layoutField.fields, basePath));
|
|
803
|
+
}
|
|
804
|
+
if (field.type === "tabs" && "tabs" in field) {
|
|
805
|
+
for (const tab of field.tabs) {
|
|
806
|
+
const tabPath = tab.name ? basePath ? `${basePath}.${tab.name}` : tab.name : basePath;
|
|
807
|
+
paths.push(...getNestedFieldPaths(tab.fields, tabPath));
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return paths;
|
|
812
|
+
}
|
|
813
|
+
function countNestedErrors(errors, fields, basePath) {
|
|
814
|
+
const paths = getNestedFieldPaths(fields, basePath);
|
|
815
|
+
return paths.filter((path) => errors[path]).length;
|
|
816
|
+
}
|
|
817
|
+
function resolveFieldState(value, formData, siblingData = formData) {
|
|
818
|
+
if (typeof value === "function") {
|
|
819
|
+
return value(formData, siblingData);
|
|
820
|
+
}
|
|
821
|
+
return Boolean(value);
|
|
822
|
+
}
|
|
823
|
+
function getArrayRowLabel(rowData, fields, uiOptions, fallbackLabel) {
|
|
824
|
+
if (uiOptions?.rowLabelField && rowData?.[uiOptions.rowLabelField]) {
|
|
825
|
+
return String(rowData[uiOptions.rowLabelField]);
|
|
826
|
+
}
|
|
827
|
+
const firstNamedField = fields.find((f) => "name" in f && f.name);
|
|
828
|
+
if (firstNamedField && "name" in firstNamedField) {
|
|
829
|
+
const value = rowData?.[firstNamedField.name];
|
|
830
|
+
if (value) {
|
|
831
|
+
return String(value);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return fallbackLabel;
|
|
835
|
+
}
|
|
836
|
+
function getFieldWidthStyle(style) {
|
|
837
|
+
if (!style?.width) return void 0;
|
|
838
|
+
return {
|
|
839
|
+
width: typeof style.width === "number" ? `${style.width}px` : style.width
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
function normalizeSelectOption(option) {
|
|
843
|
+
if (typeof option === "string") {
|
|
844
|
+
return { value: option, label: option };
|
|
845
|
+
}
|
|
846
|
+
return {
|
|
847
|
+
value: option.value,
|
|
848
|
+
label: option.label ?? String(option.value),
|
|
849
|
+
description: option.description,
|
|
850
|
+
icon: option.icon,
|
|
851
|
+
disabled: option.disabled
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
function getSelectOptionValue(option) {
|
|
855
|
+
if (typeof option === "string") return option;
|
|
856
|
+
const val = option.value;
|
|
857
|
+
if (typeof val === "boolean") return val ? "true" : "false";
|
|
858
|
+
return String(val);
|
|
859
|
+
}
|
|
860
|
+
function getSelectOptionLabel(option) {
|
|
861
|
+
if (typeof option === "string") return option;
|
|
862
|
+
return option.label ?? String(option.value);
|
|
863
|
+
}
|
|
864
|
+
function getSelectOptionLabelString(option) {
|
|
865
|
+
if (typeof option === "string") return option;
|
|
866
|
+
if (typeof option.label === "string") return option.label;
|
|
867
|
+
return String(option.value);
|
|
868
|
+
}
|
|
869
|
+
function isSelectOptionDisabled(option) {
|
|
870
|
+
if (typeof option === "string") return false;
|
|
871
|
+
return option.disabled === true;
|
|
872
|
+
}
|
|
873
|
+
function clampNumber(value, min, max) {
|
|
874
|
+
let result = value;
|
|
875
|
+
if (min !== void 0 && result < min) result = min;
|
|
876
|
+
if (max !== void 0 && result > max) result = max;
|
|
877
|
+
return result;
|
|
878
|
+
}
|
|
879
|
+
function applyNumericPrecision(value, precision) {
|
|
880
|
+
if (value === void 0 || precision === void 0) return value;
|
|
881
|
+
return parseFloat(value.toFixed(precision));
|
|
882
|
+
}
|
|
883
|
+
function formatNumberWithSeparator(value, separator = ",") {
|
|
884
|
+
if (value === void 0 || value === null || isNaN(value)) return "";
|
|
885
|
+
const [intPart, decPart] = value.toString().split(".");
|
|
886
|
+
const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
|
887
|
+
return decPart !== void 0 ? `${formattedInt}.${decPart}` : formattedInt;
|
|
888
|
+
}
|
|
889
|
+
function parseFormattedNumber(str, separator = ",") {
|
|
890
|
+
if (!str || str === "") return void 0;
|
|
891
|
+
const cleaned = str.split(separator).join("");
|
|
892
|
+
const num = parseFloat(cleaned);
|
|
893
|
+
return isNaN(num) ? void 0 : num;
|
|
894
|
+
}
|
|
895
|
+
function parseToDate(value) {
|
|
896
|
+
if (!value) return void 0;
|
|
897
|
+
if (value instanceof Date) {
|
|
898
|
+
return isNaN(value.getTime()) ? void 0 : value;
|
|
899
|
+
}
|
|
900
|
+
if (typeof value === "number") {
|
|
901
|
+
const date = new Date(value);
|
|
902
|
+
return isNaN(date.getTime()) ? void 0 : date;
|
|
903
|
+
}
|
|
904
|
+
if (typeof value === "string") {
|
|
905
|
+
const date = new Date(value);
|
|
906
|
+
return isNaN(date.getTime()) ? void 0 : date;
|
|
907
|
+
}
|
|
908
|
+
return void 0;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// src/context/form-context.ts
|
|
912
|
+
var import_react = require("react");
|
|
913
|
+
var FormConfigContext = (0, import_react.createContext)(null);
|
|
914
|
+
|
|
915
|
+
// src/providers/form-provider.tsx
|
|
916
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
917
|
+
var FormProvider = ({ children, ...config }) => {
|
|
918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormConfigContext.Provider, { value: config, children });
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
// src/hooks/use-form.ts
|
|
922
|
+
var import_react2 = require("react");
|
|
923
|
+
function extractDefaultsFromFields(fields) {
|
|
924
|
+
if (!fields || fields.length === 0) return void 0;
|
|
925
|
+
const defaults = {};
|
|
926
|
+
let hasDefaults = false;
|
|
927
|
+
for (const field of fields) {
|
|
928
|
+
if ("name" in field && "defaultValue" in field && field.defaultValue !== void 0) {
|
|
929
|
+
defaults[field.name] = field.defaultValue;
|
|
930
|
+
hasDefaults = true;
|
|
931
|
+
}
|
|
932
|
+
if ("fields" in field && Array.isArray(field.fields)) {
|
|
933
|
+
const nestedDefaults = extractDefaultsFromFields(field.fields);
|
|
934
|
+
if (nestedDefaults) {
|
|
935
|
+
Object.assign(defaults, nestedDefaults);
|
|
936
|
+
hasDefaults = true;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return hasDefaults ? defaults : void 0;
|
|
941
|
+
}
|
|
942
|
+
function applySettings(form, settings) {
|
|
943
|
+
if (!settings) return form;
|
|
944
|
+
if (settings.submitOnlyWhenDirty) {
|
|
945
|
+
const originalHandleSubmit = form.handleSubmit;
|
|
946
|
+
form.handleSubmit = (e) => {
|
|
947
|
+
if (!form.formState.isDirty) {
|
|
948
|
+
e?.preventDefault?.();
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
return originalHandleSubmit(e);
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
if (settings) {
|
|
955
|
+
form.settings = settings;
|
|
956
|
+
}
|
|
957
|
+
return form;
|
|
958
|
+
}
|
|
959
|
+
function useForm(options) {
|
|
960
|
+
const globalConfig = (0, import_react2.useContext)(FormConfigContext);
|
|
961
|
+
if (!options.schema) {
|
|
962
|
+
throw new Error(
|
|
963
|
+
"useForm: schema is required. Use createSchema([...]) to create a schema from fields, or pass a Zod schema directly."
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
const adapter = options.adapter ?? globalConfig?.adapter;
|
|
967
|
+
const resolverFn = globalConfig?.resolver;
|
|
968
|
+
const mode = options.mode ?? globalConfig?.mode ?? "onChange";
|
|
969
|
+
const reValidateMode = options.reValidateMode ?? globalConfig?.reValidateMode ?? "onChange";
|
|
970
|
+
if (!adapter) {
|
|
971
|
+
throw new Error(
|
|
972
|
+
"useForm: No adapter configured. Either wrap your app in <FormProvider adapter={...}> or pass adapter in options."
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
const resolver = resolverFn ? resolverFn(options.schema) : void 0;
|
|
976
|
+
const schemaWithFields = options.schema;
|
|
977
|
+
const fieldDefaults = (0, import_react2.useMemo)(
|
|
978
|
+
() => extractDefaultsFromFields(schemaWithFields.fields),
|
|
979
|
+
[schemaWithFields.fields]
|
|
980
|
+
);
|
|
981
|
+
const defaultValues = options.defaultValues ?? fieldDefaults;
|
|
982
|
+
const form = adapter({
|
|
983
|
+
defaultValues,
|
|
984
|
+
resolver,
|
|
985
|
+
mode,
|
|
986
|
+
reValidateMode,
|
|
987
|
+
onSubmit: options.onSubmit
|
|
988
|
+
});
|
|
989
|
+
return applySettings(form, options.settings);
|
|
990
|
+
}
|
|
991
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
992
|
+
0 && (module.exports = {
|
|
993
|
+
FormConfigContext,
|
|
994
|
+
FormProvider,
|
|
995
|
+
applyCustomValidation,
|
|
996
|
+
applyNumericPrecision,
|
|
997
|
+
clampNumber,
|
|
998
|
+
coerceToDate,
|
|
999
|
+
coerceToNumber,
|
|
1000
|
+
countNestedErrors,
|
|
1001
|
+
createArrayHelpers,
|
|
1002
|
+
createSchema,
|
|
1003
|
+
extractValidationConfig,
|
|
1004
|
+
fieldsToZodSchema,
|
|
1005
|
+
formatBytes,
|
|
1006
|
+
formatNumberWithSeparator,
|
|
1007
|
+
generateFieldId,
|
|
1008
|
+
getArrayRowLabel,
|
|
1009
|
+
getFieldWidthStyle,
|
|
1010
|
+
getNestedFieldPaths,
|
|
1011
|
+
getNestedValue,
|
|
1012
|
+
getPatternErrorMessage,
|
|
1013
|
+
getSelectOptionLabel,
|
|
1014
|
+
getSelectOptionLabelString,
|
|
1015
|
+
getSelectOptionValue,
|
|
1016
|
+
isFileLike,
|
|
1017
|
+
isFileTypeAccepted,
|
|
1018
|
+
isSelectOptionDisabled,
|
|
1019
|
+
makeOptional,
|
|
1020
|
+
normalizeSelectOption,
|
|
1021
|
+
parseFormattedNumber,
|
|
1022
|
+
parseToDate,
|
|
1023
|
+
resolveFieldState,
|
|
1024
|
+
setNestedValue,
|
|
1025
|
+
useForm,
|
|
1026
|
+
validateAdapter
|
|
1027
|
+
});
|
|
1028
|
+
//# sourceMappingURL=index.js.map
|