@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.
@@ -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 };