@dvirus-js/angular-signals 0.0.16 → 0.0.18

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,1000 @@
1
+ import { Signal, WritableSignal } from '@angular/core';
2
+ import { SignalOrValue } from '@dvirus-js/angular-signals';
3
+
4
+ /**
5
+ * Recursively extracts the value type from a form structure.
6
+ *
7
+ * Converts form control types to their underlying value types:
8
+ * - Arrays become arrays of extracted values
9
+ * - Objects become objects with extracted property values
10
+ * - Primitives become `T | undefined`
11
+ *
12
+ * @template T - The form structure type to extract values from
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * type Person = { name: string; age: number };
17
+ * type PersonValue = SignalFormValueFor<Person>;
18
+ * // Result: { name: string | undefined; age: number | undefined }
19
+ * ```
20
+ */
21
+ type SignalFormValueFor<T> = T extends (infer U)[] ? SignalFormValueFor<U>[] : T extends object ? {
22
+ [Key in keyof T]: SignalFormValueFor<T[Key]>;
23
+ } : T | undefined;
24
+ /**
25
+ * Recursively defines the error structure for a form.
26
+ *
27
+ * Mirrors the form structure where:
28
+ * - Arrays become arrays of error structures
29
+ * - Objects become objects with error properties
30
+ * - Primitives become error maps (Record<string, string>) or undefined
31
+ *
32
+ * @template T - The form structure type to create error structure for
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * type Person = { name: string; hobbies: string[] };
37
+ * type PersonErrors = SignalFormErrorFor<Person>;
38
+ * // Result: { name: Record<string, string> | undefined; hobbies: (Record<string, string> | undefined)[] }
39
+ * ```
40
+ */
41
+ type SignalFormErrorFor<T> = T extends (infer U)[] ? SignalFormErrorFor<U>[] : T extends object ? {
42
+ [Key in keyof T]: SignalFormErrorFor<T[Key]>;
43
+ } : Record<string, string> | undefined;
44
+ /**
45
+ * Represents the first error or warning found in a control.
46
+ *
47
+ * @template Type - Either 'error' or 'warning' to distinguish validation type
48
+ *
49
+ * @property name - The validator name that triggered this error/warning
50
+ * @property message - The human-readable error/warning message
51
+ * @property type - Whether this is an 'error' or 'warning'
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const firstError: FirstError<'error'> = {
56
+ * name: 'required',
57
+ * message: 'This field is required',
58
+ * type: 'error'
59
+ * };
60
+ * ```
61
+ */
62
+ type FirstError<Type extends 'warning' | 'error'> = {
63
+ name: string;
64
+ message: string;
65
+ type: Type;
66
+ } | undefined;
67
+ /**
68
+ * Represents a single form control (primitive value) with validation and state management.
69
+ *
70
+ * A control wraps a primitive value (string, number, etc.) and provides:
71
+ * - Reactive value through Angular signals
72
+ * - Validation with errors and warnings
73
+ * - State tracking (touched, dirty, disabled)
74
+ * - Manual error/warning management
75
+ *
76
+ * @template TValue - The type of value this control manages
77
+ */
78
+ interface SignalFormControl<TValue> {
79
+ /** Discriminator property set to 'control' for type checking */
80
+ kind: 'control';
81
+ /** Writable signal containing the current control value */
82
+ value: WritableSignal<TValue | undefined>;
83
+ /** Signal indicating if the control is disabled */
84
+ disabled: Signal<boolean>;
85
+ /** Signal indicating if the control has been interacted with */
86
+ touched: Signal<boolean>;
87
+ /** Signal indicating if the value has changed from initial */
88
+ dirty: Signal<boolean>;
89
+ /** Signal containing all validation errors (from validators + manual) */
90
+ errors: Signal<Record<string, string>>;
91
+ /** Signal containing all validation warnings (from warnings + manual) */
92
+ warnings: Signal<Record<string, string>>;
93
+ /** Signal containing only manually set errors */
94
+ selfErrors: Signal<Record<string, string>>;
95
+ /** Signal containing only manually set warnings */
96
+ selfWarnings: Signal<Record<string, string>>;
97
+ /** Signal true when control has errors and is not disabled */
98
+ invalid: Signal<boolean>;
99
+ /** Signal true when control has no errors */
100
+ valid: Signal<boolean>;
101
+ /** Signal with the first error, if any */
102
+ firstError: Signal<FirstError<'error'>>;
103
+ /** Signal with the first warning, if any */
104
+ firstWarning: Signal<FirstError<'warning'>>;
105
+ /** Signal with the first error or warning */
106
+ firstErrorOrWarning: Signal<FirstError<'error' | 'warning'>>;
107
+ /**
108
+ * Updates the control value with optional state flags.
109
+ * @param value - New value to set
110
+ * @param options - Optional flags for marking dirty/touched
111
+ */
112
+ setValue: (value: TValue | undefined, options?: SignalFormSetValueOptions) => void;
113
+ /**
114
+ * Resets control to initial value and clears all state.
115
+ * @param value - Optional new initial value
116
+ */
117
+ reset: (value?: TValue | undefined) => void;
118
+ /** Marks the control as touched */
119
+ markTouched: () => void;
120
+ /** Marks the control as not touched */
121
+ markUntouched: () => void;
122
+ /** Marks the control as dirty (modified) */
123
+ markDirty: () => void;
124
+ /** Marks the control as pristine (unmodified) */
125
+ markPristine: () => void;
126
+ /**
127
+ * Sets the disabled state of the control.
128
+ * @param disabled - True to disable, false to enable
129
+ */
130
+ setDisabled: (disabled: boolean) => void;
131
+ /**
132
+ * Adds a manual error with key and message.
133
+ * @param key - Error identifier key
134
+ * @param message - Error message
135
+ */
136
+ setError: (key: string, message: string) => void;
137
+ /**
138
+ * Removes a specific manual error by key.
139
+ * @param key - Error identifier key to remove
140
+ */
141
+ clearError: (key: string) => void;
142
+ /** Removes all manual errors */
143
+ clearErrors: () => void;
144
+ /**
145
+ * Adds a manual warning with key and message.
146
+ * @param key - Warning identifier key
147
+ * @param message - Warning message
148
+ */
149
+ setWarning: (key: string, message: string) => void;
150
+ /**
151
+ * Removes a specific manual warning by key.
152
+ * @param key - Warning identifier key to remove
153
+ */
154
+ clearWarning: (key: string) => void;
155
+ /** Removes all manual warnings */
156
+ clearWarnings: () => void;
157
+ }
158
+ /**
159
+ * Represents a form array - a collection of form controls/groups with dynamic add/remove capabilities.
160
+ *
161
+ * Manages an array of controls where each item can be a control, group, or nested array.
162
+ * Provides methods for array manipulation (push, insert, remove) and tracks collective state.
163
+ *
164
+ * @template TValue - The type of each item in the array
165
+ */
166
+ interface SignalFormArray<TValue> {
167
+ /** Discriminator property set to 'array' for type checking */
168
+ kind: 'array';
169
+ /** Signal containing the array of child controls */
170
+ controls: Signal<SignalFormControlLike<TValue>[]>;
171
+ /** Signal containing array of extracted values from all controls */
172
+ value: Signal<SignalFormValueFor<TValue>[]>;
173
+ /** Signal containing array of error structures from all controls */
174
+ errors: Signal<SignalFormErrorFor<TValue>[]>;
175
+ /** Signal containing array of warning structures from all controls */
176
+ warnings: Signal<SignalFormErrorFor<TValue>[]>;
177
+ /** Signal containing manually set errors on the array itself */
178
+ selfErrors: Signal<Record<string, string>>;
179
+ /** Signal containing manually set warnings on the array itself */
180
+ selfWarnings: Signal<Record<string, string>>;
181
+ /** Signal indicating if the array is disabled */
182
+ disabled: Signal<boolean>;
183
+ /** Signal true when array or any child is touched */
184
+ touched: Signal<boolean>;
185
+ /** Signal true when array or any child is dirty */
186
+ dirty: Signal<boolean>;
187
+ /** Signal true when array or any child has errors */
188
+ invalid: Signal<boolean>;
189
+ /** Signal true when array and all children have no errors */
190
+ valid: Signal<boolean>;
191
+ /**
192
+ * Inserts a control at specified index (defaults to end).
193
+ * @param item - Item to insert (value, config, or control)
194
+ * @param index - Position to insert at (optional, defaults to end)
195
+ * @returns Index where item was inserted
196
+ */
197
+ insert: (item: SignalFormInput<TValue, any> | SignalFormValueFor<TValue>, index?: number) => number;
198
+ /**
199
+ * Appends a control to the end of the array.
200
+ * @param item - Item to append (value, config, or control)
201
+ * @returns Index where item was inserted
202
+ */
203
+ push: (item: SignalFormInput<TValue, any> | SignalFormValueFor<TValue>) => number;
204
+ /**
205
+ * Removes the control at specified index.
206
+ * @param index - Index of control to remove
207
+ */
208
+ removeAt: (index: number) => void;
209
+ /** Removes all controls from the array */
210
+ clear: () => void;
211
+ /**
212
+ * Retrieves the control at specified index.
213
+ * @param index - Index of control to retrieve
214
+ * @returns Control at index, or undefined if out of bounds
215
+ */
216
+ at: (index: number) => SignalFormControlLike<TValue> | undefined;
217
+ /**
218
+ * Sets values for all controls (recreates if length differs).
219
+ * @param value - Array of new values
220
+ * @param options - Optional flags for marking dirty/touched
221
+ */
222
+ setValue: (value: SignalFormValueFor<TValue>[], options?: SignalFormSetValueOptions) => void;
223
+ /**
224
+ * Resets all controls to initial state or provided values.
225
+ * @param value - Optional new initial values
226
+ */
227
+ reset: (value?: SignalFormValueFor<TValue>[]) => void;
228
+ /** Marks the array itself as touched */
229
+ markTouched: () => void;
230
+ /** Marks the array itself as untouched */
231
+ markUntouched: () => void;
232
+ /** Marks the array itself as dirty */
233
+ markDirty: () => void;
234
+ /** Marks the array itself as pristine */
235
+ markPristine: () => void;
236
+ /** Marks the array and all children as touched */
237
+ markAllTouched: () => void;
238
+ /**
239
+ * Sets disabled state for array and optionally children.
240
+ * @param disabled - True to disable, false to enable
241
+ * @param options - Options to control if children are affected
242
+ */
243
+ setDisabled: (disabled: boolean, options?: SignalFormDisableOptions) => void;
244
+ /**
245
+ * Adds a manual error to the array.
246
+ * @param key - Error identifier key
247
+ * @param message - Error message
248
+ */
249
+ setError: (key: string, message: string) => void;
250
+ /**
251
+ * Removes a specific manual error.
252
+ * @param key - Error identifier key to remove
253
+ */
254
+ clearError: (key: string) => void;
255
+ /** Removes all manual errors */
256
+ clearErrors: () => void;
257
+ /**
258
+ * Adds a manual warning to the array.
259
+ * @param key - Warning identifier key
260
+ * @param message - Warning message
261
+ */
262
+ setWarning: (key: string, message: string) => void;
263
+ /**
264
+ * Removes a specific manual warning.
265
+ * @param key - Warning identifier key to remove
266
+ */
267
+ clearWarning: (key: string) => void;
268
+ /** Removes all manual warnings */
269
+ clearWarnings: () => void;
270
+ }
271
+ /**
272
+ * Represents a form group - a structured collection of named form controls.
273
+ *
274
+ * Manages an object/record of controls where each property is a control, group, or array.
275
+ * Provides type-safe access to controls and tracks collective validation state.
276
+ *
277
+ * @template TData - The object type defining the structure and types of all controls
278
+ */
279
+ interface SignalForm<TData extends object> {
280
+ /** Discriminator property set to 'group' for type checking */
281
+ kind: 'group';
282
+ /** Object containing all named child controls */
283
+ controls: {
284
+ [Key in keyof TData]: SignalFormControlLike<TData[Key]>;
285
+ };
286
+ /** Signal containing object with extracted values from all controls */
287
+ value: Signal<{
288
+ [Key in keyof TData]: SignalFormValueFor<TData[Key]>;
289
+ }>;
290
+ /** Signal containing object with error structures from all controls */
291
+ errors: Signal<{
292
+ [Key in keyof TData]: SignalFormErrorFor<TData[Key]>;
293
+ }>;
294
+ /** Signal containing object with warning structures from all controls */
295
+ warnings: Signal<{
296
+ [Key in keyof TData]: SignalFormErrorFor<TData[Key]>;
297
+ }>;
298
+ /** Signal containing manually set errors on the group itself */
299
+ selfErrors: Signal<Record<string, string>>;
300
+ /** Signal containing manually set warnings on the group itself */
301
+ selfWarnings: Signal<Record<string, string>>;
302
+ /** Signal indicating if the group is disabled */
303
+ disabled: Signal<boolean>;
304
+ /** Signal true when group or any child is touched */
305
+ touched: Signal<boolean>;
306
+ /** Signal true when group or any child is dirty */
307
+ dirty: Signal<boolean>;
308
+ /** Signal true when group or any child has errors */
309
+ invalid: Signal<boolean>;
310
+ /** Signal true when group and all children have no errors */
311
+ valid: Signal<boolean>;
312
+ /**
313
+ * Type-safe method to retrieve a specific control by key.
314
+ * @param key - Control property name
315
+ * @returns The control for the specified key
316
+ */
317
+ getControl: <Key extends keyof TData>(key: Key) => SignalFormControlLike<TData[Key]>;
318
+ /**
319
+ * Updates values for specified controls (partial updates supported).
320
+ * @param value - Partial object with new values
321
+ * @param options - Optional flags for marking dirty/touched
322
+ */
323
+ setValue: (value: Partial<{
324
+ [Key in keyof TData]: SignalFormValueFor<TData[Key]>;
325
+ }>, options?: SignalFormSetValueOptions) => void;
326
+ /**
327
+ * Resets all controls to initial state or provided values.
328
+ * @param value - Optional partial object with new initial values
329
+ */
330
+ reset: (value?: Partial<{
331
+ [Key in keyof TData]: SignalFormValueFor<TData[Key]>;
332
+ }>) => void;
333
+ /** Marks the group itself as touched */
334
+ markTouched: () => void;
335
+ /** Marks the group itself as untouched */
336
+ markUntouched: () => void;
337
+ /** Marks the group itself as dirty */
338
+ markDirty: () => void;
339
+ /** Marks the group itself as pristine */
340
+ markPristine: () => void;
341
+ /** Marks the group and all children as touched */
342
+ markAllTouched: () => void;
343
+ /**
344
+ * Sets disabled state for group and optionally children.
345
+ * @param disabled - True to disable, false to enable
346
+ * @param options - Options to control if children are affected
347
+ */
348
+ setDisabled: (disabled: boolean, options?: SignalFormDisableOptions) => void;
349
+ /**
350
+ * Adds a manual error to the group.
351
+ * @param key - Error identifier key
352
+ * @param message - Error message
353
+ */
354
+ setError: (key: string, message: string) => void;
355
+ /**
356
+ * Removes a specific manual error.
357
+ * @param key - Error identifier key to remove
358
+ */
359
+ clearError: (key: string) => void;
360
+ /** Removes all manual errors */
361
+ clearErrors: () => void;
362
+ /**
363
+ * Adds a manual warning to the group.
364
+ * @param key - Warning identifier key
365
+ * @param message - Warning message
366
+ */
367
+ setWarning: (key: string, message: string) => void;
368
+ /**
369
+ * Removes a specific manual warning.
370
+ * @param key - Warning identifier key to remove
371
+ */
372
+ clearWarning: (key: string) => void;
373
+ /** Removes all manual warnings */
374
+ clearWarnings: () => void;
375
+ }
376
+ /**
377
+ * Type utility that maps a value type to its appropriate control interface.
378
+ *
379
+ * Automatically determines the correct control type based on the value:
380
+ * - Arrays → SignalFormArray
381
+ * - Objects → SignalForm (group)
382
+ * - Primitives → SignalFormControl
383
+ *
384
+ * @template TValue - The value type to map to a control interface
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * type StringControl = SignalFormControlLike<string>; // SignalFormControl<string>
389
+ * type PersonControl = SignalFormControlLike<Person>; // SignalForm<Person>
390
+ * type HobbiesControl = SignalFormControlLike<string[]>; // SignalFormArray<string>
391
+ * ```
392
+ */
393
+ type SignalFormControlLike<TValue> = TValue extends (infer U)[] ? SignalFormArray<U> : TValue extends object ? SignalForm<TValue> : SignalFormControl<TValue>;
394
+ /**
395
+ * Context object passed to validators and disabled functions.
396
+ *
397
+ * Provides access to the current control's value and sibling controls,
398
+ * enabling cross-field validation and dynamic behavior based on other form values.
399
+ *
400
+ * @template TControls - Object type defining all available sibling controls
401
+ * @template TValue - The type of the current control's value
402
+ *
403
+ * @example
404
+ * ```typescript
405
+ * const validator: SignalFormValidatorFn<FormModel, string> = (ctx) => {
406
+ * const otherControl = ctx.getControl('otherField');
407
+ * return ctx.item.value === otherControl.value() ? null : { mismatch: 'Values must match' };
408
+ * };
409
+ * ```
410
+ */
411
+ interface SignalFormContext<TControls extends object, TValue> {
412
+ /** Object containing the current control's value */
413
+ item: {
414
+ value: TValue | undefined;
415
+ };
416
+ /**
417
+ * Function to retrieve sibling controls by key for cross-field logic.
418
+ * @param controlName - Key of the sibling control to retrieve
419
+ * @returns The sibling control
420
+ */
421
+ getControl: <ControlKey extends keyof TControls>(controlName: ControlKey) => SignalFormControlLike<TControls[ControlKey]>;
422
+ }
423
+ /**
424
+ * Return type for validation functions.
425
+ *
426
+ * Validators return a map of error keys to messages when validation fails,
427
+ * or null/empty when validation passes. Empty strings and null values are ignored.
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * const result: SignalFormValidationError = { required: 'Field is required', min: 'Too small' };
432
+ * const success: SignalFormValidationError = null;
433
+ * ```
434
+ */
435
+ type SignalFormValidationError = Record<string, string | undefined | null> | null;
436
+ /**
437
+ * Function signature for validators and warnings.
438
+ *
439
+ * Takes a context with the current value and sibling controls,
440
+ * returns error/warning messages or null when validation passes.
441
+ *
442
+ * @template TControls - Object type defining available sibling controls
443
+ * @template TValue - The type of value being validated
444
+ *
445
+ * @param ctx - Validation context with current value and control accessor
446
+ * @returns Error map when validation fails, null when it passes
447
+ *
448
+ * @example
449
+ * ```typescript
450
+ * const minValidator: SignalFormValidatorFn<any, number> = ({ item }) => {
451
+ * return item.value && item.value < 0 ? { min: 'Must be positive' } : null;
452
+ * };
453
+ * ```
454
+ */
455
+ type SignalFormValidatorFn<TControls extends object, TValue> = (ctx: SignalFormContext<TControls, TValue>) => SignalFormValidationError;
456
+ /**
457
+ * Configuration object for creating a form control with advanced options.
458
+ *
459
+ * Allows specifying initial value, validators, warnings, and dynamic disabled logic.
460
+ *
461
+ * @template TValue - The type of value the control will manage
462
+ * @template TControls - Object type defining available sibling controls for validators
463
+ *
464
+ * @example
465
+ * ```typescript
466
+ * const config: SignalFormControlConfig<number, FormModel> = {
467
+ * value: 0,
468
+ * validators: [signalFormValidators.min(0)],
469
+ * warnings: [signalFormValidators.max(100)],
470
+ * disabled: (ctx) => ctx.getControl('otherField').value() === 'locked'
471
+ * };
472
+ * ```
473
+ */
474
+ interface SignalFormControlConfig<TValue, TControls extends object> {
475
+ /** Initial value (can be a signal or static value) */
476
+ value: SignalOrValue<TValue | undefined>;
477
+ /** Disabled state (boolean, signal, or function based on form context) */
478
+ disabled?: SignalOrValue<boolean> | SignalFormDisabledFn<TControls, TValue>;
479
+ /** Array of validation functions that mark control as invalid */
480
+ validators?: SignalFormValidatorFn<TControls, TValue>[];
481
+ /** Array of validation functions that don't affect validity */
482
+ warnings?: SignalFormValidatorFn<TControls, TValue>[];
483
+ }
484
+ /**
485
+ * Input type accepted when creating a form control.
486
+ *
487
+ * Flexible input that accepts:
488
+ * - A raw value (primitive, signal)
489
+ * - A configuration object with validators and options
490
+ * - An existing SignalFormControl instance
491
+ *
492
+ * @template TValue - The value type for the control
493
+ * @template TControls - Object type defining available sibling controls
494
+ */
495
+ type SignalFormControlInput<TValue, TControls extends object> = SignalOrValue<TValue | undefined> | SignalFormControlConfig<TValue, TControls> | SignalFormControl<TValue>;
496
+ /**
497
+ * Input type accepted when creating a form group.
498
+ *
499
+ * @template TData - Object type defining the structure of the group
500
+ */
501
+ type SignalFormGroupInput<TData extends object> = SignalFormInputs<TData> | SignalForm<TData>;
502
+ /**
503
+ * Input type accepted when creating a form array.
504
+ *
505
+ * @template TItem - The type of each item in the array
506
+ * @template TControls - Object type defining available sibling controls
507
+ */
508
+ type SignalFormArrayInput<TItem, TControls extends object> = SignalFormArray<TItem> | SignalFormInput<TItem, TControls>[];
509
+ /**
510
+ * Recursive input type that automatically maps to the correct control input type.
511
+ *
512
+ * Determines the appropriate input type based on value structure:
513
+ * - Arrays → SignalFormArrayInput
514
+ * - Objects → SignalFormGroupInput
515
+ * - Primitives → SignalFormControlInput
516
+ *
517
+ * @template TValue - The value type to create an input for
518
+ * @template TControls - Object type defining available sibling controls
519
+ */
520
+ type SignalFormInput<TValue, TControls extends object> = TValue extends (infer U)[] ? SignalFormArrayInput<U, TControls> : TValue extends object ? SignalFormGroupInput<TValue> : SignalFormControlInput<TValue, TControls>;
521
+ /**
522
+ * Type for defining the inputs of a form group.
523
+ *
524
+ * Maps each property of TData to its appropriate input type,
525
+ * all properties are optional to allow partial form definitions.
526
+ *
527
+ * @template TData - Object type defining the structure of the form
528
+ */
529
+ type SignalFormInputs<TData extends object> = {
530
+ [Key in keyof TData]?: SignalFormInput<TData[Key], TData>;
531
+ };
532
+ /**
533
+ * Function signature for dynamic disabled logic.
534
+ *
535
+ * Determines if a control should be disabled based on form context.
536
+ *
537
+ * @template TControls - Object type defining available sibling controls
538
+ * @template TValue - The type of value in the control
539
+ *
540
+ * @param ctx - Context with current value and sibling controls
541
+ * @returns Boolean indicating if control should be disabled
542
+ */
543
+ type SignalFormDisabledFn<TControls extends object, TValue> = (ctx: SignalFormContext<TControls, TValue>) => boolean;
544
+ /**
545
+ * Options for setValue operations.
546
+ */
547
+ interface SignalFormSetValueOptions {
548
+ /** Whether to mark the control as dirty (default: true) */
549
+ markDirty?: boolean;
550
+ /** Whether to mark the control as touched (default: false) */
551
+ markTouched?: boolean;
552
+ }
553
+ /**
554
+ * Options for setDisabled operations.
555
+ */
556
+ interface SignalFormDisableOptions {
557
+ /** If true, only disable this control without affecting children (default: false) */
558
+ onlySelf?: boolean;
559
+ }
560
+
561
+ /**
562
+ * Internal type for accessing sibling controls in a form.
563
+ *
564
+ * @internal
565
+ */
566
+ type ControlAccessor$1<TControls extends object> = <Key extends keyof TControls>(controlName: Key) => SignalFormControlLike<TControls[Key]>;
567
+ /**
568
+ * Type guard to check if an object is a SignalFormArray.
569
+ *
570
+ * @template TValue - The type of items in the array
571
+ * @param obj - Object to check
572
+ * @returns True if obj is a SignalFormArray
573
+ *
574
+ * @example
575
+ * ```typescript
576
+ * if (isSignalFormArray(value)) {
577
+ * console.log(value.controls().length); // TypeScript knows this is an array
578
+ * }
579
+ * ```
580
+ */
581
+ declare function isSignalFormArray<TValue>(obj: unknown): obj is SignalFormArray<TValue>;
582
+ /**
583
+ * Creates a reactive form array for managing dynamic collections of controls.
584
+ *
585
+ * Builds an array container that can hold multiple controls (primitives, groups, or nested arrays)
586
+ * with full signal-based reactivity. Provides methods for dynamic addition/removal of items
587
+ * and tracks collective validation state.
588
+ *
589
+ * Features:
590
+ * - Dynamic array operations (push, insert, remove, clear)
591
+ * - Reactive value and error tracking across all items
592
+ * - Collective state management (touched, dirty, valid)
593
+ * - Manual error/warning management at array level
594
+ * - Type-safe access to individual controls
595
+ *
596
+ * @template TItem - The type of each item in the array
597
+ * @template TControls - Object type defining available sibling controls
598
+ *
599
+ * @param inputItems - Array of initial items (values, configs, or controls)
600
+ * @param getControl - Optional accessor for sibling controls
601
+ * @returns Fully configured SignalFormArray instance
602
+ *
603
+ * @example
604
+ * ```typescript
605
+ * // Array of primitives
606
+ * const tagsArray = createSignalFormArray(['tag1', 'tag2']);
607
+ * tagsArray.push('tag3');
608
+ *
609
+ * // Array of objects
610
+ * const addressesArray = createSignalFormArray<Address>([
611
+ * { street: '123 Main', city: 'NYC' },
612
+ * { street: '456 Oak', city: 'LA' }
613
+ * ]);
614
+ *
615
+ * // Array with validators
616
+ * const hobbiesArray = createSignalFormArray([
617
+ * { value: 'coding', validators: [signalFormValidators.minLength(3)] },
618
+ * 'gaming'
619
+ * ]);
620
+ * ```
621
+ */
622
+ declare function createSignalFormArray<TItem, TControls extends object = object>(inputItems: SignalFormInput<TItem, TControls>[], getControl?: ControlAccessor$1<TControls>): SignalFormArray<TItem>;
623
+
624
+ /**
625
+ * Internal type for accessing sibling controls in a form.
626
+ *
627
+ * @internal
628
+ */
629
+ type ControlAccessor<TControls extends object> = <Key extends keyof TControls>(controlName: Key) => SignalFormControlLike<TControls[Key]>;
630
+ /**
631
+ * Type guard to check if an object is a SignalFormControl.
632
+ *
633
+ * @template TValue - The type of value the control manages
634
+ * @param obj - Object to check
635
+ * @returns True if obj is a SignalFormControl
636
+ *
637
+ * @example
638
+ * ```typescript
639
+ * if (isSignalFormControl(value)) {
640
+ * console.log(value.value()); // TypeScript knows this is a control
641
+ * }
642
+ * ```
643
+ */
644
+ declare function isSignalFormControl<TValue>(obj: unknown): obj is SignalFormControl<TValue>;
645
+ /**
646
+ * Creates a reactive form control with signal-based state management.
647
+ *
648
+ * Builds a control that wraps a primitive value (string, number, boolean, etc.)
649
+ * with validation, state tracking, and reactive updates using Angular signals.
650
+ *
651
+ * Features:
652
+ * - Reactive value updates through signals
653
+ * - Validators for errors (mark control as invalid)
654
+ * - Warnings (validation messages without invalidating)
655
+ * - Dynamic disabled state based on form context
656
+ * - State tracking (touched, dirty)
657
+ * - Manual error/warning management
658
+ *
659
+ * @template TControls - Object type defining available sibling controls for cross-field validation
660
+ * @template TValue - The type of value this control manages
661
+ *
662
+ * @param input - Control input (raw value, config object, or existing control)
663
+ * @param getControl - Optional accessor function for sibling controls
664
+ * @returns Fully configured SignalFormControl instance
665
+ *
666
+ * @example
667
+ * ```typescript
668
+ * // Simple control
669
+ * const nameControl = createSignalFormControl('John');
670
+ *
671
+ * // With validators
672
+ * const ageControl = createSignalFormControl({
673
+ * value: 25,
674
+ * validators: [signalFormValidators.required, signalFormValidators.min(0)],
675
+ * warnings: [signalFormValidators.max(120)]
676
+ * });
677
+ *
678
+ * // With dynamic disabled
679
+ * const emailControl = createSignalFormControl({
680
+ * value: '',
681
+ * disabled: (ctx) => ctx.getControl('accountType').value() === 'guest'
682
+ * });
683
+ * ```
684
+ */
685
+ declare function createSignalFormControl<TControls extends object, TValue>(input: SignalFormControlInput<TValue, TControls>, getControl?: ControlAccessor<TControls>): SignalFormControl<TValue>;
686
+
687
+ /**
688
+ * Type guard to check if an object is a SignalForm (form group).
689
+ *
690
+ * @template TData - Object type defining the form structure
691
+ * @param obj - Object to check
692
+ * @returns True if obj is a SignalForm
693
+ *
694
+ * @example
695
+ * ```typescript
696
+ * if (isSignalFormGroup(value)) {
697
+ * console.log(value.controls.name); // TypeScript knows this is a form group
698
+ * }
699
+ * ```
700
+ */
701
+ declare function isSignalFormGroup<TData extends object>(obj: unknown): obj is SignalForm<TData>;
702
+ /**
703
+ * Creates a reactive form group for managing structured form data.
704
+ *
705
+ * Builds a typed form container that holds multiple named controls, groups, or arrays.
706
+ * Each property in the input object becomes a control with full signal-based reactivity.
707
+ * Provides type-safe access to controls and tracks collective validation state.
708
+ *
709
+ * Features:
710
+ * - Type-safe control access via `.controls` property
711
+ * - Reactive value and error tracking across all controls
712
+ * - Collective state management (touched, dirty, valid)
713
+ * - Manual error/warning management at group level
714
+ * - Support for nested groups and arrays
715
+ * - Cross-field validation via getControl accessor
716
+ *
717
+ * @template TData - Object type defining the structure and types of all controls
718
+ *
719
+ * @param inputs - Object mapping property names to their control inputs
720
+ * @returns Fully configured SignalForm instance
721
+ *
722
+ * @example
723
+ * ```typescript
724
+ * // Simple form
725
+ * const form = createSignalFormGroup({
726
+ * name: 'John',
727
+ * age: 25
728
+ * });
729
+ *
730
+ * // With validators and nested structure
731
+ * const form = createSignalFormGroup<User>({
732
+ * email: {
733
+ * value: '',
734
+ * validators: [signalFormValidators.required, signalFormValidators.email]
735
+ * },
736
+ * age: {
737
+ * value: 25,
738
+ * validators: [signalFormValidators.min(0)],
739
+ * warnings: [signalFormValidators.max(120)]
740
+ * },
741
+ * address: {
742
+ * street: '123 Main St',
743
+ * city: 'NYC'
744
+ * },
745
+ * hobbies: ['coding', 'gaming']
746
+ * });
747
+ *
748
+ * // Access controls
749
+ * form.controls.email.value(); // Type-safe access
750
+ * form.getControl('age').setValue(30);
751
+ * ```
752
+ */
753
+ declare function createSignalFormGroup<TData extends object>(inputs: SignalFormInputs<TData>): SignalForm<TData>;
754
+ /**
755
+ * Helper function to create a standalone form control.
756
+ *
757
+ * Creates a control without sibling control access. Useful for creating
758
+ * individual controls outside of a form group context.
759
+ *
760
+ * @template TValue - The type of value the control manages
761
+ * @param input - Control input (raw value, config object, or existing control)
762
+ * @returns SignalFormControl instance
763
+ *
764
+ * @example
765
+ * ```typescript
766
+ * const nameControl = formControl('John');
767
+ * const ageControl = formControl({
768
+ * value: 25,
769
+ * validators: [signalFormValidators.min(0)]
770
+ * });
771
+ * ```
772
+ */
773
+ declare function formControl<TValue>(input: SignalFormControlInput<TValue, object>): SignalFormControl<TValue>;
774
+ /**
775
+ * Helper function to create a standalone form array.
776
+ *
777
+ * Creates an array without sibling control access. Useful for creating
778
+ * array controls outside of a form group context.
779
+ *
780
+ * @template TValue - The type of each item in the array
781
+ * @param input - Array of initial items
782
+ * @returns SignalFormArray instance
783
+ *
784
+ * @example
785
+ * ```typescript
786
+ * const tagsArray = formArray(['tag1', 'tag2', 'tag3']);
787
+ * const addressesArray = formArray<Address>([
788
+ * { street: '123 Main', city: 'NYC' }
789
+ * ]);
790
+ * ```
791
+ */
792
+ declare function formArray<TValue>(input: SignalFormInput<TValue, object>[]): SignalFormArray<TValue>;
793
+ /**
794
+ * Helper function to create a form group.
795
+ *
796
+ * Alias for createSignalFormGroup. Creates a typed form with multiple controls.
797
+ *
798
+ * @template TData - Object type defining the form structure
799
+ * @param input - Object mapping property names to control inputs
800
+ * @returns SignalForm instance
801
+ *
802
+ * @example
803
+ * ```typescript
804
+ * const form = formGroup({
805
+ * name: 'John',
806
+ * email: {
807
+ * value: 'john@example.com',
808
+ * validators: [signalFormValidators.email]
809
+ * }
810
+ * });
811
+ * ```
812
+ */
813
+ declare function formGroup<TData extends object>(input: SignalFormInputs<TData>): SignalForm<TData>;
814
+ /**
815
+ * Primary API for creating signal-based reactive forms.
816
+ *
817
+ * Alias for `formGroup`. This is the main entry point for creating forms.
818
+ * Provides type-safe, signal-based form state management with built-in validation.
819
+ *
820
+ * @example
821
+ * ```typescript
822
+ * // Basic form
823
+ * const form = signalForm({ name: 'John', age: 25 });
824
+ *
825
+ * // Complex form with validation
826
+ * const form = signalForm<Person>({
827
+ * name: {
828
+ * value: '',
829
+ * validators: [signalFormValidators.required, signalFormValidators.minLength(2)]
830
+ * },
831
+ * age: {
832
+ * value: 30,
833
+ * validators: [signalFormValidators.min(0)],
834
+ * warnings: [signalFormValidators.max(120)],
835
+ * disabled: (ctx) => ctx.getControl('name').value() === 'admin'
836
+ * },
837
+ * address: {
838
+ * street: '123 Main St',
839
+ * city: 'NYC'
840
+ * },
841
+ * hobbies: ['coding', 'gaming']
842
+ * });
843
+ *
844
+ * // Access form state
845
+ * console.log(form.value()); // { name: '', age: 30, address: {...}, hobbies: [...] }
846
+ * console.log(form.valid()); // boolean
847
+ * console.log(form.controls.name.errors()); // { required: 'This field is required' }
848
+ * ```
849
+ */
850
+ declare const signalForm: typeof formGroup;
851
+
852
+ type ValidatorFn = SignalFormValidatorFn<any, any>;
853
+ /**
854
+ * Validator that enforces a maximum string or number length.
855
+ *
856
+ * Converts the value to string and checks if its length exceeds the specified maximum.
857
+ * Works with both string and number types.
858
+ *
859
+ * @param num - Maximum allowed length (inclusive)
860
+ * @returns Validator function
861
+ *
862
+ * @example
863
+ * ```typescript
864
+ * const control = signalForm({
865
+ * username: { value: 'verylongusername', validators: [signalFormValidators.maxLength(10)] }
866
+ * });
867
+ * // control.controls.username.errors() => { maxLength: 'To long' }
868
+ * ```
869
+ */
870
+ declare function maxLength(num: number): ValidatorFn;
871
+ /**
872
+ * Validator that enforces a minimum string or number length.
873
+ *
874
+ * Converts the value to string and checks if its length is less than or equal to the specified minimum.
875
+ * Works with both string and number types.
876
+ *
877
+ * @param num - Minimum required length (inclusive)
878
+ * @returns Validator function
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * const control = signalForm({
883
+ * code: { value: 'ab', validators: [signalFormValidators.minLength(3)] }
884
+ * });
885
+ * // control.controls.code.errors() => { minLength: 'To short' }
886
+ * ```
887
+ */
888
+ declare function minLength(num: number): ValidatorFn;
889
+ /**
890
+ * Validator that enforces a minimum numeric value.
891
+ *
892
+ * Checks if a numeric value is less than or equal to the specified minimum.
893
+ * Value is coerced to a number for comparison.
894
+ *
895
+ * @param num - Minimum allowed value (exclusive - value must be greater than this)
896
+ * @returns Validator function
897
+ *
898
+ * @example
899
+ * ```typescript
900
+ * const control = signalForm({
901
+ * age: { value: -5, validators: [signalFormValidators.min(0)] }
902
+ * });
903
+ * // control.controls.age.errors() => { minLength: 'To small' }
904
+ * ```
905
+ */
906
+ declare function min(num: number): ValidatorFn;
907
+ /**
908
+ * Validator that enforces a maximum numeric value.
909
+ *
910
+ * Checks if a numeric value exceeds the specified maximum.
911
+ * Value is coerced to a number for comparison.
912
+ *
913
+ * @param num - Maximum allowed value (inclusive)
914
+ * @returns Validator function
915
+ *
916
+ * @example
917
+ * ```typescript
918
+ * const control = signalForm({
919
+ * age: { value: 150, validators: [signalFormValidators.max(120)] }
920
+ * });
921
+ * // control.controls.age.errors() => { minLength: 'To big' }
922
+ * ```
923
+ */
924
+ declare function max(num: number): ValidatorFn;
925
+ /**
926
+ * Validator that checks if a value matches a specified regular expression pattern.
927
+ *
928
+ * Accepts either a RegExp object or a string pattern. String patterns are automatically
929
+ * wrapped with ^ and $ anchors to match the entire value.
930
+ *
931
+ * Skips validation for empty values (use with `required` if needed).
932
+ *
933
+ * @param valuePattern - Regular expression or pattern string to match against
934
+ * @returns Validator function
935
+ *
936
+ * @example
937
+ * ```typescript
938
+ * // Using regex
939
+ * const control1 = signalForm({
940
+ * code: { value: 'abc', validators: [signalFormValidators.pattern(/^[0-9]+$/)] }
941
+ * });
942
+ * // control1.controls.code.errors() => { pattern: 'RequiredPattern: ^[0-9]+$, ActualValue: abc' }
943
+ *
944
+ * // Using string pattern
945
+ * const control2 = signalForm({
946
+ * zipCode: { value: 'ABC', validators: [signalFormValidators.pattern('[0-9]{5}')] }
947
+ * });
948
+ * ```
949
+ */
950
+ declare function pattern(valuePattern: string | RegExp): ValidatorFn;
951
+ /**
952
+ * Collection of built-in validators for signal-form controls.
953
+ *
954
+ * Provides common validation functions that can be used in the `validators` or `warnings`
955
+ * arrays of form controls. All validators skip empty values except `required`.
956
+ *
957
+ * @property required - Ensures the value is not empty (null, undefined, '', [], 0, empty Set)
958
+ * @property maxLength - Ensures string/number length doesn't exceed maximum
959
+ * @property minLength - Ensures string/number length meets minimum requirement
960
+ * @property min - Ensures numeric value is greater than minimum (exclusive)
961
+ * @property max - Ensures numeric value doesn't exceed maximum (inclusive)
962
+ * @property email - Validates email address format using Angular-compatible regex
963
+ * @property pattern - Validates value matches a regular expression pattern
964
+ *
965
+ * @example
966
+ * ```typescript
967
+ * const form = signalForm({
968
+ * email: {
969
+ * value: '',
970
+ * validators: [signalFormValidators.required, signalFormValidators.email]
971
+ * },
972
+ * age: {
973
+ * value: 25,
974
+ * validators: [signalFormValidators.min(0), signalFormValidators.max(120)],
975
+ * warnings: [signalFormValidators.max(100)] // Warning but doesn't invalidate
976
+ * },
977
+ * username: {
978
+ * value: '',
979
+ * validators: [
980
+ * signalFormValidators.required,
981
+ * signalFormValidators.minLength(3),
982
+ * signalFormValidators.maxLength(20),
983
+ * signalFormValidators.pattern(/^[a-zA-Z0-9_]+$/)
984
+ * ]
985
+ * }
986
+ * });
987
+ * ```
988
+ */
989
+ declare const signalFormValidators: {
990
+ required: ValidatorFn;
991
+ maxLength: typeof maxLength;
992
+ minLength: typeof minLength;
993
+ min: typeof min;
994
+ max: typeof max;
995
+ email: ValidatorFn;
996
+ pattern: typeof pattern;
997
+ };
998
+
999
+ export { createSignalFormArray, createSignalFormControl, createSignalFormGroup, formArray, formControl, formGroup, isSignalFormArray, isSignalFormControl, isSignalFormGroup, signalForm, signalFormValidators };
1000
+ export type { FirstError, SignalForm, SignalFormArray, SignalFormArrayInput, SignalFormContext, SignalFormControl, SignalFormControlConfig, SignalFormControlInput, SignalFormControlLike, SignalFormDisableOptions, SignalFormDisabledFn, SignalFormErrorFor, SignalFormGroupInput, SignalFormInput, SignalFormInputs, SignalFormSetValueOptions, SignalFormValidationError, SignalFormValidatorFn, SignalFormValueFor };