formspec 0.1.0-alpha.21 → 0.1.0-alpha.23

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,1612 @@
1
+ /**
2
+ * FormSpec - Type-safe form specifications
3
+ *
4
+ * This package re-exports everything from the FormSpec library for convenience.
5
+ * You can import everything you need from a single package:
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import {
10
+ * // DSL functions
11
+ * formspec, field, group, when, is,
12
+ * // Type inference
13
+ * type InferSchema,
14
+ * // Schema generation
15
+ * buildFormSchemas,
16
+ * // Resolvers
17
+ * defineResolvers,
18
+ * // Core types
19
+ * type FormSpec, type FormElement,
20
+ * } from "formspec";
21
+ *
22
+ * // Define a form
23
+ * const InvoiceForm = formspec(
24
+ * group("Customer",
25
+ * field.text("name", { label: "Name", required: true }),
26
+ * field.dynamicEnum("country", "fetch_countries", { label: "Country" }),
27
+ * ),
28
+ * group("Details",
29
+ * field.number("amount", { label: "Amount", min: 0 }),
30
+ * field.enum("status", ["draft", "sent", "paid"]),
31
+ * when(is("status", "draft"),
32
+ * field.text("notes", { label: "Internal Notes" }),
33
+ * ),
34
+ * ),
35
+ * );
36
+ *
37
+ * // Infer the schema type
38
+ * type Schema = InferSchema<typeof InvoiceForm.elements>;
39
+ *
40
+ * // Generate JSON Schema and UI Schema
41
+ * const { jsonSchema, uiSchema } = buildFormSchemas(InvoiceForm);
42
+ *
43
+ * // Define resolvers for dynamic data
44
+ * const resolvers = defineResolvers(InvoiceForm, {
45
+ * fetch_countries: async () => ({
46
+ * options: [{ value: "us", label: "United States" }],
47
+ * validity: "valid",
48
+ * }),
49
+ * });
50
+ * ```
51
+ *
52
+ * @packageDocumentation
53
+ */
54
+
55
+ /**
56
+ * Union of all field types.
57
+ *
58
+ * @public
59
+ */
60
+ export declare type AnyField = TextField<string> | NumberField<string> | BooleanField<string> | StaticEnumField<string, readonly EnumOptionValue[]> | DynamicEnumField<string, string> | DynamicSchemaField<string> | ArrayField<string, readonly FormElement[]> | ObjectField<string, readonly FormElement[]>;
61
+
62
+ /**
63
+ * Union of all field types.
64
+ *
65
+ * @public
66
+ */
67
+ declare type AnyField_2 = TextField_2<string> | NumberField_2<string> | BooleanField_2<string> | StaticEnumField_2<string, readonly EnumOptionValue_2[]> | DynamicEnumField_2<string, string> | DynamicSchemaField_2<string> | ArrayField_2<string, readonly FormElement_2[]> | ObjectField_2<string, readonly FormElement_2[]>;
68
+
69
+ /**
70
+ * An array field containing repeating items.
71
+ *
72
+ * Use this for lists of values (e.g., multiple addresses, line items).
73
+ *
74
+ * @typeParam N - The field name (string literal type)
75
+ * @typeParam Items - The form elements that define each array item
76
+ *
77
+ * @public
78
+ */
79
+ export declare interface ArrayField<N extends string, Items extends readonly FormElement[]> {
80
+ /** Type discriminator for form elements */
81
+ readonly _type: "field";
82
+ /** Field type discriminator - identifies this as an array field */
83
+ readonly _field: "array";
84
+ /** Unique field identifier used as the schema key */
85
+ readonly name: N;
86
+ /** Form elements that define the schema for each array item */
87
+ readonly items: Items;
88
+ /** Display label for the field */
89
+ readonly label?: string;
90
+ /** Whether this field is required for form submission */
91
+ readonly required?: boolean;
92
+ /** Minimum number of items required */
93
+ readonly minItems?: number;
94
+ /** Maximum number of items allowed */
95
+ readonly maxItems?: number;
96
+ }
97
+
98
+ /**
99
+ * An array field containing repeating items.
100
+ *
101
+ * Use this for lists of values (e.g., multiple addresses, line items).
102
+ *
103
+ * @typeParam N - The field name (string literal type)
104
+ * @typeParam Items - The form elements that define each array item
105
+ *
106
+ * @public
107
+ */
108
+ declare interface ArrayField_2<N extends string, Items extends readonly FormElement_2[]> {
109
+ /** Type discriminator for form elements */
110
+ readonly _type: "field";
111
+ /** Field type discriminator - identifies this as an array field */
112
+ readonly _field: "array";
113
+ /** Unique field identifier used as the schema key */
114
+ readonly name: N;
115
+ /** Form elements that define the schema for each array item */
116
+ readonly items: Items;
117
+ /** Display label for the field */
118
+ readonly label?: string;
119
+ /** Whether this field is required for form submission */
120
+ readonly required?: boolean;
121
+ /** Minimum number of items required */
122
+ readonly minItems?: number;
123
+ /** Maximum number of items allowed */
124
+ readonly maxItems?: number;
125
+ }
126
+
127
+ /**
128
+ * A boolean checkbox field.
129
+ *
130
+ * @typeParam N - The field name (string literal type)
131
+ *
132
+ * @public
133
+ */
134
+ export declare interface BooleanField<N extends string> {
135
+ /** Type discriminator for form elements */
136
+ readonly _type: "field";
137
+ /** Field type discriminator - identifies this as a boolean field */
138
+ readonly _field: "boolean";
139
+ /** Unique field identifier used as the schema key */
140
+ readonly name: N;
141
+ /** Display label for the field */
142
+ readonly label?: string;
143
+ /** Whether this field is required for form submission */
144
+ readonly required?: boolean;
145
+ }
146
+
147
+ /**
148
+ * A boolean checkbox field.
149
+ *
150
+ * @typeParam N - The field name (string literal type)
151
+ *
152
+ * @public
153
+ */
154
+ declare interface BooleanField_2<N extends string> {
155
+ /** Type discriminator for form elements */
156
+ readonly _type: "field";
157
+ /** Field type discriminator - identifies this as a boolean field */
158
+ readonly _field: "boolean";
159
+ /** Unique field identifier used as the schema key */
160
+ readonly name: N;
161
+ /** Display label for the field */
162
+ readonly label?: string;
163
+ /** Whether this field is required for form submission */
164
+ readonly required?: boolean;
165
+ }
166
+
167
+ /**
168
+ * Builds both JSON Schema and UI Schema from a FormSpec.
169
+ *
170
+ * @public
171
+ */
172
+ export declare function buildFormSchemas<E extends readonly FormElement[]>(form: FormSpec<E>, options?: BuildFormSchemasOptions): BuildResult;
173
+
174
+ /**
175
+ * Options for building schemas from a FormSpec.
176
+ *
177
+ * Currently identical to `GenerateJsonSchemaOptions`. Defined separately so the
178
+ * Chain DSL surface can grow independently in the future if needed.
179
+ *
180
+ * @public
181
+ */
182
+ export declare type BuildFormSchemasOptions = GenerateJsonSchemaOptions;
183
+
184
+ /**
185
+ * Result of building form schemas.
186
+ *
187
+ * @public
188
+ */
189
+ export declare interface BuildResult {
190
+ /** JSON Schema 2020-12 for validation */
191
+ readonly jsonSchema: JsonSchema2020;
192
+ /** JSON Forms UI Schema for rendering */
193
+ readonly uiSchema: UISchema;
194
+ }
195
+
196
+ /**
197
+ * Builds a schema type from extracted fields.
198
+ *
199
+ * @public
200
+ */
201
+ export declare type BuildSchema<Fields> = { [N in Fields extends { name: infer K extends string } ? K : never]: InferFieldValue<Extract<Fields, { name: N } & AnyField>> };
202
+
203
+ /**
204
+ * A Categorization element (tab-based layout).
205
+ *
206
+ * @public
207
+ */
208
+ export declare interface Categorization {
209
+ readonly type: "Categorization";
210
+ readonly elements: Category[];
211
+ readonly label?: string | undefined;
212
+ readonly rule?: Rule | undefined;
213
+ readonly options?: Record<string, unknown> | undefined;
214
+ readonly [k: string]: unknown;
215
+ }
216
+
217
+ /**
218
+ * A Category element, used inside a Categorization layout.
219
+ *
220
+ * @public
221
+ */
222
+ export declare interface Category {
223
+ readonly type: "Category";
224
+ readonly label: string;
225
+ readonly elements: UISchemaElement[];
226
+ readonly rule?: Rule | undefined;
227
+ readonly options?: Record<string, unknown> | undefined;
228
+ readonly [k: string]: unknown;
229
+ }
230
+
231
+ /**
232
+ * A conditional wrapper that shows/hides elements based on another field's value.
233
+ *
234
+ * @typeParam FieldName - The field to check
235
+ * @typeParam Value - The value that triggers the condition
236
+ * @typeParam Elements - Tuple of contained form elements
237
+ *
238
+ * @public
239
+ */
240
+ export declare interface Conditional<FieldName extends string, Value, Elements extends readonly FormElement[]> {
241
+ /** Type discriminator - identifies this as a conditional element */
242
+ readonly _type: "conditional";
243
+ /** Name of the field whose value determines visibility */
244
+ readonly field: FieldName;
245
+ /** Value that triggers the condition (shows nested elements) */
246
+ readonly value: Value;
247
+ /** Form elements shown when condition is met */
248
+ readonly elements: Elements;
249
+ }
250
+
251
+ /**
252
+ * A conditional wrapper that shows/hides elements based on another field's value.
253
+ *
254
+ * @typeParam FieldName - The field to check
255
+ * @typeParam Value - The value that triggers the condition
256
+ * @typeParam Elements - Tuple of contained form elements
257
+ *
258
+ * @public
259
+ */
260
+ declare interface Conditional_2<FieldName extends string, Value, Elements extends readonly FormElement_2[]> {
261
+ /** Type discriminator - identifies this as a conditional element */
262
+ readonly _type: "conditional";
263
+ /** Name of the field whose value determines visibility */
264
+ readonly field: FieldName;
265
+ /** Value that triggers the condition (shows nested elements) */
266
+ readonly value: Value;
267
+ /** Form elements shown when condition is met */
268
+ readonly elements: Elements;
269
+ }
270
+
271
+ /**
272
+ * A Control element that binds to a JSON Schema property.
273
+ *
274
+ * @public
275
+ */
276
+ export declare interface ControlElement {
277
+ readonly type: "Control";
278
+ readonly scope: string;
279
+ readonly label?: string | false | undefined;
280
+ readonly rule?: Rule | undefined;
281
+ readonly options?: Record<string, unknown> | undefined;
282
+ readonly [k: string]: unknown;
283
+ }
284
+
285
+ /**
286
+ * Creates initial field state with default values.
287
+ *
288
+ * @typeParam T - The value type of the field
289
+ * @param value - The initial value for the field
290
+ * @returns Initial field state
291
+ *
292
+ * @public
293
+ */
294
+ export declare function createInitialFieldState<T>(value: T): FieldState<T>;
295
+
296
+ /**
297
+ * A single option returned by a data source resolver.
298
+ *
299
+ * @typeParam T - The data type for additional option metadata
300
+ *
301
+ * @public
302
+ */
303
+ export declare interface DataSourceOption<T = unknown> {
304
+ /** The value stored when this option is selected */
305
+ readonly value: string;
306
+ /** The display label for this option */
307
+ readonly label: string;
308
+ /** Optional additional data associated with this option */
309
+ readonly data?: T;
310
+ }
311
+
312
+ /**
313
+ * Registry for dynamic data sources.
314
+ *
315
+ * Extend this interface via module augmentation to register your data sources:
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * declare module "@formspec/core" {
320
+ * interface DataSourceRegistry {
321
+ * countries: { id: string; code: string; name: string };
322
+ * templates: { id: string; name: string; category: string };
323
+ * }
324
+ * }
325
+ * ```
326
+ *
327
+ * @public
328
+ */
329
+ export declare interface DataSourceRegistry {
330
+ }
331
+
332
+ /**
333
+ * Gets the value type for a registered data source.
334
+ *
335
+ * If the source has an `id` property, that becomes the value type.
336
+ * Otherwise, defaults to `string`.
337
+ *
338
+ * @public
339
+ */
340
+ export declare type DataSourceValueType<Source extends string> = Source extends keyof DataSourceRegistry ? DataSourceRegistry[Source] extends {
341
+ id: infer ID;
342
+ } ? ID : string : string;
343
+
344
+ /**
345
+ * Defines resolvers for a form's dynamic data sources.
346
+ *
347
+ * @public
348
+ */
349
+ export declare function defineResolvers<E extends readonly FormElement[], Sources extends string = ResolverSourcesForForm<E>>(form: FormSpec<E>, resolvers: ResolverMap<Sources>): ResolverRegistry<Sources>;
350
+
351
+ /**
352
+ * A field with dynamic enum options (fetched from a data source at runtime).
353
+ *
354
+ * @typeParam N - The field name (string literal type)
355
+ * @typeParam Source - The data source key (from DataSourceRegistry)
356
+ *
357
+ * @public
358
+ */
359
+ export declare interface DynamicEnumField<N extends string, Source extends string> {
360
+ /** Type discriminator for form elements */
361
+ readonly _type: "field";
362
+ /** Field type discriminator - identifies this as a dynamic enum field */
363
+ readonly _field: "dynamic_enum";
364
+ /** Unique field identifier used as the schema key */
365
+ readonly name: N;
366
+ /** Data source key for fetching options at runtime */
367
+ readonly source: Source;
368
+ /** Display label for the field */
369
+ readonly label?: string;
370
+ /** Whether this field is required for form submission */
371
+ readonly required?: boolean;
372
+ /** Field names whose values are needed to fetch options */
373
+ readonly params?: readonly string[];
374
+ }
375
+
376
+ /**
377
+ * A field with dynamic enum options (fetched from a data source at runtime).
378
+ *
379
+ * @typeParam N - The field name (string literal type)
380
+ * @typeParam Source - The data source key (from DataSourceRegistry)
381
+ *
382
+ * @public
383
+ */
384
+ declare interface DynamicEnumField_2<N extends string, Source extends string> {
385
+ /** Type discriminator for form elements */
386
+ readonly _type: "field";
387
+ /** Field type discriminator - identifies this as a dynamic enum field */
388
+ readonly _field: "dynamic_enum";
389
+ /** Unique field identifier used as the schema key */
390
+ readonly name: N;
391
+ /** Data source key for fetching options at runtime */
392
+ readonly source: Source;
393
+ /** Display label for the field */
394
+ readonly label?: string;
395
+ /** Whether this field is required for form submission */
396
+ readonly required?: boolean;
397
+ /** Field names whose values are needed to fetch options */
398
+ readonly params?: readonly string[];
399
+ }
400
+
401
+ /**
402
+ * A field that loads its schema dynamically (e.g., from an extension).
403
+ *
404
+ * @typeParam N - The field name (string literal type)
405
+ *
406
+ * @public
407
+ */
408
+ export declare interface DynamicSchemaField<N extends string> {
409
+ /** Type discriminator for form elements */
410
+ readonly _type: "field";
411
+ /** Field type discriminator - identifies this as a dynamic schema field */
412
+ readonly _field: "dynamic_schema";
413
+ /** Unique field identifier used as the schema key */
414
+ readonly name: N;
415
+ /** Identifier for the schema source */
416
+ readonly schemaSource: string;
417
+ /** Display label for the field */
418
+ readonly label?: string;
419
+ /** Whether this field is required for form submission */
420
+ readonly required?: boolean;
421
+ /** Field names whose values are needed to configure the schema */
422
+ readonly params?: readonly string[];
423
+ }
424
+
425
+ /**
426
+ * A field that loads its schema dynamically (e.g., from an extension).
427
+ *
428
+ * @typeParam N - The field name (string literal type)
429
+ *
430
+ * @public
431
+ */
432
+ declare interface DynamicSchemaField_2<N extends string> {
433
+ /** Type discriminator for form elements */
434
+ readonly _type: "field";
435
+ /** Field type discriminator - identifies this as a dynamic schema field */
436
+ readonly _field: "dynamic_schema";
437
+ /** Unique field identifier used as the schema key */
438
+ readonly name: N;
439
+ /** Identifier for the schema source */
440
+ readonly schemaSource: string;
441
+ /** Display label for the field */
442
+ readonly label?: string;
443
+ /** Whether this field is required for form submission */
444
+ readonly required?: boolean;
445
+ /** Field names whose values are needed to configure the schema */
446
+ readonly params?: readonly string[];
447
+ }
448
+
449
+ /**
450
+ * An enum option with a separate ID and display label.
451
+ *
452
+ * Use this when the stored value (id) should differ from the display text (label).
453
+ *
454
+ * @public
455
+ */
456
+ export declare interface EnumOption {
457
+ readonly id: string;
458
+ readonly label: string;
459
+ }
460
+
461
+ /**
462
+ * An enum option with a separate ID and display label.
463
+ *
464
+ * Use this when the stored value (id) should differ from the display text (label).
465
+ *
466
+ * @public
467
+ */
468
+ declare interface EnumOption_2 {
469
+ readonly id: string;
470
+ readonly label: string;
471
+ }
472
+
473
+ /**
474
+ * Valid enum option types: either plain strings or objects with id/label.
475
+ *
476
+ * @public
477
+ */
478
+ export declare type EnumOptionValue = string | EnumOption;
479
+
480
+ /**
481
+ * Valid enum option types: either plain strings or objects with id/label.
482
+ *
483
+ * @public
484
+ */
485
+ declare type EnumOptionValue_2 = string | EnumOption_2;
486
+
487
+ /**
488
+ * Predicate types for conditional logic.
489
+ *
490
+ * Predicates are used with `when()` to define conditions in a readable way.
491
+ */
492
+ /**
493
+ * An equality predicate that checks if a field equals a specific value.
494
+ *
495
+ * @typeParam K - The field name to check
496
+ * @typeParam V - The value to compare against
497
+ *
498
+ * @public
499
+ */
500
+ export declare interface EqualsPredicate<K extends string, V> {
501
+ /** Predicate type discriminator */
502
+ readonly _predicate: "equals";
503
+ /** Name of the field to check */
504
+ readonly field: K;
505
+ /** Value that the field must equal */
506
+ readonly value: V;
507
+ }
508
+
509
+ /**
510
+ * Extracts fields that are inside conditionals.
511
+ *
512
+ * @public
513
+ */
514
+ export declare type ExtractConditionalFields<E> = E extends AnyField ? never : E extends Group<infer Elements> ? ExtractConditionalFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer Elements> ? ExtractFieldsFromArray<Elements> : never;
515
+
516
+ /**
517
+ * Extracts conditional fields from an array of elements.
518
+ *
519
+ * @public
520
+ */
521
+ export declare type ExtractConditionalFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractConditionalFields<First> | ExtractConditionalFieldsFromArray<Rest> : never;
522
+
523
+ /**
524
+ * Extracts dynamic data-source names referenced by a single FormSpec element.
525
+ *
526
+ * @public
527
+ */
528
+ export declare type ExtractDynamicSources<E> = E extends DynamicEnumField<string, infer S> ? S : E extends Group<infer Elements> ? ExtractDynamicSourcesFromArray<Elements> : E extends Conditional<string, unknown, infer Elements> ? ExtractDynamicSourcesFromArray<Elements> : never;
529
+
530
+ /**
531
+ * Extracts dynamic data-source names referenced anywhere in an element array.
532
+ *
533
+ * @public
534
+ */
535
+ export declare type ExtractDynamicSourcesFromArray<Elements> = Elements extends readonly [
536
+ infer First,
537
+ ...infer Rest
538
+ ] ? ExtractDynamicSources<First> | ExtractDynamicSourcesFromArray<Rest> : never;
539
+
540
+ /**
541
+ * Extracts all fields from a single element.
542
+ *
543
+ * @public
544
+ */
545
+ export declare type ExtractFields<E> = E extends AnyField ? E : E extends Group<infer Elements> ? ExtractFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer Elements> ? ExtractFieldsFromArray<Elements> : never;
546
+
547
+ /**
548
+ * Extracts fields from an array of elements.
549
+ *
550
+ * @public
551
+ */
552
+ export declare type ExtractFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractFields<First> | ExtractFieldsFromArray<Rest> : never;
553
+
554
+ /**
555
+ * Extracts fields that are not inside conditionals.
556
+ *
557
+ * @public
558
+ */
559
+ export declare type ExtractNonConditionalFields<E> = E extends AnyField ? E : E extends Group<infer Elements> ? ExtractNonConditionalFieldsFromArray<Elements> : E extends Conditional<string, unknown, infer _Elements> ? never : never;
560
+
561
+ /**
562
+ * Extracts non-conditional fields from an array of elements.
563
+ *
564
+ * @public
565
+ */
566
+ export declare type ExtractNonConditionalFieldsFromArray<Elements> = Elements extends readonly [infer First, ...infer Rest] ? ExtractNonConditionalFields<First> | ExtractNonConditionalFieldsFromArray<Rest> : never;
567
+
568
+ /**
569
+ * Response from a data source resolver function.
570
+ *
571
+ * @typeParam T - The data type for option metadata
572
+ *
573
+ * @public
574
+ */
575
+ export declare interface FetchOptionsResponse<T = unknown> {
576
+ /** The available options */
577
+ readonly options: readonly DataSourceOption<T>[];
578
+ /** Validity state of the fetch operation */
579
+ readonly validity: "valid" | "invalid" | "unknown";
580
+ /** Optional message (e.g., error description) */
581
+ readonly message?: string;
582
+ }
583
+
584
+ /**
585
+ * Field builder namespace containing functions to create each field type.
586
+ *
587
+ * @example
588
+ * ```typescript
589
+ * import { field } from "@formspec/dsl";
590
+ *
591
+ * field.text("name", { label: "Full Name" });
592
+ * field.number("age", { min: 0, max: 150 });
593
+ * field.enum("status", ["draft", "sent", "paid"]);
594
+ * field.dynamicEnum("country", "countries", { label: "Country" });
595
+ * ```
596
+ *
597
+ * @public
598
+ */
599
+ export declare const field: {
600
+ /**
601
+ * Creates a text input field.
602
+ *
603
+ * @param name - The field name (used as the schema key)
604
+ * @param config - Optional configuration for label, placeholder, etc.
605
+ * @returns A TextField descriptor
606
+ */
607
+ text: <const N extends string>(name: N, config?: Omit<TextField_2<N>, "_type" | "_field" | "name">) => TextField_2<N>;
608
+ /**
609
+ * Creates a numeric input field.
610
+ *
611
+ * @param name - The field name (used as the schema key)
612
+ * @param config - Optional configuration for label, min, max, etc.
613
+ * @returns A NumberField descriptor
614
+ */
615
+ number: <const N extends string>(name: N, config?: Omit<NumberField_2<N>, "_type" | "_field" | "name">) => NumberField_2<N>;
616
+ /**
617
+ * Creates a boolean checkbox field.
618
+ *
619
+ * @param name - The field name (used as the schema key)
620
+ * @param config - Optional configuration for label, etc.
621
+ * @returns A BooleanField descriptor
622
+ */
623
+ boolean: <const N extends string>(name: N, config?: Omit<BooleanField_2<N>, "_type" | "_field" | "name">) => BooleanField_2<N>;
624
+ /**
625
+ * Creates a field with static enum options (known at compile time).
626
+ *
627
+ * Literal types are automatically inferred - no `as const` needed:
628
+ * ```typescript
629
+ * field.enum("status", ["draft", "sent", "paid"])
630
+ * // Schema type: "draft" | "sent" | "paid"
631
+ * ```
632
+ *
633
+ * Options can be strings or objects with `id` and `label`:
634
+ * ```typescript
635
+ * field.enum("priority", [
636
+ * { id: "low", label: "Low Priority" },
637
+ * { id: "high", label: "High Priority" },
638
+ * ])
639
+ * ```
640
+ *
641
+ * **Note:** All options must be of the same type (all strings OR all objects).
642
+ * Mixing strings and objects will throw a runtime error.
643
+ *
644
+ * @param name - The field name (used as the schema key)
645
+ * @param options - Array of allowed string values or objects with `id` and `label` properties
646
+ * @param config - Optional configuration for label, etc.
647
+ * @returns A StaticEnumField descriptor
648
+ * @throws Error if options array contains mixed types (strings and objects)
649
+ */
650
+ enum: <const N extends string, const O extends readonly EnumOptionValue_2[]>(name: N, options: O, config?: Omit<StaticEnumField_2<N, O>, "_type" | "_field" | "name" | "options">) => StaticEnumField_2<N, O>;
651
+ /**
652
+ * Creates a field with dynamic enum options (fetched from a data source at runtime).
653
+ *
654
+ * The data source must be registered in DataSourceRegistry via module augmentation:
655
+ * ```typescript
656
+ * declare module "@formspec/core" {
657
+ * interface DataSourceRegistry {
658
+ * countries: { id: string; code: string; name: string };
659
+ * }
660
+ * }
661
+ *
662
+ * field.dynamicEnum("country", "countries", { label: "Country" })
663
+ * ```
664
+ *
665
+ * @param name - The field name (used as the schema key)
666
+ * @param source - The data source key (must be in DataSourceRegistry)
667
+ * @param config - Optional configuration for label, params, etc.
668
+ * @returns A DynamicEnumField descriptor
669
+ */
670
+ dynamicEnum: <const N extends string, const Source extends string>(name: N, source: Source, config?: Omit<DynamicEnumField_2<N, Source>, "_type" | "_field" | "name" | "source">) => DynamicEnumField_2<N, Source>;
671
+ /**
672
+ * Creates a field that loads its schema dynamically (e.g., from an extension).
673
+ *
674
+ * @param name - The field name (used as the schema key)
675
+ * @param schemaSource - Identifier for the schema source
676
+ * @param config - Optional configuration for label, etc.
677
+ * @returns A DynamicSchemaField descriptor
678
+ */
679
+ dynamicSchema: <const N extends string>(name: N, schemaSource: string, config?: Omit<DynamicSchemaField_2<N>, "_type" | "_field" | "name" | "schemaSource">) => DynamicSchemaField_2<N>;
680
+ /**
681
+ * Creates an array field containing repeating items.
682
+ *
683
+ * Use this for lists of values (e.g., multiple addresses, line items).
684
+ *
685
+ * @example
686
+ * ```typescript
687
+ * field.array("addresses",
688
+ * field.text("street", { label: "Street" }),
689
+ * field.text("city", { label: "City" }),
690
+ * field.text("zip", { label: "ZIP Code" }),
691
+ * )
692
+ * ```
693
+ *
694
+ * @param name - The field name (used as the schema key)
695
+ * @param items - The form elements that define each array item
696
+ * @returns An ArrayField descriptor
697
+ */
698
+ array: <const N extends string, const Items extends readonly FormElement_2[]>(name: N, ...items: Items) => ArrayField_2<N, Items>;
699
+ /**
700
+ * Creates an array field with additional configuration options.
701
+ *
702
+ * @example
703
+ * ```typescript
704
+ * field.arrayWithConfig("lineItems", {
705
+ * label: "Line Items",
706
+ * minItems: 1,
707
+ * maxItems: 10,
708
+ * },
709
+ * field.text("description"),
710
+ * field.number("quantity"),
711
+ * )
712
+ * ```
713
+ *
714
+ * @param name - The field name (used as the schema key)
715
+ * @param config - Configuration for label, minItems, maxItems, etc.
716
+ * @param items - The form elements that define each array item
717
+ * @returns An ArrayField descriptor
718
+ */
719
+ arrayWithConfig: <const N extends string, const Items extends readonly FormElement_2[]>(name: N, config: Omit<ArrayField_2<N, Items>, "_type" | "_field" | "name" | "items">, ...items: Items) => ArrayField_2<N, Items>;
720
+ /**
721
+ * Creates an object field containing nested properties.
722
+ *
723
+ * Use this for grouping related fields under a single key in the schema.
724
+ *
725
+ * @example
726
+ * ```typescript
727
+ * field.object("address",
728
+ * field.text("street", { label: "Street" }),
729
+ * field.text("city", { label: "City" }),
730
+ * field.text("zip", { label: "ZIP Code" }),
731
+ * )
732
+ * ```
733
+ *
734
+ * @param name - The field name (used as the schema key)
735
+ * @param properties - The form elements that define the object's properties
736
+ * @returns An ObjectField descriptor
737
+ */
738
+ object: <const N extends string, const Properties extends readonly FormElement_2[]>(name: N, ...properties: Properties) => ObjectField_2<N, Properties>;
739
+ /**
740
+ * Creates an object field with additional configuration options.
741
+ *
742
+ * @example
743
+ * ```typescript
744
+ * field.objectWithConfig("billingAddress", { label: "Billing Address", required: true },
745
+ * field.text("street"),
746
+ * field.text("city"),
747
+ * )
748
+ * ```
749
+ *
750
+ * @param name - The field name (used as the schema key)
751
+ * @param config - Configuration for label, required, etc.
752
+ * @param properties - The form elements that define the object's properties
753
+ * @returns An ObjectField descriptor
754
+ */
755
+ objectWithConfig: <const N extends string, const Properties extends readonly FormElement_2[]>(name: N, config: Omit<ObjectField_2<N, Properties>, "_type" | "_field" | "name" | "properties">, ...properties: Properties) => ObjectField_2<N, Properties>;
756
+ };
757
+
758
+ /**
759
+ * Represents the runtime state of a single form field.
760
+ *
761
+ * @typeParam T - The value type of the field
762
+ *
763
+ * @public
764
+ */
765
+ export declare interface FieldState<T> {
766
+ /** Current value of the field */
767
+ readonly value: T;
768
+ /** Whether the field has been modified by the user */
769
+ readonly dirty: boolean;
770
+ /** Whether the field has been focused and blurred */
771
+ readonly touched: boolean;
772
+ /** Current validity state */
773
+ readonly validity: Validity;
774
+ /** Validation error messages, if any */
775
+ readonly errors: readonly string[];
776
+ }
777
+
778
+ /**
779
+ * Utility type that flattens intersection types.
780
+ *
781
+ * @public
782
+ */
783
+ export declare type FlattenIntersection<T> = { [K in keyof T]: T[K] } & {};
784
+
785
+ /**
786
+ * Union of all form element types (fields and structural elements).
787
+ *
788
+ * @public
789
+ */
790
+ export declare type FormElement = AnyField | Group<readonly FormElement[]> | Conditional<string, unknown, readonly FormElement[]>;
791
+
792
+ /**
793
+ * Union of all form element types (fields and structural elements).
794
+ *
795
+ * @public
796
+ */
797
+ declare type FormElement_2 = AnyField_2 | Group_2<readonly FormElement_2[]> | Conditional_2<string, unknown, readonly FormElement_2[]>;
798
+
799
+ /**
800
+ * A complete form specification.
801
+ *
802
+ * @typeParam Elements - Tuple of top-level form elements
803
+ *
804
+ * @public
805
+ */
806
+ export declare interface FormSpec<Elements extends readonly FormElement[]> {
807
+ /** Top-level form elements */
808
+ readonly elements: Elements;
809
+ }
810
+
811
+ /**
812
+ * Creates a complete form specification.
813
+ *
814
+ * @public
815
+ */
816
+ export declare function formspec<const Elements extends readonly FormElement[]>(...elements: Elements): FormSpec<Elements>;
817
+
818
+ /**
819
+ * Options for creating a form specification.
820
+ *
821
+ * @public
822
+ */
823
+ export declare interface FormSpecOptions {
824
+ /**
825
+ * Whether to validate the form structure.
826
+ * - `true` or `"warn"`: Validate and log warnings/errors to console
827
+ * - `"throw"`: Validate and throw an error if validation fails
828
+ * - `false`: Skip validation (default in production for performance)
829
+ *
830
+ * @defaultValue false
831
+ */
832
+ validate?: boolean | "warn" | "throw";
833
+ /**
834
+ * Optional name for the form (used in validation messages).
835
+ */
836
+ name?: string;
837
+ }
838
+
839
+ /**
840
+ * Creates a complete form specification with validation options.
841
+ *
842
+ * @public
843
+ */
844
+ export declare function formspecWithValidation<const Elements extends readonly FormElement[]>(options: FormSpecOptions, ...elements: Elements): FormSpec<Elements>;
845
+
846
+ /**
847
+ * Represents the runtime state of an entire form.
848
+ *
849
+ * @typeParam Schema - The form schema type (maps field names to value types)
850
+ *
851
+ * @public
852
+ */
853
+ export declare interface FormState<Schema extends Record<string, unknown>> {
854
+ /** State for each field, keyed by field name */
855
+ readonly fields: {
856
+ readonly [K in keyof Schema]: FieldState<Schema[K]>;
857
+ };
858
+ /** Whether any field has been modified */
859
+ readonly dirty: boolean;
860
+ /** Whether the form is currently being submitted */
861
+ readonly submitting: boolean;
862
+ /** Overall form validity (derived from all field validities) */
863
+ readonly validity: Validity;
864
+ }
865
+
866
+ /**
867
+ * Generates a JSON Schema 2020-12 from a FormSpec.
868
+ *
869
+ * @public
870
+ */
871
+ export declare function generateJsonSchema<E extends readonly FormElement[]>(form: FormSpec<E>, options?: GenerateJsonSchemaOptions): JsonSchema2020;
872
+
873
+ /**
874
+ * Options for generating JSON Schema from a Chain DSL form.
875
+ *
876
+ * @public
877
+ */
878
+ export declare interface GenerateJsonSchemaOptions {
879
+ /**
880
+ * Vendor prefix for emitted extension keywords.
881
+ * @defaultValue "x-formspec"
882
+ */
883
+ readonly vendorPrefix?: string | undefined;
884
+ }
885
+
886
+ /**
887
+ * Generates a UI schema from a FormSpec.
888
+ *
889
+ * @public
890
+ */
891
+ export declare function generateUiSchema<E extends readonly FormElement[]>(form: FormSpec<E>): UISchema;
892
+
893
+ /**
894
+ * A visual grouping of form elements.
895
+ *
896
+ * Groups provide visual organization and can be rendered as fieldsets or sections.
897
+ *
898
+ * @typeParam Elements - Tuple of contained form elements
899
+ *
900
+ * @public
901
+ */
902
+ export declare interface Group<Elements extends readonly FormElement[]> {
903
+ /** Type discriminator - identifies this as a group element */
904
+ readonly _type: "group";
905
+ /** Display label for the group */
906
+ readonly label: string;
907
+ /** Form elements contained within this group */
908
+ readonly elements: Elements;
909
+ }
910
+
911
+ /**
912
+ * Creates a visual group of form elements.
913
+ *
914
+ * @public
915
+ */
916
+ export declare function group<const Elements extends readonly FormElement[]>(label: string, ...elements: Elements): Group<Elements>;
917
+
918
+ /**
919
+ * A visual grouping of form elements.
920
+ *
921
+ * Groups provide visual organization and can be rendered as fieldsets or sections.
922
+ *
923
+ * @typeParam Elements - Tuple of contained form elements
924
+ *
925
+ * @public
926
+ */
927
+ declare interface Group_2<Elements extends readonly FormElement_2[]> {
928
+ /** Type discriminator - identifies this as a group element */
929
+ readonly _type: "group";
930
+ /** Display label for the group */
931
+ readonly label: string;
932
+ /** Form elements contained within this group */
933
+ readonly elements: Elements;
934
+ }
935
+
936
+ /**
937
+ * A group element with a label.
938
+ *
939
+ * @public
940
+ */
941
+ export declare interface GroupLayout {
942
+ readonly type: "Group";
943
+ readonly label: string;
944
+ readonly elements: UISchemaElement[];
945
+ readonly rule?: Rule | undefined;
946
+ readonly options?: Record<string, unknown> | undefined;
947
+ readonly [k: string]: unknown;
948
+ }
949
+
950
+ /**
951
+ * A horizontal layout element.
952
+ *
953
+ * @public
954
+ */
955
+ export declare interface HorizontalLayout {
956
+ readonly type: "HorizontalLayout";
957
+ readonly elements: UISchemaElement[];
958
+ readonly rule?: Rule | undefined;
959
+ readonly options?: Record<string, unknown> | undefined;
960
+ readonly [k: string]: unknown;
961
+ }
962
+
963
+ /**
964
+ * Infers the value type from a single field.
965
+ *
966
+ * @public
967
+ */
968
+ export declare type InferFieldValue<F> = F extends TextField<string> ? string : F extends NumberField<string> ? number : F extends BooleanField<string> ? boolean : F extends StaticEnumField<string, infer O extends readonly EnumOptionValue[]> ? O extends readonly EnumOption[] ? O[number]["id"] : O extends readonly string[] ? O[number] : never : F extends DynamicEnumField<string, infer Source> ? DataSourceValueType<Source> : F extends DynamicSchemaField<string> ? Record<string, unknown> : F extends ArrayField<string, infer Items extends readonly FormElement[]> ? InferSchema<Items>[] : F extends ObjectField<string, infer Properties extends readonly FormElement[]> ? InferSchema<Properties> : never;
969
+
970
+ /**
971
+ * Infers the schema type from a FormSpec.
972
+ *
973
+ * @public
974
+ */
975
+ export declare type InferFormSchema<F extends FormSpec<readonly FormElement[]>> = F extends FormSpec<infer Elements> ? InferSchema<Elements> : never;
976
+
977
+ /**
978
+ * Infers the schema type from an array of form elements.
979
+ *
980
+ * @public
981
+ */
982
+ export declare type InferSchema<Elements extends readonly FormElement[]> = FlattenIntersection<BuildSchema<ExtractNonConditionalFieldsFromArray<Elements>> & Partial<BuildSchema<ExtractConditionalFieldsFromArray<Elements>>>>;
983
+
984
+ /**
985
+ * Creates an equality predicate that checks if a field equals a specific value.
986
+ *
987
+ * @public
988
+ */
989
+ export declare function is<const K extends string, const V>(field: K, value: V): EqualsPredicate<K, V>;
990
+
991
+ /**
992
+ * Narrows a `FormElement` to an array field.
993
+ *
994
+ * @public
995
+ */
996
+ export declare function isArrayField(element: FormElement): element is ArrayField<string, readonly FormElement[]>;
997
+
998
+ /**
999
+ * Narrows a `FormElement` to a boolean checkbox field.
1000
+ *
1001
+ * @public
1002
+ */
1003
+ export declare function isBooleanField(element: FormElement): element is BooleanField<string>;
1004
+
1005
+ /**
1006
+ * Narrows a `FormElement` to a conditional wrapper.
1007
+ *
1008
+ * @public
1009
+ */
1010
+ export declare function isConditional(element: FormElement): element is Conditional<string, unknown, readonly FormElement[]>;
1011
+
1012
+ /**
1013
+ * Narrows a `FormElement` to a dynamic enum field.
1014
+ *
1015
+ * @public
1016
+ */
1017
+ export declare function isDynamicEnumField(element: FormElement): element is DynamicEnumField<string, string>;
1018
+
1019
+ /**
1020
+ * Narrows a `FormElement` to a dynamic schema field.
1021
+ *
1022
+ * @public
1023
+ */
1024
+ export declare function isDynamicSchemaField(element: FormElement): element is DynamicSchemaField<string>;
1025
+
1026
+ /**
1027
+ * Narrows a `FormElement` to any field type.
1028
+ *
1029
+ * @public
1030
+ */
1031
+ export declare function isField(element: FormElement): element is AnyField;
1032
+
1033
+ /**
1034
+ * Narrows a `FormElement` to a visual group.
1035
+ *
1036
+ * @public
1037
+ */
1038
+ export declare function isGroup(element: FormElement): element is Group<readonly FormElement[]>;
1039
+
1040
+ /**
1041
+ * Narrows a `FormElement` to a numeric input field.
1042
+ *
1043
+ * @public
1044
+ */
1045
+ export declare function isNumberField(element: FormElement): element is NumberField<string>;
1046
+
1047
+ /**
1048
+ * Narrows a `FormElement` to an object field.
1049
+ *
1050
+ * @public
1051
+ */
1052
+ export declare function isObjectField(element: FormElement): element is ObjectField<string, readonly FormElement[]>;
1053
+
1054
+ /**
1055
+ * Narrows a `FormElement` to a static enum field.
1056
+ *
1057
+ * @public
1058
+ */
1059
+ export declare function isStaticEnumField(element: FormElement): element is StaticEnumField<string, readonly EnumOptionValue[]>;
1060
+
1061
+ /**
1062
+ * Narrows a `FormElement` to a text input field.
1063
+ *
1064
+ * @public
1065
+ */
1066
+ export declare function isTextField(element: FormElement): element is TextField<string>;
1067
+
1068
+ /**
1069
+ * A JSON Schema 2020-12 document, sub-schema, or keyword collection.
1070
+ *
1071
+ * This interface covers the subset of JSON Schema 2020-12 that this generator
1072
+ * emits, plus an index signature for custom `x-formspec-*` extension keywords.
1073
+ *
1074
+ * @public
1075
+ */
1076
+ export declare interface JsonSchema2020 {
1077
+ $schema?: string;
1078
+ $ref?: string;
1079
+ $defs?: Record<string, JsonSchema2020>;
1080
+ type?: string;
1081
+ properties?: Record<string, JsonSchema2020>;
1082
+ required?: string[];
1083
+ items?: JsonSchema2020;
1084
+ additionalProperties?: boolean | JsonSchema2020;
1085
+ enum?: readonly (string | number)[];
1086
+ const?: unknown;
1087
+ allOf?: readonly JsonSchema2020[];
1088
+ oneOf?: readonly JsonSchema2020[];
1089
+ anyOf?: readonly JsonSchema2020[];
1090
+ minimum?: number;
1091
+ maximum?: number;
1092
+ exclusiveMinimum?: number;
1093
+ exclusiveMaximum?: number;
1094
+ multipleOf?: number;
1095
+ minLength?: number;
1096
+ maxLength?: number;
1097
+ minItems?: number;
1098
+ maxItems?: number;
1099
+ pattern?: string;
1100
+ uniqueItems?: boolean;
1101
+ format?: string;
1102
+ title?: string;
1103
+ description?: string;
1104
+ default?: unknown;
1105
+ deprecated?: boolean;
1106
+ [key: `x-${string}`]: unknown;
1107
+ }
1108
+
1109
+ /**
1110
+ * A Label element for displaying static text.
1111
+ *
1112
+ * @public
1113
+ */
1114
+ export declare interface LabelElement {
1115
+ readonly type: "Label";
1116
+ readonly text: string;
1117
+ readonly rule?: Rule | undefined;
1118
+ readonly options?: Record<string, unknown> | undefined;
1119
+ readonly [k: string]: unknown;
1120
+ }
1121
+
1122
+ /**
1123
+ * Logs validation issues to the console.
1124
+ *
1125
+ * @param result - The validation result to log
1126
+ * @param formName - Optional name for the form (for better error messages)
1127
+ *
1128
+ * @public
1129
+ */
1130
+ export declare function logValidationIssues(result: ValidationResult, formName?: string): void;
1131
+
1132
+ /**
1133
+ * A numeric input field.
1134
+ *
1135
+ * @typeParam N - The field name (string literal type)
1136
+ *
1137
+ * @public
1138
+ */
1139
+ export declare interface NumberField<N extends string> {
1140
+ /** Type discriminator for form elements */
1141
+ readonly _type: "field";
1142
+ /** Field type discriminator - identifies this as a number field */
1143
+ readonly _field: "number";
1144
+ /** Unique field identifier used as the schema key */
1145
+ readonly name: N;
1146
+ /** Display label for the field */
1147
+ readonly label?: string;
1148
+ /** Minimum allowed value */
1149
+ readonly min?: number;
1150
+ /** Maximum allowed value */
1151
+ readonly max?: number;
1152
+ /** Whether this field is required for form submission */
1153
+ readonly required?: boolean;
1154
+ /** Value must be a multiple of this number (use 1 for integer semantics) */
1155
+ readonly multipleOf?: number;
1156
+ }
1157
+
1158
+ /**
1159
+ * A numeric input field.
1160
+ *
1161
+ * @typeParam N - The field name (string literal type)
1162
+ *
1163
+ * @public
1164
+ */
1165
+ declare interface NumberField_2<N extends string> {
1166
+ /** Type discriminator for form elements */
1167
+ readonly _type: "field";
1168
+ /** Field type discriminator - identifies this as a number field */
1169
+ readonly _field: "number";
1170
+ /** Unique field identifier used as the schema key */
1171
+ readonly name: N;
1172
+ /** Display label for the field */
1173
+ readonly label?: string;
1174
+ /** Minimum allowed value */
1175
+ readonly min?: number;
1176
+ /** Maximum allowed value */
1177
+ readonly max?: number;
1178
+ /** Whether this field is required for form submission */
1179
+ readonly required?: boolean;
1180
+ /** Value must be a multiple of this number (use 1 for integer semantics) */
1181
+ readonly multipleOf?: number;
1182
+ }
1183
+
1184
+ /**
1185
+ * An object field containing nested properties.
1186
+ *
1187
+ * Use this for grouping related fields under a single key in the schema.
1188
+ *
1189
+ * @typeParam N - The field name (string literal type)
1190
+ * @typeParam Properties - The form elements that define the object's properties
1191
+ *
1192
+ * @public
1193
+ */
1194
+ export declare interface ObjectField<N extends string, Properties extends readonly FormElement[]> {
1195
+ /** Type discriminator for form elements */
1196
+ readonly _type: "field";
1197
+ /** Field type discriminator - identifies this as an object field */
1198
+ readonly _field: "object";
1199
+ /** Unique field identifier used as the schema key */
1200
+ readonly name: N;
1201
+ /** Form elements that define the properties of this object */
1202
+ readonly properties: Properties;
1203
+ /** Display label for the field */
1204
+ readonly label?: string;
1205
+ /** Whether this field is required for form submission */
1206
+ readonly required?: boolean;
1207
+ }
1208
+
1209
+ /**
1210
+ * An object field containing nested properties.
1211
+ *
1212
+ * Use this for grouping related fields under a single key in the schema.
1213
+ *
1214
+ * @typeParam N - The field name (string literal type)
1215
+ * @typeParam Properties - The form elements that define the object's properties
1216
+ *
1217
+ * @public
1218
+ */
1219
+ declare interface ObjectField_2<N extends string, Properties extends readonly FormElement_2[]> {
1220
+ /** Type discriminator for form elements */
1221
+ readonly _type: "field";
1222
+ /** Field type discriminator - identifies this as an object field */
1223
+ readonly _field: "object";
1224
+ /** Unique field identifier used as the schema key */
1225
+ readonly name: N;
1226
+ /** Form elements that define the properties of this object */
1227
+ readonly properties: Properties;
1228
+ /** Display label for the field */
1229
+ readonly label?: string;
1230
+ /** Whether this field is required for form submission */
1231
+ readonly required?: boolean;
1232
+ }
1233
+
1234
+ /**
1235
+ * Union of all predicate types.
1236
+ *
1237
+ * Currently only supports equality, but can be extended with:
1238
+ * - `OneOfPredicate` - field value is one of several options
1239
+ * - `NotPredicate` - negation of another predicate
1240
+ * - `AndPredicate` / `OrPredicate` - logical combinations
1241
+ *
1242
+ * @public
1243
+ */
1244
+ export declare type Predicate<K extends string = string, V = unknown> = EqualsPredicate<K, V>;
1245
+
1246
+ /**
1247
+ * A resolver function that fetches options for a data source.
1248
+ *
1249
+ * @typeParam Source - The data source key from DataSourceRegistry
1250
+ * @typeParam T - The data type for options (from DataSourceRegistry)
1251
+ *
1252
+ * @public
1253
+ */
1254
+ export declare type Resolver<Source extends keyof DataSourceRegistry, T = DataSourceRegistry[Source]> = (params?: Record<string, unknown>) => Promise<FetchOptionsResponse<T>>;
1255
+
1256
+ /**
1257
+ * Map of resolver functions for a form's dynamic data sources.
1258
+ *
1259
+ * @public
1260
+ */
1261
+ export declare type ResolverMap<Sources extends string> = {
1262
+ [S in Sources]: S extends keyof DataSourceRegistry ? Resolver<S> : (params?: Record<string, unknown>) => Promise<FetchOptionsResponse>;
1263
+ };
1264
+
1265
+ /**
1266
+ * A resolver registry that provides type-safe access to resolvers.
1267
+ *
1268
+ * @public
1269
+ */
1270
+ export declare interface ResolverRegistry<Sources extends string> {
1271
+ /**
1272
+ * Gets a resolver by data source name.
1273
+ */
1274
+ get<S extends Sources>(source: S): S extends keyof DataSourceRegistry ? Resolver<S> : (params?: Record<string, unknown>) => Promise<FetchOptionsResponse>;
1275
+ /**
1276
+ * Checks if a resolver exists for a data source.
1277
+ */
1278
+ has(source: string): boolean;
1279
+ /**
1280
+ * Gets all registered data source names.
1281
+ */
1282
+ sources(): Sources[];
1283
+ }
1284
+
1285
+ /**
1286
+ * Derives the resolver source-key union for a FormSpec element array.
1287
+ *
1288
+ * @public
1289
+ */
1290
+ export declare type ResolverSourcesForForm<E extends readonly FormElement[]> = ExtractDynamicSourcesFromArray<E> & string;
1291
+
1292
+ /**
1293
+ * Rule for conditional element visibility/enablement.
1294
+ *
1295
+ * @public
1296
+ */
1297
+ export declare interface Rule {
1298
+ readonly effect: RuleEffect;
1299
+ readonly condition: SchemaBasedCondition;
1300
+ }
1301
+
1302
+ /**
1303
+ * JSON Schema subset used in rule conditions.
1304
+ *
1305
+ * @public
1306
+ */
1307
+ export declare interface RuleConditionSchema {
1308
+ const?: unknown;
1309
+ enum?: readonly unknown[];
1310
+ type?: string;
1311
+ not?: RuleConditionSchema;
1312
+ minimum?: number;
1313
+ maximum?: number;
1314
+ exclusiveMinimum?: number;
1315
+ exclusiveMaximum?: number;
1316
+ minLength?: number;
1317
+ properties?: Record<string, RuleConditionSchema>;
1318
+ required?: string[];
1319
+ allOf?: RuleConditionSchema[];
1320
+ }
1321
+
1322
+ /**
1323
+ * JSON Forms UI Schema type definitions.
1324
+ *
1325
+ * These are the consumer-facing TypeScript shapes. Runtime validation remains
1326
+ * defined separately in `./schema.ts`.
1327
+ *
1328
+ * See: https://jsonforms.io/docs/uischema/
1329
+ */
1330
+ /**
1331
+ * Rule effect types for conditional visibility.
1332
+ *
1333
+ * @public
1334
+ */
1335
+ export declare type RuleEffect = "SHOW" | "HIDE" | "ENABLE" | "DISABLE";
1336
+
1337
+ /**
1338
+ * Condition for a rule.
1339
+ *
1340
+ * @public
1341
+ */
1342
+ export declare interface SchemaBasedCondition {
1343
+ readonly scope: string;
1344
+ readonly schema: RuleConditionSchema;
1345
+ }
1346
+
1347
+ /**
1348
+ * A field with static enum options (known at compile time).
1349
+ *
1350
+ * Options can be plain strings or objects with `id` and `label` properties.
1351
+ *
1352
+ * @typeParam N - The field name (string literal type)
1353
+ * @typeParam O - Tuple of option values (strings or EnumOption objects)
1354
+ *
1355
+ * @public
1356
+ */
1357
+ export declare interface StaticEnumField<N extends string, O extends readonly EnumOptionValue[]> {
1358
+ /** Type discriminator for form elements */
1359
+ readonly _type: "field";
1360
+ /** Field type discriminator - identifies this as an enum field */
1361
+ readonly _field: "enum";
1362
+ /** Unique field identifier used as the schema key */
1363
+ readonly name: N;
1364
+ /** Array of allowed option values */
1365
+ readonly options: O;
1366
+ /** Display label for the field */
1367
+ readonly label?: string;
1368
+ /** Whether this field is required for form submission */
1369
+ readonly required?: boolean;
1370
+ }
1371
+
1372
+ /**
1373
+ * A field with static enum options (known at compile time).
1374
+ *
1375
+ * Options can be plain strings or objects with `id` and `label` properties.
1376
+ *
1377
+ * @typeParam N - The field name (string literal type)
1378
+ * @typeParam O - Tuple of option values (strings or EnumOption objects)
1379
+ *
1380
+ * @public
1381
+ */
1382
+ declare interface StaticEnumField_2<N extends string, O extends readonly EnumOptionValue_2[]> {
1383
+ /** Type discriminator for form elements */
1384
+ readonly _type: "field";
1385
+ /** Field type discriminator - identifies this as an enum field */
1386
+ readonly _field: "enum";
1387
+ /** Unique field identifier used as the schema key */
1388
+ readonly name: N;
1389
+ /** Array of allowed option values */
1390
+ readonly options: O;
1391
+ /** Display label for the field */
1392
+ readonly label?: string;
1393
+ /** Whether this field is required for form submission */
1394
+ readonly required?: boolean;
1395
+ }
1396
+
1397
+ /**
1398
+ * Form element type definitions.
1399
+ *
1400
+ * These types define the structure of form specifications.
1401
+ * The structure IS the definition - nesting implies layout and conditional logic.
1402
+ */
1403
+ /**
1404
+ * A text input field.
1405
+ *
1406
+ * @typeParam N - The field name (string literal type)
1407
+ *
1408
+ * @public
1409
+ */
1410
+ export declare interface TextField<N extends string> {
1411
+ /** Type discriminator for form elements */
1412
+ readonly _type: "field";
1413
+ /** Field type discriminator - identifies this as a text field */
1414
+ readonly _field: "text";
1415
+ /** Unique field identifier used as the schema key */
1416
+ readonly name: N;
1417
+ /** Display label for the field */
1418
+ readonly label?: string;
1419
+ /** Placeholder text shown when field is empty */
1420
+ readonly placeholder?: string;
1421
+ /** Whether this field is required for form submission */
1422
+ readonly required?: boolean;
1423
+ /** Minimum string length */
1424
+ readonly minLength?: number;
1425
+ /** Maximum string length */
1426
+ readonly maxLength?: number;
1427
+ /** Regular expression pattern the value must match */
1428
+ readonly pattern?: string;
1429
+ }
1430
+
1431
+ /**
1432
+ * Form element type definitions.
1433
+ *
1434
+ * These types define the structure of form specifications.
1435
+ * The structure IS the definition - nesting implies layout and conditional logic.
1436
+ */
1437
+ /**
1438
+ * A text input field.
1439
+ *
1440
+ * @typeParam N - The field name (string literal type)
1441
+ *
1442
+ * @public
1443
+ */
1444
+ declare interface TextField_2<N extends string> {
1445
+ /** Type discriminator for form elements */
1446
+ readonly _type: "field";
1447
+ /** Field type discriminator - identifies this as a text field */
1448
+ readonly _field: "text";
1449
+ /** Unique field identifier used as the schema key */
1450
+ readonly name: N;
1451
+ /** Display label for the field */
1452
+ readonly label?: string;
1453
+ /** Placeholder text shown when field is empty */
1454
+ readonly placeholder?: string;
1455
+ /** Whether this field is required for form submission */
1456
+ readonly required?: boolean;
1457
+ /** Minimum string length */
1458
+ readonly minLength?: number;
1459
+ /** Maximum string length */
1460
+ readonly maxLength?: number;
1461
+ /** Regular expression pattern the value must match */
1462
+ readonly pattern?: string;
1463
+ }
1464
+
1465
+ /**
1466
+ * Root UI Schema (always a layout — not a Control, Category, or Label).
1467
+ *
1468
+ * @public
1469
+ */
1470
+ export declare type UISchema = VerticalLayout | HorizontalLayout | GroupLayout | Categorization;
1471
+
1472
+ /**
1473
+ * Union of all UI Schema element types.
1474
+ *
1475
+ * @public
1476
+ */
1477
+ export declare type UISchemaElement = ControlElement | VerticalLayout | HorizontalLayout | GroupLayout | Categorization | Category | LabelElement;
1478
+
1479
+ /**
1480
+ * UI Schema element types.
1481
+ *
1482
+ * @public
1483
+ */
1484
+ export declare type UISchemaElementType = "Control" | "VerticalLayout" | "HorizontalLayout" | "Group" | "Categorization" | "Category" | "Label";
1485
+
1486
+ /**
1487
+ * Validates a form specification for common issues.
1488
+ *
1489
+ * Checks for:
1490
+ * - Duplicate field names at the root level (warning)
1491
+ * - References to non-existent fields in conditionals (error)
1492
+ *
1493
+ * @example
1494
+ * ```typescript
1495
+ * const form = formspec(
1496
+ * field.text("name"),
1497
+ * field.text("name"), // Duplicate!
1498
+ * when("nonExistent", "value", // Reference to non-existent field!
1499
+ * field.text("extra"),
1500
+ * ),
1501
+ * );
1502
+ *
1503
+ * const result = validateForm(form.elements);
1504
+ * // result.valid === false
1505
+ * // result.issues contains duplicate and reference errors
1506
+ * ```
1507
+ *
1508
+ * @param elements - The form elements to validate
1509
+ * @returns Validation result with any issues found
1510
+ *
1511
+ * @public
1512
+ */
1513
+ export declare function validateForm(elements: readonly FormElement_2[]): ValidationResult;
1514
+
1515
+ /**
1516
+ * A validation issue found in a form specification.
1517
+ *
1518
+ * @public
1519
+ */
1520
+ export declare interface ValidationIssue {
1521
+ /** Severity of the issue */
1522
+ severity: ValidationSeverity;
1523
+ /** Human-readable message describing the issue */
1524
+ message: string;
1525
+ /** Path to the element with the issue (e.g., "group.fieldName") */
1526
+ path: string;
1527
+ }
1528
+
1529
+ /**
1530
+ * Result of validating a form specification.
1531
+ *
1532
+ * @public
1533
+ */
1534
+ export declare interface ValidationResult {
1535
+ /** Whether the form is valid (no errors, warnings are ok) */
1536
+ valid: boolean;
1537
+ /** List of validation issues found */
1538
+ issues: ValidationIssue[];
1539
+ }
1540
+
1541
+ /**
1542
+ * Validation issue severity levels.
1543
+ *
1544
+ * @public
1545
+ */
1546
+ export declare type ValidationSeverity = "error" | "warning";
1547
+
1548
+ /**
1549
+ * Represents the validity state of a field or form.
1550
+ *
1551
+ * - `"valid"` - All validations pass
1552
+ * - `"invalid"` - One or more validations failed
1553
+ * - `"unknown"` - Validation state not yet determined (e.g., async validation pending)
1554
+ *
1555
+ * @public
1556
+ */
1557
+ export declare type Validity = "valid" | "invalid" | "unknown";
1558
+
1559
+ /**
1560
+ * A vertical layout element.
1561
+ *
1562
+ * @public
1563
+ */
1564
+ export declare interface VerticalLayout {
1565
+ readonly type: "VerticalLayout";
1566
+ readonly elements: UISchemaElement[];
1567
+ readonly rule?: Rule | undefined;
1568
+ readonly options?: Record<string, unknown> | undefined;
1569
+ readonly [k: string]: unknown;
1570
+ }
1571
+
1572
+ /**
1573
+ * Creates a conditional wrapper that shows elements based on a predicate.
1574
+ *
1575
+ * @public
1576
+ */
1577
+ export declare function when<const K extends string, const V, const Elements extends readonly FormElement[]>(predicate: Predicate<K, V>, ...elements: Elements): Conditional<K, V, Elements>;
1578
+
1579
+ /**
1580
+ * Builds and writes both JSON Schema and UI Schema files to disk.
1581
+ *
1582
+ * @public
1583
+ */
1584
+ export declare function writeSchemas<E extends readonly FormElement[]>(form: FormSpec<E>, options: WriteSchemasOptions): WriteSchemasResult;
1585
+
1586
+ /**
1587
+ * Options for writing schemas to disk.
1588
+ *
1589
+ * @public
1590
+ */
1591
+ export declare interface WriteSchemasOptions extends GenerateJsonSchemaOptions {
1592
+ /** Output directory for the schema files */
1593
+ readonly outDir: string;
1594
+ /** Base name for the output files (without extension). Defaults to "schema" */
1595
+ readonly name?: string;
1596
+ /** Number of spaces for JSON indentation. Defaults to 2 */
1597
+ readonly indent?: number;
1598
+ }
1599
+
1600
+ /**
1601
+ * Result of writing schemas to disk.
1602
+ *
1603
+ * @public
1604
+ */
1605
+ export declare interface WriteSchemasResult {
1606
+ /** Path to the generated JSON Schema file */
1607
+ readonly jsonSchemaPath: string;
1608
+ /** Path to the generated UI Schema file */
1609
+ readonly uiSchemaPath: string;
1610
+ }
1611
+
1612
+ export { }