@saastro/forms 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +347 -0
- package/cli.js +732 -0
- package/dist/DateRenderers-3JUQNLKJ.js +139 -0
- package/dist/DateRenderers-3JUQNLKJ.js.map +1 -0
- package/dist/chunk-GHDCNAWC.js +247 -0
- package/dist/chunk-GHDCNAWC.js.map +1 -0
- package/dist/chunk-YXKDN3PU.js +687 -0
- package/dist/chunk-YXKDN3PU.js.map +1 -0
- package/dist/index.d.ts +3754 -0
- package/dist/index.js +7115 -0
- package/dist/index.js.map +1 -0
- package/dist/submitOrchestrator-RF76MOWG.js +13 -0
- package/dist/submitOrchestrator-RF76MOWG.js.map +1 -0
- package/package.json +85 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3754 @@
|
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import React__default, { ReactNode } from 'react';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
5
|
+
import { VariantProps } from 'class-variance-authority';
|
|
6
|
+
import * as react_hook_form from 'react-hook-form';
|
|
7
|
+
import { UseFormReturn, Control } from 'react-hook-form';
|
|
8
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
declare const inputVariantsConfig: {
|
|
11
|
+
readonly variants: {
|
|
12
|
+
readonly size: {
|
|
13
|
+
readonly xs: "h-6 px-2 text-xs";
|
|
14
|
+
readonly sm: "h-8 px-3 text-sm";
|
|
15
|
+
readonly md: "h-10 px-3 py-2 text-base";
|
|
16
|
+
readonly lg: "h-12 px-4 text-lg";
|
|
17
|
+
readonly xl: "h-14 px-4 text-xl";
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
readonly defaultVariants: {
|
|
21
|
+
readonly size: "md";
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
declare const textareaVariantsConfig: {
|
|
25
|
+
readonly variants: {
|
|
26
|
+
readonly size: {
|
|
27
|
+
readonly xs: "px-2 text-xs";
|
|
28
|
+
readonly sm: "px-3 text-sm";
|
|
29
|
+
readonly md: "px-3 py-2 text-base";
|
|
30
|
+
readonly lg: "px-4 text-lg";
|
|
31
|
+
readonly xl: "px-4 text-xl";
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
readonly defaultVariants: {
|
|
35
|
+
readonly size: "md";
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
declare const inputVariants: (props?: ({
|
|
39
|
+
readonly size?: "sm" | "md" | "lg" | "xl" | "xs" | null | undefined;
|
|
40
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
41
|
+
declare const textareaVariants: (props?: ({
|
|
42
|
+
readonly size?: "sm" | "md" | "lg" | "xl" | "xs" | null | undefined;
|
|
43
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
44
|
+
declare const iconVariantsConfig: {
|
|
45
|
+
readonly variants: {
|
|
46
|
+
readonly size: {
|
|
47
|
+
readonly xs: "absolute h-3 w-3 top-1.5 right-1.5";
|
|
48
|
+
readonly sm: "absolute h-4 w-4 top-2 right-2";
|
|
49
|
+
readonly md: "absolute h-5 w-5 top-2.5 right-2.5";
|
|
50
|
+
readonly lg: "absolute h-6 w-6 top-3 right-3";
|
|
51
|
+
readonly xl: "absolute h-7 w-7 top-3.5 right-3.5";
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
readonly defaultVariants: {
|
|
55
|
+
readonly size: "md";
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
declare const iconVariants: (props?: ({
|
|
59
|
+
readonly size?: "sm" | "md" | "lg" | "xl" | "xs" | null | undefined;
|
|
60
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
61
|
+
type InputSize = VariantProps<typeof inputVariants>['size'];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Logic Types
|
|
65
|
+
*
|
|
66
|
+
* Generic structures for declarative conditions and logic groups.
|
|
67
|
+
* Used for step navigation and field behavior (visibility, disabled, etc).
|
|
68
|
+
*/
|
|
69
|
+
type ConditionOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual' | 'isTrue' | 'isFalse' | 'isEmpty' | 'isNotEmpty';
|
|
70
|
+
/**
|
|
71
|
+
* A single condition evaluation
|
|
72
|
+
*/
|
|
73
|
+
type Condition = {
|
|
74
|
+
/** The field name to watch */
|
|
75
|
+
field: string;
|
|
76
|
+
/** The comparison operator */
|
|
77
|
+
operator: ConditionOperator;
|
|
78
|
+
/** The value to compare against (if applicable) */
|
|
79
|
+
value?: string | number | boolean | null;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* A group of conditions combined with a logic operator
|
|
83
|
+
*/
|
|
84
|
+
type ConditionGroup = {
|
|
85
|
+
/** Array of conditions to evaluate */
|
|
86
|
+
conditions: Condition[];
|
|
87
|
+
/** How to combine the results */
|
|
88
|
+
operator: 'AND' | 'OR';
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Submit Actions Types
|
|
93
|
+
*
|
|
94
|
+
* Sistema modular de acciones de submit que permite configurar
|
|
95
|
+
* múltiples endpoints, webhooks, emails y funciones custom.
|
|
96
|
+
* Cada acción puede tener su propio trigger (cuándo se ejecuta).
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
type SubmitActionType = 'http' | 'webhook' | 'email' | 'custom';
|
|
100
|
+
interface HttpEndpointConfig {
|
|
101
|
+
url: string;
|
|
102
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
103
|
+
headers?: Record<string, string>;
|
|
104
|
+
}
|
|
105
|
+
interface HttpBodyConfig {
|
|
106
|
+
/** Formato del body */
|
|
107
|
+
format: 'json' | 'form-data' | 'url-encoded';
|
|
108
|
+
/** Template con placeholders {{fieldName}} */
|
|
109
|
+
template?: string;
|
|
110
|
+
/** Solo incluir estos campos (si no se especifica, incluye todos) */
|
|
111
|
+
includeFields?: string[];
|
|
112
|
+
/** Excluir estos campos del payload */
|
|
113
|
+
excludeFields?: string[];
|
|
114
|
+
}
|
|
115
|
+
interface HttpAuthConfig {
|
|
116
|
+
type: 'none' | 'bearer' | 'basic' | 'api-key';
|
|
117
|
+
/** Token para bearer auth */
|
|
118
|
+
token?: string;
|
|
119
|
+
/** Usuario para basic auth */
|
|
120
|
+
username?: string;
|
|
121
|
+
/** Password para basic auth */
|
|
122
|
+
password?: string;
|
|
123
|
+
/** Nombre del header para api-key (default: X-API-Key) */
|
|
124
|
+
headerName?: string;
|
|
125
|
+
}
|
|
126
|
+
interface HttpRetryConfig {
|
|
127
|
+
enabled: boolean;
|
|
128
|
+
maxAttempts: number;
|
|
129
|
+
delayMs: number;
|
|
130
|
+
}
|
|
131
|
+
interface HttpSubmitAction {
|
|
132
|
+
type: 'http';
|
|
133
|
+
name: string;
|
|
134
|
+
endpoint: HttpEndpointConfig;
|
|
135
|
+
body?: HttpBodyConfig;
|
|
136
|
+
auth?: HttpAuthConfig;
|
|
137
|
+
retry?: HttpRetryConfig;
|
|
138
|
+
/** Timeout en ms (default: 30000) */
|
|
139
|
+
timeout?: number;
|
|
140
|
+
}
|
|
141
|
+
interface WebhookSubmitAction {
|
|
142
|
+
type: 'webhook';
|
|
143
|
+
name: string;
|
|
144
|
+
url: string;
|
|
145
|
+
/** Secret para firma HMAC (opcional) */
|
|
146
|
+
secret?: string;
|
|
147
|
+
/** Headers adicionales */
|
|
148
|
+
headers?: Record<string, string>;
|
|
149
|
+
/** Template del payload con placeholders {{fieldName}} */
|
|
150
|
+
payloadTemplate?: string;
|
|
151
|
+
/** Solo incluir estos campos */
|
|
152
|
+
includeFields?: string[];
|
|
153
|
+
/** Excluir estos campos */
|
|
154
|
+
excludeFields?: string[];
|
|
155
|
+
}
|
|
156
|
+
type EmailProvider = 'smtp' | 'sendgrid' | 'resend' | 'mailgun';
|
|
157
|
+
interface EmailSubmitAction {
|
|
158
|
+
type: 'email';
|
|
159
|
+
name: string;
|
|
160
|
+
/** Proveedor de email */
|
|
161
|
+
provider: EmailProvider;
|
|
162
|
+
/** Endpoint del servicio (para SMTP o API custom) */
|
|
163
|
+
endpoint?: string;
|
|
164
|
+
/** API Key del proveedor */
|
|
165
|
+
apiKey?: string;
|
|
166
|
+
/** Destinatarios */
|
|
167
|
+
to: string | string[];
|
|
168
|
+
cc?: string[];
|
|
169
|
+
bcc?: string[];
|
|
170
|
+
/** From address */
|
|
171
|
+
from?: string;
|
|
172
|
+
/** Asunto del email (soporta placeholders {{fieldName}}) */
|
|
173
|
+
subject: string;
|
|
174
|
+
/** Tipo de template */
|
|
175
|
+
template: 'default' | 'custom';
|
|
176
|
+
/** HTML del template custom (soporta placeholders {{fieldName}}) */
|
|
177
|
+
customTemplate?: string;
|
|
178
|
+
/** Reply-to address */
|
|
179
|
+
replyTo?: string;
|
|
180
|
+
}
|
|
181
|
+
interface CustomSubmitAction {
|
|
182
|
+
type: 'custom';
|
|
183
|
+
name: string;
|
|
184
|
+
/** Función que se ejecuta con los valores del formulario */
|
|
185
|
+
handler: (values: Record<string, unknown>) => Promise<unknown>;
|
|
186
|
+
}
|
|
187
|
+
type SubmitAction = HttpSubmitAction | WebhookSubmitAction | EmailSubmitAction | CustomSubmitAction;
|
|
188
|
+
type SubmitTriggerType = 'onSubmit' | 'onStepEnter' | 'onStepExit' | 'onFieldChange' | 'onFieldBlur' | 'onDelay' | 'manual';
|
|
189
|
+
interface SubmitTrigger {
|
|
190
|
+
type: SubmitTriggerType;
|
|
191
|
+
/** Para onStepEnter/onStepExit: ID del step */
|
|
192
|
+
stepId?: string;
|
|
193
|
+
/** Para onFieldChange/onFieldBlur: nombre del campo */
|
|
194
|
+
fieldName?: string;
|
|
195
|
+
/** Para onDelay: milisegundos de inactividad */
|
|
196
|
+
delayMs?: number;
|
|
197
|
+
/** Debounce en ms para evitar ejecuciones múltiples (default: 0) */
|
|
198
|
+
debounceMs?: number;
|
|
199
|
+
}
|
|
200
|
+
interface SubmitActionCondition {
|
|
201
|
+
/** Campo a evaluar */
|
|
202
|
+
field: string;
|
|
203
|
+
/** Operador de comparación */
|
|
204
|
+
operator: ConditionOperator;
|
|
205
|
+
/** Valor a comparar */
|
|
206
|
+
value: unknown;
|
|
207
|
+
}
|
|
208
|
+
/** Built-in value transforms applied per-field before sending. */
|
|
209
|
+
type BuiltinTransform = 'toString' | 'toNumber' | 'toBoolean' | 'booleanString' | 'dateISO' | 'dateYMD' | 'dateDMY' | 'dateTimestamp' | 'trim' | 'lowercase' | 'uppercase' | 'emptyToNull';
|
|
210
|
+
/** Custom transform function for field values. */
|
|
211
|
+
type FieldTransformFn = (value: unknown) => unknown;
|
|
212
|
+
/** Advanced field mapping entry with rename + transform. */
|
|
213
|
+
interface FieldMapEntry {
|
|
214
|
+
/** Target field name in the API payload */
|
|
215
|
+
to: string;
|
|
216
|
+
/** Value transform — built-in name or custom function */
|
|
217
|
+
transform?: BuiltinTransform | FieldTransformFn;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* A resolver injects computed/dynamic values into the payload.
|
|
221
|
+
* Distinguished from static values by the `$resolver` key.
|
|
222
|
+
*/
|
|
223
|
+
type FieldResolver = {
|
|
224
|
+
$resolver: 'timestamp';
|
|
225
|
+
} | {
|
|
226
|
+
$resolver: 'hostname';
|
|
227
|
+
} | {
|
|
228
|
+
$resolver: 'urlParam';
|
|
229
|
+
param: string;
|
|
230
|
+
fallback?: string;
|
|
231
|
+
} | {
|
|
232
|
+
$resolver: 'ip';
|
|
233
|
+
endpoint?: string;
|
|
234
|
+
fallback?: string;
|
|
235
|
+
} | {
|
|
236
|
+
$resolver: 'pageUrl';
|
|
237
|
+
} | {
|
|
238
|
+
$resolver: 'referrer';
|
|
239
|
+
} | {
|
|
240
|
+
$resolver: 'userAgent';
|
|
241
|
+
} | {
|
|
242
|
+
$resolver: 'custom';
|
|
243
|
+
fn: () => unknown;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Serializable subset of FieldResolver (excludes 'custom' which requires a runtime function).
|
|
247
|
+
* Used by hidden fields in the form builder where config must be JSON-serializable.
|
|
248
|
+
*/
|
|
249
|
+
type SerializableFieldResolver = Exclude<FieldResolver, {
|
|
250
|
+
$resolver: 'custom';
|
|
251
|
+
}>;
|
|
252
|
+
/**
|
|
253
|
+
* Built-in resolver definitions with labels and descriptions for the builder UI.
|
|
254
|
+
*/
|
|
255
|
+
declare const BUILTIN_RESOLVERS: readonly [{
|
|
256
|
+
readonly id: "timestamp";
|
|
257
|
+
readonly label: "Timestamp";
|
|
258
|
+
readonly description: "Current date/time in ISO format";
|
|
259
|
+
}, {
|
|
260
|
+
readonly id: "hostname";
|
|
261
|
+
readonly label: "Hostname";
|
|
262
|
+
readonly description: "Current page hostname";
|
|
263
|
+
}, {
|
|
264
|
+
readonly id: "pageUrl";
|
|
265
|
+
readonly label: "Page URL";
|
|
266
|
+
readonly description: "Full page URL (window.location.href)";
|
|
267
|
+
}, {
|
|
268
|
+
readonly id: "referrer";
|
|
269
|
+
readonly label: "Referrer";
|
|
270
|
+
readonly description: "Referring page URL (document.referrer)";
|
|
271
|
+
}, {
|
|
272
|
+
readonly id: "userAgent";
|
|
273
|
+
readonly label: "User Agent";
|
|
274
|
+
readonly description: "Browser user agent string";
|
|
275
|
+
}, {
|
|
276
|
+
readonly id: "ip";
|
|
277
|
+
readonly label: "IP Address";
|
|
278
|
+
readonly description: "Visitor IP via external API";
|
|
279
|
+
}, {
|
|
280
|
+
readonly id: "urlParam";
|
|
281
|
+
readonly label: "URL Parameter";
|
|
282
|
+
readonly description: "Value from a URL query parameter";
|
|
283
|
+
}];
|
|
284
|
+
/**
|
|
285
|
+
* Advanced field mapping configuration.
|
|
286
|
+
*
|
|
287
|
+
* Supports renaming, value transforms, computed field injection,
|
|
288
|
+
* field exclusion, and passthrough control.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* fieldMapping: {
|
|
293
|
+
* fields: {
|
|
294
|
+
* nombre: "first_name", // simple rename
|
|
295
|
+
* fecha: { to: "birth_date", transform: "dateYMD" }, // rename + transform
|
|
296
|
+
* acepta: { to: "accepts", transform: "booleanString" },
|
|
297
|
+
* },
|
|
298
|
+
* inject: {
|
|
299
|
+
* campaign_id: "10653", // static value
|
|
300
|
+
* timestamp: { $resolver: "timestamp" }, // computed
|
|
301
|
+
* hostname: { $resolver: "hostname" },
|
|
302
|
+
* sub_aff_id: { $resolver: "urlParam", param: "sub_aff_id", fallback: "seo_organico" },
|
|
303
|
+
* },
|
|
304
|
+
* exclude: ["internal_field"],
|
|
305
|
+
* passthrough: true,
|
|
306
|
+
* }
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
interface FieldMapping {
|
|
310
|
+
/** Map/transform form fields → API fields */
|
|
311
|
+
fields?: Record<string, string | FieldMapEntry>;
|
|
312
|
+
/** Inject additional fields not from form inputs. Use `{ $resolver: ... }` for dynamic values. */
|
|
313
|
+
inject?: Record<string, unknown>;
|
|
314
|
+
/** Exclude these form fields from the payload */
|
|
315
|
+
exclude?: string[];
|
|
316
|
+
/** If false, only mapped fields are sent. Default: true (unmapped pass through) */
|
|
317
|
+
passthrough?: boolean;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Field mapping configuration — supports two formats:
|
|
321
|
+
* - Simple: `Record<string, string>` — rename fields only (backward compatible)
|
|
322
|
+
* - Advanced: `FieldMapping` — rename, transform, inject, exclude
|
|
323
|
+
*/
|
|
324
|
+
type FieldMappingConfig = Record<string, string> | FieldMapping;
|
|
325
|
+
interface SubmitActionNode {
|
|
326
|
+
/** ID único del nodo */
|
|
327
|
+
id: string;
|
|
328
|
+
/** Configuración de la acción */
|
|
329
|
+
action: SubmitAction;
|
|
330
|
+
/** Cuándo se ejecuta */
|
|
331
|
+
trigger: SubmitTrigger;
|
|
332
|
+
/** Condición opcional para ejecutar (si no se cumple, se salta) */
|
|
333
|
+
condition?: SubmitActionCondition;
|
|
334
|
+
/** Orden de ejecución (para modo secuencial) */
|
|
335
|
+
order?: number;
|
|
336
|
+
/** Si true, continúa con las siguientes acciones aunque esta falle */
|
|
337
|
+
continueOnError?: boolean;
|
|
338
|
+
/** Si true, la acción está deshabilitada */
|
|
339
|
+
disabled?: boolean;
|
|
340
|
+
/**
|
|
341
|
+
* Maps form field names to API-expected field names, with optional
|
|
342
|
+
* value transforms and computed field injection.
|
|
343
|
+
*
|
|
344
|
+
* Supports two formats:
|
|
345
|
+
* 1. Simple rename: `Record<string, string>`
|
|
346
|
+
* 2. Advanced: `FieldMapping` with transforms, inject, exclude
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* // Simple: rename only
|
|
351
|
+
* fieldMapping: {
|
|
352
|
+
* nombre: "first_name",
|
|
353
|
+
* email: "email_address",
|
|
354
|
+
* }
|
|
355
|
+
*
|
|
356
|
+
* // Advanced: rename + transform + inject
|
|
357
|
+
* fieldMapping: {
|
|
358
|
+
* fields: {
|
|
359
|
+
* nombre: "first_name",
|
|
360
|
+
* fecha_nacimiento: { to: "birth_date", transform: "dateYMD" },
|
|
361
|
+
* seguro_enfermedad: { to: "has_insurance", transform: "booleanString" },
|
|
362
|
+
* },
|
|
363
|
+
* inject: {
|
|
364
|
+
* campaign_id: "10653",
|
|
365
|
+
* ip: { $resolver: "custom", fn: () => getIpAddress() },
|
|
366
|
+
* timestamp: { $resolver: "timestamp" },
|
|
367
|
+
* },
|
|
368
|
+
* }
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
fieldMapping?: FieldMappingConfig;
|
|
372
|
+
}
|
|
373
|
+
interface SubmitExecutionConfig {
|
|
374
|
+
/** Modo de ejecución de múltiples acciones */
|
|
375
|
+
mode: 'sequential' | 'parallel';
|
|
376
|
+
/** Si true, detiene la ejecución en el primer error (solo para sequential) */
|
|
377
|
+
stopOnFirstError?: boolean;
|
|
378
|
+
/** Timeout global para todas las acciones (ms) */
|
|
379
|
+
globalTimeout?: number;
|
|
380
|
+
}
|
|
381
|
+
interface SubmitActionResult {
|
|
382
|
+
/** ID de la acción ejecutada */
|
|
383
|
+
actionId: string;
|
|
384
|
+
/** Nombre de la acción */
|
|
385
|
+
actionName: string;
|
|
386
|
+
/** Si la ejecución fue exitosa */
|
|
387
|
+
success: boolean;
|
|
388
|
+
/** Datos de respuesta (si success = true) */
|
|
389
|
+
data?: unknown;
|
|
390
|
+
/** Error (si success = false) */
|
|
391
|
+
error?: Error;
|
|
392
|
+
/** Duración de la ejecución en ms */
|
|
393
|
+
durationMs: number;
|
|
394
|
+
/** Timestamp de inicio */
|
|
395
|
+
startedAt: Date;
|
|
396
|
+
/** Timestamp de fin */
|
|
397
|
+
completedAt: Date;
|
|
398
|
+
}
|
|
399
|
+
interface SubmitActionsResult {
|
|
400
|
+
/** Resultados de todas las acciones */
|
|
401
|
+
results: SubmitActionResult[];
|
|
402
|
+
/** Si todas las acciones fueron exitosas */
|
|
403
|
+
allSuccessful: boolean;
|
|
404
|
+
/** Número de acciones exitosas */
|
|
405
|
+
successCount: number;
|
|
406
|
+
/** Número de acciones fallidas */
|
|
407
|
+
failureCount: number;
|
|
408
|
+
/** Duración total */
|
|
409
|
+
totalDurationMs: number;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Serializable validation rules for form fields.
|
|
414
|
+
*
|
|
415
|
+
* This flat type can be stored as JSON in a database or API response.
|
|
416
|
+
* The field `type` discriminates which rules apply at runtime.
|
|
417
|
+
* Rules are compiled to Zod schemas internally via `compileValidationRules()`.
|
|
418
|
+
*/
|
|
419
|
+
type ValidationRules = {
|
|
420
|
+
required?: boolean;
|
|
421
|
+
requiredMessage?: string;
|
|
422
|
+
minLength?: number;
|
|
423
|
+
minLengthMessage?: string;
|
|
424
|
+
maxLength?: number;
|
|
425
|
+
maxLengthMessage?: string;
|
|
426
|
+
pattern?: string;
|
|
427
|
+
patternMessage?: string;
|
|
428
|
+
format?: 'email' | 'url' | 'uuid' | 'cuid' | 'emoji';
|
|
429
|
+
formatMessage?: string;
|
|
430
|
+
min?: number;
|
|
431
|
+
minMessage?: string;
|
|
432
|
+
max?: number;
|
|
433
|
+
maxMessage?: string;
|
|
434
|
+
integer?: boolean;
|
|
435
|
+
integerMessage?: string;
|
|
436
|
+
positive?: boolean;
|
|
437
|
+
positiveMessage?: string;
|
|
438
|
+
minItems?: number;
|
|
439
|
+
minItemsMessage?: string;
|
|
440
|
+
maxItems?: number;
|
|
441
|
+
maxItemsMessage?: string;
|
|
442
|
+
mustBeTrue?: boolean;
|
|
443
|
+
mustBeTrueMessage?: string;
|
|
444
|
+
minDate?: string;
|
|
445
|
+
minDateMessage?: string;
|
|
446
|
+
maxDate?: string;
|
|
447
|
+
maxDateMessage?: string;
|
|
448
|
+
mustBeFuture?: boolean;
|
|
449
|
+
mustBeFutureMessage?: string;
|
|
450
|
+
mustBePast?: boolean;
|
|
451
|
+
mustBePastMessage?: string;
|
|
452
|
+
preset?: string;
|
|
453
|
+
};
|
|
454
|
+
/**
|
|
455
|
+
* Union type for the `schema` property on field configs.
|
|
456
|
+
* Accepts either a raw Zod schema or serializable ValidationRules.
|
|
457
|
+
*/
|
|
458
|
+
type SchemaType = z.ZodType | ValidationRules;
|
|
459
|
+
|
|
460
|
+
interface LabelProps$1 {
|
|
461
|
+
/** Label shown to the user (puede ser HTML) */
|
|
462
|
+
label?: string;
|
|
463
|
+
/** Opcionalmente oculta el label del campo */
|
|
464
|
+
hideLabel?: boolean;
|
|
465
|
+
/** Clase CSS opcional para el label */
|
|
466
|
+
label_className?: string;
|
|
467
|
+
/** Descripción del campo (se muestra como texto adicional o tooltip) */
|
|
468
|
+
description?: string;
|
|
469
|
+
}
|
|
470
|
+
interface FieldLayoutConfig {
|
|
471
|
+
/** Número de columnas que ocupa el campo por breakpoint (1-12, default, sm, md, lg, xl, 2xl) */
|
|
472
|
+
columns?: Partial<Record<Breakpoint$1, number>>;
|
|
473
|
+
/** Orden de visualización (útil para reordenar sin arrastrar). Puede ser un número fijo o responsive por breakpoint */
|
|
474
|
+
order?: number | Partial<Record<Breakpoint$1, number>>;
|
|
475
|
+
}
|
|
476
|
+
interface LayoutProps {
|
|
477
|
+
/** Configuración de layout del campo (columns, orden, visibilidad) */
|
|
478
|
+
layout?: FieldLayoutConfig;
|
|
479
|
+
/** Número de columnas que ocupa el campo por breakpoint (1-12) - Atajo para layout.columns */
|
|
480
|
+
columns?: Partial<Record<Breakpoint$1, number>>;
|
|
481
|
+
/** Alias para columns - usado por form-builder */
|
|
482
|
+
gridSpan?: number | Partial<Record<Breakpoint$1, number>>;
|
|
483
|
+
/** Orden de visualización del campo */
|
|
484
|
+
order?: number | Partial<Record<Breakpoint$1, number>>;
|
|
485
|
+
/** Clase CSS opcional para el FormItem */
|
|
486
|
+
wrapper_className?: string;
|
|
487
|
+
/** Clase CSS general para el campo */
|
|
488
|
+
className?: string;
|
|
489
|
+
}
|
|
490
|
+
interface InputProps$1 {
|
|
491
|
+
/** Clase CSS opcional para el input/control */
|
|
492
|
+
input_className?: string;
|
|
493
|
+
/** Valor inicial del campo */
|
|
494
|
+
value?: unknown;
|
|
495
|
+
/** Valor por defecto del campo */
|
|
496
|
+
defaultValue?: unknown;
|
|
497
|
+
/** Placeholder del campo */
|
|
498
|
+
placeholder?: string;
|
|
499
|
+
/** Atributo HTML autocomplete */
|
|
500
|
+
autocomplete?: string;
|
|
501
|
+
/** Indica si el campo es requerido (complementa la validación Zod) */
|
|
502
|
+
required?: boolean;
|
|
503
|
+
/** Tamaño opcional para inputs y textareas */
|
|
504
|
+
size?: InputSize;
|
|
505
|
+
/** Elemento React para el icono */
|
|
506
|
+
icon?: ReactNode;
|
|
507
|
+
/** Props opcionales para el icono (color, tamaño, etc) */
|
|
508
|
+
iconProps?: {
|
|
509
|
+
className?: string;
|
|
510
|
+
[key: string]: unknown;
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
interface ValidationProps {
|
|
514
|
+
/** Esquema de validación Zod or serializable ValidationRules */
|
|
515
|
+
schema?: z.ZodType | ValidationRules;
|
|
516
|
+
/** Names of plugin-registered validators to apply to this field */
|
|
517
|
+
customValidators?: string[];
|
|
518
|
+
/** Clase CSS opcional para el mensaje de error */
|
|
519
|
+
error_className?: string;
|
|
520
|
+
/** Texto de ayuda opcional que se muestra debajo del input */
|
|
521
|
+
helperText?: string;
|
|
522
|
+
/** Clase CSS opcional para el mensaje de ayuda */
|
|
523
|
+
helper_className?: string;
|
|
524
|
+
/** Texto de ayuda contextual que se muestra en un tooltip */
|
|
525
|
+
tooltip?: string;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
interface StateProps {
|
|
529
|
+
/** Oculta el campo basado en una condición booleana, una función, un grupo de condiciones declarativas, o responsive por breakpoint */
|
|
530
|
+
hidden?: boolean | ((values: Record<string, unknown>) => boolean) | ConditionGroup | Partial<Record<Breakpoint$1, 'visible' | 'hidden'>>;
|
|
531
|
+
/** Deshabilita el campo basado en una condición booleana, una función o un grupo de condiciones declarativas */
|
|
532
|
+
disabled?: boolean | ((values: Record<string, unknown>) => boolean) | ConditionGroup;
|
|
533
|
+
/** Hace el campo de solo lectura basado en una condición booleana, una función o un grupo de condiciones declarativas */
|
|
534
|
+
readOnly?: boolean | ((values: Record<string, unknown>) => boolean) | ConditionGroup;
|
|
535
|
+
}
|
|
536
|
+
interface OptionsLayoutProps {
|
|
537
|
+
/** Clases CSS para controlar el layout del grid de opciones (por defecto: "grid grid-cols-1 gap-2") */
|
|
538
|
+
optionsClassName?: string;
|
|
539
|
+
}
|
|
540
|
+
interface TransformProps {
|
|
541
|
+
/** Value transform(s) applied before submission.
|
|
542
|
+
* Runs before plugin transformValues and action-level fieldMapping.
|
|
543
|
+
* Use a single built-in name, an array for chaining, or a custom function.
|
|
544
|
+
*/
|
|
545
|
+
transform?: BuiltinTransform | BuiltinTransform[] | FieldTransformFn;
|
|
546
|
+
}
|
|
547
|
+
interface ComputedProps {
|
|
548
|
+
/** Reactive computation — value is auto-set from other field values.
|
|
549
|
+
* The field is readOnly while computed is active.
|
|
550
|
+
*/
|
|
551
|
+
computed?: {
|
|
552
|
+
/** Field names this computation depends on */
|
|
553
|
+
dependsOn: string[];
|
|
554
|
+
/** Pure function that computes the value from all form values */
|
|
555
|
+
compute: (values: Record<string, unknown>) => unknown;
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
interface AdvancedProps {
|
|
559
|
+
/** Clave para tracking/analytics */
|
|
560
|
+
trackingKey?: string;
|
|
561
|
+
}
|
|
562
|
+
interface BaseFieldProps extends LabelProps$1, LayoutProps, InputProps$1, ValidationProps, StateProps, TransformProps, ComputedProps, AdvancedProps {
|
|
563
|
+
}
|
|
564
|
+
type Option = {
|
|
565
|
+
label: string;
|
|
566
|
+
value: string;
|
|
567
|
+
icon?: ReactNode;
|
|
568
|
+
iconProps?: Record<string, unknown>;
|
|
569
|
+
};
|
|
570
|
+
type ButtonCardOption = {
|
|
571
|
+
value: string;
|
|
572
|
+
text: string;
|
|
573
|
+
description?: string;
|
|
574
|
+
icon?: ReactNode;
|
|
575
|
+
iconProps?: Record<string, unknown>;
|
|
576
|
+
};
|
|
577
|
+
interface TextFieldProps extends BaseFieldProps {
|
|
578
|
+
type: 'text' | 'email' | 'tel' | 'url' | 'password' | 'number';
|
|
579
|
+
placeholder?: string;
|
|
580
|
+
schema: z.ZodType | ValidationRules;
|
|
581
|
+
}
|
|
582
|
+
interface TextareaFieldProps extends BaseFieldProps {
|
|
583
|
+
type: 'textarea';
|
|
584
|
+
placeholder?: string;
|
|
585
|
+
schema: z.ZodType | ValidationRules;
|
|
586
|
+
rows?: number;
|
|
587
|
+
maxLength?: number;
|
|
588
|
+
}
|
|
589
|
+
interface SliderFieldProps extends BaseFieldProps {
|
|
590
|
+
type: 'slider';
|
|
591
|
+
defaultValue?: number[];
|
|
592
|
+
max?: number;
|
|
593
|
+
min?: number;
|
|
594
|
+
step?: number;
|
|
595
|
+
/** 'default' = single thumb, 'range' = two thumbs (min/max), 'multi' = multiple thumbs */
|
|
596
|
+
variant?: 'default' | 'range' | 'multi';
|
|
597
|
+
/** Slider orientation */
|
|
598
|
+
orientation?: 'horizontal' | 'vertical';
|
|
599
|
+
/** Number of thumbs for 'multi' variant (default: 3) */
|
|
600
|
+
thumbCount?: number;
|
|
601
|
+
/** Show min/max labels below slider */
|
|
602
|
+
showLabels?: boolean;
|
|
603
|
+
/** Show current value(s) */
|
|
604
|
+
showValue?: boolean;
|
|
605
|
+
/** Format function for displayed values (e.g., add units) */
|
|
606
|
+
valueFormat?: string;
|
|
607
|
+
schema: z.ZodType | ValidationRules;
|
|
608
|
+
}
|
|
609
|
+
interface SelectFieldProps extends BaseFieldProps {
|
|
610
|
+
type: 'select';
|
|
611
|
+
options: Option[];
|
|
612
|
+
schema: z.ZodType | ValidationRules;
|
|
613
|
+
}
|
|
614
|
+
interface ComboboxFieldProps extends BaseFieldProps {
|
|
615
|
+
type: 'combobox';
|
|
616
|
+
options: Option[];
|
|
617
|
+
schema: z.ZodType | ValidationRules;
|
|
618
|
+
placeholder?: string;
|
|
619
|
+
searchPlaceholder?: string;
|
|
620
|
+
emptyText?: string;
|
|
621
|
+
}
|
|
622
|
+
interface NativeSelectFieldProps extends BaseFieldProps {
|
|
623
|
+
type: 'native-select';
|
|
624
|
+
options: Option[];
|
|
625
|
+
schema: z.ZodType | ValidationRules;
|
|
626
|
+
}
|
|
627
|
+
interface RadioFieldProps extends BaseFieldProps {
|
|
628
|
+
type: 'radio';
|
|
629
|
+
options: Option[];
|
|
630
|
+
schema: z.ZodType | ValidationRules;
|
|
631
|
+
}
|
|
632
|
+
interface ButtonRadioFieldProps extends BaseFieldProps, OptionsLayoutProps {
|
|
633
|
+
type: 'button-radio';
|
|
634
|
+
options: Option[];
|
|
635
|
+
schema: z.ZodType | ValidationRules;
|
|
636
|
+
}
|
|
637
|
+
interface CheckboxFieldProps extends BaseFieldProps {
|
|
638
|
+
type: 'checkbox';
|
|
639
|
+
schema: z.ZodType | ValidationRules;
|
|
640
|
+
}
|
|
641
|
+
interface SwitchFieldProps extends BaseFieldProps {
|
|
642
|
+
type: 'switch';
|
|
643
|
+
schema: z.ZodType | ValidationRules;
|
|
644
|
+
}
|
|
645
|
+
interface CheckboxGroupFieldProps extends BaseFieldProps, OptionsLayoutProps {
|
|
646
|
+
type: 'checkbox-group';
|
|
647
|
+
options: Option[];
|
|
648
|
+
schema: z.ZodType | ValidationRules;
|
|
649
|
+
}
|
|
650
|
+
interface SwitchGroupFieldProps extends BaseFieldProps, OptionsLayoutProps {
|
|
651
|
+
type: 'switch-group';
|
|
652
|
+
options: Option[];
|
|
653
|
+
schema: z.ZodType | ValidationRules;
|
|
654
|
+
}
|
|
655
|
+
interface ButtonCheckboxFieldProps extends BaseFieldProps, OptionsLayoutProps {
|
|
656
|
+
type: 'button-checkbox';
|
|
657
|
+
options: Option[];
|
|
658
|
+
schema: z.ZodType | ValidationRules;
|
|
659
|
+
}
|
|
660
|
+
interface DateFieldProps extends BaseFieldProps {
|
|
661
|
+
type: 'date';
|
|
662
|
+
schema: z.ZodType | ValidationRules;
|
|
663
|
+
placeholder?: string;
|
|
664
|
+
dateType?: 'simple' | 'popover';
|
|
665
|
+
showTime?: boolean;
|
|
666
|
+
presets?: Array<{
|
|
667
|
+
label: string;
|
|
668
|
+
value: number;
|
|
669
|
+
}>;
|
|
670
|
+
}
|
|
671
|
+
interface DateRangeFieldProps extends BaseFieldProps {
|
|
672
|
+
type: 'daterange';
|
|
673
|
+
schema: z.ZodType | ValidationRules;
|
|
674
|
+
placeholder?: string;
|
|
675
|
+
}
|
|
676
|
+
interface HtmlFieldProps extends BaseFieldProps {
|
|
677
|
+
type: 'html';
|
|
678
|
+
html?: string;
|
|
679
|
+
content?: string;
|
|
680
|
+
}
|
|
681
|
+
interface ButtonCardFieldProps extends BaseFieldProps, OptionsLayoutProps {
|
|
682
|
+
type: 'button-card';
|
|
683
|
+
options: ButtonCardOption[];
|
|
684
|
+
multiple?: boolean;
|
|
685
|
+
schema: z.ZodType | ValidationRules;
|
|
686
|
+
}
|
|
687
|
+
interface OtpFieldProps extends BaseFieldProps {
|
|
688
|
+
type: 'otp';
|
|
689
|
+
length?: number;
|
|
690
|
+
schema: z.ZodType | ValidationRules;
|
|
691
|
+
}
|
|
692
|
+
interface CommandFieldProps extends BaseFieldProps {
|
|
693
|
+
type: 'command';
|
|
694
|
+
options: Option[];
|
|
695
|
+
schema: z.ZodType | ValidationRules;
|
|
696
|
+
placeholder?: string;
|
|
697
|
+
searchPlaceholder?: string;
|
|
698
|
+
emptyText?: string;
|
|
699
|
+
}
|
|
700
|
+
interface InputGroupFieldProps extends BaseFieldProps {
|
|
701
|
+
type: 'input-group';
|
|
702
|
+
prefix?: string;
|
|
703
|
+
suffix?: string;
|
|
704
|
+
placeholder?: string;
|
|
705
|
+
schema: z.ZodType | ValidationRules;
|
|
706
|
+
}
|
|
707
|
+
interface RepeaterFieldProps extends BaseFieldProps {
|
|
708
|
+
type: 'repeater';
|
|
709
|
+
/** Sub-field definitions for each item in the list */
|
|
710
|
+
itemFields: Record<string, FieldConfig>;
|
|
711
|
+
/** Minimum number of items (default: 0) */
|
|
712
|
+
minItems?: number;
|
|
713
|
+
/** Maximum number of items */
|
|
714
|
+
maxItems?: number;
|
|
715
|
+
/** Label for the add button (default: "Add item") */
|
|
716
|
+
addLabel?: string;
|
|
717
|
+
/** Label for the remove button (default: "Remove") */
|
|
718
|
+
removeLabel?: string;
|
|
719
|
+
schema?: z.ZodType | ValidationRules;
|
|
720
|
+
}
|
|
721
|
+
interface FileFieldProps extends BaseFieldProps {
|
|
722
|
+
type: 'file';
|
|
723
|
+
/** Accepted file types (e.g. "image/*", ".pdf,.doc") */
|
|
724
|
+
accept?: string;
|
|
725
|
+
/** Allow multiple file selection */
|
|
726
|
+
multiple?: boolean;
|
|
727
|
+
/** Max file size in bytes */
|
|
728
|
+
maxSize?: number;
|
|
729
|
+
schema?: z.ZodType | ValidationRules;
|
|
730
|
+
}
|
|
731
|
+
interface CurrencyFieldProps extends BaseFieldProps {
|
|
732
|
+
type: 'currency';
|
|
733
|
+
prefix?: string;
|
|
734
|
+
suffix?: string;
|
|
735
|
+
placeholder?: string;
|
|
736
|
+
schema: z.ZodType | ValidationRules;
|
|
737
|
+
}
|
|
738
|
+
interface RangeFieldProps extends BaseFieldProps {
|
|
739
|
+
type: 'range';
|
|
740
|
+
defaultValue?: number[];
|
|
741
|
+
max?: number;
|
|
742
|
+
min?: number;
|
|
743
|
+
step?: number;
|
|
744
|
+
variant?: 'default' | 'range' | 'multi';
|
|
745
|
+
orientation?: 'horizontal' | 'vertical';
|
|
746
|
+
thumbCount?: number;
|
|
747
|
+
showLabels?: boolean;
|
|
748
|
+
showValue?: boolean;
|
|
749
|
+
valueFormat?: string;
|
|
750
|
+
schema: z.ZodType | ValidationRules;
|
|
751
|
+
}
|
|
752
|
+
interface HiddenFieldProps extends BaseFieldProps {
|
|
753
|
+
type: 'hidden';
|
|
754
|
+
/** Resolver that computes the field value at form init */
|
|
755
|
+
resolver: SerializableFieldResolver;
|
|
756
|
+
}
|
|
757
|
+
type FieldConfig = TextFieldProps | TextareaFieldProps | SliderFieldProps | RangeFieldProps | SelectFieldProps | ComboboxFieldProps | NativeSelectFieldProps | RadioFieldProps | ButtonRadioFieldProps | CheckboxFieldProps | SwitchFieldProps | CheckboxGroupFieldProps | SwitchGroupFieldProps | ButtonCheckboxFieldProps | DateFieldProps | DateRangeFieldProps | HtmlFieldProps | ButtonCardFieldProps | OtpFieldProps | CommandFieldProps | InputGroupFieldProps | CurrencyFieldProps | FileFieldProps | RepeaterFieldProps | HiddenFieldProps | ButtonConfig;
|
|
758
|
+
|
|
759
|
+
interface ButtonConfig extends BaseFieldProps {
|
|
760
|
+
type: 'button' | 'submit' | 'next' | 'back';
|
|
761
|
+
action?: () => void;
|
|
762
|
+
loading?: boolean;
|
|
763
|
+
/** Elemento React para el icono */
|
|
764
|
+
icon?: ReactNode;
|
|
765
|
+
iconPosition?: 'left' | 'right';
|
|
766
|
+
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
|
|
767
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
768
|
+
effect?: string;
|
|
769
|
+
rounded?: string;
|
|
770
|
+
label?: string;
|
|
771
|
+
}
|
|
772
|
+
/** Props que puede recibir un botón del formulario */
|
|
773
|
+
type FormButtonProps = React.ComponentProps<'button'> & {
|
|
774
|
+
/** Clase CSS opcional para el botón */
|
|
775
|
+
className?: string;
|
|
776
|
+
/** Col-span para el botón en el grid */
|
|
777
|
+
colSpan?: number;
|
|
778
|
+
/** Texto del botón */
|
|
779
|
+
text?: string;
|
|
780
|
+
variant?: string;
|
|
781
|
+
size?: string;
|
|
782
|
+
};
|
|
783
|
+
interface FormButtons {
|
|
784
|
+
submit?: ButtonConfig;
|
|
785
|
+
next?: ButtonConfig;
|
|
786
|
+
back?: ButtonConfig;
|
|
787
|
+
/** Alineación horizontal de los botones */
|
|
788
|
+
align?: 'start' | 'center' | 'end' | 'between' | 'responsive';
|
|
789
|
+
/** Si true, los botones se muestran en la misma línea que los campos (inline form) */
|
|
790
|
+
inline?: boolean;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
type StepCondition = ConditionGroup & {
|
|
794
|
+
target: string;
|
|
795
|
+
};
|
|
796
|
+
type Step = {
|
|
797
|
+
/** Step identifier. Optional when using `Record<string, Step>` — the key serves as the id. */
|
|
798
|
+
id?: string;
|
|
799
|
+
fields: string[];
|
|
800
|
+
next?: StepCondition[];
|
|
801
|
+
defaultNext?: string;
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
interface RecaptchaConfig {
|
|
805
|
+
siteKey: string;
|
|
806
|
+
action: string;
|
|
807
|
+
}
|
|
808
|
+
interface EndpointConfig {
|
|
809
|
+
url: string;
|
|
810
|
+
clientId: string;
|
|
811
|
+
}
|
|
812
|
+
type SubmitType = 'default' | 'default-no-recaptcha' | 'custom';
|
|
813
|
+
interface DefaultSubmitConfig {
|
|
814
|
+
type: 'default' | 'default-no-recaptcha';
|
|
815
|
+
endpoint: EndpointConfig;
|
|
816
|
+
recaptcha?: RecaptchaConfig;
|
|
817
|
+
}
|
|
818
|
+
interface CustomSubmitConfig {
|
|
819
|
+
type: 'custom';
|
|
820
|
+
onSubmit: (values: Record<string, any>) => Promise<void>;
|
|
821
|
+
}
|
|
822
|
+
type SubmitConfig = DefaultSubmitConfig | CustomSubmitConfig;
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* ============================================
|
|
826
|
+
* PLUGIN SYSTEM - Extensibility Architecture
|
|
827
|
+
* ============================================
|
|
828
|
+
*
|
|
829
|
+
* Sistema de plugins para extender funcionalidad sin modificar código fuente.
|
|
830
|
+
*/
|
|
831
|
+
/**
|
|
832
|
+
* Contexto de validación para plugins.
|
|
833
|
+
*/
|
|
834
|
+
interface ValidationContext {
|
|
835
|
+
fieldName: string;
|
|
836
|
+
allValues: Record<string, unknown>;
|
|
837
|
+
abortSignal?: AbortSignal;
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Renderer personalizado de campo para plugins.
|
|
841
|
+
*/
|
|
842
|
+
type FieldRenderer$1 = React.ComponentType<{
|
|
843
|
+
name: string;
|
|
844
|
+
fieldConfig: any;
|
|
845
|
+
control: any;
|
|
846
|
+
colSpanItem: string;
|
|
847
|
+
}>;
|
|
848
|
+
/**
|
|
849
|
+
* Interfaz principal de un plugin de formulario.
|
|
850
|
+
*
|
|
851
|
+
* Los plugins pueden interceptar el ciclo de vida del formulario,
|
|
852
|
+
* registrar campos personalizados y transformar configuraciones.
|
|
853
|
+
*/
|
|
854
|
+
interface FormPlugin {
|
|
855
|
+
/** Nombre único del plugin */
|
|
856
|
+
name: string;
|
|
857
|
+
/** Versión del plugin */
|
|
858
|
+
version: string;
|
|
859
|
+
/** Descripción opcional del plugin */
|
|
860
|
+
description?: string;
|
|
861
|
+
/**
|
|
862
|
+
* Se ejecuta cuando el formulario se inicializa.
|
|
863
|
+
*
|
|
864
|
+
* @param config - Configuración del formulario
|
|
865
|
+
*/
|
|
866
|
+
onFormInit?: (config: FormConfig) => void;
|
|
867
|
+
/**
|
|
868
|
+
* Se ejecuta cuando cambia el step actual.
|
|
869
|
+
*
|
|
870
|
+
* @param stepId - ID del nuevo step
|
|
871
|
+
* @param values - Valores actuales del formulario
|
|
872
|
+
*/
|
|
873
|
+
onStepChange?: (stepId: string, values: Record<string, unknown>) => void;
|
|
874
|
+
/**
|
|
875
|
+
* Se ejecuta antes de enviar el formulario.
|
|
876
|
+
* Puede ser asíncrono para validaciones adicionales.
|
|
877
|
+
*
|
|
878
|
+
* @param values - Valores a enviar
|
|
879
|
+
* @throws Error si la validación falla
|
|
880
|
+
*/
|
|
881
|
+
onBeforeSubmit?: (values: Record<string, unknown>) => void | Promise<void>;
|
|
882
|
+
/**
|
|
883
|
+
* Se ejecuta después de enviar exitosamente el formulario.
|
|
884
|
+
*
|
|
885
|
+
* @param values - Valores enviados
|
|
886
|
+
* @param response - Respuesta del servidor
|
|
887
|
+
*/
|
|
888
|
+
onAfterSubmit?: (values: Record<string, unknown>, response: unknown) => void;
|
|
889
|
+
/**
|
|
890
|
+
* Se ejecuta cuando ocurre un error.
|
|
891
|
+
*
|
|
892
|
+
* @param error - Error ocurrido
|
|
893
|
+
* @param values - Valores actuales del formulario
|
|
894
|
+
*/
|
|
895
|
+
onError?: (error: Error, values?: Record<string, unknown>) => void;
|
|
896
|
+
/**
|
|
897
|
+
* Se ejecuta cuando un campo cambia de valor.
|
|
898
|
+
*
|
|
899
|
+
* @param fieldName - Nombre del campo
|
|
900
|
+
* @param value - Nuevo valor
|
|
901
|
+
* @param allValues - Todos los valores del formulario
|
|
902
|
+
*/
|
|
903
|
+
onFieldChange?: (fieldName: string, value: unknown, allValues: Record<string, unknown>) => void;
|
|
904
|
+
/**
|
|
905
|
+
* Registra campos personalizados.
|
|
906
|
+
*
|
|
907
|
+
* @returns Objeto con tipos de campo y sus renderizadores
|
|
908
|
+
*
|
|
909
|
+
* @example
|
|
910
|
+
* ```tsx
|
|
911
|
+
* registerFields() {
|
|
912
|
+
* return {
|
|
913
|
+
* signature: SignatureFieldRenderer,
|
|
914
|
+
* wysiwyg: WysiwygFieldRenderer,
|
|
915
|
+
* };
|
|
916
|
+
* }
|
|
917
|
+
* ```
|
|
918
|
+
*/
|
|
919
|
+
registerFields?: () => Record<string, FieldRenderer$1>;
|
|
920
|
+
/**
|
|
921
|
+
* Transforma la configuración del formulario antes de usarla.
|
|
922
|
+
*
|
|
923
|
+
* @param config - Configuración original
|
|
924
|
+
* @returns Configuración transformada
|
|
925
|
+
*
|
|
926
|
+
* @example
|
|
927
|
+
* ```tsx
|
|
928
|
+
* transformConfig(config) {
|
|
929
|
+
* // Agregar prefijo a todos los campos
|
|
930
|
+
* return {
|
|
931
|
+
* ...config,
|
|
932
|
+
* fields: Object.fromEntries(
|
|
933
|
+
* Object.entries(config.fields).map(([key, value]) => [
|
|
934
|
+
* `prefix_${key}`,
|
|
935
|
+
* value
|
|
936
|
+
* ])
|
|
937
|
+
* )
|
|
938
|
+
* };
|
|
939
|
+
* }
|
|
940
|
+
* ```
|
|
941
|
+
*/
|
|
942
|
+
transformConfig?: (config: FormConfig) => FormConfig;
|
|
943
|
+
/**
|
|
944
|
+
* Transforma los valores antes de enviar.
|
|
945
|
+
*
|
|
946
|
+
* @param values - Valores originales
|
|
947
|
+
* @returns Valores transformados
|
|
948
|
+
*
|
|
949
|
+
* @example
|
|
950
|
+
* ```tsx
|
|
951
|
+
* transformValues(values) {
|
|
952
|
+
* // Convertir fechas a ISO string
|
|
953
|
+
* return Object.fromEntries(
|
|
954
|
+
* Object.entries(values).map(([key, value]) => [
|
|
955
|
+
* key,
|
|
956
|
+
* value instanceof Date ? value.toISOString() : value
|
|
957
|
+
* ])
|
|
958
|
+
* );
|
|
959
|
+
* }
|
|
960
|
+
* ```
|
|
961
|
+
*/
|
|
962
|
+
transformValues?: (values: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
963
|
+
/**
|
|
964
|
+
* Registra validadores personalizados.
|
|
965
|
+
*
|
|
966
|
+
* @returns Objeto con nombre del validador y función de validación
|
|
967
|
+
*
|
|
968
|
+
* @example
|
|
969
|
+
* ```tsx
|
|
970
|
+
* validators: {
|
|
971
|
+
* uniqueEmail: async (value, context) => {
|
|
972
|
+
* const response = await fetch(`/api/check-email?email=${value}`);
|
|
973
|
+
* const { exists } = await response.json();
|
|
974
|
+
* return exists ? "Email already registered" : true;
|
|
975
|
+
* }
|
|
976
|
+
* }
|
|
977
|
+
* ```
|
|
978
|
+
*/
|
|
979
|
+
validators?: Record<string, (value: unknown, context: ValidationContext) => boolean | string | Promise<boolean | string>>;
|
|
980
|
+
/**
|
|
981
|
+
* Opciones de configuración del plugin.
|
|
982
|
+
*/
|
|
983
|
+
options?: Record<string, unknown>;
|
|
984
|
+
/**
|
|
985
|
+
* Inicializa el plugin con opciones personalizadas.
|
|
986
|
+
*
|
|
987
|
+
* @param options - Opciones de configuración
|
|
988
|
+
*/
|
|
989
|
+
init?: (options?: Record<string, unknown>) => void;
|
|
990
|
+
/**
|
|
991
|
+
* Limpia recursos del plugin.
|
|
992
|
+
*/
|
|
993
|
+
cleanup?: () => void;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Tipo helper para crear plugins con type safety.
|
|
997
|
+
*/
|
|
998
|
+
type DefinePlugin = (options?: Record<string, unknown>) => FormPlugin;
|
|
999
|
+
/**
|
|
1000
|
+
* Helper para definir un plugin con type safety.
|
|
1001
|
+
*
|
|
1002
|
+
* @param plugin - Configuración del plugin
|
|
1003
|
+
* @returns Plugin tipado
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* ```tsx
|
|
1007
|
+
* export const myPlugin = definePlugin({
|
|
1008
|
+
* name: "my-plugin",
|
|
1009
|
+
* version: "1.0.0",
|
|
1010
|
+
* onFormInit(config) {
|
|
1011
|
+
* console.log("Form initialized:", config.formId);
|
|
1012
|
+
* },
|
|
1013
|
+
* });
|
|
1014
|
+
* ```
|
|
1015
|
+
*/
|
|
1016
|
+
declare function definePlugin(plugin: FormPlugin): FormPlugin;
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* ============================================
|
|
1020
|
+
* PLUGIN MANAGER - Plugin System Core
|
|
1021
|
+
* ============================================
|
|
1022
|
+
*
|
|
1023
|
+
* Gestiona el registro, ejecución y coordinación de plugins.
|
|
1024
|
+
*/
|
|
1025
|
+
declare class PluginManager {
|
|
1026
|
+
private plugins;
|
|
1027
|
+
private customFields;
|
|
1028
|
+
private validators;
|
|
1029
|
+
/**
|
|
1030
|
+
* Registra un nuevo plugin.
|
|
1031
|
+
*
|
|
1032
|
+
* @param plugin - Plugin a registrar
|
|
1033
|
+
* @throws Error si el plugin ya está registrado
|
|
1034
|
+
*
|
|
1035
|
+
* @example
|
|
1036
|
+
* ```tsx
|
|
1037
|
+
* const pluginManager = new PluginManager();
|
|
1038
|
+
* pluginManager.register(localStoragePlugin);
|
|
1039
|
+
* pluginManager.register(analyticsPlugin);
|
|
1040
|
+
* ```
|
|
1041
|
+
*/
|
|
1042
|
+
register(plugin: FormPlugin): void;
|
|
1043
|
+
/**
|
|
1044
|
+
* Desregistra un plugin.
|
|
1045
|
+
*
|
|
1046
|
+
* @param pluginName - Nombre del plugin a desregistrar
|
|
1047
|
+
* @returns true si se desregistró, false si no existía
|
|
1048
|
+
*/
|
|
1049
|
+
unregister(pluginName: string): boolean;
|
|
1050
|
+
/**
|
|
1051
|
+
* Obtiene un plugin registrado.
|
|
1052
|
+
*
|
|
1053
|
+
* @param pluginName - Nombre del plugin
|
|
1054
|
+
* @returns Plugin o undefined si no existe
|
|
1055
|
+
*/
|
|
1056
|
+
getPlugin(pluginName: string): FormPlugin | undefined;
|
|
1057
|
+
/**
|
|
1058
|
+
* Obtiene todos los plugins registrados.
|
|
1059
|
+
*
|
|
1060
|
+
* @returns Array de plugins
|
|
1061
|
+
*/
|
|
1062
|
+
getAllPlugins(): FormPlugin[];
|
|
1063
|
+
/**
|
|
1064
|
+
* Obtiene un renderer de campo personalizado.
|
|
1065
|
+
*
|
|
1066
|
+
* @param type - Tipo de campo
|
|
1067
|
+
* @returns Renderer o undefined si no existe
|
|
1068
|
+
*/
|
|
1069
|
+
getCustomField(type: string): FieldRenderer$1 | undefined;
|
|
1070
|
+
/**
|
|
1071
|
+
* Verifica si existe un tipo de campo personalizado.
|
|
1072
|
+
*
|
|
1073
|
+
* @param type - Tipo de campo
|
|
1074
|
+
* @returns true si existe
|
|
1075
|
+
*/
|
|
1076
|
+
hasCustomField(type: string): boolean;
|
|
1077
|
+
/**
|
|
1078
|
+
* Obtiene un validador personalizado.
|
|
1079
|
+
*
|
|
1080
|
+
* @param name - Nombre del validador
|
|
1081
|
+
* @returns Validador o undefined si no existe
|
|
1082
|
+
*/
|
|
1083
|
+
getValidator(name: string): ((value: unknown, context: ValidationContext) => boolean | string | Promise<boolean | string>) | undefined;
|
|
1084
|
+
/**
|
|
1085
|
+
* Ejecuta un hook en todos los plugins que lo implementen.
|
|
1086
|
+
*
|
|
1087
|
+
* @param hook - Nombre del hook a ejecutar
|
|
1088
|
+
* @param args - Argumentos para el hook
|
|
1089
|
+
*
|
|
1090
|
+
* @example
|
|
1091
|
+
* ```tsx
|
|
1092
|
+
* await pluginManager.executeHook("onFormInit", formConfig);
|
|
1093
|
+
* await pluginManager.executeHook("onStepChange", "step2", values);
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
executeHook(hook: keyof FormPlugin, ...args: any[]): Promise<void>;
|
|
1097
|
+
/**
|
|
1098
|
+
* Transforma la configuración del formulario aplicando todos los transformers.
|
|
1099
|
+
*
|
|
1100
|
+
* @param config - Configuración original
|
|
1101
|
+
* @returns Configuración transformada
|
|
1102
|
+
*/
|
|
1103
|
+
transformConfig(config: FormConfig): FormConfig;
|
|
1104
|
+
/**
|
|
1105
|
+
* Transforma los valores del formulario aplicando todos los transformers.
|
|
1106
|
+
* Supports both sync and async transformers (chained in registration order).
|
|
1107
|
+
*
|
|
1108
|
+
* @param values - Valores originales
|
|
1109
|
+
* @returns Valores transformados
|
|
1110
|
+
*/
|
|
1111
|
+
transformValues(values: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
1112
|
+
/**
|
|
1113
|
+
* Limpia todos los plugins registrados.
|
|
1114
|
+
*/
|
|
1115
|
+
cleanup(): void;
|
|
1116
|
+
/**
|
|
1117
|
+
* Obtiene estadísticas del plugin manager.
|
|
1118
|
+
*
|
|
1119
|
+
* @returns Objeto con estadísticas
|
|
1120
|
+
*/
|
|
1121
|
+
getStats(): {
|
|
1122
|
+
totalPlugins: number;
|
|
1123
|
+
customFields: number;
|
|
1124
|
+
validators: number;
|
|
1125
|
+
plugins: {
|
|
1126
|
+
name: string;
|
|
1127
|
+
version: string;
|
|
1128
|
+
description: string | undefined;
|
|
1129
|
+
}[];
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Instancia global del plugin manager (opcional).
|
|
1134
|
+
* Los usuarios pueden crear sus propias instancias si lo prefieren.
|
|
1135
|
+
*/
|
|
1136
|
+
declare const globalPluginManager: PluginManager;
|
|
1137
|
+
|
|
1138
|
+
type Fields = Record<string, FieldConfig>;
|
|
1139
|
+
type Steps = Record<string, Step>;
|
|
1140
|
+
/** Breakpoints de Tailwind */
|
|
1141
|
+
type Breakpoint$1 = 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
1142
|
+
/** Tipo para valores de gap (0-12, donde 0 = sin gap) */
|
|
1143
|
+
type GapValue = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
1144
|
+
/** Tipo para valores de columnas (1-12) */
|
|
1145
|
+
type ColumnsValue = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
1146
|
+
interface FormLayout {
|
|
1147
|
+
/** Modo de layout: "auto" (adaptativo) o "manual" (fijo) */
|
|
1148
|
+
mode: 'auto' | 'manual';
|
|
1149
|
+
/** Tamaño de gap entre campos (0-12, default: 4, donde 0 = sin gap) */
|
|
1150
|
+
gap?: GapValue;
|
|
1151
|
+
/** Ancho mínimo de campo en píxeles (solo para modo "auto", default: 240) */
|
|
1152
|
+
minFieldWidth?: number;
|
|
1153
|
+
/** Número de columnas (1-12, default: 1)
|
|
1154
|
+
* - En modo "auto": máximo de columnas (opcional)
|
|
1155
|
+
* - En modo "manual": columnas fijas (opcional, default: 1)
|
|
1156
|
+
*/
|
|
1157
|
+
columns?: ColumnsValue;
|
|
1158
|
+
/** Clases CSS adicionales para el contenedor del grid */
|
|
1159
|
+
className?: string;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Configuración para el sistema de confirmación de envío con campos opcionales.
|
|
1163
|
+
* Permite advertir al usuario antes de enviar si hay campos opcionales vacíos.
|
|
1164
|
+
*/
|
|
1165
|
+
interface SubmitConfirmationConfig {
|
|
1166
|
+
/**
|
|
1167
|
+
* Campos opcionales que generan advertencia si están vacíos.
|
|
1168
|
+
* El sistema verifica estos campos antes de submit/navegación.
|
|
1169
|
+
*/
|
|
1170
|
+
optionalFields: Array<{
|
|
1171
|
+
/** Nombre del campo a verificar */
|
|
1172
|
+
name: string;
|
|
1173
|
+
/** Mensaje descriptivo de por qué es importante este campo */
|
|
1174
|
+
message: string;
|
|
1175
|
+
}>;
|
|
1176
|
+
/**
|
|
1177
|
+
* Comportamiento visual del botón durante la advertencia
|
|
1178
|
+
*/
|
|
1179
|
+
buttonBehavior: {
|
|
1180
|
+
/** Texto original del botón (opcional, se usa el del ButtonConfig si no se especifica) */
|
|
1181
|
+
defaultText?: string;
|
|
1182
|
+
/** Texto a mostrar cuando hay campos vacíos (primera vez que se hace click) */
|
|
1183
|
+
warningText: string;
|
|
1184
|
+
/** Variant del botón durante advertencia (opcional) */
|
|
1185
|
+
warningVariant?: ButtonConfig['variant'];
|
|
1186
|
+
/** Effect del botón durante advertencia (opcional) */
|
|
1187
|
+
warningEffect?: ButtonConfig['effect'];
|
|
1188
|
+
/** Tiempo en ms antes de volver al estado normal (default: 3000) */
|
|
1189
|
+
resetDelay?: number;
|
|
1190
|
+
};
|
|
1191
|
+
/**
|
|
1192
|
+
* Dónde aplicar la confirmación:
|
|
1193
|
+
* - "submit": Solo en el botón de envío final
|
|
1194
|
+
* - "steps": Solo en navegación entre steps (botón Next)
|
|
1195
|
+
* - "both": En ambos casos
|
|
1196
|
+
*/
|
|
1197
|
+
applyOn: 'submit' | 'steps' | 'both';
|
|
1198
|
+
/**
|
|
1199
|
+
* Si true, la advertencia solo se muestra una vez por sesión.
|
|
1200
|
+
* Después de confirmar una vez, no vuelve a aparecer.
|
|
1201
|
+
* @default true
|
|
1202
|
+
*/
|
|
1203
|
+
showOnce?: boolean;
|
|
1204
|
+
}
|
|
1205
|
+
interface FormConfig {
|
|
1206
|
+
formId: string;
|
|
1207
|
+
fields: Fields;
|
|
1208
|
+
steps: Steps;
|
|
1209
|
+
initialStep?: string;
|
|
1210
|
+
layout?: FormLayout;
|
|
1211
|
+
/** @deprecated Use submitActions for modular submit configuration */
|
|
1212
|
+
submit?: SubmitConfig;
|
|
1213
|
+
buttons?: FormButtons;
|
|
1214
|
+
submitConfirmation?: SubmitConfirmationConfig;
|
|
1215
|
+
pluginManager?: PluginManager;
|
|
1216
|
+
successMessage?: string | ((values: Record<string, unknown>) => string);
|
|
1217
|
+
errorMessage?: string | ((error: Error, values: Record<string, unknown>) => string);
|
|
1218
|
+
onStepChange?: (step: string) => void;
|
|
1219
|
+
onSuccess?: (values: Record<string, unknown>) => void;
|
|
1220
|
+
onError?: (error: Error, values: Record<string, unknown>) => void;
|
|
1221
|
+
/**
|
|
1222
|
+
* Redirect after successful submission.
|
|
1223
|
+
*
|
|
1224
|
+
* - `string` — static URL (e.g. "/thanks")
|
|
1225
|
+
* - `(values) => string` — dynamic URL based on submitted values
|
|
1226
|
+
*
|
|
1227
|
+
* The redirect executes after onSuccess and plugin hooks.
|
|
1228
|
+
* If set, the success message UI is never shown.
|
|
1229
|
+
*/
|
|
1230
|
+
redirect?: string | ((values: Record<string, unknown>) => string);
|
|
1231
|
+
/**
|
|
1232
|
+
* Acciones de submit modulares.
|
|
1233
|
+
* Permite configurar múltiples endpoints, webhooks, emails, etc.
|
|
1234
|
+
* Cada acción tiene su propio trigger (cuándo se ejecuta).
|
|
1235
|
+
*/
|
|
1236
|
+
submitActions?: Record<string, SubmitActionNode>;
|
|
1237
|
+
/**
|
|
1238
|
+
* Configuración de ejecución para submitActions.
|
|
1239
|
+
* Define si las acciones se ejecutan en paralelo o secuencial.
|
|
1240
|
+
*/
|
|
1241
|
+
submitExecution?: SubmitExecutionConfig;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/**
|
|
1245
|
+
* ============================================
|
|
1246
|
+
* COMPONENT REGISTRY - Dependency Injection System
|
|
1247
|
+
* ============================================
|
|
1248
|
+
*
|
|
1249
|
+
* Este sistema permite que el plugin sea agnóstico de la librería UI.
|
|
1250
|
+
* Los usuarios inyectan sus propios componentes (shadcn, Chakra, Material UI, etc.)
|
|
1251
|
+
*/
|
|
1252
|
+
interface InputProps extends React__default.InputHTMLAttributes<HTMLInputElement> {
|
|
1253
|
+
className?: string;
|
|
1254
|
+
}
|
|
1255
|
+
interface TextareaProps extends React__default.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
1256
|
+
className?: string;
|
|
1257
|
+
}
|
|
1258
|
+
interface ButtonProps extends React__default.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
1259
|
+
className?: string;
|
|
1260
|
+
variant?: string;
|
|
1261
|
+
size?: string;
|
|
1262
|
+
}
|
|
1263
|
+
interface LabelProps extends React__default.LabelHTMLAttributes<HTMLLabelElement> {
|
|
1264
|
+
className?: string;
|
|
1265
|
+
}
|
|
1266
|
+
interface CheckboxProps {
|
|
1267
|
+
id?: string;
|
|
1268
|
+
checked?: boolean;
|
|
1269
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
1270
|
+
disabled?: boolean;
|
|
1271
|
+
className?: string;
|
|
1272
|
+
}
|
|
1273
|
+
interface SwitchProps {
|
|
1274
|
+
id?: string;
|
|
1275
|
+
checked?: boolean;
|
|
1276
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
1277
|
+
disabled?: boolean;
|
|
1278
|
+
className?: string;
|
|
1279
|
+
}
|
|
1280
|
+
interface RadioGroupProps {
|
|
1281
|
+
value?: string;
|
|
1282
|
+
onValueChange?: (value: string) => void;
|
|
1283
|
+
disabled?: boolean;
|
|
1284
|
+
className?: string;
|
|
1285
|
+
children?: React__default.ReactNode;
|
|
1286
|
+
}
|
|
1287
|
+
interface RadioGroupItemProps {
|
|
1288
|
+
id?: string;
|
|
1289
|
+
value: string;
|
|
1290
|
+
disabled?: boolean;
|
|
1291
|
+
className?: string;
|
|
1292
|
+
}
|
|
1293
|
+
interface SelectProps {
|
|
1294
|
+
value?: string;
|
|
1295
|
+
onValueChange?: (value: string) => void;
|
|
1296
|
+
disabled?: boolean;
|
|
1297
|
+
children?: React__default.ReactNode;
|
|
1298
|
+
}
|
|
1299
|
+
interface SelectTriggerProps {
|
|
1300
|
+
className?: string;
|
|
1301
|
+
children?: React__default.ReactNode;
|
|
1302
|
+
}
|
|
1303
|
+
interface SelectContentProps {
|
|
1304
|
+
className?: string;
|
|
1305
|
+
children?: React__default.ReactNode;
|
|
1306
|
+
}
|
|
1307
|
+
interface SelectItemProps {
|
|
1308
|
+
value: string;
|
|
1309
|
+
className?: string;
|
|
1310
|
+
children?: React__default.ReactNode;
|
|
1311
|
+
}
|
|
1312
|
+
interface SelectValueProps {
|
|
1313
|
+
placeholder?: string;
|
|
1314
|
+
}
|
|
1315
|
+
interface NativeSelectProps extends React__default.SelectHTMLAttributes<HTMLSelectElement> {
|
|
1316
|
+
className?: string;
|
|
1317
|
+
}
|
|
1318
|
+
interface SliderProps {
|
|
1319
|
+
value?: number[];
|
|
1320
|
+
defaultValue?: number[];
|
|
1321
|
+
onValueChange?: (value: number[]) => void;
|
|
1322
|
+
min?: number;
|
|
1323
|
+
max?: number;
|
|
1324
|
+
step?: number;
|
|
1325
|
+
disabled?: boolean;
|
|
1326
|
+
orientation?: 'horizontal' | 'vertical';
|
|
1327
|
+
className?: string;
|
|
1328
|
+
}
|
|
1329
|
+
interface PopoverProps {
|
|
1330
|
+
open?: boolean;
|
|
1331
|
+
onOpenChange?: (open: boolean) => void;
|
|
1332
|
+
children?: React__default.ReactNode;
|
|
1333
|
+
}
|
|
1334
|
+
interface PopoverTriggerProps {
|
|
1335
|
+
asChild?: boolean;
|
|
1336
|
+
children?: React__default.ReactNode;
|
|
1337
|
+
}
|
|
1338
|
+
interface PopoverContentProps {
|
|
1339
|
+
className?: string;
|
|
1340
|
+
align?: 'start' | 'center' | 'end';
|
|
1341
|
+
children?: React__default.ReactNode;
|
|
1342
|
+
}
|
|
1343
|
+
interface TooltipProps {
|
|
1344
|
+
children?: React__default.ReactNode;
|
|
1345
|
+
}
|
|
1346
|
+
interface TooltipTriggerProps {
|
|
1347
|
+
asChild?: boolean;
|
|
1348
|
+
children?: React__default.ReactNode;
|
|
1349
|
+
}
|
|
1350
|
+
interface TooltipContentProps {
|
|
1351
|
+
className?: string;
|
|
1352
|
+
children?: React__default.ReactNode;
|
|
1353
|
+
}
|
|
1354
|
+
interface TooltipProviderProps {
|
|
1355
|
+
children?: React__default.ReactNode;
|
|
1356
|
+
}
|
|
1357
|
+
interface SeparatorProps {
|
|
1358
|
+
className?: string;
|
|
1359
|
+
orientation?: 'horizontal' | 'vertical';
|
|
1360
|
+
}
|
|
1361
|
+
interface DialogProps {
|
|
1362
|
+
open?: boolean;
|
|
1363
|
+
onOpenChange?: (open: boolean) => void;
|
|
1364
|
+
children?: React__default.ReactNode;
|
|
1365
|
+
}
|
|
1366
|
+
interface DialogTriggerProps {
|
|
1367
|
+
asChild?: boolean;
|
|
1368
|
+
children?: React__default.ReactNode;
|
|
1369
|
+
}
|
|
1370
|
+
interface DialogContentProps {
|
|
1371
|
+
className?: string;
|
|
1372
|
+
children?: React__default.ReactNode;
|
|
1373
|
+
}
|
|
1374
|
+
interface DialogHeaderProps {
|
|
1375
|
+
className?: string;
|
|
1376
|
+
children?: React__default.ReactNode;
|
|
1377
|
+
}
|
|
1378
|
+
interface DialogTitleProps {
|
|
1379
|
+
className?: string;
|
|
1380
|
+
children?: React__default.ReactNode;
|
|
1381
|
+
}
|
|
1382
|
+
interface DialogDescriptionProps {
|
|
1383
|
+
className?: string;
|
|
1384
|
+
children?: React__default.ReactNode;
|
|
1385
|
+
}
|
|
1386
|
+
interface CommandProps {
|
|
1387
|
+
className?: string;
|
|
1388
|
+
children?: React__default.ReactNode;
|
|
1389
|
+
}
|
|
1390
|
+
interface CommandInputProps {
|
|
1391
|
+
placeholder?: string;
|
|
1392
|
+
className?: string;
|
|
1393
|
+
}
|
|
1394
|
+
interface CommandListProps {
|
|
1395
|
+
className?: string;
|
|
1396
|
+
children?: React__default.ReactNode;
|
|
1397
|
+
}
|
|
1398
|
+
interface CommandEmptyProps {
|
|
1399
|
+
className?: string;
|
|
1400
|
+
children?: React__default.ReactNode;
|
|
1401
|
+
}
|
|
1402
|
+
interface CommandGroupProps {
|
|
1403
|
+
className?: string;
|
|
1404
|
+
children?: React__default.ReactNode;
|
|
1405
|
+
}
|
|
1406
|
+
interface CommandItemProps {
|
|
1407
|
+
value: string;
|
|
1408
|
+
onSelect?: (value: string) => void;
|
|
1409
|
+
className?: string;
|
|
1410
|
+
children?: React__default.ReactNode;
|
|
1411
|
+
}
|
|
1412
|
+
interface InputOTPProps {
|
|
1413
|
+
value?: string;
|
|
1414
|
+
onChange?: (value: string) => void;
|
|
1415
|
+
maxLength?: number;
|
|
1416
|
+
disabled?: boolean;
|
|
1417
|
+
className?: string;
|
|
1418
|
+
containerClassName?: string;
|
|
1419
|
+
children?: React__default.ReactNode;
|
|
1420
|
+
}
|
|
1421
|
+
interface InputOTPGroupProps {
|
|
1422
|
+
className?: string;
|
|
1423
|
+
children?: React__default.ReactNode;
|
|
1424
|
+
}
|
|
1425
|
+
interface InputOTPSlotProps {
|
|
1426
|
+
index: number;
|
|
1427
|
+
className?: string;
|
|
1428
|
+
}
|
|
1429
|
+
interface AccordionProps {
|
|
1430
|
+
type?: 'single' | 'multiple';
|
|
1431
|
+
collapsible?: boolean;
|
|
1432
|
+
value?: string;
|
|
1433
|
+
onValueChange?: (value: string) => void;
|
|
1434
|
+
className?: string;
|
|
1435
|
+
children?: React__default.ReactNode;
|
|
1436
|
+
}
|
|
1437
|
+
interface AccordionItemProps {
|
|
1438
|
+
value: string;
|
|
1439
|
+
className?: string;
|
|
1440
|
+
children?: React__default.ReactNode;
|
|
1441
|
+
}
|
|
1442
|
+
interface AccordionTriggerProps {
|
|
1443
|
+
className?: string;
|
|
1444
|
+
children?: React__default.ReactNode;
|
|
1445
|
+
}
|
|
1446
|
+
interface AccordionContentProps {
|
|
1447
|
+
className?: string;
|
|
1448
|
+
children?: React__default.ReactNode;
|
|
1449
|
+
}
|
|
1450
|
+
interface CalendarProps {
|
|
1451
|
+
mode?: 'single' | 'range' | 'multiple';
|
|
1452
|
+
selected?: unknown;
|
|
1453
|
+
onSelect?: unknown;
|
|
1454
|
+
className?: string;
|
|
1455
|
+
disabled?: unknown;
|
|
1456
|
+
captionLayout?: string;
|
|
1457
|
+
buttonVariant?: string;
|
|
1458
|
+
numberOfMonths?: number;
|
|
1459
|
+
children?: React__default.ReactNode;
|
|
1460
|
+
}
|
|
1461
|
+
interface FormFieldProps {
|
|
1462
|
+
name: string;
|
|
1463
|
+
control?: unknown;
|
|
1464
|
+
render: (props: {
|
|
1465
|
+
field: {
|
|
1466
|
+
value: unknown;
|
|
1467
|
+
onChange: (value: unknown) => void;
|
|
1468
|
+
onBlur: () => void;
|
|
1469
|
+
name: string;
|
|
1470
|
+
ref: React__default.Ref<unknown>;
|
|
1471
|
+
};
|
|
1472
|
+
fieldState: {
|
|
1473
|
+
invalid: boolean;
|
|
1474
|
+
isTouched: boolean;
|
|
1475
|
+
isDirty: boolean;
|
|
1476
|
+
isValidating: boolean;
|
|
1477
|
+
error?: {
|
|
1478
|
+
message?: string;
|
|
1479
|
+
};
|
|
1480
|
+
};
|
|
1481
|
+
}) => React__default.ReactElement;
|
|
1482
|
+
}
|
|
1483
|
+
interface FormControlProps {
|
|
1484
|
+
children?: React__default.ReactNode;
|
|
1485
|
+
}
|
|
1486
|
+
interface FieldProps {
|
|
1487
|
+
className?: string;
|
|
1488
|
+
children?: React__default.ReactNode;
|
|
1489
|
+
orientation?: 'horizontal' | 'vertical';
|
|
1490
|
+
'data-invalid'?: boolean;
|
|
1491
|
+
}
|
|
1492
|
+
interface FieldLabelProps {
|
|
1493
|
+
className?: string;
|
|
1494
|
+
children?: React__default.ReactNode;
|
|
1495
|
+
dangerouslySetInnerHTML?: {
|
|
1496
|
+
__html: string;
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
interface FieldDescriptionProps {
|
|
1500
|
+
className?: string;
|
|
1501
|
+
children?: React__default.ReactNode;
|
|
1502
|
+
}
|
|
1503
|
+
interface FieldErrorProps {
|
|
1504
|
+
className?: string;
|
|
1505
|
+
children?: React__default.ReactNode;
|
|
1506
|
+
errors?: Array<{
|
|
1507
|
+
message?: string;
|
|
1508
|
+
}>;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Registry de todos los componentes UI necesarios para el plugin.
|
|
1512
|
+
* Los usuarios deben proveer una implementación completa de esta interfaz.
|
|
1513
|
+
*/
|
|
1514
|
+
interface ComponentRegistry {
|
|
1515
|
+
Input: React__default.ComponentType<InputProps>;
|
|
1516
|
+
Textarea: React__default.ComponentType<TextareaProps>;
|
|
1517
|
+
Button: React__default.ComponentType<ButtonProps>;
|
|
1518
|
+
Label: React__default.ComponentType<LabelProps>;
|
|
1519
|
+
Checkbox: React__default.ComponentType<CheckboxProps>;
|
|
1520
|
+
Switch: React__default.ComponentType<SwitchProps>;
|
|
1521
|
+
RadioGroup: React__default.ComponentType<RadioGroupProps>;
|
|
1522
|
+
RadioGroupItem: React__default.ComponentType<RadioGroupItemProps>;
|
|
1523
|
+
Select: React__default.ComponentType<SelectProps>;
|
|
1524
|
+
SelectTrigger: React__default.ComponentType<SelectTriggerProps>;
|
|
1525
|
+
SelectContent: React__default.ComponentType<SelectContentProps>;
|
|
1526
|
+
SelectItem: React__default.ComponentType<SelectItemProps>;
|
|
1527
|
+
SelectValue: React__default.ComponentType<SelectValueProps>;
|
|
1528
|
+
NativeSelect: React__default.ComponentType<NativeSelectProps>;
|
|
1529
|
+
Slider: React__default.ComponentType<SliderProps>;
|
|
1530
|
+
Popover: React__default.ComponentType<PopoverProps>;
|
|
1531
|
+
PopoverTrigger: React__default.ComponentType<PopoverTriggerProps>;
|
|
1532
|
+
PopoverContent: React__default.ComponentType<PopoverContentProps>;
|
|
1533
|
+
Tooltip: React__default.ComponentType<TooltipProps>;
|
|
1534
|
+
TooltipTrigger: React__default.ComponentType<TooltipTriggerProps>;
|
|
1535
|
+
TooltipContent: React__default.ComponentType<TooltipContentProps>;
|
|
1536
|
+
TooltipProvider: React__default.ComponentType<TooltipProviderProps>;
|
|
1537
|
+
Separator: React__default.ComponentType<SeparatorProps>;
|
|
1538
|
+
Dialog: React__default.ComponentType<DialogProps>;
|
|
1539
|
+
DialogTrigger: React__default.ComponentType<DialogTriggerProps>;
|
|
1540
|
+
DialogContent: React__default.ComponentType<DialogContentProps>;
|
|
1541
|
+
DialogHeader: React__default.ComponentType<DialogHeaderProps>;
|
|
1542
|
+
DialogTitle: React__default.ComponentType<DialogTitleProps>;
|
|
1543
|
+
DialogDescription: React__default.ComponentType<DialogDescriptionProps>;
|
|
1544
|
+
Command: React__default.ComponentType<CommandProps>;
|
|
1545
|
+
CommandInput: React__default.ComponentType<CommandInputProps>;
|
|
1546
|
+
CommandList: React__default.ComponentType<CommandListProps>;
|
|
1547
|
+
CommandEmpty: React__default.ComponentType<CommandEmptyProps>;
|
|
1548
|
+
CommandGroup: React__default.ComponentType<CommandGroupProps>;
|
|
1549
|
+
CommandItem: React__default.ComponentType<CommandItemProps>;
|
|
1550
|
+
InputOTP: React__default.ComponentType<InputOTPProps>;
|
|
1551
|
+
InputOTPGroup: React__default.ComponentType<InputOTPGroupProps>;
|
|
1552
|
+
InputOTPSlot: React__default.ComponentType<InputOTPSlotProps>;
|
|
1553
|
+
Accordion: React__default.ComponentType<AccordionProps>;
|
|
1554
|
+
AccordionItem: React__default.ComponentType<AccordionItemProps>;
|
|
1555
|
+
AccordionTrigger: React__default.ComponentType<AccordionTriggerProps>;
|
|
1556
|
+
AccordionContent: React__default.ComponentType<AccordionContentProps>;
|
|
1557
|
+
Calendar: React__default.ComponentType<CalendarProps>;
|
|
1558
|
+
FormField: React__default.ComponentType<FormFieldProps>;
|
|
1559
|
+
FormControl: React__default.ComponentType<FormControlProps>;
|
|
1560
|
+
Field: React__default.ComponentType<FieldProps>;
|
|
1561
|
+
FieldLabel: React__default.ComponentType<FieldLabelProps>;
|
|
1562
|
+
FieldDescription: React__default.ComponentType<FieldDescriptionProps>;
|
|
1563
|
+
FieldError: React__default.ComponentType<FieldErrorProps>;
|
|
1564
|
+
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Partial registry para desarrollo incremental.
|
|
1567
|
+
* Permite proveer solo los componentes que se necesitan.
|
|
1568
|
+
*/
|
|
1569
|
+
type PartialComponentRegistry = Partial<ComponentRegistry>;
|
|
1570
|
+
/**
|
|
1571
|
+
* Input type for createComponentRegistry() and Form's components prop.
|
|
1572
|
+
* Uses React.ComponentType<any> for each slot to avoid contravariance issues
|
|
1573
|
+
* when the consumer's components have stricter prop types (e.g. shadcn Button
|
|
1574
|
+
* with specific variant literals vs our generic `variant?: string`).
|
|
1575
|
+
*/
|
|
1576
|
+
type ComponentRegistryInput = {
|
|
1577
|
+
[K in keyof ComponentRegistry]: React__default.ComponentType<any>;
|
|
1578
|
+
};
|
|
1579
|
+
/**
|
|
1580
|
+
* Type for the Form component's `components` prop.
|
|
1581
|
+
* More permissive than PartialComponentRegistry to accept any compatible components.
|
|
1582
|
+
* This avoids TypeScript contravariance errors when users pass their own shadcn
|
|
1583
|
+
* components which may have stricter prop types (e.g., specific size/variant literals).
|
|
1584
|
+
*/
|
|
1585
|
+
type ComponentOverrides = Partial<{
|
|
1586
|
+
[K in keyof ComponentRegistry]: React__default.ComponentType<any>;
|
|
1587
|
+
}>;
|
|
1588
|
+
/**
|
|
1589
|
+
* Helper type para validar que un objeto implementa ComponentRegistry
|
|
1590
|
+
*/
|
|
1591
|
+
type ValidateComponentRegistry<T extends ComponentRegistry> = T;
|
|
1592
|
+
|
|
1593
|
+
interface ComponentProviderProps {
|
|
1594
|
+
/** Registry completo de componentes UI */
|
|
1595
|
+
components: ComponentRegistry;
|
|
1596
|
+
/** Componentes hijos que tendrán acceso al registry */
|
|
1597
|
+
children: React__default.ReactNode;
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Provider que inyecta los componentes UI en el árbol de React.
|
|
1601
|
+
* This is the legacy provider that requires a full ComponentRegistry.
|
|
1602
|
+
*
|
|
1603
|
+
* @example
|
|
1604
|
+
* ```tsx
|
|
1605
|
+
* import { ComponentProvider, createComponentRegistry } from "@saastro/forms";
|
|
1606
|
+
* import * as shadcn from "@/lib/form-components";
|
|
1607
|
+
*
|
|
1608
|
+
* const registry = createComponentRegistry(shadcn);
|
|
1609
|
+
*
|
|
1610
|
+
* function App() {
|
|
1611
|
+
* return (
|
|
1612
|
+
* <ComponentProvider components={registry}>
|
|
1613
|
+
* <MyForm />
|
|
1614
|
+
* </ComponentProvider>
|
|
1615
|
+
* );
|
|
1616
|
+
* }
|
|
1617
|
+
* ```
|
|
1618
|
+
*
|
|
1619
|
+
* @deprecated Consider using the zero-config approach with inline components prop on Form
|
|
1620
|
+
*/
|
|
1621
|
+
declare const ComponentProvider: React__default.FC<ComponentProviderProps>;
|
|
1622
|
+
interface InternalComponentProviderProps {
|
|
1623
|
+
/** Partial registry de componentes UI */
|
|
1624
|
+
components: PartialComponentRegistry;
|
|
1625
|
+
/** Componentes hijos que tendrán acceso al registry */
|
|
1626
|
+
children: React__default.ReactNode;
|
|
1627
|
+
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Internal provider used by Form component for zero-config mode.
|
|
1630
|
+
* Accepts a partial registry - only the components needed for the form.
|
|
1631
|
+
*
|
|
1632
|
+
* @internal
|
|
1633
|
+
*/
|
|
1634
|
+
declare const InternalComponentProvider: React__default.FC<InternalComponentProviderProps>;
|
|
1635
|
+
/**
|
|
1636
|
+
* Hook para acceder al registry de componentes inyectados.
|
|
1637
|
+
*
|
|
1638
|
+
* Supports both legacy (ComponentProvider) and zero-config (InternalComponentContext) modes.
|
|
1639
|
+
* Legacy mode takes precedence for backwards compatibility.
|
|
1640
|
+
*
|
|
1641
|
+
* @throws Error si se usa fuera de cualquier provider
|
|
1642
|
+
*
|
|
1643
|
+
* @example
|
|
1644
|
+
* ```tsx
|
|
1645
|
+
* function MyComponent() {
|
|
1646
|
+
* const { Input, Button } = useComponents();
|
|
1647
|
+
*
|
|
1648
|
+
* return (
|
|
1649
|
+
* <div>
|
|
1650
|
+
* <Input placeholder="Email" />
|
|
1651
|
+
* <Button>Submit</Button>
|
|
1652
|
+
* </div>
|
|
1653
|
+
* );
|
|
1654
|
+
* }
|
|
1655
|
+
* ```
|
|
1656
|
+
*/
|
|
1657
|
+
declare const useComponents: () => ComponentRegistry;
|
|
1658
|
+
/**
|
|
1659
|
+
* Hook to access partial components safely (may have missing components).
|
|
1660
|
+
* Returns null for components that are not provided.
|
|
1661
|
+
*
|
|
1662
|
+
* @example
|
|
1663
|
+
* ```tsx
|
|
1664
|
+
* function MyComponent() {
|
|
1665
|
+
* const components = usePartialComponents();
|
|
1666
|
+
*
|
|
1667
|
+
* if (!components.Input) {
|
|
1668
|
+
* return <MissingComponentFallback missingComponents={['Input']} />;
|
|
1669
|
+
* }
|
|
1670
|
+
*
|
|
1671
|
+
* return <components.Input placeholder="Email" />;
|
|
1672
|
+
* }
|
|
1673
|
+
* ```
|
|
1674
|
+
*/
|
|
1675
|
+
declare const usePartialComponents: () => PartialComponentRegistry;
|
|
1676
|
+
/**
|
|
1677
|
+
* HOC para envolver componentes que necesitan acceso a los componentes UI.
|
|
1678
|
+
*
|
|
1679
|
+
* @example
|
|
1680
|
+
* ```tsx
|
|
1681
|
+
* const MyFormWithComponents = withComponents(MyForm);
|
|
1682
|
+
* ```
|
|
1683
|
+
*/
|
|
1684
|
+
declare function withComponents<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Hook para verificar si estamos dentro de un ComponentProvider.
|
|
1687
|
+
* Útil para componentes que pueden funcionar con o sin provider.
|
|
1688
|
+
*
|
|
1689
|
+
* @returns true si hay un provider activo (legacy or internal), false en caso contrario
|
|
1690
|
+
*/
|
|
1691
|
+
declare const useHasComponentProvider: () => boolean;
|
|
1692
|
+
/**
|
|
1693
|
+
* Hook to check which mode we're operating in
|
|
1694
|
+
*/
|
|
1695
|
+
declare const useComponentMode: () => "legacy" | "zero-config" | "none";
|
|
1696
|
+
/**
|
|
1697
|
+
* Merge multiple component registries with later ones taking precedence
|
|
1698
|
+
*/
|
|
1699
|
+
declare function mergeComponentRegistries(...registries: Array<PartialComponentRegistry | undefined>): PartialComponentRegistry;
|
|
1700
|
+
/**
|
|
1701
|
+
* Type for Vite's import.meta.glob result.
|
|
1702
|
+
* Accepts the actual Vite return type which is Record<string, unknown>.
|
|
1703
|
+
*/
|
|
1704
|
+
type GlobModules = Record<string, unknown>;
|
|
1705
|
+
/**
|
|
1706
|
+
* Parse Vite's import.meta.glob result into a component registry.
|
|
1707
|
+
*
|
|
1708
|
+
* This function extracts all named exports from the glob modules
|
|
1709
|
+
* and creates a flat registry of components.
|
|
1710
|
+
*
|
|
1711
|
+
* @param modules - Result of import.meta.glob('@/components/ui/*.tsx', { eager: true })
|
|
1712
|
+
* @returns Component registry ready to use with Form
|
|
1713
|
+
*
|
|
1714
|
+
* @example
|
|
1715
|
+
* ```tsx
|
|
1716
|
+
* const modules = import.meta.glob('@/components/ui/*.tsx', { eager: true });
|
|
1717
|
+
* const components = parseGlobModules(modules);
|
|
1718
|
+
* // { Button, Input, Label, Select, SelectTrigger, ... }
|
|
1719
|
+
* ```
|
|
1720
|
+
*/
|
|
1721
|
+
declare function parseGlobModules(modules: GlobModules): PartialComponentRegistry;
|
|
1722
|
+
interface FormComponentsProviderProps {
|
|
1723
|
+
/**
|
|
1724
|
+
* Glob modules from import.meta.glob.
|
|
1725
|
+
* Use { eager: true } for synchronous loading.
|
|
1726
|
+
*
|
|
1727
|
+
* @example
|
|
1728
|
+
* ```tsx
|
|
1729
|
+
* <FormComponentsProvider
|
|
1730
|
+
* components={import.meta.glob('@/components/ui/*.tsx', { eager: true })}
|
|
1731
|
+
* >
|
|
1732
|
+
* ```
|
|
1733
|
+
*/
|
|
1734
|
+
components: GlobModules;
|
|
1735
|
+
/** Child components */
|
|
1736
|
+
children: React__default.ReactNode;
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Provider for auto-discovered shadcn components using Vite's import.meta.glob.
|
|
1740
|
+
*
|
|
1741
|
+
* Place this once at your app's root layout. Forms will automatically
|
|
1742
|
+
* use any shadcn components installed in your project.
|
|
1743
|
+
*
|
|
1744
|
+
* @example
|
|
1745
|
+
* ```tsx
|
|
1746
|
+
* // app/layout.tsx or _app.tsx - ONE TIME SETUP
|
|
1747
|
+
* import { FormComponentsProvider } from '@saastro/forms';
|
|
1748
|
+
*
|
|
1749
|
+
* export default function RootLayout({ children }) {
|
|
1750
|
+
* return (
|
|
1751
|
+
* <FormComponentsProvider
|
|
1752
|
+
* components={import.meta.glob('@/components/ui/*.tsx', { eager: true })}
|
|
1753
|
+
* >
|
|
1754
|
+
* {children}
|
|
1755
|
+
* </FormComponentsProvider>
|
|
1756
|
+
* );
|
|
1757
|
+
* }
|
|
1758
|
+
* ```
|
|
1759
|
+
*
|
|
1760
|
+
* Then use Form anywhere without passing components:
|
|
1761
|
+
* ```tsx
|
|
1762
|
+
* <Form config={config} />
|
|
1763
|
+
* ```
|
|
1764
|
+
*
|
|
1765
|
+
* If a component is missing, a helpful message will appear
|
|
1766
|
+
* with installation instructions.
|
|
1767
|
+
*/
|
|
1768
|
+
declare const FormComponentsProvider: React__default.FC<FormComponentsProviderProps>;
|
|
1769
|
+
|
|
1770
|
+
/**
|
|
1771
|
+
* Form Component - Renders a complete form from FormConfig
|
|
1772
|
+
*
|
|
1773
|
+
* This component is the main entry point for rendering forms from configuration.
|
|
1774
|
+
* Supports two modes:
|
|
1775
|
+
* 1. Zero-config: Provide components inline via `components` prop
|
|
1776
|
+
* 2. Legacy: Wrap with ComponentProvider for global component injection
|
|
1777
|
+
*/
|
|
1778
|
+
|
|
1779
|
+
/** Methods exposed via ref on the Form component */
|
|
1780
|
+
interface FormRef {
|
|
1781
|
+
setValue: UseFormReturn['setValue'];
|
|
1782
|
+
reset: UseFormReturn['reset'];
|
|
1783
|
+
getValues: UseFormReturn['getValues'];
|
|
1784
|
+
trigger: UseFormReturn['trigger'];
|
|
1785
|
+
}
|
|
1786
|
+
interface FormProps {
|
|
1787
|
+
/** Form configuration */
|
|
1788
|
+
config: FormConfig;
|
|
1789
|
+
/**
|
|
1790
|
+
* UI components for the form. Accepts either:
|
|
1791
|
+
*
|
|
1792
|
+
* 1. **Glob modules (Recommended)** - Pass Vite's import.meta.glob result directly:
|
|
1793
|
+
* ```tsx
|
|
1794
|
+
* <Form
|
|
1795
|
+
* config={config}
|
|
1796
|
+
* components={import.meta.glob('@/components/ui/*.tsx', { eager: true })}
|
|
1797
|
+
* />
|
|
1798
|
+
* ```
|
|
1799
|
+
*
|
|
1800
|
+
* 2. **Component object** - Pass individual components:
|
|
1801
|
+
* ```tsx
|
|
1802
|
+
* <Form
|
|
1803
|
+
* config={config}
|
|
1804
|
+
* components={{ Input, Button, Label }}
|
|
1805
|
+
* />
|
|
1806
|
+
* ```
|
|
1807
|
+
*
|
|
1808
|
+
* Both approaches support partial registries - only provide what you need.
|
|
1809
|
+
* Missing components will show helpful installation instructions.
|
|
1810
|
+
*/
|
|
1811
|
+
components?: ComponentOverrides | GlobModules;
|
|
1812
|
+
/**
|
|
1813
|
+
* Called when the form is submitted successfully
|
|
1814
|
+
*/
|
|
1815
|
+
onSubmit?: (values: Record<string, unknown>) => void | Promise<void>;
|
|
1816
|
+
/**
|
|
1817
|
+
* Called when form submission fails
|
|
1818
|
+
*/
|
|
1819
|
+
onError?: (error: Error) => void;
|
|
1820
|
+
/**
|
|
1821
|
+
* CSS class for the form element
|
|
1822
|
+
*/
|
|
1823
|
+
className?: string;
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Form component that renders a complete form from configuration.
|
|
1827
|
+
*
|
|
1828
|
+
* Supports multiple modes:
|
|
1829
|
+
*
|
|
1830
|
+
* **1. Auto-discovery with glob (Recommended):**
|
|
1831
|
+
* Pass Vite's import.meta.glob result directly - components are auto-discovered.
|
|
1832
|
+
*
|
|
1833
|
+
* ```tsx
|
|
1834
|
+
* import { Form } from "@saastro/forms";
|
|
1835
|
+
*
|
|
1836
|
+
* <Form
|
|
1837
|
+
* config={config}
|
|
1838
|
+
* components={import.meta.glob('@/components/ui/*.tsx', { eager: true })}
|
|
1839
|
+
* />
|
|
1840
|
+
* ```
|
|
1841
|
+
*
|
|
1842
|
+
* **2. Explicit components:**
|
|
1843
|
+
* Pass specific components you need.
|
|
1844
|
+
*
|
|
1845
|
+
* ```tsx
|
|
1846
|
+
* import { Form } from "@saastro/forms";
|
|
1847
|
+
* import { Input, Button } from "@/components/ui";
|
|
1848
|
+
*
|
|
1849
|
+
* <Form
|
|
1850
|
+
* config={config}
|
|
1851
|
+
* components={{ Input, Button }}
|
|
1852
|
+
* />
|
|
1853
|
+
* ```
|
|
1854
|
+
*
|
|
1855
|
+
* **3. Provider-based (Legacy):**
|
|
1856
|
+
* Wrap with `ComponentProvider` or `FormComponentsProvider`.
|
|
1857
|
+
*
|
|
1858
|
+
* ```tsx
|
|
1859
|
+
* <FormComponentsProvider components={globModules}>
|
|
1860
|
+
* <Form config={config} />
|
|
1861
|
+
* </FormComponentsProvider>
|
|
1862
|
+
* ```
|
|
1863
|
+
*
|
|
1864
|
+
* The `components` prop takes precedence over context-provided components.
|
|
1865
|
+
*/
|
|
1866
|
+
declare const Form: React__default.ForwardRefExoticComponent<FormProps & React__default.RefAttributes<FormRef>>;
|
|
1867
|
+
|
|
1868
|
+
/**
|
|
1869
|
+
* ============================================
|
|
1870
|
+
* FIELD BUILDER - Fluent API for Field Configuration
|
|
1871
|
+
* ============================================
|
|
1872
|
+
*
|
|
1873
|
+
* Builder pattern para crear configuraciones de campo de forma fluida y type-safe.
|
|
1874
|
+
*/
|
|
1875
|
+
declare class FieldBuilder {
|
|
1876
|
+
private name;
|
|
1877
|
+
private config;
|
|
1878
|
+
constructor(name: string);
|
|
1879
|
+
/**
|
|
1880
|
+
* Configura el tipo de campo.
|
|
1881
|
+
*
|
|
1882
|
+
* @param type - Tipo de campo
|
|
1883
|
+
* @returns this para encadenamiento
|
|
1884
|
+
*/
|
|
1885
|
+
type(type: FieldConfig['type']): this;
|
|
1886
|
+
/**
|
|
1887
|
+
* Configura el label del campo.
|
|
1888
|
+
*
|
|
1889
|
+
* @param label - Texto del label
|
|
1890
|
+
* @returns this para encadenamiento
|
|
1891
|
+
*/
|
|
1892
|
+
label(label: string): this;
|
|
1893
|
+
/**
|
|
1894
|
+
* Oculta el label del campo.
|
|
1895
|
+
*
|
|
1896
|
+
* @returns this para encadenamiento
|
|
1897
|
+
*/
|
|
1898
|
+
hideLabel(): this;
|
|
1899
|
+
/**
|
|
1900
|
+
* Configura el esquema de validación Zod.
|
|
1901
|
+
*
|
|
1902
|
+
* @param schema - Esquema Zod
|
|
1903
|
+
* @returns this para encadenamiento
|
|
1904
|
+
*/
|
|
1905
|
+
schema(schema: z.ZodType): this;
|
|
1906
|
+
/**
|
|
1907
|
+
* Adds plugin-registered validator names to apply to this field.
|
|
1908
|
+
*
|
|
1909
|
+
* @param names - Validator names registered via plugin.validators
|
|
1910
|
+
* @returns this para encadenamiento
|
|
1911
|
+
*
|
|
1912
|
+
* @example
|
|
1913
|
+
* ```tsx
|
|
1914
|
+
* field.type('email').customValidators('uniqueEmail', 'corporateOnly')
|
|
1915
|
+
* ```
|
|
1916
|
+
*/
|
|
1917
|
+
customValidators(...names: string[]): this;
|
|
1918
|
+
/**
|
|
1919
|
+
* Configura el placeholder del campo.
|
|
1920
|
+
*
|
|
1921
|
+
* @param placeholder - Texto placeholder
|
|
1922
|
+
* @returns this para encadenamiento
|
|
1923
|
+
*/
|
|
1924
|
+
placeholder(placeholder: string): this;
|
|
1925
|
+
/**
|
|
1926
|
+
* Configura el valor inicial del campo.
|
|
1927
|
+
*
|
|
1928
|
+
* @param value - Valor inicial
|
|
1929
|
+
* @returns this para encadenamiento
|
|
1930
|
+
*/
|
|
1931
|
+
value(value: unknown): this;
|
|
1932
|
+
/**
|
|
1933
|
+
* Configura el texto de ayuda del campo.
|
|
1934
|
+
*
|
|
1935
|
+
* @param helperText - Texto de ayuda
|
|
1936
|
+
* @returns this para encadenamiento
|
|
1937
|
+
*/
|
|
1938
|
+
helperText(helperText: string): this;
|
|
1939
|
+
/**
|
|
1940
|
+
* Configura el tooltip del campo.
|
|
1941
|
+
*
|
|
1942
|
+
* @param tooltip - Texto del tooltip
|
|
1943
|
+
* @returns this para encadenamiento
|
|
1944
|
+
*/
|
|
1945
|
+
tooltip(tooltip: string): this;
|
|
1946
|
+
/**
|
|
1947
|
+
* Configura el icono del campo.
|
|
1948
|
+
*
|
|
1949
|
+
* @param icon - Elemento React del icono
|
|
1950
|
+
* @param iconProps - Props adicionales para el icono
|
|
1951
|
+
* @returns this para encadenamiento
|
|
1952
|
+
*/
|
|
1953
|
+
icon(icon: ReactNode, iconProps?: Record<string, unknown>): this;
|
|
1954
|
+
/**
|
|
1955
|
+
* Configura el tamaño del campo.
|
|
1956
|
+
*
|
|
1957
|
+
* @param size - Tamaño del campo
|
|
1958
|
+
* @returns this para encadenamiento
|
|
1959
|
+
*/
|
|
1960
|
+
size(size: 'sm' | 'md' | 'lg'): this;
|
|
1961
|
+
/**
|
|
1962
|
+
* Configura las opciones del campo (para select, radio, checkbox-group, etc.).
|
|
1963
|
+
*
|
|
1964
|
+
* @param options - Array de opciones
|
|
1965
|
+
* @returns this para encadenamiento
|
|
1966
|
+
*/
|
|
1967
|
+
options(options: Option[]): this;
|
|
1968
|
+
/**
|
|
1969
|
+
* Configura las opciones de button-card.
|
|
1970
|
+
*
|
|
1971
|
+
* @param options - Array de opciones de button-card
|
|
1972
|
+
* @returns this para encadenamiento
|
|
1973
|
+
*/
|
|
1974
|
+
buttonCardOptions(options: ButtonCardOption[]): this;
|
|
1975
|
+
/**
|
|
1976
|
+
* Configura el número de filas (para textarea).
|
|
1977
|
+
*
|
|
1978
|
+
* @param rows - Número de filas
|
|
1979
|
+
* @returns this para encadenamiento
|
|
1980
|
+
*/
|
|
1981
|
+
rows(rows: number): this;
|
|
1982
|
+
/**
|
|
1983
|
+
* Configura el máximo de caracteres (para textarea).
|
|
1984
|
+
*
|
|
1985
|
+
* @param maxLength - Máximo de caracteres
|
|
1986
|
+
* @returns this para encadenamiento
|
|
1987
|
+
*/
|
|
1988
|
+
maxLength(maxLength: number): this;
|
|
1989
|
+
/**
|
|
1990
|
+
* Configura el rango del slider.
|
|
1991
|
+
*
|
|
1992
|
+
* @param min - Valor mínimo
|
|
1993
|
+
* @param max - Valor máximo
|
|
1994
|
+
* @param step - Paso del slider
|
|
1995
|
+
* @returns this para encadenamiento
|
|
1996
|
+
*/
|
|
1997
|
+
range(min: number, max: number, step?: number): this;
|
|
1998
|
+
/**
|
|
1999
|
+
* Configura la variante del slider.
|
|
2000
|
+
*
|
|
2001
|
+
* @param variant - 'default' (single thumb), 'range' (two thumbs), 'multi' (multiple thumbs)
|
|
2002
|
+
* @returns this para encadenamiento
|
|
2003
|
+
*
|
|
2004
|
+
* @example
|
|
2005
|
+
* .sliderVariant('range') // Two thumbs for min/max selection
|
|
2006
|
+
*/
|
|
2007
|
+
sliderVariant(variant: 'default' | 'range' | 'multi'): this;
|
|
2008
|
+
/**
|
|
2009
|
+
* Configura la orientación del slider.
|
|
2010
|
+
*
|
|
2011
|
+
* @param orientation - 'horizontal' o 'vertical'
|
|
2012
|
+
* @returns this para encadenamiento
|
|
2013
|
+
*
|
|
2014
|
+
* @example
|
|
2015
|
+
* .sliderOrientation('vertical')
|
|
2016
|
+
*/
|
|
2017
|
+
sliderOrientation(orientation: 'horizontal' | 'vertical'): this;
|
|
2018
|
+
/**
|
|
2019
|
+
* Configura el número de thumbs para slider 'multi'.
|
|
2020
|
+
*
|
|
2021
|
+
* @param count - Número de thumbs (default: 3)
|
|
2022
|
+
* @returns this para encadenamiento
|
|
2023
|
+
*
|
|
2024
|
+
* @example
|
|
2025
|
+
* .thumbCount(4)
|
|
2026
|
+
*/
|
|
2027
|
+
thumbCount(count: number): this;
|
|
2028
|
+
/**
|
|
2029
|
+
* Muestra u oculta las etiquetas min/max del slider.
|
|
2030
|
+
*
|
|
2031
|
+
* @param show - true para mostrar, false para ocultar
|
|
2032
|
+
* @returns this para encadenamiento
|
|
2033
|
+
*/
|
|
2034
|
+
showLabels(show: boolean): this;
|
|
2035
|
+
/**
|
|
2036
|
+
* Muestra u oculta el valor actual del slider.
|
|
2037
|
+
*
|
|
2038
|
+
* @param show - true para mostrar, false para ocultar
|
|
2039
|
+
* @returns this para encadenamiento
|
|
2040
|
+
*/
|
|
2041
|
+
showValue(show: boolean): this;
|
|
2042
|
+
/**
|
|
2043
|
+
* Formato para mostrar el valor del slider.
|
|
2044
|
+
* Usa {value} como placeholder para el valor numérico.
|
|
2045
|
+
*
|
|
2046
|
+
* @param format - String de formato (e.g., "${value}", "{value}%", "{value}°C")
|
|
2047
|
+
* @returns this para encadenamiento
|
|
2048
|
+
*
|
|
2049
|
+
* @example
|
|
2050
|
+
* .valueFormat('${value}') // Shows "$50"
|
|
2051
|
+
* .valueFormat('{value}%') // Shows "75%"
|
|
2052
|
+
* .valueFormat('{value}°C') // Shows "22°C"
|
|
2053
|
+
*/
|
|
2054
|
+
valueFormat(format: string): this;
|
|
2055
|
+
/**
|
|
2056
|
+
* Configura la condición de visibilidad del campo.
|
|
2057
|
+
*
|
|
2058
|
+
* @param condition - Condición booleana, función, grupo de condiciones, o visibilidad responsive por breakpoint
|
|
2059
|
+
* @returns this para encadenamiento
|
|
2060
|
+
*
|
|
2061
|
+
* @example
|
|
2062
|
+
* // Ocultar siempre
|
|
2063
|
+
* .hidden(true)
|
|
2064
|
+
*
|
|
2065
|
+
* @example
|
|
2066
|
+
* // Ocultar condicionalmente
|
|
2067
|
+
* .hidden((values) => values.premium === false)
|
|
2068
|
+
*
|
|
2069
|
+
* @example
|
|
2070
|
+
* // Ocultar responsive: oculto en mobile, visible en desktop
|
|
2071
|
+
* .hidden({ default: "hidden", md: "visible" })
|
|
2072
|
+
*
|
|
2073
|
+
* @example
|
|
2074
|
+
* // Visible hasta tablet, oculto en desktop
|
|
2075
|
+
* .hidden({ default: "visible", lg: "hidden" })
|
|
2076
|
+
*/
|
|
2077
|
+
hidden(condition: boolean | ((values: Record<string, unknown>) => boolean) | Partial<Record<Breakpoint$1, 'visible' | 'hidden'>> | ConditionGroup): this;
|
|
2078
|
+
/**
|
|
2079
|
+
* Configura la condición de deshabilitación del campo.
|
|
2080
|
+
*
|
|
2081
|
+
* @param condition - Condición booleana, función o grupo de condiciones
|
|
2082
|
+
* @returns this para encadenamiento
|
|
2083
|
+
*/
|
|
2084
|
+
disabled(condition: boolean | ((values: Record<string, unknown>) => boolean) | ConditionGroup): this;
|
|
2085
|
+
/**
|
|
2086
|
+
* Configura la condición de solo lectura del campo.
|
|
2087
|
+
*
|
|
2088
|
+
* @param condition - Condición booleana, función o grupo de condiciones
|
|
2089
|
+
* @returns this para encadenamiento
|
|
2090
|
+
*/
|
|
2091
|
+
readOnly(condition: boolean | ((values: Record<string, unknown>) => boolean) | ConditionGroup): this;
|
|
2092
|
+
/**
|
|
2093
|
+
* Configura el layout del campo.
|
|
2094
|
+
*
|
|
2095
|
+
* @param layout - Configuración de layout
|
|
2096
|
+
* @returns this para encadenamiento
|
|
2097
|
+
*/
|
|
2098
|
+
layout(layout: FieldLayoutConfig): this;
|
|
2099
|
+
/**
|
|
2100
|
+
* Configura las columnas del campo por breakpoint.
|
|
2101
|
+
*
|
|
2102
|
+
* Si no se define, el campo ocupará todas las columnas disponibles del formulario.
|
|
2103
|
+
*
|
|
2104
|
+
* @param columns - Objeto con columnas por breakpoint (1-12)
|
|
2105
|
+
*
|
|
2106
|
+
* @example
|
|
2107
|
+
* // Ocupar todo el ancho en mobile, mitad en desktop
|
|
2108
|
+
* .columns({ default: 12, md: 6 })
|
|
2109
|
+
*
|
|
2110
|
+
* @example
|
|
2111
|
+
* // Ocupar todo el ancho siempre
|
|
2112
|
+
* .columns({ default: 12 })
|
|
2113
|
+
*
|
|
2114
|
+
* @example
|
|
2115
|
+
* // Ocupar 1/3 en mobile, 1/2 en tablet, 1/4 en desktop
|
|
2116
|
+
* .columns({ default: 12, sm: 6, md: 4, lg: 3 })
|
|
2117
|
+
*
|
|
2118
|
+
* @returns this para encadenamiento
|
|
2119
|
+
*/
|
|
2120
|
+
columns(columns: Partial<Record<Breakpoint$1, number>>): this;
|
|
2121
|
+
/**
|
|
2122
|
+
* Configura el orden del campo.
|
|
2123
|
+
*
|
|
2124
|
+
* @param order - Orden de visualización (número fijo o responsive por breakpoint)
|
|
2125
|
+
* @returns this para encadenamiento
|
|
2126
|
+
*
|
|
2127
|
+
* @example
|
|
2128
|
+
* // Orden fijo
|
|
2129
|
+
* .order(1)
|
|
2130
|
+
*
|
|
2131
|
+
* @example
|
|
2132
|
+
* // Orden responsive: primero en mobile, tercero en desktop
|
|
2133
|
+
* .order({ default: 1, md: 3 })
|
|
2134
|
+
*
|
|
2135
|
+
* @example
|
|
2136
|
+
* // Reordenar según tamaño: último en mobile, primero en desktop
|
|
2137
|
+
* .order({ default: 5, lg: 1 })
|
|
2138
|
+
*/
|
|
2139
|
+
order(order: number | Partial<Record<Breakpoint$1, number>>): this;
|
|
2140
|
+
/**
|
|
2141
|
+
* Configura clases CSS personalizadas.
|
|
2142
|
+
*
|
|
2143
|
+
* @param wrapper - Clases para el wrapper
|
|
2144
|
+
* @param input - Clases para el input
|
|
2145
|
+
* @param label - Clases para el label
|
|
2146
|
+
* @param error - Clases para el mensaje de error
|
|
2147
|
+
* @param helper - Clases para el mensaje de ayuda
|
|
2148
|
+
* @returns this para encadenamiento
|
|
2149
|
+
*/
|
|
2150
|
+
classNames(options: {
|
|
2151
|
+
wrapper?: string;
|
|
2152
|
+
input?: string;
|
|
2153
|
+
label?: string;
|
|
2154
|
+
error?: string;
|
|
2155
|
+
helper?: string;
|
|
2156
|
+
}): this;
|
|
2157
|
+
/**
|
|
2158
|
+
* Sets value transform(s) applied before submission.
|
|
2159
|
+
* Accepts a single built-in transform name, multiple names (chained left-to-right),
|
|
2160
|
+
* or a custom function.
|
|
2161
|
+
*
|
|
2162
|
+
* @example
|
|
2163
|
+
* .transform('trim')
|
|
2164
|
+
* .transform('trim', 'lowercase')
|
|
2165
|
+
* .transform((v) => String(v).replace(/\s+/g, '-'))
|
|
2166
|
+
*/
|
|
2167
|
+
transform(...transforms: (BuiltinTransform | FieldTransformFn)[]): this;
|
|
2168
|
+
/**
|
|
2169
|
+
* Sets the slider minimum value (individual setter; see also `.range()`).
|
|
2170
|
+
*/
|
|
2171
|
+
min(value: number): this;
|
|
2172
|
+
/**
|
|
2173
|
+
* Sets the slider maximum value (individual setter; see also `.range()`).
|
|
2174
|
+
*/
|
|
2175
|
+
max(value: number): this;
|
|
2176
|
+
/**
|
|
2177
|
+
* Sets the slider step size (individual setter; see also `.range()`).
|
|
2178
|
+
*/
|
|
2179
|
+
step(value: number): this;
|
|
2180
|
+
/**
|
|
2181
|
+
* Sets the date picker style.
|
|
2182
|
+
*
|
|
2183
|
+
* @param style - 'simple' (inline calendar) or 'popover' (dropdown calendar)
|
|
2184
|
+
*/
|
|
2185
|
+
dateType(style: 'simple' | 'popover'): this;
|
|
2186
|
+
/**
|
|
2187
|
+
* Enables or disables the time picker on date fields.
|
|
2188
|
+
*/
|
|
2189
|
+
showTime(show: boolean): this;
|
|
2190
|
+
/**
|
|
2191
|
+
* Sets quick-select date presets.
|
|
2192
|
+
*
|
|
2193
|
+
* @param presets - Array of { label, value } where value is days from today
|
|
2194
|
+
*/
|
|
2195
|
+
datePresets(presets: Array<{
|
|
2196
|
+
label: string;
|
|
2197
|
+
value: number;
|
|
2198
|
+
}>): this;
|
|
2199
|
+
/**
|
|
2200
|
+
* Sets the input-group prefix text.
|
|
2201
|
+
*/
|
|
2202
|
+
prefix(text: string): this;
|
|
2203
|
+
/**
|
|
2204
|
+
* Sets the input-group suffix text.
|
|
2205
|
+
*/
|
|
2206
|
+
suffix(text: string): this;
|
|
2207
|
+
/**
|
|
2208
|
+
* Sets the combobox/command search placeholder.
|
|
2209
|
+
*/
|
|
2210
|
+
searchPlaceholder(text: string): this;
|
|
2211
|
+
/**
|
|
2212
|
+
* Sets the combobox/command empty state text.
|
|
2213
|
+
*/
|
|
2214
|
+
emptyText(text: string): this;
|
|
2215
|
+
/**
|
|
2216
|
+
* Enables or disables multi-select on button-card fields.
|
|
2217
|
+
*/
|
|
2218
|
+
multiple(allow: boolean): this;
|
|
2219
|
+
/**
|
|
2220
|
+
* Sets the OTP digit count.
|
|
2221
|
+
*
|
|
2222
|
+
* @param length - Number of digits (default: 6)
|
|
2223
|
+
*/
|
|
2224
|
+
otpLength(length: number): this;
|
|
2225
|
+
/**
|
|
2226
|
+
* Sets the field default value.
|
|
2227
|
+
*/
|
|
2228
|
+
defaultValue(value: unknown): this;
|
|
2229
|
+
/**
|
|
2230
|
+
* Sets the field description (metadata, shown as additional text or tooltip).
|
|
2231
|
+
*/
|
|
2232
|
+
description(text: string): this;
|
|
2233
|
+
/**
|
|
2234
|
+
* Sets the HTML autocomplete attribute.
|
|
2235
|
+
*/
|
|
2236
|
+
autocomplete(attr: string): this;
|
|
2237
|
+
/**
|
|
2238
|
+
* Sets CSS classes for the options grid layout (checkbox-group, button-radio, etc.).
|
|
2239
|
+
*/
|
|
2240
|
+
optionsClassName(cls: string): this;
|
|
2241
|
+
/**
|
|
2242
|
+
* Sets the resolver for a hidden field.
|
|
2243
|
+
* Resolvers compute dynamic values (IP, URL params, timestamps, etc.) at form init.
|
|
2244
|
+
*
|
|
2245
|
+
* @param config - Serializable resolver configuration
|
|
2246
|
+
* @returns this for chaining
|
|
2247
|
+
*
|
|
2248
|
+
* @example
|
|
2249
|
+
* field.type('hidden').resolver({ $resolver: 'timestamp' })
|
|
2250
|
+
* field.type('hidden').resolver({ $resolver: 'urlParam', param: 'utm_source', fallback: 'direct' })
|
|
2251
|
+
* field.type('hidden').resolver({ $resolver: 'ip' })
|
|
2252
|
+
*/
|
|
2253
|
+
resolver(config: SerializableFieldResolver): this;
|
|
2254
|
+
/**
|
|
2255
|
+
* Sets accepted file types for a file field.
|
|
2256
|
+
*
|
|
2257
|
+
* @param types - MIME types or extensions (e.g. "image/*", ".pdf,.doc")
|
|
2258
|
+
* @returns this for chaining
|
|
2259
|
+
*
|
|
2260
|
+
* @example
|
|
2261
|
+
* field.type('file').accept('image/*')
|
|
2262
|
+
* field.type('file').accept('.pdf,.docx')
|
|
2263
|
+
*/
|
|
2264
|
+
accept(types: string): this;
|
|
2265
|
+
/**
|
|
2266
|
+
* Sets maximum file size in bytes for a file field.
|
|
2267
|
+
*
|
|
2268
|
+
* @param bytes - Max size in bytes
|
|
2269
|
+
* @returns this for chaining
|
|
2270
|
+
*
|
|
2271
|
+
* @example
|
|
2272
|
+
* field.type('file').maxSize(5 * 1024 * 1024) // 5MB
|
|
2273
|
+
*/
|
|
2274
|
+
maxSize(bytes: number): this;
|
|
2275
|
+
/**
|
|
2276
|
+
* Sets the sub-field definitions for a repeater field.
|
|
2277
|
+
* @example
|
|
2278
|
+
* field.type('repeater').itemFields({ name: { type: 'text', label: 'Name' } })
|
|
2279
|
+
*/
|
|
2280
|
+
itemFields(fields: Record<string, unknown>): this;
|
|
2281
|
+
/** Minimum number of items for a repeater field. */
|
|
2282
|
+
minItems(n: number): this;
|
|
2283
|
+
/** Maximum number of items for a repeater field. */
|
|
2284
|
+
maxItems(n: number): this;
|
|
2285
|
+
/** Label for the repeater "add" button. */
|
|
2286
|
+
addLabel(label: string): this;
|
|
2287
|
+
/** Label for the repeater "remove" button. */
|
|
2288
|
+
removeLabel(label: string): this;
|
|
2289
|
+
/**
|
|
2290
|
+
* Ensures `this.config.schema` is a ValidationRules object (not a Zod schema).
|
|
2291
|
+
* If it's already a Zod schema, it's left untouched and a new ValidationRules is created.
|
|
2292
|
+
*/
|
|
2293
|
+
private ensureValidationRules;
|
|
2294
|
+
/**
|
|
2295
|
+
* Mark the field as required (validation).
|
|
2296
|
+
*/
|
|
2297
|
+
required(message?: string): this;
|
|
2298
|
+
/**
|
|
2299
|
+
* Mark the field as optional (validation).
|
|
2300
|
+
*/
|
|
2301
|
+
optional(): this;
|
|
2302
|
+
/**
|
|
2303
|
+
* Set minimum length validation (string fields).
|
|
2304
|
+
*/
|
|
2305
|
+
minLength(n: number, message?: string): this;
|
|
2306
|
+
/**
|
|
2307
|
+
* Set maximum length validation (string fields).
|
|
2308
|
+
* Note: This sets validation rules, not the HTML maxLength attribute.
|
|
2309
|
+
* For textarea HTML maxLength, use the existing `.maxLength()` method before calling validation methods.
|
|
2310
|
+
*/
|
|
2311
|
+
maxLengthValidation(n: number, message?: string): this;
|
|
2312
|
+
/**
|
|
2313
|
+
* Set email format validation.
|
|
2314
|
+
*/
|
|
2315
|
+
email(message?: string): this;
|
|
2316
|
+
/**
|
|
2317
|
+
* Set URL format validation.
|
|
2318
|
+
*/
|
|
2319
|
+
url(message?: string): this;
|
|
2320
|
+
/**
|
|
2321
|
+
* Set regex pattern validation.
|
|
2322
|
+
*/
|
|
2323
|
+
regex(pattern: string, message?: string): this;
|
|
2324
|
+
/**
|
|
2325
|
+
* Set number range validation.
|
|
2326
|
+
*/
|
|
2327
|
+
numberRange(min?: number, max?: number): this;
|
|
2328
|
+
/**
|
|
2329
|
+
* Set array item count validation.
|
|
2330
|
+
*/
|
|
2331
|
+
itemCount(min?: number, max?: number): this;
|
|
2332
|
+
/**
|
|
2333
|
+
* Require the boolean field to be true (e.g. terms checkbox).
|
|
2334
|
+
*/
|
|
2335
|
+
mustBeTrue(message?: string): this;
|
|
2336
|
+
/**
|
|
2337
|
+
* Apply a named validation preset.
|
|
2338
|
+
*/
|
|
2339
|
+
preset(id: string): this;
|
|
2340
|
+
/**
|
|
2341
|
+
* Construye y valida la configuración final del campo.
|
|
2342
|
+
*
|
|
2343
|
+
* @returns FieldConfig completo y validado
|
|
2344
|
+
* @throws Error si falta información requerida
|
|
2345
|
+
*/
|
|
2346
|
+
build(): FieldConfig;
|
|
2347
|
+
/**
|
|
2348
|
+
* Construye sin validaciones (útil para desarrollo).
|
|
2349
|
+
*
|
|
2350
|
+
* @returns FieldConfig parcial
|
|
2351
|
+
*/
|
|
2352
|
+
buildUnsafe(): Partial<FieldConfig>;
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
interface DatabowlConfig {
|
|
2356
|
+
/** DataBowl API token (Bearer auth) */
|
|
2357
|
+
token: string;
|
|
2358
|
+
/**
|
|
2359
|
+
* API endpoint. Default: `https://www.databowl.com/api/v4/leads`
|
|
2360
|
+
*
|
|
2361
|
+
* Set to a local proxy route (e.g. `/api/send-lead`) for CORS/security.
|
|
2362
|
+
* The proxy should forward the request to DataBowl.
|
|
2363
|
+
*/
|
|
2364
|
+
endpoint?: string;
|
|
2365
|
+
/**
|
|
2366
|
+
* Field mapping — simple rename or advanced with transforms/inject.
|
|
2367
|
+
*
|
|
2368
|
+
* @example
|
|
2369
|
+
* ```ts
|
|
2370
|
+
* // Simple rename
|
|
2371
|
+
* fieldMapping: { nombre: "first_name", telefono: "phone" }
|
|
2372
|
+
*
|
|
2373
|
+
* // Advanced: transform dates, booleans, inject computed fields
|
|
2374
|
+
* fieldMapping: {
|
|
2375
|
+
* fields: {
|
|
2376
|
+
* nombre: "first_name",
|
|
2377
|
+
* fecha_nacimiento: { to: "birth_date", transform: "dateYMD" },
|
|
2378
|
+
* seguro_enfermedad: { to: "has_insurance", transform: "booleanString" },
|
|
2379
|
+
* },
|
|
2380
|
+
* inject: {
|
|
2381
|
+
* campaign_id: "10653",
|
|
2382
|
+
* ip: { $resolver: "custom", fn: () => fetchIpAddress() },
|
|
2383
|
+
* sub_aff_id: { $resolver: "urlParam", param: "sub_aff_id", fallback: "seo_organico" },
|
|
2384
|
+
* timestamp: { $resolver: "timestamp" },
|
|
2385
|
+
* hostname: { $resolver: "hostname" },
|
|
2386
|
+
* },
|
|
2387
|
+
* }
|
|
2388
|
+
* ```
|
|
2389
|
+
*/
|
|
2390
|
+
fieldMapping?: FieldMappingConfig;
|
|
2391
|
+
/** Extra static fields to include in every submission */
|
|
2392
|
+
staticFields?: Record<string, unknown>;
|
|
2393
|
+
/**
|
|
2394
|
+
* Body format. Default: `'url-encoded'` (DataBowl standard).
|
|
2395
|
+
* Set to `'json'` if your proxy expects JSON.
|
|
2396
|
+
*/
|
|
2397
|
+
bodyFormat?: 'json' | 'url-encoded';
|
|
2398
|
+
/** Action ID (default: "databowl") */
|
|
2399
|
+
actionId?: string;
|
|
2400
|
+
/** Continue form submission if DataBowl fails (default: false) */
|
|
2401
|
+
continueOnError?: boolean;
|
|
2402
|
+
}
|
|
2403
|
+
/**
|
|
2404
|
+
* Creates a pre-configured HTTP submit action for DataBowl.
|
|
2405
|
+
*
|
|
2406
|
+
* Use this with `.submitAction()` when you need fine-grained control
|
|
2407
|
+
* or want to combine it with other actions.
|
|
2408
|
+
*
|
|
2409
|
+
* @example
|
|
2410
|
+
* ```tsx
|
|
2411
|
+
* FormBuilder.create("lead")
|
|
2412
|
+
* .addField("nombre", f => f.type("text").label("Nombre"))
|
|
2413
|
+
* .addStep("main", ["nombre"])
|
|
2414
|
+
* .submitAction("databowl", databowlAction({
|
|
2415
|
+
* token: import.meta.env.DATABOWL_TOKEN,
|
|
2416
|
+
* endpoint: "/api/send-lead-databowl", // proxy
|
|
2417
|
+
* }), "onSubmit", {
|
|
2418
|
+
* fieldMapping: { nombre: "first_name" },
|
|
2419
|
+
* })
|
|
2420
|
+
* .build();
|
|
2421
|
+
* ```
|
|
2422
|
+
*/
|
|
2423
|
+
declare function databowlAction(config: Pick<DatabowlConfig, 'token' | 'endpoint' | 'bodyFormat'>): HttpSubmitAction;
|
|
2424
|
+
/**
|
|
2425
|
+
* DataBowl plugin for @saastro/forms.
|
|
2426
|
+
*
|
|
2427
|
+
* Automatically injects a DataBowl submit action into the form config.
|
|
2428
|
+
* Handles field mapping (with transforms + inject), static fields, and error tracking.
|
|
2429
|
+
*
|
|
2430
|
+
* @example
|
|
2431
|
+
* ```tsx
|
|
2432
|
+
* // Basic usage with simple rename
|
|
2433
|
+
* const pm = new PluginManager();
|
|
2434
|
+
* pm.register(databowlPlugin({
|
|
2435
|
+
* token: import.meta.env.DATABOWL_TOKEN,
|
|
2436
|
+
* fieldMapping: {
|
|
2437
|
+
* nombre: "first_name",
|
|
2438
|
+
* email: "email_address",
|
|
2439
|
+
* telefono: "phone",
|
|
2440
|
+
* },
|
|
2441
|
+
* staticFields: {
|
|
2442
|
+
* source: "landing-energy",
|
|
2443
|
+
* },
|
|
2444
|
+
* }));
|
|
2445
|
+
*
|
|
2446
|
+
* // Advanced: proxy + transforms + computed fields
|
|
2447
|
+
* pm.register(databowlPlugin({
|
|
2448
|
+
* token: import.meta.env.DATABOWL_TOKEN,
|
|
2449
|
+
* endpoint: "/api/send-lead-databowl",
|
|
2450
|
+
* bodyFormat: "json", // proxy expects JSON, converts to url-encoded
|
|
2451
|
+
* fieldMapping: {
|
|
2452
|
+
* fields: {
|
|
2453
|
+
* nombre: "first_name",
|
|
2454
|
+
* fecha_nacimiento: { to: "birth_date", transform: "dateYMD" },
|
|
2455
|
+
* seguro_enfermedad: { to: "has_insurance", transform: "booleanString" },
|
|
2456
|
+
* },
|
|
2457
|
+
* inject: {
|
|
2458
|
+
* campaign_id: "10653",
|
|
2459
|
+
* sub_aff_id: { $resolver: "urlParam", param: "sub_aff_id", fallback: "seo_organico" },
|
|
2460
|
+
* timestamp: { $resolver: "timestamp" },
|
|
2461
|
+
* hostname: { $resolver: "hostname" },
|
|
2462
|
+
* },
|
|
2463
|
+
* },
|
|
2464
|
+
* }));
|
|
2465
|
+
*
|
|
2466
|
+
* const form = FormBuilder.create("lead")
|
|
2467
|
+
* .usePlugins(pm)
|
|
2468
|
+
* .addField("nombre", f => f.type("text").label("Nombre"))
|
|
2469
|
+
* .addStep("main", ["nombre"])
|
|
2470
|
+
* .redirect("/gracias")
|
|
2471
|
+
* .build();
|
|
2472
|
+
* ```
|
|
2473
|
+
*/
|
|
2474
|
+
declare const databowlPlugin: (config: DatabowlConfig) => FormPlugin;
|
|
2475
|
+
|
|
2476
|
+
/**
|
|
2477
|
+
* ============================================
|
|
2478
|
+
* FORM BUILDER - Fluent API for Form Configuration
|
|
2479
|
+
* ============================================
|
|
2480
|
+
*
|
|
2481
|
+
* Builder pattern para crear configuraciones de formulario de forma fluida y type-safe.
|
|
2482
|
+
*/
|
|
2483
|
+
declare class FormBuilder {
|
|
2484
|
+
private config;
|
|
2485
|
+
/**
|
|
2486
|
+
* Asegura que el objeto layout existe en la configuración.
|
|
2487
|
+
* @private
|
|
2488
|
+
*/
|
|
2489
|
+
private ensureLayout;
|
|
2490
|
+
/**
|
|
2491
|
+
* Asegura que el PluginManager existe en la configuración.
|
|
2492
|
+
* @private
|
|
2493
|
+
*/
|
|
2494
|
+
private ensurePluginManager;
|
|
2495
|
+
/**
|
|
2496
|
+
* Valida la configuración de botones.
|
|
2497
|
+
* @private
|
|
2498
|
+
*/
|
|
2499
|
+
private validateButtons;
|
|
2500
|
+
/**
|
|
2501
|
+
* Crea una nueva instancia del builder.
|
|
2502
|
+
*
|
|
2503
|
+
* @param formId - ID único del formulario
|
|
2504
|
+
* @returns Nueva instancia de FormBuilder
|
|
2505
|
+
*
|
|
2506
|
+
* @example
|
|
2507
|
+
* ```tsx
|
|
2508
|
+
* const form = FormBuilder.create("registro")
|
|
2509
|
+
* .layout("manual")
|
|
2510
|
+
* .columns(4)
|
|
2511
|
+
* .build();
|
|
2512
|
+
* ```
|
|
2513
|
+
*/
|
|
2514
|
+
static create(formId: string): FormBuilder;
|
|
2515
|
+
/**
|
|
2516
|
+
* Configura el modo de layout del formulario.
|
|
2517
|
+
*
|
|
2518
|
+
* @param mode - "auto" (adaptativo) o "manual" (fijo)
|
|
2519
|
+
* @returns this para encadenamiento
|
|
2520
|
+
*/
|
|
2521
|
+
layout(mode: 'auto' | 'manual'): this;
|
|
2522
|
+
/**
|
|
2523
|
+
* Configura el gap entre campos.
|
|
2524
|
+
*
|
|
2525
|
+
* @param gap - Valor de gap (1-12), cada unidad = 0.25rem
|
|
2526
|
+
* @returns this para encadenamiento
|
|
2527
|
+
*/
|
|
2528
|
+
gap(gap: GapValue): this;
|
|
2529
|
+
/**
|
|
2530
|
+
* Configura el número de columnas del grid.
|
|
2531
|
+
*
|
|
2532
|
+
* - En modo 'manual': crea un grid fijo de N columnas (col-span funciona)
|
|
2533
|
+
* - En modo 'auto': actúa como límite máximo de columnas
|
|
2534
|
+
*
|
|
2535
|
+
* @param columns - Número de columnas (1-12)
|
|
2536
|
+
* @returns this para encadenamiento
|
|
2537
|
+
*/
|
|
2538
|
+
columns(columns: ColumnsValue): this;
|
|
2539
|
+
/**
|
|
2540
|
+
* Configura el ancho mínimo de campo (solo para modo "auto").
|
|
2541
|
+
*
|
|
2542
|
+
* @param minWidth - Ancho mínimo en píxeles
|
|
2543
|
+
* @returns this para encadenamiento
|
|
2544
|
+
*/
|
|
2545
|
+
minFieldWidth(minWidth: number): this;
|
|
2546
|
+
/**
|
|
2547
|
+
* Agrega clases CSS personalizadas al contenedor del formulario.
|
|
2548
|
+
*
|
|
2549
|
+
* @param className - Clases CSS
|
|
2550
|
+
* @returns this para encadenamiento
|
|
2551
|
+
*/
|
|
2552
|
+
layoutClassName(className: string): this;
|
|
2553
|
+
/**
|
|
2554
|
+
* Agrega un campo al formulario usando un builder fluido.
|
|
2555
|
+
*
|
|
2556
|
+
* @param name - Nombre único del campo
|
|
2557
|
+
* @param builder - Función que recibe un FieldBuilder y retorna la configuración
|
|
2558
|
+
* @returns this para encadenamiento
|
|
2559
|
+
*
|
|
2560
|
+
* @example
|
|
2561
|
+
* ```tsx
|
|
2562
|
+
* builder.addField("email", field =>
|
|
2563
|
+
* field
|
|
2564
|
+
* .type("email")
|
|
2565
|
+
* .label("Email")
|
|
2566
|
+
* .schema(z.string().email())
|
|
2567
|
+
* .columns({ default: 12, md: 6 })
|
|
2568
|
+
* )
|
|
2569
|
+
* ```
|
|
2570
|
+
*/
|
|
2571
|
+
addField(name: string, builder: (field: FieldBuilder) => FieldBuilder): this;
|
|
2572
|
+
/**
|
|
2573
|
+
* Agrega múltiples campos al formulario.
|
|
2574
|
+
*
|
|
2575
|
+
* @param fields - Objeto con campos configurados
|
|
2576
|
+
* @returns this para encadenamiento
|
|
2577
|
+
*/
|
|
2578
|
+
addFields(fields: Fields): this;
|
|
2579
|
+
/**
|
|
2580
|
+
* Agrega un step al formulario.
|
|
2581
|
+
*
|
|
2582
|
+
* @param stepId - ID único del step
|
|
2583
|
+
* @param fields - Array de nombres de campos que pertenecen a este step
|
|
2584
|
+
* @param options - Opciones adicionales del step
|
|
2585
|
+
* @returns this para encadenamiento
|
|
2586
|
+
*
|
|
2587
|
+
* @example
|
|
2588
|
+
* ```tsx
|
|
2589
|
+
* builder.addStep("step1", ["email", "password"])
|
|
2590
|
+
* ```
|
|
2591
|
+
*/
|
|
2592
|
+
addStep(stepId: string, fields: string[], options?: {
|
|
2593
|
+
defaultNext?: string;
|
|
2594
|
+
next?: StepCondition[];
|
|
2595
|
+
}): this;
|
|
2596
|
+
/**
|
|
2597
|
+
* Configura el step inicial del formulario.
|
|
2598
|
+
*
|
|
2599
|
+
* @param stepId - ID del step inicial
|
|
2600
|
+
* @returns this para encadenamiento
|
|
2601
|
+
*/
|
|
2602
|
+
initialStep(stepId: string): this;
|
|
2603
|
+
/**
|
|
2604
|
+
* Configura el callback de éxito.
|
|
2605
|
+
*
|
|
2606
|
+
* @param callback - Función que se ejecuta al enviar exitosamente
|
|
2607
|
+
* @returns this para encadenamiento
|
|
2608
|
+
*/
|
|
2609
|
+
onSuccess(callback: (values: Record<string, unknown>) => void): this;
|
|
2610
|
+
/**
|
|
2611
|
+
* Configura el callback de error.
|
|
2612
|
+
*
|
|
2613
|
+
* @param callback - Función que se ejecuta al fallar el envío
|
|
2614
|
+
* @returns this para encadenamiento
|
|
2615
|
+
*/
|
|
2616
|
+
onError(callback: (error: Error, values: Record<string, unknown>) => void): this;
|
|
2617
|
+
/**
|
|
2618
|
+
* Configura el callback de cambio de step.
|
|
2619
|
+
*
|
|
2620
|
+
* @param callback - Función que se ejecuta al cambiar de step
|
|
2621
|
+
* @returns this para encadenamiento
|
|
2622
|
+
*/
|
|
2623
|
+
onStepChange(callback: (stepId: string) => void): this;
|
|
2624
|
+
/**
|
|
2625
|
+
* Configura el mensaje de éxito.
|
|
2626
|
+
*
|
|
2627
|
+
* @param message - Mensaje estático o función que retorna el mensaje
|
|
2628
|
+
* @returns this para encadenamiento
|
|
2629
|
+
*/
|
|
2630
|
+
successMessage(message: string | ((values: Record<string, unknown>) => string)): this;
|
|
2631
|
+
/**
|
|
2632
|
+
* Configura el mensaje de error.
|
|
2633
|
+
*
|
|
2634
|
+
* @param message - Mensaje estático o función que retorna el mensaje
|
|
2635
|
+
* @returns this para encadenamiento
|
|
2636
|
+
*/
|
|
2637
|
+
errorMessage(message: string | ((error: Error, values: Record<string, unknown>) => string)): this;
|
|
2638
|
+
/**
|
|
2639
|
+
* Configura los botones del formulario.
|
|
2640
|
+
*
|
|
2641
|
+
* @param buttons - Configuración de botones
|
|
2642
|
+
* @returns this para encadenamiento
|
|
2643
|
+
*/
|
|
2644
|
+
buttons(buttons: FormButtons): this;
|
|
2645
|
+
/**
|
|
2646
|
+
* Configura el envío del formulario.
|
|
2647
|
+
*
|
|
2648
|
+
* @param submit - Configuración de envío
|
|
2649
|
+
* @returns this para encadenamiento
|
|
2650
|
+
*/
|
|
2651
|
+
submit(submit: SubmitConfig): this;
|
|
2652
|
+
/**
|
|
2653
|
+
* Redirect after successful submission.
|
|
2654
|
+
*
|
|
2655
|
+
* @param url - Static URL string or function that receives values and returns URL
|
|
2656
|
+
* @returns this para encadenamiento
|
|
2657
|
+
*
|
|
2658
|
+
* @example
|
|
2659
|
+
* ```tsx
|
|
2660
|
+
* FormBuilder.create("lead")
|
|
2661
|
+
* .redirect("/thanks")
|
|
2662
|
+
* // or dynamic:
|
|
2663
|
+
* .redirect((values) => `/thanks?email=${values.email}`)
|
|
2664
|
+
* ```
|
|
2665
|
+
*/
|
|
2666
|
+
redirect(url: string | ((values: Record<string, unknown>) => string)): this;
|
|
2667
|
+
/**
|
|
2668
|
+
* Configura el gestor de plugins del formulario.
|
|
2669
|
+
*
|
|
2670
|
+
* @param pluginManager - Instancia de PluginManager con plugins registrados
|
|
2671
|
+
* @returns this para encadenamiento
|
|
2672
|
+
*
|
|
2673
|
+
* @example
|
|
2674
|
+
* ```tsx
|
|
2675
|
+
* import { FormBuilder, PluginManager, analyticsPlugin } from "@saastro/forms";
|
|
2676
|
+
*
|
|
2677
|
+
* const pluginManager = new PluginManager();
|
|
2678
|
+
* pluginManager.register(analyticsPlugin());
|
|
2679
|
+
*
|
|
2680
|
+
* const form = FormBuilder.create("my-form")
|
|
2681
|
+
* .usePlugins(pluginManager)
|
|
2682
|
+
* .addField("name", f => f.type("text").label("Name"))
|
|
2683
|
+
* .build();
|
|
2684
|
+
* ```
|
|
2685
|
+
*/
|
|
2686
|
+
usePlugins(pluginManager: PluginManager): this;
|
|
2687
|
+
/**
|
|
2688
|
+
* Enable DataBowl lead integration.
|
|
2689
|
+
*
|
|
2690
|
+
* Automatically registers the DataBowl plugin, which injects an HTTP submit
|
|
2691
|
+
* action via `transformConfig` and merges `staticFields` via `transformValues`.
|
|
2692
|
+
* Compatible with other plugins — can be combined with `.usePlugins()`.
|
|
2693
|
+
*
|
|
2694
|
+
* @param config - DataBowl configuration
|
|
2695
|
+
* @returns this for chaining
|
|
2696
|
+
*
|
|
2697
|
+
* @example
|
|
2698
|
+
* ```tsx
|
|
2699
|
+
* FormBuilder.create("lead-energy")
|
|
2700
|
+
* .addField("nombre", f => f.type("text").label("Nombre"))
|
|
2701
|
+
* .addField("email", f => f.type("email").label("Email"))
|
|
2702
|
+
* .addField("telefono", f => f.type("tel").label("Teléfono"))
|
|
2703
|
+
* .addStep("main", ["nombre", "email", "telefono"])
|
|
2704
|
+
*
|
|
2705
|
+
* .useDatabowl({
|
|
2706
|
+
* token: import.meta.env.DATABOWL_TOKEN,
|
|
2707
|
+
* fieldMapping: {
|
|
2708
|
+
* nombre: "first_name",
|
|
2709
|
+
* email: "email_address",
|
|
2710
|
+
* telefono: "phone",
|
|
2711
|
+
* },
|
|
2712
|
+
* staticFields: {
|
|
2713
|
+
* source: "landing-energy",
|
|
2714
|
+
* campaign: "google-ads",
|
|
2715
|
+
* },
|
|
2716
|
+
* })
|
|
2717
|
+
*
|
|
2718
|
+
* .redirect("/gracias")
|
|
2719
|
+
* .build();
|
|
2720
|
+
* ```
|
|
2721
|
+
*/
|
|
2722
|
+
useDatabowl(config: DatabowlConfig): this;
|
|
2723
|
+
/**
|
|
2724
|
+
* Configura advertencia de confirmación para campos opcionales.
|
|
2725
|
+
*
|
|
2726
|
+
* Permite mostrar una advertencia cuando el usuario intenta enviar el formulario
|
|
2727
|
+
* (o navegar entre steps) con campos opcionales vacíos. El botón cambia su texto
|
|
2728
|
+
* y variant, requiriendo un segundo click para confirmar.
|
|
2729
|
+
*
|
|
2730
|
+
* @param config - Configuración de confirmación
|
|
2731
|
+
* @returns this para encadenamiento
|
|
2732
|
+
*
|
|
2733
|
+
* @example
|
|
2734
|
+
* ```tsx
|
|
2735
|
+
* FormBuilder.create("registro")
|
|
2736
|
+
* .addField("email", f => f.type("email").label("Email").schema(z.string().email()))
|
|
2737
|
+
* .addField("phone", f => f.type("text").label("Teléfono (opcional)"))
|
|
2738
|
+
* .addStep("main", ["email", "phone"])
|
|
2739
|
+
*
|
|
2740
|
+
* .submitConfirmation({
|
|
2741
|
+
* optionalFields: [
|
|
2742
|
+
* {
|
|
2743
|
+
* name: "phone",
|
|
2744
|
+
* message: "Sin teléfono no podremos contactarte para confirmar"
|
|
2745
|
+
* }
|
|
2746
|
+
* ],
|
|
2747
|
+
* buttonBehavior: {
|
|
2748
|
+
* warningText: "⚠️ Continuar sin teléfono",
|
|
2749
|
+
* warningVariant: "outline",
|
|
2750
|
+
* resetDelay: 4000
|
|
2751
|
+
* },
|
|
2752
|
+
* applyOn: "submit",
|
|
2753
|
+
* showOnce: true
|
|
2754
|
+
* })
|
|
2755
|
+
*
|
|
2756
|
+
* .buttons({
|
|
2757
|
+
* submit: { type: "submit", label: "Crear Cuenta" }
|
|
2758
|
+
* })
|
|
2759
|
+
* .build();
|
|
2760
|
+
* ```
|
|
2761
|
+
*/
|
|
2762
|
+
submitConfirmation(config: SubmitConfirmationConfig): this;
|
|
2763
|
+
/**
|
|
2764
|
+
* Add a modular submit action to the form.
|
|
2765
|
+
*
|
|
2766
|
+
* Submit actions replace the legacy `.submit()` config with a more flexible system
|
|
2767
|
+
* that supports multiple endpoints, webhooks, emails, and custom handlers — each
|
|
2768
|
+
* with its own trigger, condition, and execution order.
|
|
2769
|
+
*
|
|
2770
|
+
* @param id - Unique action identifier
|
|
2771
|
+
* @param action - Action configuration (http, webhook, email, or custom)
|
|
2772
|
+
* @param trigger - When to execute: trigger type string or full SubmitTrigger object
|
|
2773
|
+
* @param options - Optional: condition, order, continueOnError, disabled
|
|
2774
|
+
* @returns this for chaining
|
|
2775
|
+
*
|
|
2776
|
+
* @example
|
|
2777
|
+
* ```tsx
|
|
2778
|
+
* FormBuilder.create("lead")
|
|
2779
|
+
* .addField("email", f => f.type("email").label("Email"))
|
|
2780
|
+
* .addField("name", f => f.type("text").label("Name"))
|
|
2781
|
+
* .addStep("main", ["email", "name"])
|
|
2782
|
+
*
|
|
2783
|
+
* // HTTP POST to your API
|
|
2784
|
+
* .submitAction("save-lead", {
|
|
2785
|
+
* type: "http",
|
|
2786
|
+
* name: "Save Lead",
|
|
2787
|
+
* endpoint: { url: "/api/leads", method: "POST" },
|
|
2788
|
+
* body: { format: "json" },
|
|
2789
|
+
* }, "onSubmit")
|
|
2790
|
+
*
|
|
2791
|
+
* // Webhook to external service
|
|
2792
|
+
* .submitAction("notify-crm", {
|
|
2793
|
+
* type: "webhook",
|
|
2794
|
+
* name: "CRM Webhook",
|
|
2795
|
+
* url: "https://hooks.example.com/lead",
|
|
2796
|
+
* }, "onSubmit", { continueOnError: true, order: 2 })
|
|
2797
|
+
*
|
|
2798
|
+
* // Custom handler
|
|
2799
|
+
* .submitAction("analytics", {
|
|
2800
|
+
* type: "custom",
|
|
2801
|
+
* name: "Track Conversion",
|
|
2802
|
+
* handler: async (values) => { analytics.track("lead", values); },
|
|
2803
|
+
* }, "onSubmit", { continueOnError: true })
|
|
2804
|
+
*
|
|
2805
|
+
* // Field mapping: form uses "nombre"/"email", API expects "first_name"/"email_address"
|
|
2806
|
+
* .submitAction("crm", {
|
|
2807
|
+
* type: "http",
|
|
2808
|
+
* name: "CRM Sync",
|
|
2809
|
+
* endpoint: { url: "https://crm.example.com/api/leads", method: "POST" },
|
|
2810
|
+
* }, "onSubmit", {
|
|
2811
|
+
* fieldMapping: { nombre: "first_name", email: "email_address" },
|
|
2812
|
+
* })
|
|
2813
|
+
*
|
|
2814
|
+
* .submitExecution({ mode: "sequential", stopOnFirstError: true })
|
|
2815
|
+
* .build();
|
|
2816
|
+
* ```
|
|
2817
|
+
*/
|
|
2818
|
+
submitAction(id: string, action: SubmitAction, trigger: SubmitTriggerType | SubmitTrigger, options?: {
|
|
2819
|
+
condition?: SubmitActionCondition;
|
|
2820
|
+
order?: number;
|
|
2821
|
+
continueOnError?: boolean;
|
|
2822
|
+
disabled?: boolean;
|
|
2823
|
+
/** Map form field names to API-expected field names (simple or advanced) */
|
|
2824
|
+
fieldMapping?: FieldMappingConfig;
|
|
2825
|
+
}): this;
|
|
2826
|
+
/**
|
|
2827
|
+
* Configure how multiple submit actions are executed.
|
|
2828
|
+
*
|
|
2829
|
+
* @param config - Execution configuration
|
|
2830
|
+
* @returns this for chaining
|
|
2831
|
+
*
|
|
2832
|
+
* @example
|
|
2833
|
+
* ```tsx
|
|
2834
|
+
* builder
|
|
2835
|
+
* .submitAction("primary", { ... }, "onSubmit")
|
|
2836
|
+
* .submitAction("secondary", { ... }, "onSubmit", { continueOnError: true })
|
|
2837
|
+
* .submitExecution({ mode: "sequential", stopOnFirstError: true })
|
|
2838
|
+
* ```
|
|
2839
|
+
*/
|
|
2840
|
+
submitExecution(config: SubmitExecutionConfig): this;
|
|
2841
|
+
/**
|
|
2842
|
+
* Construye y valida la configuración final del formulario.
|
|
2843
|
+
*
|
|
2844
|
+
* @returns FormConfig completo y validado
|
|
2845
|
+
* @throws Error si falta información requerida
|
|
2846
|
+
*/
|
|
2847
|
+
build(): FormConfig;
|
|
2848
|
+
/**
|
|
2849
|
+
* Construye sin validaciones (útil para desarrollo).
|
|
2850
|
+
*
|
|
2851
|
+
* @returns FormConfig parcial
|
|
2852
|
+
*/
|
|
2853
|
+
buildUnsafe(): Partial<FormConfig>;
|
|
2854
|
+
}
|
|
2855
|
+
|
|
2856
|
+
/**
|
|
2857
|
+
* ============================================
|
|
2858
|
+
* FIELD BUILDER REGISTRY MAP
|
|
2859
|
+
* ============================================
|
|
2860
|
+
*
|
|
2861
|
+
* Single source of truth that keeps FieldBuilder methods, the TSX code generator,
|
|
2862
|
+
* and the docs in sync. A contract test verifies all three stay aligned.
|
|
2863
|
+
*
|
|
2864
|
+
* When `method` is omitted in a PropertyMapping, it defaults to `prop` (the common case).
|
|
2865
|
+
* Entries where prop ≠ method are the historic bug sources (e.g. presets → datePresets).
|
|
2866
|
+
*/
|
|
2867
|
+
type SerializationHint = 'string' | 'number' | 'boolean' | 'json';
|
|
2868
|
+
type PropertyMapping = {
|
|
2869
|
+
/** The config property name on the FieldConfig object */
|
|
2870
|
+
prop: string;
|
|
2871
|
+
/** The FieldBuilder method name. Defaults to `prop` if omitted. */
|
|
2872
|
+
method?: string;
|
|
2873
|
+
/** How to serialize the value in generated code */
|
|
2874
|
+
serialize: SerializationHint;
|
|
2875
|
+
};
|
|
2876
|
+
/**
|
|
2877
|
+
* Maps field types to their type-specific config properties and the
|
|
2878
|
+
* corresponding FieldBuilder methods. Used by the TSX generator to
|
|
2879
|
+
* emit the correct method calls.
|
|
2880
|
+
*/
|
|
2881
|
+
declare const TYPE_SPECIFIC_PROPERTIES: Record<string, PropertyMapping[]>;
|
|
2882
|
+
/**
|
|
2883
|
+
* Field types that accept an `.options()` array.
|
|
2884
|
+
* The generator emits `.options(...)` for these when options exist.
|
|
2885
|
+
*/
|
|
2886
|
+
declare const OPTION_BASED_TYPES: string[];
|
|
2887
|
+
/**
|
|
2888
|
+
* Methods available on all field types (common configuration).
|
|
2889
|
+
*/
|
|
2890
|
+
declare const COMMON_METHODS: string[];
|
|
2891
|
+
/**
|
|
2892
|
+
* Declarative validation methods (produce ValidationRules).
|
|
2893
|
+
*/
|
|
2894
|
+
declare const VALIDATION_METHODS: string[];
|
|
2895
|
+
/**
|
|
2896
|
+
* Build methods (terminal operations).
|
|
2897
|
+
*/
|
|
2898
|
+
declare const BUILD_METHODS: string[];
|
|
2899
|
+
/**
|
|
2900
|
+
* Returns the union of all known FieldBuilder method names across all categories.
|
|
2901
|
+
* Used by the contract test to verify FieldBuilder ↔ Map completeness.
|
|
2902
|
+
*
|
|
2903
|
+
* Includes: common, type-specific, validation, build methods,
|
|
2904
|
+
* plus composite helpers like `range()` that set multiple props.
|
|
2905
|
+
*/
|
|
2906
|
+
declare function getAllKnownMethods(): string[];
|
|
2907
|
+
|
|
2908
|
+
/**
|
|
2909
|
+
* Plugin para persistir el estado del formulario en localStorage.
|
|
2910
|
+
*
|
|
2911
|
+
* Uses `transformConfig` to restore saved values as field defaults,
|
|
2912
|
+
* `onFieldChange` to persist progress, and `onAfterSubmit` to clean up.
|
|
2913
|
+
*
|
|
2914
|
+
* @example
|
|
2915
|
+
* ```tsx
|
|
2916
|
+
* const pluginManager = new PluginManager();
|
|
2917
|
+
* pluginManager.register(localStoragePlugin);
|
|
2918
|
+
*
|
|
2919
|
+
* const config = FormBuilder.create('contact')
|
|
2920
|
+
* .addField('name', f => f.type('text').label('Name'))
|
|
2921
|
+
* .pluginManager(pluginManager)
|
|
2922
|
+
* .build();
|
|
2923
|
+
*
|
|
2924
|
+
* // On page reload, field values are automatically restored.
|
|
2925
|
+
* ```
|
|
2926
|
+
*/
|
|
2927
|
+
declare const localStoragePlugin: FormPlugin;
|
|
2928
|
+
|
|
2929
|
+
/**
|
|
2930
|
+
* Plugin para tracking de analytics (Google Analytics, Mixpanel, etc.).
|
|
2931
|
+
*
|
|
2932
|
+
* @param options - Opciones de configuración
|
|
2933
|
+
* @returns Plugin configurado
|
|
2934
|
+
*
|
|
2935
|
+
* @example
|
|
2936
|
+
* ```tsx
|
|
2937
|
+
* const pluginManager = new PluginManager();
|
|
2938
|
+
* pluginManager.register(analyticsPlugin());
|
|
2939
|
+
* ```
|
|
2940
|
+
*/
|
|
2941
|
+
declare const analyticsPlugin: FormPlugin;
|
|
2942
|
+
|
|
2943
|
+
/**
|
|
2944
|
+
* Plugin para guardado automático periódico.
|
|
2945
|
+
*
|
|
2946
|
+
* @param options - Opciones de configuración
|
|
2947
|
+
* @returns Plugin configurado
|
|
2948
|
+
*
|
|
2949
|
+
* @example
|
|
2950
|
+
* ```tsx
|
|
2951
|
+
* const pluginManager = new PluginManager();
|
|
2952
|
+
* pluginManager.register(autosavePlugin({ interval: 30000 })); // 30 segundos
|
|
2953
|
+
* ```
|
|
2954
|
+
*/
|
|
2955
|
+
declare const autosavePlugin: (options?: {
|
|
2956
|
+
interval?: number;
|
|
2957
|
+
endpoint?: string;
|
|
2958
|
+
}) => FormPlugin;
|
|
2959
|
+
|
|
2960
|
+
/**
|
|
2961
|
+
* ============================================
|
|
2962
|
+
* RECAPTCHA PLUGIN - Google reCAPTCHA v3
|
|
2963
|
+
* ============================================
|
|
2964
|
+
*
|
|
2965
|
+
* Injects the reCAPTCHA v3 script and attaches a fresh token
|
|
2966
|
+
* to every submission via `transformValues`.
|
|
2967
|
+
*/
|
|
2968
|
+
interface RecaptchaPluginConfig {
|
|
2969
|
+
/** reCAPTCHA v3 site key */
|
|
2970
|
+
siteKey: string;
|
|
2971
|
+
/** Action name sent to Google (default: 'submit') */
|
|
2972
|
+
action?: string;
|
|
2973
|
+
/** Field name for the token in submitted values (default: '_recaptchaToken') */
|
|
2974
|
+
tokenField?: string;
|
|
2975
|
+
}
|
|
2976
|
+
declare global {
|
|
2977
|
+
interface Window {
|
|
2978
|
+
grecaptcha?: {
|
|
2979
|
+
ready: (cb: () => void) => void;
|
|
2980
|
+
execute: (siteKey: string, options: {
|
|
2981
|
+
action: string;
|
|
2982
|
+
}) => Promise<string>;
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
/**
|
|
2987
|
+
* Google reCAPTCHA v3 plugin.
|
|
2988
|
+
*
|
|
2989
|
+
* - `onFormInit`: Injects the reCAPTCHA script into `<body>` (once, deduped)
|
|
2990
|
+
* - `transformValues`: Fetches a fresh token and adds it to the submitted values
|
|
2991
|
+
* - `cleanup`: Removes the injected script
|
|
2992
|
+
*
|
|
2993
|
+
* @example
|
|
2994
|
+
* ```tsx
|
|
2995
|
+
* import { recaptchaPlugin, PluginManager, FormBuilder } from '@saastro/forms';
|
|
2996
|
+
*
|
|
2997
|
+
* const pm = new PluginManager();
|
|
2998
|
+
* pm.register(recaptchaPlugin({ siteKey: 'your-site-key' }));
|
|
2999
|
+
*
|
|
3000
|
+
* const config = FormBuilder.create('contact')
|
|
3001
|
+
* .usePlugins(pm)
|
|
3002
|
+
* .addField('email', (f) => f.type('email').label('Email').required().email())
|
|
3003
|
+
* .addStep('main', ['email'])
|
|
3004
|
+
* .build();
|
|
3005
|
+
* ```
|
|
3006
|
+
*/
|
|
3007
|
+
declare function recaptchaPlugin(config: RecaptchaPluginConfig): FormPlugin;
|
|
3008
|
+
|
|
3009
|
+
/**
|
|
3010
|
+
* ============================================
|
|
3011
|
+
* SHADCN/UI PRESET - Component Registry
|
|
3012
|
+
* ============================================
|
|
3013
|
+
*
|
|
3014
|
+
* Preset predefinido para usar con shadcn/ui.
|
|
3015
|
+
* Los usuarios pueden importar este preset y usarlo directamente,
|
|
3016
|
+
* o crear su propio mapeo personalizado.
|
|
3017
|
+
*/
|
|
3018
|
+
|
|
3019
|
+
/**
|
|
3020
|
+
* Crea un registry de componentes UI a partir de un objeto con los componentes importados.
|
|
3021
|
+
* Genérico — funciona con shadcn/ui, saastro, o cualquier set de componentes compatibles.
|
|
3022
|
+
*
|
|
3023
|
+
* @param components - Objeto con todos los componentes UI importados
|
|
3024
|
+
* @returns ComponentRegistry completo listo para usar con ComponentProvider
|
|
3025
|
+
*
|
|
3026
|
+
* @example
|
|
3027
|
+
* ```tsx
|
|
3028
|
+
* import { ComponentProvider, createComponentRegistry } from "@saastro/forms";
|
|
3029
|
+
* import * as uiComponents from "@/lib/form-components-shadcn";
|
|
3030
|
+
*
|
|
3031
|
+
* const registry = createComponentRegistry(uiComponents);
|
|
3032
|
+
*
|
|
3033
|
+
* function App() {
|
|
3034
|
+
* return (
|
|
3035
|
+
* <ComponentProvider components={registry}>
|
|
3036
|
+
* <MyForm />
|
|
3037
|
+
* </ComponentProvider>
|
|
3038
|
+
* );
|
|
3039
|
+
* }
|
|
3040
|
+
* ```
|
|
3041
|
+
*/
|
|
3042
|
+
declare function createComponentRegistry(components: ComponentRegistryInput): ComponentRegistry;
|
|
3043
|
+
/** @deprecated Use createComponentRegistry instead */
|
|
3044
|
+
declare const createShadcnRegistry: typeof createComponentRegistry;
|
|
3045
|
+
|
|
3046
|
+
/**
|
|
3047
|
+
* Props for MissingComponentFallback
|
|
3048
|
+
*/
|
|
3049
|
+
interface MissingComponentFallbackProps {
|
|
3050
|
+
/** Name of the field that requires the missing component */
|
|
3051
|
+
fieldName: string;
|
|
3052
|
+
/** Type of the field (e.g., 'text', 'select', 'date') */
|
|
3053
|
+
fieldType: string;
|
|
3054
|
+
/** List of missing component names */
|
|
3055
|
+
missingComponents: string[];
|
|
3056
|
+
/** Optional custom message */
|
|
3057
|
+
message?: string;
|
|
3058
|
+
/** Optional className for layout (e.g., column span classes) */
|
|
3059
|
+
className?: string;
|
|
3060
|
+
}
|
|
3061
|
+
/**
|
|
3062
|
+
* Fallback component displayed when required UI components are missing.
|
|
3063
|
+
* Shows a helpful warning with installation instructions.
|
|
3064
|
+
*
|
|
3065
|
+
* @example
|
|
3066
|
+
* ```tsx
|
|
3067
|
+
* <MissingComponentFallback
|
|
3068
|
+
* fieldName="birthdate"
|
|
3069
|
+
* fieldType="date"
|
|
3070
|
+
* missingComponents={['Calendar', 'Popover']}
|
|
3071
|
+
* />
|
|
3072
|
+
* ```
|
|
3073
|
+
*/
|
|
3074
|
+
declare function MissingComponentFallback({ fieldName, fieldType, missingComponents, message, className, }: MissingComponentFallbackProps): React__default.ReactElement;
|
|
3075
|
+
/**
|
|
3076
|
+
* Creates a placeholder component that renders the MissingComponentFallback
|
|
3077
|
+
* Can be used as a drop-in replacement for missing components
|
|
3078
|
+
*/
|
|
3079
|
+
declare function createMissingComponentPlaceholder(componentName: string, fieldType: string): React__default.FC<{
|
|
3080
|
+
name?: string;
|
|
3081
|
+
}>;
|
|
3082
|
+
|
|
3083
|
+
/**
|
|
3084
|
+
* ============================================
|
|
3085
|
+
* FIELD TYPE COMPONENTS - Mapping System
|
|
3086
|
+
* ============================================
|
|
3087
|
+
*
|
|
3088
|
+
* Maps field types to their required UI components.
|
|
3089
|
+
* Used for auto-discovery to determine which components need to be loaded.
|
|
3090
|
+
*/
|
|
3091
|
+
|
|
3092
|
+
/**
|
|
3093
|
+
* Type for the component registry keys
|
|
3094
|
+
*/
|
|
3095
|
+
type ComponentName = keyof ComponentRegistry;
|
|
3096
|
+
/**
|
|
3097
|
+
* Mapping of field type → required components
|
|
3098
|
+
* Each field type lists all the UI components it needs to render properly
|
|
3099
|
+
*/
|
|
3100
|
+
declare const fieldTypeComponents: Record<string, ComponentName[]>;
|
|
3101
|
+
/**
|
|
3102
|
+
* Core components that are always needed for any form
|
|
3103
|
+
*/
|
|
3104
|
+
declare const coreComponents: ComponentName[];
|
|
3105
|
+
/**
|
|
3106
|
+
* Get all required components for a form configuration
|
|
3107
|
+
*
|
|
3108
|
+
* @param config - The form configuration
|
|
3109
|
+
* @returns Array of unique component names needed for this form
|
|
3110
|
+
*
|
|
3111
|
+
* @example
|
|
3112
|
+
* ```ts
|
|
3113
|
+
* const config = FormBuilder.create('contact')
|
|
3114
|
+
* .addField('name', f => f.type('text'))
|
|
3115
|
+
* .addField('email', f => f.type('email'))
|
|
3116
|
+
* .build();
|
|
3117
|
+
*
|
|
3118
|
+
* const needed = getRequiredComponents(config);
|
|
3119
|
+
* // ['Input', 'Label', 'Button', 'Field', 'FieldLabel', 'FieldDescription', 'FieldError', 'FormField', 'FormControl']
|
|
3120
|
+
* ```
|
|
3121
|
+
*/
|
|
3122
|
+
declare function getRequiredComponents(config: FormConfig): ComponentName[];
|
|
3123
|
+
/**
|
|
3124
|
+
* Get missing components by comparing required vs provided
|
|
3125
|
+
*
|
|
3126
|
+
* @param required - Components needed for the form
|
|
3127
|
+
* @param provided - Components available in the registry
|
|
3128
|
+
* @returns Array of missing component names
|
|
3129
|
+
*/
|
|
3130
|
+
declare function getMissingComponents(required: ComponentName[], provided: Partial<Record<ComponentName, unknown>>): ComponentName[];
|
|
3131
|
+
/**
|
|
3132
|
+
* Group missing components by their source package
|
|
3133
|
+
* Useful for generating install commands
|
|
3134
|
+
*/
|
|
3135
|
+
declare function groupMissingByPackage(missing: ComponentName[]): Record<string, ComponentName[]>;
|
|
3136
|
+
/**
|
|
3137
|
+
* Generate a shell command to install missing components
|
|
3138
|
+
*/
|
|
3139
|
+
declare function getInstallCommand(missing: ComponentName[]): string;
|
|
3140
|
+
|
|
3141
|
+
/**
|
|
3142
|
+
* ============================================
|
|
3143
|
+
* COMPONENT RESOLVER - Auto-discovery System
|
|
3144
|
+
* ============================================
|
|
3145
|
+
*
|
|
3146
|
+
* Automatically resolves UI components from the user's project.
|
|
3147
|
+
* Detects shadcn/ui installation and loads components dynamically.
|
|
3148
|
+
*
|
|
3149
|
+
* Features:
|
|
3150
|
+
* - Zero config for shadcn/ui projects
|
|
3151
|
+
* - Caches resolved components
|
|
3152
|
+
* - Graceful fallback for missing components
|
|
3153
|
+
* - Works with custom component paths
|
|
3154
|
+
*/
|
|
3155
|
+
|
|
3156
|
+
/**
|
|
3157
|
+
* Configuration for component resolution
|
|
3158
|
+
*/
|
|
3159
|
+
interface ComponentResolverConfig {
|
|
3160
|
+
/** Base path for UI components (e.g., "@/components/ui") */
|
|
3161
|
+
uiPath?: string;
|
|
3162
|
+
/** Custom component importers for non-standard setups */
|
|
3163
|
+
importers?: Record<string, () => Promise<React__default.ComponentType<any>>>;
|
|
3164
|
+
}
|
|
3165
|
+
/**
|
|
3166
|
+
* Result of component resolution
|
|
3167
|
+
*/
|
|
3168
|
+
interface ResolvedComponents {
|
|
3169
|
+
/** Successfully resolved components */
|
|
3170
|
+
components: PartialComponentRegistry;
|
|
3171
|
+
/** Components that failed to load */
|
|
3172
|
+
missing: string[];
|
|
3173
|
+
}
|
|
3174
|
+
/**
|
|
3175
|
+
* ComponentResolver - Handles auto-discovery and caching of UI components
|
|
3176
|
+
*/
|
|
3177
|
+
declare class ComponentResolver {
|
|
3178
|
+
private cache;
|
|
3179
|
+
private uiPath;
|
|
3180
|
+
private importers;
|
|
3181
|
+
private resolvePromises;
|
|
3182
|
+
constructor(config?: ComponentResolverConfig);
|
|
3183
|
+
/**
|
|
3184
|
+
* Get or create the singleton resolver instance
|
|
3185
|
+
*/
|
|
3186
|
+
static getInstance(config?: ComponentResolverConfig): ComponentResolver;
|
|
3187
|
+
/**
|
|
3188
|
+
* Reset the singleton (useful for testing)
|
|
3189
|
+
*/
|
|
3190
|
+
static reset(): void;
|
|
3191
|
+
/**
|
|
3192
|
+
* Configure the resolver's UI path
|
|
3193
|
+
*/
|
|
3194
|
+
setUiPath(path: string): void;
|
|
3195
|
+
/**
|
|
3196
|
+
* Get the current UI path
|
|
3197
|
+
*/
|
|
3198
|
+
getUiPath(): string;
|
|
3199
|
+
/**
|
|
3200
|
+
* Register custom importers for specific components
|
|
3201
|
+
*/
|
|
3202
|
+
registerImporter(name: string, importer: () => Promise<React__default.ComponentType<any>>): void;
|
|
3203
|
+
/**
|
|
3204
|
+
* Check if a component is cached
|
|
3205
|
+
*/
|
|
3206
|
+
isCached(name: string): boolean;
|
|
3207
|
+
/**
|
|
3208
|
+
* Get a cached component (returns null if not cached or missing)
|
|
3209
|
+
*/
|
|
3210
|
+
getCached(name: string): React__default.ComponentType<any> | null;
|
|
3211
|
+
/**
|
|
3212
|
+
* Pre-cache components (useful for SSR or avoiding loading states)
|
|
3213
|
+
*/
|
|
3214
|
+
preCache(components: PartialComponentRegistry): void;
|
|
3215
|
+
/**
|
|
3216
|
+
* Resolve a single component by name
|
|
3217
|
+
* Returns null if the component cannot be loaded
|
|
3218
|
+
*/
|
|
3219
|
+
resolve(name: keyof ComponentRegistry): Promise<React__default.ComponentType<any> | null>;
|
|
3220
|
+
/**
|
|
3221
|
+
* Internal resolution logic
|
|
3222
|
+
*/
|
|
3223
|
+
private doResolve;
|
|
3224
|
+
/**
|
|
3225
|
+
* Resolve multiple components at once
|
|
3226
|
+
* Returns an object with resolved components and a list of missing ones
|
|
3227
|
+
*/
|
|
3228
|
+
resolveMany(names: Array<keyof ComponentRegistry>): Promise<ResolvedComponents>;
|
|
3229
|
+
/**
|
|
3230
|
+
* Clear the component cache
|
|
3231
|
+
*/
|
|
3232
|
+
clearCache(): void;
|
|
3233
|
+
}
|
|
3234
|
+
/**
|
|
3235
|
+
* Get the singleton ComponentResolver instance
|
|
3236
|
+
*/
|
|
3237
|
+
declare function getComponentResolver(config?: ComponentResolverConfig): ComponentResolver;
|
|
3238
|
+
/**
|
|
3239
|
+
* Pre-configure components synchronously (for use in providers)
|
|
3240
|
+
* This bypasses dynamic imports by accepting already-imported components
|
|
3241
|
+
*/
|
|
3242
|
+
declare function configureComponents(components: PartialComponentRegistry): void;
|
|
3243
|
+
|
|
3244
|
+
interface StepsAccordionProps {
|
|
3245
|
+
steps: Steps;
|
|
3246
|
+
currentStepId: string;
|
|
3247
|
+
stepHistory: string[];
|
|
3248
|
+
fields: Fields;
|
|
3249
|
+
onStepSelect?: (stepId: string) => void;
|
|
3250
|
+
allowNavigation?: boolean;
|
|
3251
|
+
className?: string;
|
|
3252
|
+
showFieldCount?: boolean;
|
|
3253
|
+
showErrors?: boolean;
|
|
3254
|
+
showProgress?: boolean;
|
|
3255
|
+
}
|
|
3256
|
+
declare function StepsAccordion({ steps, currentStepId, stepHistory, fields, onStepSelect, allowNavigation, className, showFieldCount, showErrors, showProgress, }: StepsAccordionProps): react_jsx_runtime.JSX.Element;
|
|
3257
|
+
|
|
3258
|
+
interface StepsNavigationProps {
|
|
3259
|
+
steps: Steps;
|
|
3260
|
+
currentStepId: string;
|
|
3261
|
+
stepHistory: string[];
|
|
3262
|
+
fields: Fields;
|
|
3263
|
+
onStepClick?: (stepId: string) => void;
|
|
3264
|
+
className?: string;
|
|
3265
|
+
orientation?: 'horizontal' | 'vertical';
|
|
3266
|
+
showLabels?: boolean;
|
|
3267
|
+
showFieldCount?: boolean;
|
|
3268
|
+
allowNavigation?: boolean;
|
|
3269
|
+
}
|
|
3270
|
+
declare function StepsNavigation({ steps, currentStepId, stepHistory, fields, onStepClick, className, orientation, showLabels, showFieldCount, allowNavigation, }: StepsNavigationProps): react_jsx_runtime.JSX.Element;
|
|
3271
|
+
|
|
3272
|
+
interface StepsProgressProps {
|
|
3273
|
+
steps: Steps;
|
|
3274
|
+
currentStepId: string;
|
|
3275
|
+
stepHistory: string[];
|
|
3276
|
+
fields: Fields;
|
|
3277
|
+
className?: string;
|
|
3278
|
+
showLabels?: boolean;
|
|
3279
|
+
showPercentage?: boolean;
|
|
3280
|
+
variant?: 'bar' | 'dots' | 'steps';
|
|
3281
|
+
}
|
|
3282
|
+
declare function StepsProgress({ steps, currentStepId, stepHistory, fields, className, showLabels, showPercentage, variant, }: StepsProgressProps): react_jsx_runtime.JSX.Element;
|
|
3283
|
+
|
|
3284
|
+
interface Props {
|
|
3285
|
+
/** React-Hook-Form control */
|
|
3286
|
+
control: Control<Record<string, unknown>>;
|
|
3287
|
+
/** Field name (path) */
|
|
3288
|
+
name: string;
|
|
3289
|
+
fieldConfig: FieldConfig;
|
|
3290
|
+
/** Clase CSS opcional para el Field */
|
|
3291
|
+
colSpanItem?: string;
|
|
3292
|
+
/** Plugin manager for custom field types */
|
|
3293
|
+
pluginManager?: PluginManager;
|
|
3294
|
+
}
|
|
3295
|
+
declare const FieldRenderer: React__default.NamedExoticComponent<Props>;
|
|
3296
|
+
|
|
3297
|
+
/**
|
|
3298
|
+
* ============================================
|
|
3299
|
+
* CONSTANTS - Magic numbers and strings
|
|
3300
|
+
* ============================================
|
|
3301
|
+
*
|
|
3302
|
+
* Constantes extraídas para mejorar mantenibilidad
|
|
3303
|
+
*/
|
|
3304
|
+
/**
|
|
3305
|
+
* Valores por defecto para campos de formulario
|
|
3306
|
+
*/
|
|
3307
|
+
declare const FIELD_DEFAULTS: {
|
|
3308
|
+
/** Valor por defecto para slider min */
|
|
3309
|
+
readonly SLIDER_MIN: 0;
|
|
3310
|
+
/** Valor por defecto para slider max */
|
|
3311
|
+
readonly SLIDER_MAX: 100;
|
|
3312
|
+
/** Valor por defecto para slider step */
|
|
3313
|
+
readonly SLIDER_STEP: 1;
|
|
3314
|
+
/** Valor por defecto para slider defaultValue */
|
|
3315
|
+
readonly SLIDER_DEFAULT_VALUE: number[];
|
|
3316
|
+
/** Longitud por defecto para OTP */
|
|
3317
|
+
readonly OTP_DEFAULT_LENGTH: 6;
|
|
3318
|
+
};
|
|
3319
|
+
/**
|
|
3320
|
+
* Clases CSS comunes para componentes
|
|
3321
|
+
*/
|
|
3322
|
+
declare const COMMON_CLASSES: {
|
|
3323
|
+
/** Clase para width completo */
|
|
3324
|
+
readonly FULL_WIDTH: "w-full";
|
|
3325
|
+
/** Clase para gap entre elementos */
|
|
3326
|
+
readonly GAP_4: "gap-4";
|
|
3327
|
+
/** Clase para padding right cuando hay icono */
|
|
3328
|
+
readonly ICON_PADDING: "pr-10";
|
|
3329
|
+
/** Clase para items center */
|
|
3330
|
+
readonly ITEMS_CENTER: "items-center";
|
|
3331
|
+
/** Clase para flex */
|
|
3332
|
+
readonly FLEX: "flex";
|
|
3333
|
+
/** Clase para space-x-2 */
|
|
3334
|
+
readonly SPACE_X_2: "space-x-2";
|
|
3335
|
+
};
|
|
3336
|
+
/**
|
|
3337
|
+
* Mensajes y strings comunes
|
|
3338
|
+
*/
|
|
3339
|
+
declare const COMMON_STRINGS: {
|
|
3340
|
+
/** Placeholder por defecto para daterange */
|
|
3341
|
+
readonly DATERANGE_PLACEHOLDER: "Select date range";
|
|
3342
|
+
/** Texto por defecto cuando no hay opciones en command */
|
|
3343
|
+
readonly COMMAND_EMPTY: "No option found.";
|
|
3344
|
+
/** Placeholder por defecto para búsqueda en command */
|
|
3345
|
+
readonly COMMAND_SEARCH_PLACEHOLDER: "Search...";
|
|
3346
|
+
};
|
|
3347
|
+
/**
|
|
3348
|
+
* Configuraciones de loading/suspense
|
|
3349
|
+
*/
|
|
3350
|
+
declare const SUSPENSE_CONFIG: {
|
|
3351
|
+
/** Fallback para date picker */
|
|
3352
|
+
readonly DATE_FALLBACK: "h-10 w-full animate-pulse rounded-md bg-muted";
|
|
3353
|
+
};
|
|
3354
|
+
|
|
3355
|
+
declare function useFormLayout(layout?: FormLayout): {
|
|
3356
|
+
gridClassName: string;
|
|
3357
|
+
gridStyle: React$1.CSSProperties;
|
|
3358
|
+
};
|
|
3359
|
+
|
|
3360
|
+
declare function useFormState({ config: rawConfig, fields: rawFields, steps: rawSteps, }: {
|
|
3361
|
+
config: FormConfig;
|
|
3362
|
+
fields: Fields;
|
|
3363
|
+
steps?: Steps;
|
|
3364
|
+
}): {
|
|
3365
|
+
currentStepId: string;
|
|
3366
|
+
loading: boolean;
|
|
3367
|
+
submitted: boolean;
|
|
3368
|
+
error: Error | null;
|
|
3369
|
+
methods: react_hook_form.UseFormReturn<{
|
|
3370
|
+
[x: string]: any;
|
|
3371
|
+
}, unknown, {
|
|
3372
|
+
[x: string]: any;
|
|
3373
|
+
}>;
|
|
3374
|
+
nextStep: (values: Record<string, unknown>) => boolean;
|
|
3375
|
+
prevStep: () => boolean;
|
|
3376
|
+
handleSubmit: (data: Record<string, unknown>) => Promise<void>;
|
|
3377
|
+
validateAndNext: (e?: React.MouseEvent) => Promise<void>;
|
|
3378
|
+
isLast: boolean;
|
|
3379
|
+
getSuccessMessage: () => string;
|
|
3380
|
+
getErrorMessage: () => string;
|
|
3381
|
+
resetError: () => void;
|
|
3382
|
+
stepHistory: string[];
|
|
3383
|
+
};
|
|
3384
|
+
|
|
3385
|
+
type StepStatus = 'pending' | 'current' | 'completed' | 'error';
|
|
3386
|
+
interface StepInfo {
|
|
3387
|
+
id: string;
|
|
3388
|
+
fields: string[];
|
|
3389
|
+
fieldCount: number;
|
|
3390
|
+
status: StepStatus;
|
|
3391
|
+
hasErrors: boolean;
|
|
3392
|
+
errorCount: number;
|
|
3393
|
+
isVisited: boolean;
|
|
3394
|
+
isCurrent: boolean;
|
|
3395
|
+
isCompleted: boolean;
|
|
3396
|
+
canNavigate: boolean;
|
|
3397
|
+
}
|
|
3398
|
+
interface FormStepsInfo {
|
|
3399
|
+
steps: StepInfo[];
|
|
3400
|
+
currentStepId: string;
|
|
3401
|
+
totalSteps: number;
|
|
3402
|
+
completedSteps: number;
|
|
3403
|
+
progress: number;
|
|
3404
|
+
stepHistory: string[];
|
|
3405
|
+
canGoNext: boolean;
|
|
3406
|
+
canGoPrev: boolean;
|
|
3407
|
+
getStepInfo: (stepId: string) => StepInfo | undefined;
|
|
3408
|
+
getStepStatus: (stepId: string) => StepStatus;
|
|
3409
|
+
}
|
|
3410
|
+
/**
|
|
3411
|
+
* Hook que expone información completa sobre los pasos del formulario
|
|
3412
|
+
* para construir componentes de UI como acordeones, barras de progreso, etc.
|
|
3413
|
+
*/
|
|
3414
|
+
declare function useFormStepsInfo({ steps, currentStepId, stepHistory, fields, }: {
|
|
3415
|
+
steps: Steps;
|
|
3416
|
+
currentStepId: string;
|
|
3417
|
+
stepHistory: string[];
|
|
3418
|
+
fields: Fields;
|
|
3419
|
+
}): FormStepsInfo;
|
|
3420
|
+
|
|
3421
|
+
/**
|
|
3422
|
+
* @deprecated Use `recaptchaPlugin()` instead. This hook only injects the script —
|
|
3423
|
+
* the plugin also handles token generation via `transformValues`.
|
|
3424
|
+
*
|
|
3425
|
+
* ```tsx
|
|
3426
|
+
* // Before (hook — only injects script, token must be handled manually):
|
|
3427
|
+
* useRecaptcha(config);
|
|
3428
|
+
*
|
|
3429
|
+
* // After (plugin — injects script AND adds token to submitted values):
|
|
3430
|
+
* import { recaptchaPlugin } from '@saastro/forms';
|
|
3431
|
+
* pm.register(recaptchaPlugin({ siteKey: '...' }));
|
|
3432
|
+
* ```
|
|
3433
|
+
*/
|
|
3434
|
+
declare function useRecaptcha(config: FormConfig): void;
|
|
3435
|
+
|
|
3436
|
+
/**
|
|
3437
|
+
* Props override para el botón durante advertencia
|
|
3438
|
+
*/
|
|
3439
|
+
interface ButtonOverrideProps {
|
|
3440
|
+
text?: string;
|
|
3441
|
+
variant?: ButtonConfig['variant'];
|
|
3442
|
+
effect?: ButtonConfig['effect'];
|
|
3443
|
+
}
|
|
3444
|
+
/**
|
|
3445
|
+
* Resultado del hook useSubmitConfirmation
|
|
3446
|
+
*/
|
|
3447
|
+
interface UseSubmitConfirmationReturn {
|
|
3448
|
+
/** Hay campos opcionales vacíos que requieren confirmación? */
|
|
3449
|
+
needsConfirmation: boolean;
|
|
3450
|
+
/** Esperando segundo click para confirmar? */
|
|
3451
|
+
isAwaitingConfirmation: boolean;
|
|
3452
|
+
/** Campos vacíos detectados */
|
|
3453
|
+
warningFields: string[];
|
|
3454
|
+
/** Props para override del botón (text, variant, effect) */
|
|
3455
|
+
buttonProps: ButtonOverrideProps;
|
|
3456
|
+
/** Handler del click que intercepta y gestiona la confirmación */
|
|
3457
|
+
handleClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
3458
|
+
/** Reset manual del estado de confirmación */
|
|
3459
|
+
resetConfirmation: () => void;
|
|
3460
|
+
}
|
|
3461
|
+
/**
|
|
3462
|
+
* Hook para manejar confirmación condicional de submit/navegación.
|
|
3463
|
+
*
|
|
3464
|
+
* Detecta si hay campos opcionales vacíos configurados y requiere
|
|
3465
|
+
* doble click para confirmar (primera vez muestra advertencia cambiando
|
|
3466
|
+
* el botón, segunda vez procede con la acción).
|
|
3467
|
+
*
|
|
3468
|
+
* @param config - Configuración del formulario
|
|
3469
|
+
* @param currentValues - Valores actuales del formulario (de methods.watch())
|
|
3470
|
+
* @param onProceed - Callback a ejecutar cuando se confirma o no hay advertencia
|
|
3471
|
+
* @param buttonType - Tipo de botón: "submit" o "next" (para aplicar según applyOn)
|
|
3472
|
+
* @returns Objeto con estado y handlers para gestionar la confirmación
|
|
3473
|
+
*
|
|
3474
|
+
* @example
|
|
3475
|
+
* ```tsx
|
|
3476
|
+
* const submitConfirmation = useSubmitConfirmation(
|
|
3477
|
+
* config,
|
|
3478
|
+
* methods.watch(),
|
|
3479
|
+
* () => methods.handleSubmit(onFormSubmit)(),
|
|
3480
|
+
* "submit"
|
|
3481
|
+
* );
|
|
3482
|
+
*
|
|
3483
|
+
* <ButtonPro
|
|
3484
|
+
* onClick={submitConfirmation.handleClick}
|
|
3485
|
+
* variant={submitConfirmation.isAwaitingConfirmation
|
|
3486
|
+
* ? submitConfirmation.buttonProps.variant
|
|
3487
|
+
* : "default"}
|
|
3488
|
+
* >
|
|
3489
|
+
* {submitConfirmation.isAwaitingConfirmation
|
|
3490
|
+
* ? submitConfirmation.buttonProps.text
|
|
3491
|
+
* : "Submit"}
|
|
3492
|
+
* </ButtonPro>
|
|
3493
|
+
* ```
|
|
3494
|
+
*/
|
|
3495
|
+
declare function useSubmitConfirmation(config: FormConfig, currentValues: Record<string, unknown>, onProceed: () => void, buttonType?: 'submit' | 'next'): UseSubmitConfirmationReturn;
|
|
3496
|
+
|
|
3497
|
+
/**
|
|
3498
|
+
* useSubmitActionTriggers
|
|
3499
|
+
*
|
|
3500
|
+
* Hook que maneja la ejecución automática de submit actions
|
|
3501
|
+
* basada en diferentes triggers (step change, field change, delay).
|
|
3502
|
+
*/
|
|
3503
|
+
|
|
3504
|
+
interface UseSubmitActionTriggersOptions {
|
|
3505
|
+
/** Configuración del formulario */
|
|
3506
|
+
config: FormConfig;
|
|
3507
|
+
/** Función para obtener los valores actuales (evita re-renders por valores) */
|
|
3508
|
+
getValues: () => Record<string, unknown>;
|
|
3509
|
+
/** Step actual */
|
|
3510
|
+
currentStep: string;
|
|
3511
|
+
/** Callback cuando se ejecuta una acción */
|
|
3512
|
+
onActionExecuted?: (result: SubmitActionsResult) => void;
|
|
3513
|
+
/** Callback cuando hay un error */
|
|
3514
|
+
onActionError?: (error: Error, actionName: string) => void;
|
|
3515
|
+
/** Si los triggers están habilitados */
|
|
3516
|
+
enabled?: boolean;
|
|
3517
|
+
}
|
|
3518
|
+
interface UseSubmitActionTriggersReturn {
|
|
3519
|
+
/** Ejecutar acciones para un cambio de campo específico */
|
|
3520
|
+
triggerFieldChange: (fieldName: string, value: unknown) => void;
|
|
3521
|
+
/** Ejecutar acciones para blur de un campo */
|
|
3522
|
+
triggerFieldBlur: (fieldName: string) => void;
|
|
3523
|
+
/** Ejecutar acciones manuales */
|
|
3524
|
+
triggerManual: (actionIds?: string[]) => Promise<SubmitActionsResult>;
|
|
3525
|
+
/** Verificar si hay acciones para un trigger específico */
|
|
3526
|
+
hasActionsForTrigger: (triggerType: 'onSubmit' | 'onStepEnter' | 'onStepExit' | 'onFieldChange' | 'onFieldBlur' | 'onDelay' | 'manual', triggerValue?: string) => boolean;
|
|
3527
|
+
}
|
|
3528
|
+
declare function useSubmitActionTriggers({ config, getValues, currentStep, onActionExecuted, onActionError, enabled, }: UseSubmitActionTriggersOptions): UseSubmitActionTriggersReturn;
|
|
3529
|
+
|
|
3530
|
+
/**
|
|
3531
|
+
* Resolves hidden field values at form init.
|
|
3532
|
+
* Filters fields with type 'hidden', runs their resolvers,
|
|
3533
|
+
* and sets the values via react-hook-form's setValue.
|
|
3534
|
+
*/
|
|
3535
|
+
declare function useHiddenFieldResolvers(methods: UseFormReturn<Record<string, unknown>>, fields: Fields): void;
|
|
3536
|
+
|
|
3537
|
+
/**
|
|
3538
|
+
* useComputedFields
|
|
3539
|
+
*
|
|
3540
|
+
* Watches dependency fields and reactively updates computed field values.
|
|
3541
|
+
* Only runs when at least one field has a `computed` config.
|
|
3542
|
+
*/
|
|
3543
|
+
declare function useComputedFields(methods: UseFormReturn<Record<string, unknown>>, fields: Fields): void;
|
|
3544
|
+
|
|
3545
|
+
/**
|
|
3546
|
+
* Check if a schema value is a Zod schema instance.
|
|
3547
|
+
* Zod schemas have a `_def` property on their prototype.
|
|
3548
|
+
*/
|
|
3549
|
+
declare function isZodSchema(schema: unknown): schema is z.ZodType;
|
|
3550
|
+
/**
|
|
3551
|
+
* Check if a schema value is a plain ValidationRules object (serializable JSON).
|
|
3552
|
+
*/
|
|
3553
|
+
declare function isValidationRules(schema: unknown): schema is ValidationRules;
|
|
3554
|
+
|
|
3555
|
+
/**
|
|
3556
|
+
* Compile a serializable `ValidationRules` object into a Zod schema.
|
|
3557
|
+
*
|
|
3558
|
+
* @param rules - The declarative validation rules
|
|
3559
|
+
* @param fieldType - The field type (used to determine the base Zod type)
|
|
3560
|
+
* @returns A Zod schema ready for use with react-hook-form
|
|
3561
|
+
*/
|
|
3562
|
+
declare function compileValidationRules(rules: ValidationRules, fieldType: string): z.ZodTypeAny;
|
|
3563
|
+
|
|
3564
|
+
type ValidationPresetMeta = {
|
|
3565
|
+
id: string;
|
|
3566
|
+
label: string;
|
|
3567
|
+
description: string;
|
|
3568
|
+
category: 'string' | 'number' | 'array' | 'boolean' | 'date';
|
|
3569
|
+
rules: ValidationRules;
|
|
3570
|
+
};
|
|
3571
|
+
/**
|
|
3572
|
+
* Resolve a preset ID to its ValidationRules.
|
|
3573
|
+
* Returns `undefined` if the preset doesn't exist.
|
|
3574
|
+
*/
|
|
3575
|
+
declare function resolvePreset(id: string): ValidationRules | undefined;
|
|
3576
|
+
/**
|
|
3577
|
+
* Register a custom validation preset at runtime.
|
|
3578
|
+
*/
|
|
3579
|
+
declare function registerPreset(preset: ValidationPresetMeta): void;
|
|
3580
|
+
/**
|
|
3581
|
+
* Get all available presets (built-in + registered).
|
|
3582
|
+
*/
|
|
3583
|
+
declare function getAvailablePresets(): ValidationPresetMeta[];
|
|
3584
|
+
|
|
3585
|
+
declare function defaultSubmit({ values, config, }: {
|
|
3586
|
+
values: Record<string, unknown>;
|
|
3587
|
+
config: FormConfig;
|
|
3588
|
+
}): Promise<void>;
|
|
3589
|
+
|
|
3590
|
+
/**
|
|
3591
|
+
* Field Mapping Utility
|
|
3592
|
+
*
|
|
3593
|
+
* Transforms form values before sending to an API endpoint.
|
|
3594
|
+
* Supports field renaming, value transforms, computed field injection,
|
|
3595
|
+
* field exclusion, and passthrough control.
|
|
3596
|
+
*
|
|
3597
|
+
* Two formats:
|
|
3598
|
+
* 1. Simple: Record<string, string> — rename fields only (backward compatible)
|
|
3599
|
+
* 2. Advanced: FieldMapping — rename, transform, inject, exclude
|
|
3600
|
+
*/
|
|
3601
|
+
|
|
3602
|
+
/**
|
|
3603
|
+
* Checks whether a mapping config is the advanced FieldMapping format
|
|
3604
|
+
* (vs the simple Record<string, string> format).
|
|
3605
|
+
*/
|
|
3606
|
+
declare function isAdvancedMapping(mapping: FieldMappingConfig): mapping is FieldMapping;
|
|
3607
|
+
/** Applies a built-in transform to a value. */
|
|
3608
|
+
declare function applyBuiltinTransform(value: unknown, transform: BuiltinTransform): unknown;
|
|
3609
|
+
/** Applies a transform (built-in or custom function) to a value. */
|
|
3610
|
+
declare function applyTransform(value: unknown, transform: BuiltinTransform | FieldTransformFn): unknown;
|
|
3611
|
+
/** Resolves a dynamic field value from a FieldResolver (async — supports IP fetch). */
|
|
3612
|
+
declare function resolveValue(resolver: FieldResolver): Promise<unknown>;
|
|
3613
|
+
/**
|
|
3614
|
+
* Synchronous resolver — returns instant values for sync resolvers,
|
|
3615
|
+
* placeholders for async ones (ip, custom). Used by debug panel dry-runs.
|
|
3616
|
+
*/
|
|
3617
|
+
declare function resolveValueSync(resolver: FieldResolver): unknown;
|
|
3618
|
+
/**
|
|
3619
|
+
* Applies field mapping configuration to form values.
|
|
3620
|
+
*
|
|
3621
|
+
* Supports two formats:
|
|
3622
|
+
* 1. Simple: `Record<string, string>` — rename fields, unmapped pass through
|
|
3623
|
+
* 2. Advanced: `FieldMapping` — rename, transform, inject, exclude, passthrough control
|
|
3624
|
+
*
|
|
3625
|
+
* @param values - Raw form values
|
|
3626
|
+
* @param mapping - Field mapping configuration
|
|
3627
|
+
* @returns Transformed values ready for the API
|
|
3628
|
+
*
|
|
3629
|
+
* @example
|
|
3630
|
+
* ```ts
|
|
3631
|
+
* // Simple rename
|
|
3632
|
+
* applyFieldMapping({ nombre: "Ana" }, { nombre: "first_name" });
|
|
3633
|
+
* // → { first_name: "Ana" }
|
|
3634
|
+
*
|
|
3635
|
+
* // Advanced: transform + inject
|
|
3636
|
+
* applyFieldMapping({ fecha: new Date("2000-01-15"), acepta: true }, {
|
|
3637
|
+
* fields: {
|
|
3638
|
+
* fecha: { to: "birth_date", transform: "dateYMD" },
|
|
3639
|
+
* acepta: { to: "accepts", transform: "booleanString" },
|
|
3640
|
+
* },
|
|
3641
|
+
* inject: {
|
|
3642
|
+
* campaign: "10653",
|
|
3643
|
+
* timestamp: { $resolver: "timestamp" },
|
|
3644
|
+
* },
|
|
3645
|
+
* });
|
|
3646
|
+
* // → { birth_date: "2000-01-15", accepts: "true", campaign: "10653", timestamp: "2026-..." }
|
|
3647
|
+
* ```
|
|
3648
|
+
*/
|
|
3649
|
+
declare function applyFieldMapping(values: Record<string, unknown>, mapping: FieldMappingConfig): Promise<Record<string, unknown>>;
|
|
3650
|
+
/**
|
|
3651
|
+
* Synchronous version of applyFieldMapping — uses resolveValueSync for inject resolvers.
|
|
3652
|
+
* Suitable for debug panel dry-runs where async is not practical.
|
|
3653
|
+
*/
|
|
3654
|
+
declare function applyFieldMappingSync(values: Record<string, unknown>, mapping: FieldMappingConfig): Record<string, unknown>;
|
|
3655
|
+
/**
|
|
3656
|
+
* Applies field-level transforms to form values.
|
|
3657
|
+
* Iterates over all fields in the config and applies their `transform` property.
|
|
3658
|
+
* Returns a new object with transformed values (does not mutate input).
|
|
3659
|
+
*
|
|
3660
|
+
* @param fields - Form field configurations (from config.fields)
|
|
3661
|
+
* @param values - Raw form values from react-hook-form
|
|
3662
|
+
* @returns New object with field-level transforms applied
|
|
3663
|
+
*/
|
|
3664
|
+
declare function applyFieldTransforms(fields: Record<string, any>, values: Record<string, unknown>): Record<string, unknown>;
|
|
3665
|
+
|
|
3666
|
+
/**
|
|
3667
|
+
* Submit Action Executors
|
|
3668
|
+
*
|
|
3669
|
+
* Ejecutores individuales para cada tipo de acción de submit.
|
|
3670
|
+
* Cada ejecutor maneja la lógica específica de su tipo.
|
|
3671
|
+
*/
|
|
3672
|
+
|
|
3673
|
+
declare function executeHttpAction(action: HttpSubmitAction, values: Record<string, unknown>): Promise<unknown>;
|
|
3674
|
+
declare function executeWebhookAction(action: WebhookSubmitAction, values: Record<string, unknown>): Promise<unknown>;
|
|
3675
|
+
declare function executeEmailAction(action: EmailSubmitAction, values: Record<string, unknown>): Promise<unknown>;
|
|
3676
|
+
declare function executeCustomAction(action: CustomSubmitAction, values: Record<string, unknown>): Promise<unknown>;
|
|
3677
|
+
declare function executeSubmitAction(action: SubmitAction, values: Record<string, unknown>): Promise<unknown>;
|
|
3678
|
+
|
|
3679
|
+
/**
|
|
3680
|
+
* Submit Orchestrator
|
|
3681
|
+
*
|
|
3682
|
+
* Orquesta la ejecución de múltiples submit actions,
|
|
3683
|
+
* manejando ejecución secuencial o paralela, condiciones, y errores.
|
|
3684
|
+
*/
|
|
3685
|
+
|
|
3686
|
+
declare function getActionsByTrigger(config: FormConfig, triggerType: SubmitTriggerType, triggerValue?: string): SubmitActionNode[];
|
|
3687
|
+
/**
|
|
3688
|
+
* Obtiene el delay mínimo para acciones con trigger onDelay
|
|
3689
|
+
*/
|
|
3690
|
+
declare function getMinDelayMs(config: FormConfig): number;
|
|
3691
|
+
/**
|
|
3692
|
+
* Ejecuta múltiples acciones de submit según la configuración
|
|
3693
|
+
*/
|
|
3694
|
+
declare function executeSubmitActions(actions: SubmitActionNode[], values: Record<string, unknown>, config: FormConfig): Promise<SubmitActionsResult>;
|
|
3695
|
+
/**
|
|
3696
|
+
* Ejecuta todas las acciones de submit del formulario filtradas por trigger
|
|
3697
|
+
*/
|
|
3698
|
+
declare function executeSubmitActionsByTrigger(config: FormConfig, triggerType: SubmitTriggerType, values: Record<string, unknown>, triggerValue?: string): Promise<SubmitActionsResult>;
|
|
3699
|
+
|
|
3700
|
+
/**
|
|
3701
|
+
* Test Data Generator — generates realistic field values for form testing.
|
|
3702
|
+
*
|
|
3703
|
+
* Lightweight, no external dependencies (no faker.js).
|
|
3704
|
+
* Two layers of intelligence:
|
|
3705
|
+
* 1. Field type → appropriate format (email, date, select option, etc.)
|
|
3706
|
+
* 2. Label/name heuristics → contextual data ("nombre" → "Carlos", "email" → "test@example.com")
|
|
3707
|
+
*/
|
|
3708
|
+
|
|
3709
|
+
type TestDataLocale = 'en' | 'es';
|
|
3710
|
+
interface TestDataOptions {
|
|
3711
|
+
/** Force a specific locale instead of auto-detecting */
|
|
3712
|
+
locale?: TestDataLocale;
|
|
3713
|
+
/** Seed for deterministic pseudo-random (optional) */
|
|
3714
|
+
seed?: number;
|
|
3715
|
+
}
|
|
3716
|
+
declare function detectLocale(fields: Fields): TestDataLocale;
|
|
3717
|
+
declare function generateFieldValue(name: string, config: FieldConfig, options?: TestDataOptions & {
|
|
3718
|
+
rng?: () => number;
|
|
3719
|
+
}): unknown;
|
|
3720
|
+
declare function generateTestData(fields: Fields, options?: TestDataOptions): Record<string, unknown>;
|
|
3721
|
+
|
|
3722
|
+
type Breakpoint = 'default' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
3723
|
+
/**
|
|
3724
|
+
* Convierte píxeles a rem (asumiendo base 16px)
|
|
3725
|
+
*/
|
|
3726
|
+
declare function pxToRem(px: number): number;
|
|
3727
|
+
/**
|
|
3728
|
+
* Genera las clases CSS para el grid del formulario
|
|
3729
|
+
*/
|
|
3730
|
+
declare function getFormGridClass(layout?: {
|
|
3731
|
+
mode?: 'manual' | 'auto';
|
|
3732
|
+
columns?: number;
|
|
3733
|
+
gap?: number;
|
|
3734
|
+
minFieldWidth?: number;
|
|
3735
|
+
}): {
|
|
3736
|
+
className: string;
|
|
3737
|
+
style: React__default.CSSProperties;
|
|
3738
|
+
};
|
|
3739
|
+
/**
|
|
3740
|
+
* Genera las clases CSS para un campo individual
|
|
3741
|
+
*/
|
|
3742
|
+
declare function getFieldClass(formLayout?: {
|
|
3743
|
+
mode?: 'manual' | 'auto';
|
|
3744
|
+
columns?: number;
|
|
3745
|
+
}, fieldLayout?: {
|
|
3746
|
+
columns?: Partial<Record<Breakpoint, number>>;
|
|
3747
|
+
order?: number | Partial<Record<Breakpoint, number>>;
|
|
3748
|
+
}): string;
|
|
3749
|
+
/**
|
|
3750
|
+
* Genera clases de hidden responsive
|
|
3751
|
+
*/
|
|
3752
|
+
declare function getHiddenClasses(hidden?: Partial<Record<Breakpoint, 'visible' | 'hidden'>>): string;
|
|
3753
|
+
|
|
3754
|
+
export { type AccordionContentProps, type AccordionItemProps, type AccordionProps, type AccordionTriggerProps, BUILD_METHODS, BUILTIN_RESOLVERS, type BaseFieldProps, type Breakpoint$1 as Breakpoint, type BuiltinTransform, type ButtonCardFieldProps, type ButtonCardOption, type ButtonCheckboxFieldProps, type ButtonConfig, type ButtonProps, type ButtonRadioFieldProps, COMMON_CLASSES, COMMON_METHODS, COMMON_STRINGS, type CalendarProps, type CheckboxFieldProps, type CheckboxGroupFieldProps, type CheckboxProps, type ColumnsValue, type ComboboxFieldProps, type CommandEmptyProps, type CommandFieldProps, type CommandGroupProps, type CommandInputProps, type CommandItemProps, type CommandListProps, type CommandProps, type ComponentName, type ComponentOverrides, ComponentProvider, type ComponentProviderProps, type ComponentRegistry, type ComponentRegistryInput, ComponentResolver, type ComponentResolverConfig, type Condition, type ConditionGroup, type ConditionOperator, type CurrencyFieldProps, type CustomSubmitAction, type CustomSubmitConfig, type DatabowlConfig, type DateFieldProps, type DateRangeFieldProps, type DefaultSubmitConfig, type DefinePlugin, type DialogContentProps, type DialogDescriptionProps, type DialogHeaderProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, type EmailProvider, type EmailSubmitAction, type EndpointConfig, FIELD_DEFAULTS, FieldBuilder, type FieldConfig, type FieldDescriptionProps, type FieldErrorProps, type FieldLabelProps, type FieldLayoutConfig, type FieldMapEntry, type FieldMapping, type FieldMappingConfig, type FieldProps, FieldRenderer, type FieldResolver, type FieldTransformFn, type Fields, type FileFieldProps, Form, FormBuilder, type FormButtonProps, type FormButtons, FormComponentsProvider, type FormComponentsProviderProps, type FormConfig, type FormControlProps, type FormFieldProps, type FormLayout, type FormPlugin, type FormProps, type FormRef, type FormStepsInfo, type GapValue, type GlobModules, type HiddenFieldProps, type HtmlFieldProps, type HttpAuthConfig, type HttpBodyConfig, type HttpEndpointConfig, type HttpRetryConfig, type HttpSubmitAction, type InputGroupFieldProps, type InputOTPGroupProps, type InputOTPProps, type InputOTPSlotProps, type InputProps, type InputSize, InternalComponentProvider, type InternalComponentProviderProps, type LabelProps, MissingComponentFallback, type MissingComponentFallbackProps, type NativeSelectFieldProps, type NativeSelectProps, OPTION_BASED_TYPES, type Option, type OtpFieldProps, type PartialComponentRegistry, PluginManager, type PopoverContentProps, type PopoverProps, type PopoverTriggerProps, type PropertyMapping, type RadioFieldProps, type RadioGroupItemProps, type RadioGroupProps, type RangeFieldProps, type RecaptchaConfig, type RecaptchaPluginConfig, type RepeaterFieldProps, type ResolvedComponents, SUSPENSE_CONFIG, type SchemaType, type SelectContentProps, type SelectFieldProps, type SelectItemProps, type SelectProps, type SelectTriggerProps, type SelectValueProps, type SeparatorProps, type SerializableFieldResolver, type SerializationHint, type SliderFieldProps, type SliderProps, type Step, type StepCondition, type StepInfo, type StepStatus, type Steps, StepsAccordion, StepsNavigation, StepsProgress, type SubmitAction, type SubmitActionCondition, type SubmitActionNode, type SubmitActionResult, type SubmitActionType, type SubmitActionsResult, type SubmitConfig, type SubmitConfirmationConfig, type SubmitExecutionConfig, type SubmitTrigger, type SubmitTriggerType, type SubmitType, type SwitchFieldProps, type SwitchGroupFieldProps, type SwitchProps, TYPE_SPECIFIC_PROPERTIES, type TestDataLocale, type TestDataOptions, type TextFieldProps, type TextareaFieldProps, type TextareaProps, type TooltipContentProps, type TooltipProps, type TooltipProviderProps, type TooltipTriggerProps, type UseSubmitConfirmationReturn, VALIDATION_METHODS, type ValidateComponentRegistry, type ValidationContext, type ValidationPresetMeta, type ValidationRules, type WebhookSubmitAction, analyticsPlugin, applyBuiltinTransform, applyFieldMapping, applyFieldMappingSync, applyFieldTransforms, applyTransform, autosavePlugin, compileValidationRules, configureComponents, coreComponents, createComponentRegistry, createMissingComponentPlaceholder, createShadcnRegistry, databowlAction, databowlPlugin, defaultSubmit, definePlugin, detectLocale, executeCustomAction, executeEmailAction, executeHttpAction, executeSubmitAction, executeSubmitActions, executeSubmitActionsByTrigger, executeWebhookAction, fieldTypeComponents, generateFieldValue, generateTestData, getActionsByTrigger, getAllKnownMethods, getAvailablePresets, getComponentResolver, getFieldClass, getFormGridClass, getHiddenClasses, getInstallCommand, getMinDelayMs, getMissingComponents, getRequiredComponents, globalPluginManager, groupMissingByPackage, iconVariants, iconVariantsConfig, inputVariants, inputVariantsConfig, isAdvancedMapping, isValidationRules, isZodSchema, localStoragePlugin, mergeComponentRegistries, parseGlobModules, pxToRem, recaptchaPlugin, registerPreset, resolvePreset, resolveValue, resolveValueSync, textareaVariants, textareaVariantsConfig, useComponentMode, useComponents, useComputedFields, useFormLayout, useFormState, useFormStepsInfo, useHasComponentProvider, useHiddenFieldResolvers, usePartialComponents, useRecaptcha, useSubmitActionTriggers, useSubmitConfirmation, withComponents };
|