@otl-core/forms 1.1.18 → 1.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/form-context.cjs +99 -0
  2. package/dist/form-context.cjs.map +1 -0
  3. package/dist/form-context.d.cts +55 -0
  4. package/dist/form-context.d.ts +55 -0
  5. package/dist/form-context.js +80 -0
  6. package/dist/form-context.js.map +1 -0
  7. package/dist/index.cjs +25 -943
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +6 -84
  10. package/dist/index.d.ts +6 -84
  11. package/dist/index.js +3 -939
  12. package/dist/index.js.map +1 -1
  13. package/dist/use-form-action.cjs +281 -0
  14. package/dist/use-form-action.cjs.map +1 -0
  15. package/dist/use-form-action.d.cts +12 -0
  16. package/dist/use-form-action.d.ts +12 -0
  17. package/dist/use-form-action.js +264 -0
  18. package/dist/use-form-action.js.map +1 -0
  19. package/dist/use-form-field.cjs +181 -0
  20. package/dist/use-form-field.cjs.map +1 -0
  21. package/dist/use-form-field.d.cts +19 -0
  22. package/dist/use-form-field.d.ts +19 -0
  23. package/dist/use-form-field.js +160 -0
  24. package/dist/use-form-field.js.map +1 -0
  25. package/dist/utils/page.utils.cjs +76 -0
  26. package/dist/utils/page.utils.cjs.map +1 -0
  27. package/dist/utils/page.utils.d.cts +7 -0
  28. package/dist/utils/page.utils.d.ts +7 -0
  29. package/dist/utils/page.utils.js +50 -0
  30. package/dist/utils/page.utils.js.map +1 -0
  31. package/dist/utils/rule.utils.cjs +94 -0
  32. package/dist/utils/rule.utils.cjs.map +1 -0
  33. package/dist/utils/rule.utils.d.cts +6 -0
  34. package/dist/utils/rule.utils.d.ts +6 -0
  35. package/dist/utils/rule.utils.js +69 -0
  36. package/dist/utils/rule.utils.js.map +1 -0
  37. package/dist/utils/validation.utils.cjs +391 -0
  38. package/dist/utils/validation.utils.cjs.map +1 -0
  39. package/dist/utils/validation.utils.d.cts +15 -0
  40. package/dist/utils/validation.utils.d.ts +15 -0
  41. package/dist/utils/validation.utils.js +366 -0
  42. package/dist/utils/validation.utils.js.map +1 -0
  43. package/package.json +2 -2
@@ -0,0 +1,366 @@
1
+ function isEmpty(value) {
2
+ return value === void 0 || value === null || value === "";
3
+ }
4
+ function interpolateMessage(template, params) {
5
+ return template.replace(/\{(\w+)\}/g, (_, key) => String(params[key] || ""));
6
+ }
7
+ function validateMinLength(value, minLength) {
8
+ if (isEmpty(value)) return true;
9
+ return typeof value === "string" && value.length >= parseInt(minLength);
10
+ }
11
+ function validateMaxLength(value, maxLength) {
12
+ if (isEmpty(value)) return true;
13
+ return typeof value === "string" && value.length <= parseInt(maxLength);
14
+ }
15
+ function validatePattern(value, pattern) {
16
+ if (isEmpty(value)) return true;
17
+ return typeof value === "string" && new RegExp(pattern).test(value);
18
+ }
19
+ function validateMinValue(value, min) {
20
+ if (isEmpty(value)) return true;
21
+ const numValue = typeof value === "number" ? value : parseFloat(value);
22
+ const minValue = typeof min === "number" ? min : parseFloat(min);
23
+ return !isNaN(numValue) && !isNaN(minValue) && numValue >= minValue;
24
+ }
25
+ function validateMaxValue(value, max) {
26
+ if (isEmpty(value)) return true;
27
+ const numValue = typeof value === "number" ? value : parseFloat(value);
28
+ const maxValue = typeof max === "number" ? max : parseFloat(max);
29
+ return !isNaN(numValue) && !isNaN(maxValue) && numValue <= maxValue;
30
+ }
31
+ function validateEmail(value) {
32
+ if (isEmpty(value)) return true;
33
+ if (typeof value !== "string") return false;
34
+ const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
35
+ return emailRegex.test(value);
36
+ }
37
+ function validateURL(value) {
38
+ if (isEmpty(value)) return true;
39
+ if (typeof value !== "string") return false;
40
+ try {
41
+ const url = new URL(value);
42
+ return url.protocol === "http:" || url.protocol === "https:";
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+ function validatePhoneNumber(value) {
48
+ if (isEmpty(value)) return true;
49
+ if (typeof value !== "string") return false;
50
+ const phoneRegex = /^[\+]?[(]?[0-9]{1,4}[)]?[-\s\.]?[(]?[0-9]{1,4}[)]?[-\s\.]?[0-9]{1,4}[-\s\.]?[0-9]{1,9}$/;
51
+ return phoneRegex.test(value.replace(/\s/g, ""));
52
+ }
53
+ function validateDate(value) {
54
+ if (isEmpty(value)) return true;
55
+ if (typeof value !== "string") return false;
56
+ const date = new Date(value);
57
+ return !isNaN(date.getTime());
58
+ }
59
+ function validateTime(value) {
60
+ if (isEmpty(value)) return true;
61
+ if (typeof value !== "string") return false;
62
+ const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;
63
+ return timeRegex.test(value);
64
+ }
65
+ function validateColor(value) {
66
+ if (isEmpty(value)) return true;
67
+ if (typeof value !== "string") return false;
68
+ const hexRegex = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/;
69
+ return hexRegex.test(value);
70
+ }
71
+ function validateZipCode(value) {
72
+ if (isEmpty(value)) return true;
73
+ if (typeof value !== "string") return false;
74
+ const usZipRegex = /^\d{5}(-\d{4})?$/;
75
+ const ukPostcodeRegex = /^[A-Z]{1,2}\d{1,2}[A-Z]?\s?\d[A-Z]{2}$/i;
76
+ const dePostcodeRegex = /^\d{5}$/;
77
+ return usZipRegex.test(value) || ukPostcodeRegex.test(value) || dePostcodeRegex.test(value);
78
+ }
79
+ function validateCreditCard(value) {
80
+ if (isEmpty(value)) return true;
81
+ if (typeof value !== "string") return false;
82
+ const cleaned = value.replace(/[\s-]/g, "");
83
+ if (!/^\d{13,19}$/.test(cleaned)) return false;
84
+ let sum = 0;
85
+ let isEven = false;
86
+ for (let i = cleaned.length - 1; i >= 0; i--) {
87
+ let digit = parseInt(cleaned.charAt(i), 10);
88
+ if (isEven) {
89
+ digit *= 2;
90
+ if (digit > 9) {
91
+ digit -= 9;
92
+ }
93
+ }
94
+ sum += digit;
95
+ isEven = !isEven;
96
+ }
97
+ return sum % 10 === 0;
98
+ }
99
+ function validateIPAddress(value) {
100
+ if (isEmpty(value)) return true;
101
+ if (typeof value !== "string") return false;
102
+ const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
103
+ const ipv6Regex = /^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}$/i;
104
+ return ipv4Regex.test(value) || ipv6Regex.test(value);
105
+ }
106
+ const TYPE_ERROR_MESSAGES = {
107
+ email: "Please enter a valid email address",
108
+ url: "Please enter a valid URL (e.g., https://example.com)",
109
+ tel: "Please enter a valid phone number",
110
+ date: "Please enter a valid date",
111
+ time: "Please enter a valid time",
112
+ color: "Please enter a valid color code (e.g., #FF0000)",
113
+ zipcode: "Please enter a valid ZIP/postal code",
114
+ creditcard: "Please enter a valid credit card number",
115
+ ip: "Please enter a valid IP address"
116
+ };
117
+ function getAllBlocksFromPage(blocks) {
118
+ const allBlocks = [];
119
+ for (const block of blocks) {
120
+ allBlocks.push(block);
121
+ if (block.config.blocks && Array.isArray(block.config.blocks)) {
122
+ const nestedBlocks = block.config.blocks.map(
123
+ (b) => ({
124
+ id: b.id,
125
+ type: b.type,
126
+ config: b.config || {}
127
+ })
128
+ );
129
+ allBlocks.push(...getAllBlocksFromPage(nestedBlocks));
130
+ }
131
+ }
132
+ return allBlocks;
133
+ }
134
+ function validatePage(page, formValues, settings) {
135
+ const errors = {};
136
+ const allBlocks = getAllBlocksFromPage(page.blocks);
137
+ const errorMessages = settings?.error_messages || {};
138
+ for (const block of allBlocks) {
139
+ if (block.type === "form-button" || block.type === "form-inline-group") {
140
+ continue;
141
+ }
142
+ const fieldId = typeof block.config.field_id === "string" ? block.config.field_id : block.id;
143
+ const value = formValues[fieldId];
144
+ const inputType = typeof block.config.input_type === "string" ? block.config.input_type : "";
145
+ if (block.config.required && isEmpty(value)) {
146
+ errors[fieldId] = errorMessages.required || "This field is required";
147
+ continue;
148
+ }
149
+ if (block.config.check_required && block.type === "form-checkbox") {
150
+ const isChecked = value === true || Array.isArray(value) && value.length > 0;
151
+ if (!isChecked) {
152
+ errors[fieldId] = errorMessages.check_required || "You must check this box to continue";
153
+ continue;
154
+ }
155
+ }
156
+ if (block.type === "form-checkbox" && block.config.options) {
157
+ const options = block.config.options;
158
+ const checkedValues = Array.isArray(value) ? value : [];
159
+ for (const option of options) {
160
+ if (option.check_required && !checkedValues.includes(option.value)) {
161
+ errors[fieldId] = `You must check "${option.label}" to continue`;
162
+ break;
163
+ }
164
+ }
165
+ if (errors[fieldId]) {
166
+ continue;
167
+ }
168
+ }
169
+ if (isEmpty(value)) {
170
+ continue;
171
+ }
172
+ switch (inputType) {
173
+ case "email":
174
+ if (!validateEmail(value)) {
175
+ errors[fieldId] = errorMessages.invalid_email || "Please enter a valid email address";
176
+ continue;
177
+ }
178
+ break;
179
+ case "url":
180
+ if (!validateURL(value)) {
181
+ errors[fieldId] = errorMessages.invalid_url || "Please enter a valid URL (e.g., https://example.com)";
182
+ continue;
183
+ }
184
+ break;
185
+ case "tel":
186
+ if (!validatePhoneNumber(value)) {
187
+ errors[fieldId] = errorMessages.invalid_phone || "Please enter a valid phone number";
188
+ continue;
189
+ }
190
+ break;
191
+ case "date":
192
+ if (!validateDate(value)) {
193
+ errors[fieldId] = errorMessages.invalid_date || "Please enter a valid date";
194
+ continue;
195
+ }
196
+ break;
197
+ case "time":
198
+ if (!validateTime(value)) {
199
+ errors[fieldId] = errorMessages.invalid_time || "Please enter a valid time";
200
+ continue;
201
+ }
202
+ break;
203
+ case "color":
204
+ if (!validateColor(value)) {
205
+ errors[fieldId] = errorMessages.invalid_color || "Please enter a valid color code (e.g., #FF0000)";
206
+ continue;
207
+ }
208
+ break;
209
+ }
210
+ if (block.config.validation_type) {
211
+ const validationType = block.config.validation_type;
212
+ switch (validationType) {
213
+ case "zipcode":
214
+ if (!validateZipCode(value)) {
215
+ errors[fieldId] = TYPE_ERROR_MESSAGES.zipcode;
216
+ continue;
217
+ }
218
+ break;
219
+ case "creditcard":
220
+ if (!validateCreditCard(value)) {
221
+ errors[fieldId] = TYPE_ERROR_MESSAGES.creditcard;
222
+ continue;
223
+ }
224
+ break;
225
+ case "ip":
226
+ if (!validateIPAddress(value)) {
227
+ errors[fieldId] = TYPE_ERROR_MESSAGES.ip;
228
+ continue;
229
+ }
230
+ break;
231
+ }
232
+ }
233
+ if (block.config.minLength && !validateMinLength(value, block.config.minLength)) {
234
+ errors[fieldId] = errorMessages.min_length ? interpolateMessage(errorMessages.min_length, {
235
+ min: block.config.minLength
236
+ }) : "This field must be at least " + block.config.minLength + " characters long";
237
+ continue;
238
+ }
239
+ if (block.config.maxLength && !validateMaxLength(value, block.config.maxLength)) {
240
+ errors[fieldId] = errorMessages.max_length ? interpolateMessage(errorMessages.max_length, {
241
+ max: block.config.maxLength
242
+ }) : "This field must be less than " + block.config.maxLength + " characters long";
243
+ continue;
244
+ }
245
+ if (block.config.min !== void 0 && !validateMinValue(value, block.config.min)) {
246
+ errors[fieldId] = errorMessages.min_value ? interpolateMessage(errorMessages.min_value, { min: block.config.min }) : "Value must be at least " + block.config.min;
247
+ continue;
248
+ }
249
+ if (block.config.max !== void 0 && !validateMaxValue(value, block.config.max)) {
250
+ errors[fieldId] = errorMessages.max_value ? interpolateMessage(errorMessages.max_value, { max: block.config.max }) : "Value must be no more than " + block.config.max;
251
+ continue;
252
+ }
253
+ if (block.config.pattern && !validatePattern(value, block.config.pattern)) {
254
+ const patternMessage = block.config.pattern_message ? block.config.pattern_message : "This field has an invalid format";
255
+ errors[fieldId] = patternMessage;
256
+ continue;
257
+ }
258
+ }
259
+ return Object.keys(errors).length > 0 ? errors : true;
260
+ }
261
+ function validateField(block, value, settings) {
262
+ if (block.type === "form-button" || block.type === "form-inline-group") {
263
+ return void 0;
264
+ }
265
+ const errorMessages = settings?.error_messages || {};
266
+ const inputType = typeof block.config.input_type === "string" ? block.config.input_type : "";
267
+ if (block.config.required && isEmpty(value)) {
268
+ return errorMessages.required || "This field is required";
269
+ }
270
+ if (block.config.check_required && block.type === "form-checkbox") {
271
+ const isChecked = value === true || Array.isArray(value) && value.length > 0;
272
+ if (!isChecked) {
273
+ return errorMessages.check_required || "You must check this box to continue";
274
+ }
275
+ }
276
+ if (block.type === "form-checkbox" && block.config.options) {
277
+ const options = block.config.options;
278
+ const checkedValues = Array.isArray(value) ? value : [];
279
+ for (const option of options) {
280
+ if (option.check_required && !checkedValues.includes(option.value)) {
281
+ return `You must check "${option.label}" to continue`;
282
+ }
283
+ }
284
+ }
285
+ if (isEmpty(value)) {
286
+ return void 0;
287
+ }
288
+ switch (inputType) {
289
+ case "email":
290
+ if (!validateEmail(value)) {
291
+ return errorMessages.invalid_email || "Please enter a valid email address";
292
+ }
293
+ break;
294
+ case "url":
295
+ if (!validateURL(value)) {
296
+ return errorMessages.invalid_url || "Please enter a valid URL (e.g., https://example.com)";
297
+ }
298
+ break;
299
+ case "tel":
300
+ if (!validatePhoneNumber(value)) {
301
+ return errorMessages.invalid_phone || "Please enter a valid phone number";
302
+ }
303
+ break;
304
+ case "date":
305
+ if (!validateDate(value)) {
306
+ return errorMessages.invalid_date || "Please enter a valid date";
307
+ }
308
+ break;
309
+ case "time":
310
+ if (!validateTime(value)) {
311
+ return errorMessages.invalid_time || "Please enter a valid time";
312
+ }
313
+ break;
314
+ case "color":
315
+ if (!validateColor(value)) {
316
+ return errorMessages.invalid_color || "Please enter a valid color code (e.g., #FF0000)";
317
+ }
318
+ break;
319
+ }
320
+ if (block.config.validation_type) {
321
+ const validationType = block.config.validation_type;
322
+ switch (validationType) {
323
+ case "zipcode":
324
+ if (!validateZipCode(value)) {
325
+ return TYPE_ERROR_MESSAGES.zipcode;
326
+ }
327
+ break;
328
+ case "creditcard":
329
+ if (!validateCreditCard(value)) {
330
+ return TYPE_ERROR_MESSAGES.creditcard;
331
+ }
332
+ break;
333
+ case "ip":
334
+ if (!validateIPAddress(value)) {
335
+ return TYPE_ERROR_MESSAGES.ip;
336
+ }
337
+ break;
338
+ }
339
+ }
340
+ if (block.config.minLength && !validateMinLength(value, block.config.minLength)) {
341
+ return errorMessages.min_length ? interpolateMessage(errorMessages.min_length, {
342
+ min: block.config.minLength
343
+ }) : "This field must be at least " + block.config.minLength + " characters long";
344
+ }
345
+ if (block.config.maxLength && !validateMaxLength(value, block.config.maxLength)) {
346
+ return errorMessages.max_length ? interpolateMessage(errorMessages.max_length, {
347
+ max: block.config.maxLength
348
+ }) : "This field must be less than " + block.config.maxLength + " characters long";
349
+ }
350
+ if (block.config.min !== void 0 && !validateMinValue(value, block.config.min)) {
351
+ return errorMessages.min_value ? interpolateMessage(errorMessages.min_value, { min: block.config.min }) : "Value must be at least " + block.config.min;
352
+ }
353
+ if (block.config.max !== void 0 && !validateMaxValue(value, block.config.max)) {
354
+ return errorMessages.max_value ? interpolateMessage(errorMessages.max_value, { max: block.config.max }) : "Value must be no more than " + block.config.max;
355
+ }
356
+ if (block.config.pattern && !validatePattern(value, block.config.pattern)) {
357
+ const patternMessage = block.config.pattern_message ? block.config.pattern_message : "This field has an invalid format";
358
+ return patternMessage;
359
+ }
360
+ return void 0;
361
+ }
362
+ export {
363
+ validateField,
364
+ validatePage
365
+ };
366
+ //# sourceMappingURL=validation.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/validation.utils.ts"],"sourcesContent":["import { BlockInstance, FormPage, FormSettings } from \"@otl-core/cms-types\";\n\nfunction isEmpty(value: unknown) {\n return value === undefined || value === null || value === \"\";\n}\n\nfunction interpolateMessage(\n template: string,\n params: Record<string, unknown>,\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (_, key) => String(params[key] || \"\"));\n}\n\nfunction validateMinLength(value: unknown, minLength: unknown) {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n return (\n typeof value === \"string\" && value.length >= parseInt(minLength as string)\n );\n}\n\nfunction validateMaxLength(value: unknown, maxLength: unknown) {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n return (\n typeof value === \"string\" && value.length <= parseInt(maxLength as string)\n );\n}\n\nfunction validatePattern(value: unknown, pattern: unknown) {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n return typeof value === \"string\" && new RegExp(pattern as string).test(value);\n}\n\nfunction validateMinValue(value: unknown, min: unknown) {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n const numValue =\n typeof value === \"number\" ? value : parseFloat(value as string);\n const minValue = typeof min === \"number\" ? min : parseFloat(min as string);\n return !isNaN(numValue) && !isNaN(minValue) && numValue >= minValue;\n}\n\nfunction validateMaxValue(value: unknown, max: unknown) {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n const numValue =\n typeof value === \"number\" ? value : parseFloat(value as string);\n const maxValue = typeof max === \"number\" ? max : parseFloat(max as string);\n return !isNaN(numValue) && !isNaN(maxValue) && numValue <= maxValue;\n}\n\n// Type-specific validators\nfunction validateEmail(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // RFC 5322 compliant email regex (simplified but robust)\n const emailRegex =\n /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n return emailRegex.test(value);\n}\n\nfunction validateURL(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n try {\n const url = new URL(value);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nfunction validatePhoneNumber(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // International phone number format (E.164 and common formats)\n // Allows: +1234567890, (123) 456-7890, 123-456-7890, 123.456.7890, 1234567890\n const phoneRegex =\n /^[\\+]?[(]?[0-9]{1,4}[)]?[-\\s\\.]?[(]?[0-9]{1,4}[)]?[-\\s\\.]?[0-9]{1,4}[-\\s\\.]?[0-9]{1,9}$/;\n return phoneRegex.test(value.replace(/\\s/g, \"\"));\n}\n\nfunction validateDate(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n const date = new Date(value);\n return !isNaN(date.getTime());\n}\n\nfunction validateTime(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // HH:MM or HH:MM:SS format\n const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;\n return timeRegex.test(value);\n}\n\nfunction validateColor(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // Hex color (#RGB, #RRGGBB, #RRGGBBAA)\n const hexRegex = /^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/;\n return hexRegex.test(value);\n}\n\nfunction validateZipCode(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // US ZIP code (12345 or 12345-6789)\n const usZipRegex = /^\\d{5}(-\\d{4})?$/;\n // UK postcode (basic pattern)\n const ukPostcodeRegex = /^[A-Z]{1,2}\\d{1,2}[A-Z]?\\s?\\d[A-Z]{2}$/i;\n // German postcode\n const dePostcodeRegex = /^\\d{5}$/;\n\n return (\n usZipRegex.test(value) ||\n ukPostcodeRegex.test(value) ||\n dePostcodeRegex.test(value)\n );\n}\n\nfunction validateCreditCard(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // Remove spaces and dashes\n const cleaned = value.replace(/[\\s-]/g, \"\");\n\n // Check if it's all digits and 13-19 characters (standard credit card length)\n if (!/^\\d{13,19}$/.test(cleaned)) return false;\n\n // Luhn algorithm\n let sum = 0;\n let isEven = false;\n\n for (let i = cleaned.length - 1; i >= 0; i--) {\n let digit = parseInt(cleaned.charAt(i), 10);\n\n if (isEven) {\n digit *= 2;\n if (digit > 9) {\n digit -= 9;\n }\n }\n\n sum += digit;\n isEven = !isEven;\n }\n\n return sum % 10 === 0;\n}\n\nfunction validateIPAddress(value: unknown): boolean {\n if (isEmpty(value)) return true; // Skip if empty (handled by required)\n if (typeof value !== \"string\") return false;\n\n // IPv4\n const ipv4Regex =\n /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n // IPv6 (simplified)\n const ipv6Regex = /^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}$/i;\n\n return ipv4Regex.test(value) || ipv6Regex.test(value);\n}\n\n// Validation error messages\nconst TYPE_ERROR_MESSAGES: Record<string, string> = {\n email: \"Please enter a valid email address\",\n url: \"Please enter a valid URL (e.g., https://example.com)\",\n tel: \"Please enter a valid phone number\",\n date: \"Please enter a valid date\",\n time: \"Please enter a valid time\",\n color: \"Please enter a valid color code (e.g., #FF0000)\",\n zipcode: \"Please enter a valid ZIP/postal code\",\n creditcard: \"Please enter a valid credit card number\",\n ip: \"Please enter a valid IP address\",\n};\n\nfunction getAllBlocksFromPage(blocks: BlockInstance[]): BlockInstance[] {\n const allBlocks: BlockInstance[] = [];\n\n for (const block of blocks) {\n allBlocks.push(block);\n\n // Check for nested blocks (e.g., form-inline-group)\n if (block.config.blocks && Array.isArray(block.config.blocks)) {\n const nestedBlocks = block.config.blocks.map(\n (b) =>\n ({\n id: b.id,\n type: b.type,\n config: b.config || {},\n }) as BlockInstance,\n );\n allBlocks.push(...getAllBlocksFromPage(nestedBlocks));\n }\n }\n\n return allBlocks;\n}\n\nexport function validatePage(\n page: FormPage,\n formValues: Record<string, unknown>,\n settings?: FormSettings,\n): true | { [key: string]: string } {\n const errors: { [key: string]: string } = {};\n const allBlocks = getAllBlocksFromPage(page.blocks);\n const errorMessages = settings?.error_messages || {};\n\n for (const block of allBlocks) {\n // Skip button blocks and non-input blocks\n if (block.type === \"form-button\" || block.type === \"form-inline-group\") {\n continue;\n }\n\n // Get the field_id (or fallback to block.id)\n const fieldId =\n typeof block.config.field_id === \"string\"\n ? block.config.field_id\n : block.id;\n\n const value = formValues[fieldId];\n const inputType =\n typeof block.config.input_type === \"string\"\n ? block.config.input_type\n : \"\";\n\n // Validate required fields (standard required)\n if (block.config.required && isEmpty(value)) {\n errors[fieldId] = errorMessages.required || \"This field is required\";\n continue; // Skip other validations if empty and required\n }\n\n // Validate checkbox required (must be checked)\n if (block.config.check_required && block.type === \"form-checkbox\") {\n const isChecked =\n value === true || (Array.isArray(value) && value.length > 0);\n if (!isChecked) {\n errors[fieldId] =\n errorMessages.check_required || \"You must check this box to continue\";\n continue;\n }\n }\n\n // Validate per-option check_required for checkbox groups\n if (block.type === \"form-checkbox\" && block.config.options) {\n const options = block.config.options as Array<{\n value: string;\n label: string;\n check_required?: boolean;\n }>;\n const checkedValues = Array.isArray(value) ? value : [];\n\n for (const option of options) {\n if (option.check_required && !checkedValues.includes(option.value)) {\n errors[fieldId] = `You must check \"${option.label}\" to continue`;\n break;\n }\n }\n\n if (errors[fieldId]) {\n continue;\n }\n }\n\n // Skip further validations if field is empty and not required\n if (isEmpty(value)) {\n continue;\n }\n\n // Type-specific validation\n switch (inputType) {\n case \"email\":\n if (!validateEmail(value)) {\n errors[fieldId] =\n errorMessages.invalid_email || \"Please enter a valid email address\";\n continue;\n }\n break;\n case \"url\":\n if (!validateURL(value)) {\n errors[fieldId] =\n errorMessages.invalid_url ||\n \"Please enter a valid URL (e.g., https://example.com)\";\n continue;\n }\n break;\n case \"tel\":\n if (!validatePhoneNumber(value)) {\n errors[fieldId] =\n errorMessages.invalid_phone || \"Please enter a valid phone number\";\n continue;\n }\n break;\n case \"date\":\n if (!validateDate(value)) {\n errors[fieldId] =\n errorMessages.invalid_date || \"Please enter a valid date\";\n continue;\n }\n break;\n case \"time\":\n if (!validateTime(value)) {\n errors[fieldId] =\n errorMessages.invalid_time || \"Please enter a valid time\";\n continue;\n }\n break;\n case \"color\":\n if (!validateColor(value)) {\n errors[fieldId] =\n errorMessages.invalid_color ||\n \"Please enter a valid color code (e.g., #FF0000)\";\n continue;\n }\n break;\n }\n\n // Custom validation type\n if (block.config.validation_type) {\n const validationType = block.config.validation_type as string;\n\n switch (validationType) {\n case \"zipcode\":\n if (!validateZipCode(value)) {\n errors[fieldId] = TYPE_ERROR_MESSAGES.zipcode;\n continue;\n }\n break;\n case \"creditcard\":\n if (!validateCreditCard(value)) {\n errors[fieldId] = TYPE_ERROR_MESSAGES.creditcard;\n continue;\n }\n break;\n case \"ip\":\n if (!validateIPAddress(value)) {\n errors[fieldId] = TYPE_ERROR_MESSAGES.ip;\n continue;\n }\n break;\n }\n }\n\n // Validate min/max length\n if (\n block.config.minLength &&\n !validateMinLength(value, block.config.minLength)\n ) {\n errors[fieldId] = errorMessages.min_length\n ? interpolateMessage(errorMessages.min_length, {\n min: block.config.minLength,\n })\n : \"This field must be at least \" +\n block.config.minLength +\n \" characters long\";\n continue;\n }\n\n if (\n block.config.maxLength &&\n !validateMaxLength(value, block.config.maxLength)\n ) {\n errors[fieldId] = errorMessages.max_length\n ? interpolateMessage(errorMessages.max_length, {\n max: block.config.maxLength,\n })\n : \"This field must be less than \" +\n block.config.maxLength +\n \" characters long\";\n continue;\n }\n\n // Validate min/max value (for number inputs)\n if (\n block.config.min !== undefined &&\n !validateMinValue(value, block.config.min)\n ) {\n errors[fieldId] = errorMessages.min_value\n ? interpolateMessage(errorMessages.min_value, { min: block.config.min })\n : \"Value must be at least \" + block.config.min;\n continue;\n }\n\n if (\n block.config.max !== undefined &&\n !validateMaxValue(value, block.config.max)\n ) {\n errors[fieldId] = errorMessages.max_value\n ? interpolateMessage(errorMessages.max_value, { max: block.config.max })\n : \"Value must be no more than \" + block.config.max;\n continue;\n }\n\n // Validate custom pattern (runs last, after type-specific validation)\n if (block.config.pattern && !validatePattern(value, block.config.pattern)) {\n const patternMessage = block.config.pattern_message\n ? block.config.pattern_message\n : \"This field has an invalid format\";\n errors[fieldId] = patternMessage as string;\n continue;\n }\n }\n\n return Object.keys(errors).length > 0 ? errors : true;\n}\n\n/**\n * Validates a single field\n * @param block The block instance to validate\n * @param value The current value of the field\n * @param settings Optional form settings for custom error messages\n * @returns Error message if validation fails, undefined if valid\n */\nexport function validateField(\n block: BlockInstance,\n value: unknown,\n settings?: FormSettings,\n): string | undefined {\n // Skip button blocks and non-input blocks\n if (block.type === \"form-button\" || block.type === \"form-inline-group\") {\n return undefined;\n }\n\n const errorMessages = settings?.error_messages || {};\n const inputType =\n typeof block.config.input_type === \"string\" ? block.config.input_type : \"\";\n\n // Validate required fields (standard required)\n if (block.config.required && isEmpty(value)) {\n return errorMessages.required || \"This field is required\";\n }\n\n // Validate checkbox required (must be checked)\n if (block.config.check_required && block.type === \"form-checkbox\") {\n const isChecked =\n value === true || (Array.isArray(value) && value.length > 0);\n if (!isChecked) {\n return (\n errorMessages.check_required || \"You must check this box to continue\"\n );\n }\n }\n\n // Validate per-option check_required for checkbox groups\n if (block.type === \"form-checkbox\" && block.config.options) {\n const options = block.config.options as Array<{\n value: string;\n label: string;\n check_required?: boolean;\n }>;\n const checkedValues = Array.isArray(value) ? value : [];\n\n for (const option of options) {\n if (option.check_required && !checkedValues.includes(option.value)) {\n return `You must check \"${option.label}\" to continue`;\n }\n }\n }\n\n // Skip further validations if field is empty and not required\n if (isEmpty(value)) {\n return undefined;\n }\n\n // Type-specific validation\n switch (inputType) {\n case \"email\":\n if (!validateEmail(value)) {\n return (\n errorMessages.invalid_email || \"Please enter a valid email address\"\n );\n }\n break;\n case \"url\":\n if (!validateURL(value)) {\n return (\n errorMessages.invalid_url ||\n \"Please enter a valid URL (e.g., https://example.com)\"\n );\n }\n break;\n case \"tel\":\n if (!validatePhoneNumber(value)) {\n return (\n errorMessages.invalid_phone || \"Please enter a valid phone number\"\n );\n }\n break;\n case \"date\":\n if (!validateDate(value)) {\n return errorMessages.invalid_date || \"Please enter a valid date\";\n }\n break;\n case \"time\":\n if (!validateTime(value)) {\n return errorMessages.invalid_time || \"Please enter a valid time\";\n }\n break;\n case \"color\":\n if (!validateColor(value)) {\n return (\n errorMessages.invalid_color ||\n \"Please enter a valid color code (e.g., #FF0000)\"\n );\n }\n break;\n }\n\n // Custom validation type\n if (block.config.validation_type) {\n const validationType = block.config.validation_type as string;\n\n switch (validationType) {\n case \"zipcode\":\n if (!validateZipCode(value)) {\n return TYPE_ERROR_MESSAGES.zipcode;\n }\n break;\n case \"creditcard\":\n if (!validateCreditCard(value)) {\n return TYPE_ERROR_MESSAGES.creditcard;\n }\n break;\n case \"ip\":\n if (!validateIPAddress(value)) {\n return TYPE_ERROR_MESSAGES.ip;\n }\n break;\n }\n }\n\n // Validate min/max length\n if (\n block.config.minLength &&\n !validateMinLength(value, block.config.minLength)\n ) {\n return errorMessages.min_length\n ? interpolateMessage(errorMessages.min_length, {\n min: block.config.minLength,\n })\n : \"This field must be at least \" +\n block.config.minLength +\n \" characters long\";\n }\n\n if (\n block.config.maxLength &&\n !validateMaxLength(value, block.config.maxLength)\n ) {\n return errorMessages.max_length\n ? interpolateMessage(errorMessages.max_length, {\n max: block.config.maxLength,\n })\n : \"This field must be less than \" +\n block.config.maxLength +\n \" characters long\";\n }\n\n // Validate min/max value (for number inputs)\n if (\n block.config.min !== undefined &&\n !validateMinValue(value, block.config.min)\n ) {\n return errorMessages.min_value\n ? interpolateMessage(errorMessages.min_value, { min: block.config.min })\n : \"Value must be at least \" + block.config.min;\n }\n\n if (\n block.config.max !== undefined &&\n !validateMaxValue(value, block.config.max)\n ) {\n return errorMessages.max_value\n ? interpolateMessage(errorMessages.max_value, { max: block.config.max })\n : \"Value must be no more than \" + block.config.max;\n }\n\n // Validate custom pattern (runs last, after type-specific validation)\n if (block.config.pattern && !validatePattern(value, block.config.pattern)) {\n const patternMessage = block.config.pattern_message\n ? block.config.pattern_message\n : \"This field has an invalid format\";\n return patternMessage as string;\n }\n\n return undefined;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otl-core/forms",
3
- "version": "1.1.18",
3
+ "version": "1.1.20",
4
4
  "type": "module",
5
5
  "description": "Form utilities and context for OTL CMS",
6
6
  "main": "./dist/index.cjs",
@@ -36,7 +36,7 @@
36
36
  "react": ">=18.0.0"
37
37
  },
38
38
  "dependencies": {
39
- "@otl-core/cms-types": "^1.1.18"
39
+ "@otl-core/cms-types": "^1.1.20"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@testing-library/dom": "^10.4.1",