@page-speed/forms 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.
Files changed (77) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +469 -0
  3. package/dist/builder.cjs +4 -0
  4. package/dist/builder.cjs.map +1 -0
  5. package/dist/builder.d.cts +2 -0
  6. package/dist/builder.d.ts +2 -0
  7. package/dist/builder.js +3 -0
  8. package/dist/builder.js.map +1 -0
  9. package/dist/chunk-2FXAQT7S.cjs +236 -0
  10. package/dist/chunk-2FXAQT7S.cjs.map +1 -0
  11. package/dist/chunk-A3UV7BIN.js +357 -0
  12. package/dist/chunk-A3UV7BIN.js.map +1 -0
  13. package/dist/chunk-P37YLBFA.cjs +138 -0
  14. package/dist/chunk-P37YLBFA.cjs.map +1 -0
  15. package/dist/chunk-WHQMBQNI.js +127 -0
  16. package/dist/chunk-WHQMBQNI.js.map +1 -0
  17. package/dist/chunk-YTTOWHBZ.js +217 -0
  18. package/dist/chunk-YTTOWHBZ.js.map +1 -0
  19. package/dist/chunk-ZQCPEOB6.cjs +382 -0
  20. package/dist/chunk-ZQCPEOB6.cjs.map +1 -0
  21. package/dist/core.cjs +28 -0
  22. package/dist/core.cjs.map +1 -0
  23. package/dist/core.d.cts +143 -0
  24. package/dist/core.d.ts +143 -0
  25. package/dist/core.js +3 -0
  26. package/dist/core.js.map +1 -0
  27. package/dist/index.cjs +28 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +3 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +3 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/inputs.cjs +555 -0
  34. package/dist/inputs.cjs.map +1 -0
  35. package/dist/inputs.d.cts +433 -0
  36. package/dist/inputs.d.ts +433 -0
  37. package/dist/inputs.js +529 -0
  38. package/dist/inputs.js.map +1 -0
  39. package/dist/integration.cjs +4 -0
  40. package/dist/integration.cjs.map +1 -0
  41. package/dist/integration.d.cts +2 -0
  42. package/dist/integration.d.ts +2 -0
  43. package/dist/integration.js +3 -0
  44. package/dist/integration.js.map +1 -0
  45. package/dist/types-Cw5CeZP-.d.cts +387 -0
  46. package/dist/types-Cw5CeZP-.d.ts +387 -0
  47. package/dist/upload.cjs +4 -0
  48. package/dist/upload.cjs.map +1 -0
  49. package/dist/upload.d.cts +2 -0
  50. package/dist/upload.d.ts +2 -0
  51. package/dist/upload.js +3 -0
  52. package/dist/upload.js.map +1 -0
  53. package/dist/validation-rules.cjs +80 -0
  54. package/dist/validation-rules.cjs.map +1 -0
  55. package/dist/validation-rules.d.cts +123 -0
  56. package/dist/validation-rules.d.ts +123 -0
  57. package/dist/validation-rules.js +3 -0
  58. package/dist/validation-rules.js.map +1 -0
  59. package/dist/validation-utils.cjs +48 -0
  60. package/dist/validation-utils.cjs.map +1 -0
  61. package/dist/validation-utils.d.cts +166 -0
  62. package/dist/validation-utils.d.ts +166 -0
  63. package/dist/validation-utils.js +3 -0
  64. package/dist/validation-utils.js.map +1 -0
  65. package/dist/validation-valibot.cjs +94 -0
  66. package/dist/validation-valibot.cjs.map +1 -0
  67. package/dist/validation-valibot.d.cts +92 -0
  68. package/dist/validation-valibot.d.ts +92 -0
  69. package/dist/validation-valibot.js +91 -0
  70. package/dist/validation-valibot.js.map +1 -0
  71. package/dist/validation.cjs +121 -0
  72. package/dist/validation.cjs.map +1 -0
  73. package/dist/validation.d.cts +4 -0
  74. package/dist/validation.d.ts +4 -0
  75. package/dist/validation.js +4 -0
  76. package/dist/validation.js.map +1 -0
  77. package/package.json +133 -0
@@ -0,0 +1,123 @@
1
+ import { F as FieldValidator } from './types-Cw5CeZP-.js';
2
+ import 'react';
3
+
4
+ /**
5
+ * @page-speed/forms - Validation Rules
6
+ *
7
+ * Common validation rules for form fields.
8
+ * Tree-shakable - import only the rules you need.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * import { required, email, minLength } from '@page-speed/forms/validation/rules';
13
+ *
14
+ * const form = useForm({
15
+ * validationSchema: {
16
+ * email: [required(), email()],
17
+ * password: [required(), minLength(8)],
18
+ * }
19
+ * });
20
+ * ```
21
+ */
22
+
23
+ /**
24
+ * Error message template function
25
+ * Allows customization of error messages
26
+ */
27
+ type ErrorMessageFn = (params?: Record<string, any>) => string;
28
+ /**
29
+ * Validation rule options
30
+ */
31
+ interface ValidationRuleOptions {
32
+ /**
33
+ * Custom error message
34
+ */
35
+ message?: string | ErrorMessageFn;
36
+ }
37
+ /**
38
+ * Required field validator
39
+ * Ensures field has a truthy value
40
+ */
41
+ declare function required(options?: ValidationRuleOptions): FieldValidator;
42
+ /**
43
+ * Email validator
44
+ * Validates email format using RFC 5322 compatible regex
45
+ */
46
+ declare function email(options?: ValidationRuleOptions): FieldValidator;
47
+ /**
48
+ * URL validator
49
+ * Validates URL format
50
+ */
51
+ declare function url(options?: ValidationRuleOptions): FieldValidator;
52
+ /**
53
+ * Phone number validator
54
+ * Validates US phone numbers (flexible formats)
55
+ */
56
+ declare function phone(options?: ValidationRuleOptions): FieldValidator;
57
+ /**
58
+ * Minimum length validator
59
+ */
60
+ declare function minLength(min: number, options?: ValidationRuleOptions): FieldValidator;
61
+ /**
62
+ * Maximum length validator
63
+ */
64
+ declare function maxLength(max: number, options?: ValidationRuleOptions): FieldValidator;
65
+ /**
66
+ * Minimum value validator (for numbers)
67
+ */
68
+ declare function min(minValue: number, options?: ValidationRuleOptions): FieldValidator;
69
+ /**
70
+ * Maximum value validator (for numbers)
71
+ */
72
+ declare function max(maxValue: number, options?: ValidationRuleOptions): FieldValidator;
73
+ /**
74
+ * Pattern validator
75
+ * Validates against a regular expression
76
+ */
77
+ declare function pattern(regex: RegExp, options?: ValidationRuleOptions): FieldValidator;
78
+ /**
79
+ * Match validator
80
+ * Ensures field matches another field (e.g., password confirmation)
81
+ */
82
+ declare function matches(fieldName: string, options?: ValidationRuleOptions): FieldValidator;
83
+ /**
84
+ * One of validator
85
+ * Ensures value is one of the allowed values
86
+ */
87
+ declare function oneOf<T = any>(allowedValues: T[], options?: ValidationRuleOptions): FieldValidator<T>;
88
+ /**
89
+ * Credit card validator
90
+ * Validates credit card numbers using Luhn algorithm
91
+ */
92
+ declare function creditCard(options?: ValidationRuleOptions): FieldValidator;
93
+ /**
94
+ * Postal code validator (US ZIP codes)
95
+ */
96
+ declare function postalCode(options?: ValidationRuleOptions): FieldValidator;
97
+ /**
98
+ * Alpha validator
99
+ * Ensures value contains only alphabetic characters
100
+ */
101
+ declare function alpha(options?: ValidationRuleOptions): FieldValidator;
102
+ /**
103
+ * Alphanumeric validator
104
+ * Ensures value contains only letters and numbers
105
+ */
106
+ declare function alphanumeric(options?: ValidationRuleOptions): FieldValidator;
107
+ /**
108
+ * Numeric validator
109
+ * Ensures value is a valid number
110
+ */
111
+ declare function numeric(options?: ValidationRuleOptions): FieldValidator;
112
+ /**
113
+ * Integer validator
114
+ * Ensures value is a valid integer
115
+ */
116
+ declare function integer(options?: ValidationRuleOptions): FieldValidator;
117
+ /**
118
+ * Compose multiple validators
119
+ * Runs validators in sequence and returns first error
120
+ */
121
+ declare function compose(...validators: FieldValidator[]): FieldValidator;
122
+
123
+ export { type ErrorMessageFn, type ValidationRuleOptions, alpha, alphanumeric, compose, creditCard, email, integer, matches, max, maxLength, min, minLength, numeric, oneOf, pattern, phone, postalCode, required, url };
@@ -0,0 +1,3 @@
1
+ export { alpha, alphanumeric, compose, creditCard, email, integer, matches, max, maxLength, min, minLength, numeric, oneOf, pattern, phone, postalCode, required, url } from './chunk-YTTOWHBZ.js';
2
+ //# sourceMappingURL=validation-rules.js.map
3
+ //# sourceMappingURL=validation-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"validation-rules.js"}
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ var chunkP37YLBFA_cjs = require('./chunk-P37YLBFA.cjs');
4
+
5
+
6
+
7
+ Object.defineProperty(exports, "asyncValidator", {
8
+ enumerable: true,
9
+ get: function () { return chunkP37YLBFA_cjs.asyncValidator; }
10
+ });
11
+ Object.defineProperty(exports, "crossFieldValidator", {
12
+ enumerable: true,
13
+ get: function () { return chunkP37YLBFA_cjs.crossFieldValidator; }
14
+ });
15
+ Object.defineProperty(exports, "debounce", {
16
+ enumerable: true,
17
+ get: function () { return chunkP37YLBFA_cjs.debounce; }
18
+ });
19
+ Object.defineProperty(exports, "defaultMessages", {
20
+ enumerable: true,
21
+ get: function () { return chunkP37YLBFA_cjs.defaultMessages; }
22
+ });
23
+ Object.defineProperty(exports, "getErrorMessage", {
24
+ enumerable: true,
25
+ get: function () { return chunkP37YLBFA_cjs.getErrorMessage; }
26
+ });
27
+ Object.defineProperty(exports, "messageRegistry", {
28
+ enumerable: true,
29
+ get: function () { return chunkP37YLBFA_cjs.messageRegistry; }
30
+ });
31
+ Object.defineProperty(exports, "resetErrorMessages", {
32
+ enumerable: true,
33
+ get: function () { return chunkP37YLBFA_cjs.resetErrorMessages; }
34
+ });
35
+ Object.defineProperty(exports, "setErrorMessages", {
36
+ enumerable: true,
37
+ get: function () { return chunkP37YLBFA_cjs.setErrorMessages; }
38
+ });
39
+ Object.defineProperty(exports, "when", {
40
+ enumerable: true,
41
+ get: function () { return chunkP37YLBFA_cjs.when; }
42
+ });
43
+ Object.defineProperty(exports, "withRaceConditionPrevention", {
44
+ enumerable: true,
45
+ get: function () { return chunkP37YLBFA_cjs.withRaceConditionPrevention; }
46
+ });
47
+ //# sourceMappingURL=validation-utils.cjs.map
48
+ //# sourceMappingURL=validation-utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"validation-utils.cjs"}
@@ -0,0 +1,166 @@
1
+ import { F as FieldValidator, b as FormValues } from './types-Cw5CeZP-.cjs';
2
+ import 'react';
3
+
4
+ /**
5
+ * @page-speed/forms - Validation Utilities
6
+ *
7
+ * Utilities for advanced validation scenarios
8
+ */
9
+
10
+ /**
11
+ * Debounce options for async validators
12
+ */
13
+ interface DebounceOptions {
14
+ /**
15
+ * Debounce delay in milliseconds
16
+ * @default 300
17
+ */
18
+ delay?: number;
19
+ /**
20
+ * Leading edge - call immediately on first invocation
21
+ * @default false
22
+ */
23
+ leading?: boolean;
24
+ /**
25
+ * Trailing edge - call after delay
26
+ * @default true
27
+ */
28
+ trailing?: boolean;
29
+ }
30
+ /**
31
+ * Debounce an async validator
32
+ * Prevents rapid validation calls (e.g., for username availability checks)
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * const checkUsername = debounce(
37
+ * async (value) => {
38
+ * const available = await api.checkUsername(value);
39
+ * return available ? undefined : 'Username is taken';
40
+ * },
41
+ * { delay: 500 }
42
+ * );
43
+ * ```
44
+ */
45
+ declare function debounce<T = any>(validator: FieldValidator<T>, options?: DebounceOptions): FieldValidator<T>;
46
+ /**
47
+ * Error message template function
48
+ */
49
+ type MessageTemplate = (params?: any) => string;
50
+ /**
51
+ * Error message templates for internationalization
52
+ */
53
+ interface ErrorMessages {
54
+ [key: string]: string | MessageTemplate;
55
+ }
56
+ /**
57
+ * Default error messages (English)
58
+ */
59
+ declare const defaultMessages: ErrorMessages;
60
+ /**
61
+ * Error message registry for i18n support
62
+ */
63
+ declare class MessageRegistry {
64
+ private messages;
65
+ /**
66
+ * Set custom messages (for i18n or customization)
67
+ */
68
+ setMessages(messages: ErrorMessages): void;
69
+ /**
70
+ * Get message by key
71
+ */
72
+ getMessage(key: string, params?: Record<string, any>): string;
73
+ /**
74
+ * Reset to default messages
75
+ */
76
+ reset(): void;
77
+ }
78
+ /**
79
+ * Global message registry instance
80
+ */
81
+ declare const messageRegistry: MessageRegistry;
82
+ /**
83
+ * Set custom error messages globally
84
+ * Useful for internationalization
85
+ *
86
+ * @example
87
+ * ```tsx
88
+ * setErrorMessages({
89
+ * required: 'Este campo es obligatorio',
90
+ * email: 'Por favor ingrese un email válido',
91
+ * });
92
+ * ```
93
+ */
94
+ declare function setErrorMessages(messages: ErrorMessages): void;
95
+ /**
96
+ * Get error message by key
97
+ */
98
+ declare function getErrorMessage(key: string, params?: Record<string, any>): string;
99
+ /**
100
+ * Reset error messages to defaults
101
+ */
102
+ declare function resetErrorMessages(): void;
103
+ /**
104
+ * Cross-field validator helper
105
+ * Creates a validator that depends on multiple fields
106
+ *
107
+ * @example
108
+ * ```tsx
109
+ * const passwordMatch = crossFieldValidator(
110
+ * ['password', 'confirmPassword'],
111
+ * (values) => {
112
+ * if (values.password !== values.confirmPassword) {
113
+ * return 'Passwords must match';
114
+ * }
115
+ * return undefined;
116
+ * }
117
+ * );
118
+ * ```
119
+ */
120
+ declare function crossFieldValidator<T extends FormValues = FormValues>(fields: (keyof T)[], validate: (values: Pick<T, keyof T>) => string | undefined | Promise<string | undefined>): FieldValidator;
121
+ /**
122
+ * Conditional validator
123
+ * Only validates when condition is met
124
+ *
125
+ * @example
126
+ * ```tsx
127
+ * const conditionalRequired = when(
128
+ * (values) => values.country === 'US',
129
+ * required()
130
+ * );
131
+ * ```
132
+ */
133
+ declare function when<T = any>(condition: (allValues: FormValues) => boolean, validator: FieldValidator<T>): FieldValidator<T>;
134
+ /**
135
+ * Async validator with race condition prevention
136
+ * Ensures only the latest validation call resolves
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * const checkUsername = withRaceConditionPrevention(
141
+ * async (value) => {
142
+ * const available = await api.checkUsername(value);
143
+ * return available ? undefined : 'Username is taken';
144
+ * }
145
+ * );
146
+ * ```
147
+ */
148
+ declare function withRaceConditionPrevention<T = any>(validator: FieldValidator<T>): FieldValidator<T>;
149
+ /**
150
+ * Combine debounce with race condition prevention
151
+ * Best practice for async validators
152
+ *
153
+ * @example
154
+ * ```tsx
155
+ * const checkUsername = asyncValidator(
156
+ * async (value) => {
157
+ * const available = await api.checkUsername(value);
158
+ * return available ? undefined : 'Username is taken';
159
+ * },
160
+ * { delay: 500 }
161
+ * );
162
+ * ```
163
+ */
164
+ declare function asyncValidator<T = any>(validator: FieldValidator<T>, options?: DebounceOptions): FieldValidator<T>;
165
+
166
+ export { type DebounceOptions, type ErrorMessages, type MessageTemplate, asyncValidator, crossFieldValidator, debounce, defaultMessages, getErrorMessage, messageRegistry, resetErrorMessages, setErrorMessages, when, withRaceConditionPrevention };
@@ -0,0 +1,166 @@
1
+ import { F as FieldValidator, b as FormValues } from './types-Cw5CeZP-.js';
2
+ import 'react';
3
+
4
+ /**
5
+ * @page-speed/forms - Validation Utilities
6
+ *
7
+ * Utilities for advanced validation scenarios
8
+ */
9
+
10
+ /**
11
+ * Debounce options for async validators
12
+ */
13
+ interface DebounceOptions {
14
+ /**
15
+ * Debounce delay in milliseconds
16
+ * @default 300
17
+ */
18
+ delay?: number;
19
+ /**
20
+ * Leading edge - call immediately on first invocation
21
+ * @default false
22
+ */
23
+ leading?: boolean;
24
+ /**
25
+ * Trailing edge - call after delay
26
+ * @default true
27
+ */
28
+ trailing?: boolean;
29
+ }
30
+ /**
31
+ * Debounce an async validator
32
+ * Prevents rapid validation calls (e.g., for username availability checks)
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * const checkUsername = debounce(
37
+ * async (value) => {
38
+ * const available = await api.checkUsername(value);
39
+ * return available ? undefined : 'Username is taken';
40
+ * },
41
+ * { delay: 500 }
42
+ * );
43
+ * ```
44
+ */
45
+ declare function debounce<T = any>(validator: FieldValidator<T>, options?: DebounceOptions): FieldValidator<T>;
46
+ /**
47
+ * Error message template function
48
+ */
49
+ type MessageTemplate = (params?: any) => string;
50
+ /**
51
+ * Error message templates for internationalization
52
+ */
53
+ interface ErrorMessages {
54
+ [key: string]: string | MessageTemplate;
55
+ }
56
+ /**
57
+ * Default error messages (English)
58
+ */
59
+ declare const defaultMessages: ErrorMessages;
60
+ /**
61
+ * Error message registry for i18n support
62
+ */
63
+ declare class MessageRegistry {
64
+ private messages;
65
+ /**
66
+ * Set custom messages (for i18n or customization)
67
+ */
68
+ setMessages(messages: ErrorMessages): void;
69
+ /**
70
+ * Get message by key
71
+ */
72
+ getMessage(key: string, params?: Record<string, any>): string;
73
+ /**
74
+ * Reset to default messages
75
+ */
76
+ reset(): void;
77
+ }
78
+ /**
79
+ * Global message registry instance
80
+ */
81
+ declare const messageRegistry: MessageRegistry;
82
+ /**
83
+ * Set custom error messages globally
84
+ * Useful for internationalization
85
+ *
86
+ * @example
87
+ * ```tsx
88
+ * setErrorMessages({
89
+ * required: 'Este campo es obligatorio',
90
+ * email: 'Por favor ingrese un email válido',
91
+ * });
92
+ * ```
93
+ */
94
+ declare function setErrorMessages(messages: ErrorMessages): void;
95
+ /**
96
+ * Get error message by key
97
+ */
98
+ declare function getErrorMessage(key: string, params?: Record<string, any>): string;
99
+ /**
100
+ * Reset error messages to defaults
101
+ */
102
+ declare function resetErrorMessages(): void;
103
+ /**
104
+ * Cross-field validator helper
105
+ * Creates a validator that depends on multiple fields
106
+ *
107
+ * @example
108
+ * ```tsx
109
+ * const passwordMatch = crossFieldValidator(
110
+ * ['password', 'confirmPassword'],
111
+ * (values) => {
112
+ * if (values.password !== values.confirmPassword) {
113
+ * return 'Passwords must match';
114
+ * }
115
+ * return undefined;
116
+ * }
117
+ * );
118
+ * ```
119
+ */
120
+ declare function crossFieldValidator<T extends FormValues = FormValues>(fields: (keyof T)[], validate: (values: Pick<T, keyof T>) => string | undefined | Promise<string | undefined>): FieldValidator;
121
+ /**
122
+ * Conditional validator
123
+ * Only validates when condition is met
124
+ *
125
+ * @example
126
+ * ```tsx
127
+ * const conditionalRequired = when(
128
+ * (values) => values.country === 'US',
129
+ * required()
130
+ * );
131
+ * ```
132
+ */
133
+ declare function when<T = any>(condition: (allValues: FormValues) => boolean, validator: FieldValidator<T>): FieldValidator<T>;
134
+ /**
135
+ * Async validator with race condition prevention
136
+ * Ensures only the latest validation call resolves
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * const checkUsername = withRaceConditionPrevention(
141
+ * async (value) => {
142
+ * const available = await api.checkUsername(value);
143
+ * return available ? undefined : 'Username is taken';
144
+ * }
145
+ * );
146
+ * ```
147
+ */
148
+ declare function withRaceConditionPrevention<T = any>(validator: FieldValidator<T>): FieldValidator<T>;
149
+ /**
150
+ * Combine debounce with race condition prevention
151
+ * Best practice for async validators
152
+ *
153
+ * @example
154
+ * ```tsx
155
+ * const checkUsername = asyncValidator(
156
+ * async (value) => {
157
+ * const available = await api.checkUsername(value);
158
+ * return available ? undefined : 'Username is taken';
159
+ * },
160
+ * { delay: 500 }
161
+ * );
162
+ * ```
163
+ */
164
+ declare function asyncValidator<T = any>(validator: FieldValidator<T>, options?: DebounceOptions): FieldValidator<T>;
165
+
166
+ export { type DebounceOptions, type ErrorMessages, type MessageTemplate, asyncValidator, crossFieldValidator, debounce, defaultMessages, getErrorMessage, messageRegistry, resetErrorMessages, setErrorMessages, when, withRaceConditionPrevention };
@@ -0,0 +1,3 @@
1
+ export { asyncValidator, crossFieldValidator, debounce, defaultMessages, getErrorMessage, messageRegistry, resetErrorMessages, setErrorMessages, when, withRaceConditionPrevention } from './chunk-WHQMBQNI.js';
2
+ //# sourceMappingURL=validation-utils.js.map
3
+ //# sourceMappingURL=validation-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"validation-utils.js"}
@@ -0,0 +1,94 @@
1
+ 'use strict';
2
+
3
+ // src/validation/valibot.ts
4
+ function createValibotSchema(schema) {
5
+ const hasSafeParse = "safeParse" in schema && typeof schema.safeParse === "function";
6
+ const validationSchema = {};
7
+ const createFieldValidator2 = (fieldName) => {
8
+ return async (_value, allValues) => {
9
+ try {
10
+ const result = hasSafeParse ? schema.safeParse(allValues) : (() => {
11
+ try {
12
+ const parsed = schema._parse(allValues);
13
+ return { success: !parsed.issues || parsed.issues.length === 0, output: parsed.output, issues: parsed.issues };
14
+ } catch (error) {
15
+ return { success: false, issues: error.issues || [{ path: [], message: error.message }] };
16
+ }
17
+ })();
18
+ if (!result.success && result.issues) {
19
+ for (const issue of result.issues) {
20
+ const path = issue.path || [];
21
+ if (path.length > 0) {
22
+ const key = path[0].key || path[0];
23
+ if (key === fieldName) {
24
+ return issue.message || "Validation error";
25
+ }
26
+ } else if (path.length === 0 && Object.keys(allValues).length === 1) {
27
+ return issue.message || "Validation error";
28
+ }
29
+ }
30
+ }
31
+ return void 0;
32
+ } catch (error) {
33
+ if (error.issues && Array.isArray(error.issues)) {
34
+ for (const issue of error.issues) {
35
+ const path = issue.path || [];
36
+ if (path.length > 0) {
37
+ const key = path[0].key || path[0];
38
+ if (key === fieldName) {
39
+ return issue.message || "Validation error";
40
+ }
41
+ }
42
+ }
43
+ }
44
+ return error.message || "Validation error";
45
+ }
46
+ };
47
+ };
48
+ return new Proxy(validationSchema, {
49
+ get(_target, prop) {
50
+ if (typeof prop === "string") {
51
+ return createFieldValidator2(prop);
52
+ }
53
+ return void 0;
54
+ },
55
+ ownKeys() {
56
+ return [];
57
+ },
58
+ getOwnPropertyDescriptor() {
59
+ return {
60
+ enumerable: true,
61
+ configurable: true
62
+ };
63
+ }
64
+ });
65
+ }
66
+ function createFieldValidator(schema) {
67
+ const hasSafeParse = "safeParse" in schema && typeof schema.safeParse === "function";
68
+ return async (value) => {
69
+ try {
70
+ const result = hasSafeParse ? schema.safeParse(value) : (() => {
71
+ try {
72
+ const parsed = schema._parse(value);
73
+ return { success: !parsed.issues || parsed.issues.length === 0, output: parsed.output, issues: parsed.issues };
74
+ } catch (error) {
75
+ return { success: false, issues: error.issues || [{ message: error.message }] };
76
+ }
77
+ })();
78
+ if (!result.success && result.issues && result.issues.length > 0) {
79
+ return result.issues[0].message || "Validation error";
80
+ }
81
+ return void 0;
82
+ } catch (error) {
83
+ if (error.issues && error.issues.length > 0) {
84
+ return error.issues[0].message || "Validation error";
85
+ }
86
+ return error.message || "Validation error";
87
+ }
88
+ };
89
+ }
90
+
91
+ exports.createFieldValidator = createFieldValidator;
92
+ exports.createValibotSchema = createValibotSchema;
93
+ //# sourceMappingURL=validation-valibot.cjs.map
94
+ //# sourceMappingURL=validation-valibot.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validation/valibot.ts"],"names":["createFieldValidator"],"mappings":"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","file":"validation-valibot.cjs","sourcesContent":["/**\n * @page-speed/forms - Valibot Validation Adapter\n *\n * Integrates Valibot schema validation with @page-speed/forms.\n * Provides tree-shakable validation with excellent performance.\n *\n * Valibot Benefits:\n * - 95% smaller than Zod (0.6KB vs 13.4KB base)\n * - 2-3x faster validation performance\n * - Modular, tree-shakable API\n * - Full TypeScript inference\n *\n * @see https://opensite.ai/developers/page-speed/forms/validation\n * @see https://valibot.dev\n */\n\nimport type { FormValues, ValidationSchema, FieldValidator } from \"../core/types\";\n\n/**\n * Valibot schema type (generic to avoid direct import)\n * Users will pass their own Valibot schemas\n */\nexport type ValibotSchema<T = any> = {\n _types?: {\n input: T;\n output: T;\n };\n _parse(input: unknown): { output: T; issues?: any[] };\n};\n\n/**\n * Create a validation schema from a Valibot schema\n *\n * Converts a Valibot object schema into @page-speed/forms ValidationSchema format.\n * Supports both synchronous and asynchronous validation.\n *\n * @example\n * ```tsx\n * import * as v from 'valibot';\n * import { useForm } from '@page-speed/forms/core';\n * import { createValibotSchema } from '@page-speed/forms/validation/valibot';\n *\n * const LoginSchema = v.object({\n * email: v.pipe(v.string(), v.email('Invalid email')),\n * password: v.pipe(v.string(), v.minLength(8, 'Too short')),\n * });\n *\n * const form = useForm({\n * initialValues: { email: '', password: '' },\n * validationSchema: createValibotSchema(LoginSchema),\n * onSubmit: async (values) => {\n * await login(values);\n * },\n * });\n * ```\n */\nexport function createValibotSchema<T extends FormValues>(\n schema: ValibotSchema<T>\n): ValidationSchema<T> {\n // Check if safeParse exists (Valibot v0.31+)\n const hasSafeParse = \"safeParse\" in schema && typeof schema.safeParse === \"function\";\n\n const validationSchema: ValidationSchema<T> = {} as ValidationSchema<T>;\n\n // Create a validator function that will be called per-field\n const createFieldValidator = <K extends keyof T>(\n fieldName: K\n ): FieldValidator<T[K]> => {\n return async (_value: T[K], allValues: FormValues): Promise<string | undefined> => {\n try {\n // Validate the entire object to get field-specific errors\n const result = hasSafeParse\n ? (schema as any).safeParse(allValues)\n : (() => {\n try {\n const parsed = schema._parse(allValues);\n return { success: !parsed.issues || parsed.issues.length === 0, output: parsed.output, issues: parsed.issues };\n } catch (error: any) {\n return { success: false, issues: error.issues || [{ path: [], message: error.message }] };\n }\n })();\n\n if (!result.success && result.issues) {\n // Find error for this specific field\n for (const issue of result.issues) {\n const path = issue.path || [];\n\n // Check if this issue is for the current field\n if (path.length > 0) {\n const key = path[0].key || path[0];\n if (key === fieldName) {\n return issue.message || \"Validation error\";\n }\n } else if (path.length === 0 && Object.keys(allValues).length === 1) {\n // Single field validation\n return issue.message || \"Validation error\";\n }\n }\n }\n\n return undefined;\n } catch (error: any) {\n // Handle parsing errors\n if (error.issues && Array.isArray(error.issues)) {\n for (const issue of error.issues) {\n const path = issue.path || [];\n if (path.length > 0) {\n const key = path[0].key || path[0];\n if (key === fieldName) {\n return issue.message || \"Validation error\";\n }\n }\n }\n }\n\n return error.message || \"Validation error\";\n }\n };\n };\n\n // We can't introspect Valibot schema keys directly in a type-safe way,\n // so we'll return a proxy that creates validators on-demand\n return new Proxy(validationSchema, {\n get(_target, prop: string | symbol) {\n if (typeof prop === \"string\") {\n return createFieldValidator(prop as keyof T);\n }\n return undefined;\n },\n ownKeys() {\n // Return empty array - validators are created on-demand\n return [];\n },\n getOwnPropertyDescriptor() {\n return {\n enumerable: true,\n configurable: true,\n };\n },\n }) as ValidationSchema<T>;\n}\n\n/**\n * Create a field validator from a Valibot schema\n *\n * For single-field validation without a full form schema.\n *\n * @example\n * ```tsx\n * import * as v from 'valibot';\n * import { Field } from '@page-speed/forms/core';\n * import { createFieldValidator } from '@page-speed/forms/validation/valibot';\n *\n * const emailSchema = v.pipe(v.string(), v.email('Invalid email'));\n *\n * <Field\n * name=\"email\"\n * validate={createFieldValidator(emailSchema)}\n * >\n * {({ field, meta }) => <input {...field} />}\n * </Field>\n * ```\n */\nexport function createFieldValidator<T = any>(\n schema: ValibotSchema<T>\n): FieldValidator<T> {\n const hasSafeParse = \"safeParse\" in schema && typeof schema.safeParse === \"function\";\n\n return async (value: T): Promise<string | undefined> => {\n try {\n const result = hasSafeParse\n ? (schema as any).safeParse(value)\n : (() => {\n try {\n const parsed = schema._parse(value);\n return { success: !parsed.issues || parsed.issues.length === 0, output: parsed.output, issues: parsed.issues };\n } catch (error: any) {\n return { success: false, issues: error.issues || [{ message: error.message }] };\n }\n })();\n\n if (!result.success && result.issues && result.issues.length > 0) {\n return result.issues[0].message || \"Validation error\";\n }\n\n return undefined;\n } catch (error: any) {\n if (error.issues && error.issues.length > 0) {\n return error.issues[0].message || \"Validation error\";\n }\n return error.message || \"Validation error\";\n }\n };\n}\n\n/**\n * Helper to infer form values type from Valibot schema\n */\nexport type InferValibotInput<T extends ValibotSchema> = T extends ValibotSchema<\n infer U\n>\n ? U\n : never;\n\n/**\n * Helper to infer form values type from Valibot schema output\n */\nexport type InferValibotOutput<T extends ValibotSchema> = T extends ValibotSchema<\n infer U\n>\n ? U\n : never;\n"]}