@dvirus-js/angular-signals 0.0.1

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,1560 @@
1
+ import { Signal, WritableSignal, DestroyRef } from '@angular/core';
2
+ import { AbstractControl, FormControlStatus, ValidationErrors, FormArray, FormGroup, FormControl } from '@angular/forms';
3
+
4
+ /**
5
+ * Represents a generic object with string keys and values of any type.
6
+ * Useful as a base type for utility functions and signal helpers.
7
+ *
8
+ * @typedef {Record<string, any>} ObjectType
9
+ */
10
+ type ObjectType = Record<string, any>;
11
+
12
+ /**
13
+ * Represents an object where each property is a read-only Signal.
14
+ * Useful for mapping state objects to their signal equivalents.
15
+ */
16
+ type SignalObj<T extends ObjectType = ObjectType> = {
17
+ [Key in keyof T]: Signal<T[Key]>;
18
+ };
19
+ /**
20
+ * Represents an object where each property is a WritableSignal.
21
+ * Allows for direct modification of the signal values within the object structure.
22
+ */
23
+ type SignalObjWritable<T extends ObjectType> = {
24
+ [Key in keyof T]: WritableSignal<T[Key]>;
25
+ };
26
+ /**
27
+ * A type representing either a Signal of type T or the raw value of type T.
28
+ * Useful for inputs that can accept both static values and reactive signals.
29
+ */
30
+ type SignalOrValue<T> = Signal<T> | T;
31
+ /**
32
+ * Represents an object where each property can be either a Signal of a certain type
33
+ * or the raw value of that type.
34
+ *
35
+ * @template TValues The type of the values contained within the SignalOrValue properties.
36
+ * Defaults to a union of ObjectType, string, number, or undefined.
37
+ */
38
+ type SignalOrValueObj<TValues = ObjectType | string | number | boolean | undefined> = TValues extends object ? {
39
+ [Key in keyof TValues]: SignalOrValue<TValues[Key]>;
40
+ } : Record<string, SignalOrValue<TValues>>;
41
+ /**
42
+ * Converts a plain object into a writable signal object.
43
+ * Each property of the source object becomes a WritableSignal initialized with the property's value.
44
+ *
45
+ * @param src - The source object to convert.
46
+ * @returns An object with the same keys as the source, but with values wrapped in WritableSignals.
47
+ */
48
+ declare function toSignalObj<T extends ObjectType>(src: T): SignalObjWritable<T>;
49
+ /**
50
+ * Converts a signal object into a plain object.
51
+ * Each property of the signal object becomes a value from the signal.
52
+ *
53
+ * @param src - The signal object to convert.
54
+ * @returns An object with the same keys as the source, but with values from the signals.
55
+ */
56
+ declare function fromSignalObj<TData extends ObjectType>(src: SignalOrValueObj<TData>): TData;
57
+ /**
58
+ * Unwraps a value that might be a Signal.
59
+ * If the input is a Signal, it returns the signal's value.
60
+ * If the input is a raw value, it returns the value itself.
61
+ *
62
+ * @param value - The signal or value to unwrap.
63
+ * @returns The raw value of type T.
64
+ */
65
+ declare function signalOrValue<T>(value: SignalOrValue<T>): T;
66
+ declare function signalOrFunction<T, FnArgs extends any[] = []>(value: SignalOrValue<T> | ((...args: FnArgs) => T), ...fnArgs: FnArgs): T;
67
+
68
+ /**
69
+ * Recursively extracts the value type from a form structure.
70
+ *
71
+ * Converts form control types to their underlying value types:
72
+ * - Arrays become arrays of extracted values
73
+ * - Objects become objects with extracted property values
74
+ * - Primitives become `T | undefined`
75
+ *
76
+ * @template T - The form structure type to extract values from
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * type Person = { name: string; age: number };
81
+ * type PersonValue = SignalFormValueFor<Person>;
82
+ * // Result: { name: string | undefined; age: number | undefined }
83
+ * ```
84
+ */
85
+ type SignalFormValueFor<T> = T extends (infer U)[] ? SignalFormValueFor<U>[] : T extends object ? {
86
+ [Key in keyof T]: SignalFormValueFor<T[Key]>;
87
+ } : T | undefined;
88
+ /**
89
+ * Recursively defines the error structure for a form.
90
+ *
91
+ * Mirrors the form structure where:
92
+ * - Arrays become arrays of error structures
93
+ * - Objects become objects with error properties
94
+ * - Primitives become error maps (Record<string, string>) or undefined
95
+ *
96
+ * @template T - The form structure type to create error structure for
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * type Person = { name: string; hobbies: string[] };
101
+ * type PersonErrors = SignalFormErrorFor<Person>;
102
+ * // Result: { name: Record<string, string> | undefined; hobbies: (Record<string, string> | undefined)[] }
103
+ * ```
104
+ */
105
+ type SignalFormErrorFor<T> = T extends (infer U)[] ? SignalFormErrorFor<U>[] : T extends object ? {
106
+ [Key in keyof T]: SignalFormErrorFor<T[Key]>;
107
+ } : Record<string, string> | undefined;
108
+ /**
109
+ * Represents the first error or warning found in a control.
110
+ *
111
+ * @template Type - Either 'error' or 'warning' to distinguish validation type
112
+ *
113
+ * @property name - The validator name that triggered this error/warning
114
+ * @property message - The human-readable error/warning message
115
+ * @property type - Whether this is an 'error' or 'warning'
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const firstError: FirstError<'error'> = {
120
+ * name: 'required',
121
+ * message: 'This field is required',
122
+ * type: 'error'
123
+ * };
124
+ * ```
125
+ */
126
+ type FirstError<Type extends 'warning' | 'error'> = {
127
+ name: string;
128
+ message: string;
129
+ type: Type;
130
+ } | undefined;
131
+ /**
132
+ * Represents a single form control (primitive value) with validation and state management.
133
+ *
134
+ * A control wraps a primitive value (string, number, etc.) and provides:
135
+ * - Reactive value through Angular signals
136
+ * - Validation with errors and warnings
137
+ * - State tracking (touched, dirty, disabled)
138
+ * - Manual error/warning management
139
+ *
140
+ * @template TValue - The type of value this control manages
141
+ */
142
+ interface SignalFormControl<TValue> {
143
+ /** Discriminator property set to 'control' for type checking */
144
+ kind: 'control';
145
+ /** Writable signal containing the current control value */
146
+ value: WritableSignal<TValue | undefined>;
147
+ /** Signal indicating if the control is disabled */
148
+ disabled: Signal<boolean>;
149
+ /** Signal indicating if the control has been interacted with */
150
+ touched: Signal<boolean>;
151
+ /** Signal indicating if the value has changed from initial */
152
+ dirty: Signal<boolean>;
153
+ /** Signal containing all validation errors (from validators + manual) */
154
+ errors: Signal<Record<string, string>>;
155
+ /** Signal containing all validation warnings (from warnings + manual) */
156
+ warnings: Signal<Record<string, string>>;
157
+ /** Signal containing only manually set errors */
158
+ selfErrors: Signal<Record<string, string>>;
159
+ /** Signal containing only manually set warnings */
160
+ selfWarnings: Signal<Record<string, string>>;
161
+ /** Signal true when control has errors and is not disabled */
162
+ invalid: Signal<boolean>;
163
+ /** Signal true when control has no errors */
164
+ valid: Signal<boolean>;
165
+ /** Signal with the first error, if any */
166
+ firstError: Signal<FirstError<'error'>>;
167
+ /** Signal with the first warning, if any */
168
+ firstWarning: Signal<FirstError<'warning'>>;
169
+ /** Signal with the first error or warning */
170
+ firstErrorOrWarning: Signal<FirstError<'error' | 'warning'>>;
171
+ /**
172
+ * Updates the control value with optional state flags.
173
+ * @param value - New value to set
174
+ * @param options - Optional flags for marking dirty/touched
175
+ */
176
+ setValue: (value: TValue | undefined, options?: SignalFormSetValueOptions) => void;
177
+ /**
178
+ * Resets control to initial value and clears all state.
179
+ * @param value - Optional new initial value
180
+ */
181
+ reset: (value?: TValue | undefined) => void;
182
+ /** Marks the control as touched */
183
+ markTouched: () => void;
184
+ /** Marks the control as not touched */
185
+ markUntouched: () => void;
186
+ /** Marks the control as dirty (modified) */
187
+ markDirty: () => void;
188
+ /** Marks the control as pristine (unmodified) */
189
+ markPristine: () => void;
190
+ /**
191
+ * Sets the disabled state of the control.
192
+ * @param disabled - True to disable, false to enable
193
+ */
194
+ setDisabled: (disabled: boolean) => void;
195
+ /**
196
+ * Adds a manual error with key and message.
197
+ * @param key - Error identifier key
198
+ * @param message - Error message
199
+ */
200
+ setError: (key: string, message: string) => void;
201
+ /**
202
+ * Removes a specific manual error by key.
203
+ * @param key - Error identifier key to remove
204
+ */
205
+ clearError: (key: string) => void;
206
+ /** Removes all manual errors */
207
+ clearErrors: () => void;
208
+ /**
209
+ * Adds a manual warning with key and message.
210
+ * @param key - Warning identifier key
211
+ * @param message - Warning message
212
+ */
213
+ setWarning: (key: string, message: string) => void;
214
+ /**
215
+ * Removes a specific manual warning by key.
216
+ * @param key - Warning identifier key to remove
217
+ */
218
+ clearWarning: (key: string) => void;
219
+ /** Removes all manual warnings */
220
+ clearWarnings: () => void;
221
+ }
222
+ /**
223
+ * Represents a form array - a collection of form controls/groups with dynamic add/remove capabilities.
224
+ *
225
+ * Manages an array of controls where each item can be a control, group, or nested array.
226
+ * Provides methods for array manipulation (push, insert, remove) and tracks collective state.
227
+ *
228
+ * @template TValue - The type of each item in the array
229
+ */
230
+ interface SignalFormArray<TValue> {
231
+ /** Discriminator property set to 'array' for type checking */
232
+ kind: 'array';
233
+ /** Signal containing the array of child controls */
234
+ controls: Signal<SignalFormControlLike<TValue>[]>;
235
+ /** Signal containing array of extracted values from all controls */
236
+ value: Signal<SignalFormValueFor<TValue>[]>;
237
+ /** Signal containing array of error structures from all controls */
238
+ errors: Signal<SignalFormErrorFor<TValue>[]>;
239
+ /** Signal containing array of warning structures from all controls */
240
+ warnings: Signal<SignalFormErrorFor<TValue>[]>;
241
+ /** Signal containing manually set errors on the array itself */
242
+ selfErrors: Signal<Record<string, string>>;
243
+ /** Signal containing manually set warnings on the array itself */
244
+ selfWarnings: Signal<Record<string, string>>;
245
+ /** Signal indicating if the array is disabled */
246
+ disabled: Signal<boolean>;
247
+ /** Signal true when array or any child is touched */
248
+ touched: Signal<boolean>;
249
+ /** Signal true when array or any child is dirty */
250
+ dirty: Signal<boolean>;
251
+ /** Signal true when array or any child has errors */
252
+ invalid: Signal<boolean>;
253
+ /** Signal true when array and all children have no errors */
254
+ valid: Signal<boolean>;
255
+ /**
256
+ * Inserts a control at specified index (defaults to end).
257
+ * @param item - Item to insert (value, config, or control)
258
+ * @param index - Position to insert at (optional, defaults to end)
259
+ * @returns Index where item was inserted
260
+ */
261
+ insert: (item: SignalFormInput<TValue, any> | SignalFormValueFor<TValue>, index?: number) => number;
262
+ /**
263
+ * Appends a control to the end of the array.
264
+ * @param item - Item to append (value, config, or control)
265
+ * @returns Index where item was inserted
266
+ */
267
+ push: (item: SignalFormInput<TValue, any> | SignalFormValueFor<TValue>) => number;
268
+ /**
269
+ * Removes the control at specified index.
270
+ * @param index - Index of control to remove
271
+ */
272
+ removeAt: (index: number) => void;
273
+ /** Removes all controls from the array */
274
+ clear: () => void;
275
+ /**
276
+ * Retrieves the control at specified index.
277
+ * @param index - Index of control to retrieve
278
+ * @returns Control at index, or undefined if out of bounds
279
+ */
280
+ at: (index: number) => SignalFormControlLike<TValue> | undefined;
281
+ /**
282
+ * Sets values for all controls (recreates if length differs).
283
+ * @param value - Array of new values
284
+ * @param options - Optional flags for marking dirty/touched
285
+ */
286
+ setValue: (value: SignalFormValueFor<TValue>[], options?: SignalFormSetValueOptions) => void;
287
+ /**
288
+ * Resets all controls to initial state or provided values.
289
+ * @param value - Optional new initial values
290
+ */
291
+ reset: (value?: SignalFormValueFor<TValue>[]) => void;
292
+ /** Marks the array itself as touched */
293
+ markTouched: () => void;
294
+ /** Marks the array itself as untouched */
295
+ markUntouched: () => void;
296
+ /** Marks the array itself as dirty */
297
+ markDirty: () => void;
298
+ /** Marks the array itself as pristine */
299
+ markPristine: () => void;
300
+ /** Marks the array and all children as touched */
301
+ markAllTouched: () => void;
302
+ /**
303
+ * Sets disabled state for array and optionally children.
304
+ * @param disabled - True to disable, false to enable
305
+ * @param options - Options to control if children are affected
306
+ */
307
+ setDisabled: (disabled: boolean, options?: SignalFormDisableOptions) => void;
308
+ /**
309
+ * Adds a manual error to the array.
310
+ * @param key - Error identifier key
311
+ * @param message - Error message
312
+ */
313
+ setError: (key: string, message: string) => void;
314
+ /**
315
+ * Removes a specific manual error.
316
+ * @param key - Error identifier key to remove
317
+ */
318
+ clearError: (key: string) => void;
319
+ /** Removes all manual errors */
320
+ clearErrors: () => void;
321
+ /**
322
+ * Adds a manual warning to the array.
323
+ * @param key - Warning identifier key
324
+ * @param message - Warning message
325
+ */
326
+ setWarning: (key: string, message: string) => void;
327
+ /**
328
+ * Removes a specific manual warning.
329
+ * @param key - Warning identifier key to remove
330
+ */
331
+ clearWarning: (key: string) => void;
332
+ /** Removes all manual warnings */
333
+ clearWarnings: () => void;
334
+ }
335
+ /**
336
+ * Represents a form group - a structured collection of named form controls.
337
+ *
338
+ * Manages an object/record of controls where each property is a control, group, or array.
339
+ * Provides type-safe access to controls and tracks collective validation state.
340
+ *
341
+ * @template TData - The object type defining the structure and types of all controls
342
+ */
343
+ interface SignalForm<TData extends object> {
344
+ /** Discriminator property set to 'group' for type checking */
345
+ kind: 'group';
346
+ /** Object containing all named child controls */
347
+ controls: {
348
+ [Key in keyof TData]: SignalFormControlLike<TData[Key]>;
349
+ };
350
+ /** Signal containing object with extracted values from all controls */
351
+ value: Signal<{
352
+ [Key in keyof TData]: SignalFormValueFor<TData[Key]>;
353
+ }>;
354
+ /** Signal containing object with error structures from all controls */
355
+ errors: Signal<{
356
+ [Key in keyof TData]: SignalFormErrorFor<TData[Key]>;
357
+ }>;
358
+ /** Signal containing object with warning structures from all controls */
359
+ warnings: Signal<{
360
+ [Key in keyof TData]: SignalFormErrorFor<TData[Key]>;
361
+ }>;
362
+ /** Signal containing manually set errors on the group itself */
363
+ selfErrors: Signal<Record<string, string>>;
364
+ /** Signal containing manually set warnings on the group itself */
365
+ selfWarnings: Signal<Record<string, string>>;
366
+ /** Signal indicating if the group is disabled */
367
+ disabled: Signal<boolean>;
368
+ /** Signal true when group or any child is touched */
369
+ touched: Signal<boolean>;
370
+ /** Signal true when group or any child is dirty */
371
+ dirty: Signal<boolean>;
372
+ /** Signal true when group or any child has errors */
373
+ invalid: Signal<boolean>;
374
+ /** Signal true when group and all children have no errors */
375
+ valid: Signal<boolean>;
376
+ /**
377
+ * Type-safe method to retrieve a specific control by key.
378
+ * @param key - Control property name
379
+ * @returns The control for the specified key
380
+ */
381
+ getControl: <Key extends keyof TData>(key: Key) => SignalFormControlLike<TData[Key]>;
382
+ /**
383
+ * Updates values for specified controls (partial updates supported).
384
+ * @param value - Partial object with new values
385
+ * @param options - Optional flags for marking dirty/touched
386
+ */
387
+ setValue: (value: Partial<{
388
+ [Key in keyof TData]: SignalFormValueFor<TData[Key]>;
389
+ }>, options?: SignalFormSetValueOptions) => void;
390
+ /**
391
+ * Resets all controls to initial state or provided values.
392
+ * @param value - Optional partial object with new initial values
393
+ */
394
+ reset: (value?: Partial<{
395
+ [Key in keyof TData]: SignalFormValueFor<TData[Key]>;
396
+ }>) => void;
397
+ /** Marks the group itself as touched */
398
+ markTouched: () => void;
399
+ /** Marks the group itself as untouched */
400
+ markUntouched: () => void;
401
+ /** Marks the group itself as dirty */
402
+ markDirty: () => void;
403
+ /** Marks the group itself as pristine */
404
+ markPristine: () => void;
405
+ /** Marks the group and all children as touched */
406
+ markAllTouched: () => void;
407
+ /**
408
+ * Sets disabled state for group and optionally children.
409
+ * @param disabled - True to disable, false to enable
410
+ * @param options - Options to control if children are affected
411
+ */
412
+ setDisabled: (disabled: boolean, options?: SignalFormDisableOptions) => void;
413
+ /**
414
+ * Adds a manual error to the group.
415
+ * @param key - Error identifier key
416
+ * @param message - Error message
417
+ */
418
+ setError: (key: string, message: string) => void;
419
+ /**
420
+ * Removes a specific manual error.
421
+ * @param key - Error identifier key to remove
422
+ */
423
+ clearError: (key: string) => void;
424
+ /** Removes all manual errors */
425
+ clearErrors: () => void;
426
+ /**
427
+ * Adds a manual warning to the group.
428
+ * @param key - Warning identifier key
429
+ * @param message - Warning message
430
+ */
431
+ setWarning: (key: string, message: string) => void;
432
+ /**
433
+ * Removes a specific manual warning.
434
+ * @param key - Warning identifier key to remove
435
+ */
436
+ clearWarning: (key: string) => void;
437
+ /** Removes all manual warnings */
438
+ clearWarnings: () => void;
439
+ }
440
+ /**
441
+ * Type utility that maps a value type to its appropriate control interface.
442
+ *
443
+ * Automatically determines the correct control type based on the value:
444
+ * - Arrays → SignalFormArray
445
+ * - Objects → SignalForm (group)
446
+ * - Primitives → SignalFormControl
447
+ *
448
+ * @template TValue - The value type to map to a control interface
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * type StringControl = SignalFormControlLike<string>; // SignalFormControl<string>
453
+ * type PersonControl = SignalFormControlLike<Person>; // SignalForm<Person>
454
+ * type HobbiesControl = SignalFormControlLike<string[]>; // SignalFormArray<string>
455
+ * ```
456
+ */
457
+ type SignalFormControlLike<TValue> = TValue extends (infer U)[] ? SignalFormArray<U> : TValue extends object ? SignalForm<TValue> : SignalFormControl<TValue>;
458
+ /**
459
+ * Context object passed to validators and disabled functions.
460
+ *
461
+ * Provides access to the current control's value and sibling controls,
462
+ * enabling cross-field validation and dynamic behavior based on other form values.
463
+ *
464
+ * @template TControls - Object type defining all available sibling controls
465
+ * @template TValue - The type of the current control's value
466
+ *
467
+ * @example
468
+ * ```typescript
469
+ * const validator: SignalFormValidatorFn<FormModel, string> = (ctx) => {
470
+ * const otherControl = ctx.getControl('otherField');
471
+ * return ctx.item.value === otherControl.value() ? null : { mismatch: 'Values must match' };
472
+ * };
473
+ * ```
474
+ */
475
+ interface SignalFormContext<TControls extends object, TValue> {
476
+ /** Object containing the current control's value */
477
+ item: {
478
+ value: TValue | undefined;
479
+ };
480
+ /**
481
+ * Function to retrieve sibling controls by key for cross-field logic.
482
+ * @param controlName - Key of the sibling control to retrieve
483
+ * @returns The sibling control
484
+ */
485
+ getControl: <ControlKey extends keyof TControls>(controlName: ControlKey) => SignalFormControlLike<TControls[ControlKey]>;
486
+ }
487
+ /**
488
+ * Return type for validation functions.
489
+ *
490
+ * Validators return a map of error keys to messages when validation fails,
491
+ * or null/empty when validation passes. Empty strings and null values are ignored.
492
+ *
493
+ * @example
494
+ * ```typescript
495
+ * const result: SignalFormValidationError = { required: 'Field is required', min: 'Too small' };
496
+ * const success: SignalFormValidationError = null;
497
+ * ```
498
+ */
499
+ type SignalFormValidationError = Record<string, string | undefined | null> | null;
500
+ /**
501
+ * Function signature for validators and warnings.
502
+ *
503
+ * Takes a context with the current value and sibling controls,
504
+ * returns error/warning messages or null when validation passes.
505
+ *
506
+ * @template TControls - Object type defining available sibling controls
507
+ * @template TValue - The type of value being validated
508
+ *
509
+ * @param ctx - Validation context with current value and control accessor
510
+ * @returns Error map when validation fails, null when it passes
511
+ *
512
+ * @example
513
+ * ```typescript
514
+ * const minValidator: SignalFormValidatorFn<any, number> = ({ item }) => {
515
+ * return item.value && item.value < 0 ? { min: 'Must be positive' } : null;
516
+ * };
517
+ * ```
518
+ */
519
+ type SignalFormValidatorFn<TControls extends object, TValue> = (ctx: SignalFormContext<TControls, TValue>) => SignalFormValidationError;
520
+ /**
521
+ * Configuration object for creating a form control with advanced options.
522
+ *
523
+ * Allows specifying initial value, validators, warnings, and dynamic disabled logic.
524
+ *
525
+ * @template TValue - The type of value the control will manage
526
+ * @template TControls - Object type defining available sibling controls for validators
527
+ *
528
+ * @example
529
+ * ```typescript
530
+ * const config: SignalFormControlConfig<number, FormModel> = {
531
+ * value: 0,
532
+ * validators: [signalFormValidators.min(0)],
533
+ * warnings: [signalFormValidators.max(100)],
534
+ * disabled: (ctx) => ctx.getControl('otherField').value() === 'locked'
535
+ * };
536
+ * ```
537
+ */
538
+ interface SignalFormControlConfig<TValue, TControls extends object> {
539
+ /** Initial value (can be a signal or static value) */
540
+ value: SignalOrValue<TValue | undefined>;
541
+ /** Disabled state (boolean, signal, or function based on form context) */
542
+ disabled?: SignalOrValue<boolean> | SignalFormDisabledFn<TControls, TValue>;
543
+ /** Array of validation functions that mark control as invalid */
544
+ validators?: SignalFormValidatorFn<TControls, TValue>[];
545
+ /** Array of validation functions that don't affect validity */
546
+ warnings?: SignalFormValidatorFn<TControls, TValue>[];
547
+ }
548
+ /**
549
+ * Input type accepted when creating a form control.
550
+ *
551
+ * Flexible input that accepts:
552
+ * - A raw value (primitive, signal)
553
+ * - A configuration object with validators and options
554
+ * - An existing SignalFormControl instance
555
+ *
556
+ * @template TValue - The value type for the control
557
+ * @template TControls - Object type defining available sibling controls
558
+ */
559
+ type SignalFormControlInput<TValue, TControls extends object> = SignalOrValue<TValue | undefined> | SignalFormControlConfig<TValue, TControls> | SignalFormControl<TValue>;
560
+ /**
561
+ * Input type accepted when creating a form group.
562
+ *
563
+ * @template TData - Object type defining the structure of the group
564
+ */
565
+ type SignalFormGroupInput<TData extends object> = SignalFormInputs<TData> | SignalForm<TData>;
566
+ /**
567
+ * Input type accepted when creating a form array.
568
+ *
569
+ * @template TItem - The type of each item in the array
570
+ * @template TControls - Object type defining available sibling controls
571
+ */
572
+ type SignalFormArrayInput<TItem, TControls extends object> = SignalFormArray<TItem> | SignalFormInput<TItem, TControls>[];
573
+ /**
574
+ * Recursive input type that automatically maps to the correct control input type.
575
+ *
576
+ * Determines the appropriate input type based on value structure:
577
+ * - Arrays → SignalFormArrayInput
578
+ * - Objects → SignalFormGroupInput
579
+ * - Primitives → SignalFormControlInput
580
+ *
581
+ * @template TValue - The value type to create an input for
582
+ * @template TControls - Object type defining available sibling controls
583
+ */
584
+ type SignalFormInput<TValue, TControls extends object> = TValue extends (infer U)[] ? SignalFormArrayInput<U, TControls> : TValue extends object ? SignalFormGroupInput<TValue> : SignalFormControlInput<TValue, TControls>;
585
+ /**
586
+ * Type for defining the inputs of a form group.
587
+ *
588
+ * Maps each property of TData to its appropriate input type,
589
+ * all properties are optional to allow partial form definitions.
590
+ *
591
+ * @template TData - Object type defining the structure of the form
592
+ */
593
+ type SignalFormInputs<TData extends object> = {
594
+ [Key in keyof TData]?: SignalFormInput<TData[Key], TData>;
595
+ };
596
+ /**
597
+ * Function signature for dynamic disabled logic.
598
+ *
599
+ * Determines if a control should be disabled based on form context.
600
+ *
601
+ * @template TControls - Object type defining available sibling controls
602
+ * @template TValue - The type of value in the control
603
+ *
604
+ * @param ctx - Context with current value and sibling controls
605
+ * @returns Boolean indicating if control should be disabled
606
+ */
607
+ type SignalFormDisabledFn<TControls extends object, TValue> = (ctx: SignalFormContext<TControls, TValue>) => boolean;
608
+ /**
609
+ * Options for setValue operations.
610
+ */
611
+ interface SignalFormSetValueOptions {
612
+ /** Whether to mark the control as dirty (default: true) */
613
+ markDirty?: boolean;
614
+ /** Whether to mark the control as touched (default: false) */
615
+ markTouched?: boolean;
616
+ }
617
+ /**
618
+ * Options for setDisabled operations.
619
+ */
620
+ interface SignalFormDisableOptions {
621
+ /** If true, only disable this control without affecting children (default: false) */
622
+ onlySelf?: boolean;
623
+ }
624
+
625
+ /**
626
+ * Internal type for accessing sibling controls in a form.
627
+ *
628
+ * @internal
629
+ */
630
+ type ControlAccessor$1<TControls extends object> = <Key extends keyof TControls>(controlName: Key) => SignalFormControlLike<TControls[Key]>;
631
+ /**
632
+ * Type guard to check if an object is a SignalFormArray.
633
+ *
634
+ * @template TValue - The type of items in the array
635
+ * @param obj - Object to check
636
+ * @returns True if obj is a SignalFormArray
637
+ *
638
+ * @example
639
+ * ```typescript
640
+ * if (isSignalFormArray(value)) {
641
+ * console.log(value.controls().length); // TypeScript knows this is an array
642
+ * }
643
+ * ```
644
+ */
645
+ declare function isSignalFormArray<TValue>(obj: unknown): obj is SignalFormArray<TValue>;
646
+ /**
647
+ * Creates a reactive form array for managing dynamic collections of controls.
648
+ *
649
+ * Builds an array container that can hold multiple controls (primitives, groups, or nested arrays)
650
+ * with full signal-based reactivity. Provides methods for dynamic addition/removal of items
651
+ * and tracks collective validation state.
652
+ *
653
+ * Features:
654
+ * - Dynamic array operations (push, insert, remove, clear)
655
+ * - Reactive value and error tracking across all items
656
+ * - Collective state management (touched, dirty, valid)
657
+ * - Manual error/warning management at array level
658
+ * - Type-safe access to individual controls
659
+ *
660
+ * @template TItem - The type of each item in the array
661
+ * @template TControls - Object type defining available sibling controls
662
+ *
663
+ * @param inputItems - Array of initial items (values, configs, or controls)
664
+ * @param getControl - Optional accessor for sibling controls
665
+ * @returns Fully configured SignalFormArray instance
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * // Array of primitives
670
+ * const tagsArray = createSignalFormArray(['tag1', 'tag2']);
671
+ * tagsArray.push('tag3');
672
+ *
673
+ * // Array of objects
674
+ * const addressesArray = createSignalFormArray<Address>([
675
+ * { street: '123 Main', city: 'NYC' },
676
+ * { street: '456 Oak', city: 'LA' }
677
+ * ]);
678
+ *
679
+ * // Array with validators
680
+ * const hobbiesArray = createSignalFormArray([
681
+ * { value: 'coding', validators: [signalFormValidators.minLength(3)] },
682
+ * 'gaming'
683
+ * ]);
684
+ * ```
685
+ */
686
+ declare function createSignalFormArray<TItem, TControls extends object = object>(inputItems: SignalFormInput<TItem, TControls>[], getControl?: ControlAccessor$1<TControls>): SignalFormArray<TItem>;
687
+
688
+ /**
689
+ * Internal type for accessing sibling controls in a form.
690
+ *
691
+ * @internal
692
+ */
693
+ type ControlAccessor<TControls extends object> = <Key extends keyof TControls>(controlName: Key) => SignalFormControlLike<TControls[Key]>;
694
+ /**
695
+ * Type guard to check if an object is a SignalFormControl.
696
+ *
697
+ * @template TValue - The type of value the control manages
698
+ * @param obj - Object to check
699
+ * @returns True if obj is a SignalFormControl
700
+ *
701
+ * @example
702
+ * ```typescript
703
+ * if (isSignalFormControl(value)) {
704
+ * console.log(value.value()); // TypeScript knows this is a control
705
+ * }
706
+ * ```
707
+ */
708
+ declare function isSignalFormControl<TValue>(obj: unknown): obj is SignalFormControl<TValue>;
709
+ /**
710
+ * Creates a reactive form control with signal-based state management.
711
+ *
712
+ * Builds a control that wraps a primitive value (string, number, boolean, etc.)
713
+ * with validation, state tracking, and reactive updates using Angular signals.
714
+ *
715
+ * Features:
716
+ * - Reactive value updates through signals
717
+ * - Validators for errors (mark control as invalid)
718
+ * - Warnings (validation messages without invalidating)
719
+ * - Dynamic disabled state based on form context
720
+ * - State tracking (touched, dirty)
721
+ * - Manual error/warning management
722
+ *
723
+ * @template TControls - Object type defining available sibling controls for cross-field validation
724
+ * @template TValue - The type of value this control manages
725
+ *
726
+ * @param input - Control input (raw value, config object, or existing control)
727
+ * @param getControl - Optional accessor function for sibling controls
728
+ * @returns Fully configured SignalFormControl instance
729
+ *
730
+ * @example
731
+ * ```typescript
732
+ * // Simple control
733
+ * const nameControl = createSignalFormControl('John');
734
+ *
735
+ * // With validators
736
+ * const ageControl = createSignalFormControl({
737
+ * value: 25,
738
+ * validators: [signalFormValidators.required, signalFormValidators.min(0)],
739
+ * warnings: [signalFormValidators.max(120)]
740
+ * });
741
+ *
742
+ * // With dynamic disabled
743
+ * const emailControl = createSignalFormControl({
744
+ * value: '',
745
+ * disabled: (ctx) => ctx.getControl('accountType').value() === 'guest'
746
+ * });
747
+ * ```
748
+ */
749
+ declare function createSignalFormControl<TControls extends object, TValue>(input: SignalFormControlInput<TValue, TControls>, getControl?: ControlAccessor<TControls>): SignalFormControl<TValue>;
750
+
751
+ /**
752
+ * Type guard to check if an object is a SignalForm (form group).
753
+ *
754
+ * @template TData - Object type defining the form structure
755
+ * @param obj - Object to check
756
+ * @returns True if obj is a SignalForm
757
+ *
758
+ * @example
759
+ * ```typescript
760
+ * if (isSignalFormGroup(value)) {
761
+ * console.log(value.controls.name); // TypeScript knows this is a form group
762
+ * }
763
+ * ```
764
+ */
765
+ declare function isSignalFormGroup<TData extends object>(obj: unknown): obj is SignalForm<TData>;
766
+ /**
767
+ * Creates a reactive form group for managing structured form data.
768
+ *
769
+ * Builds a typed form container that holds multiple named controls, groups, or arrays.
770
+ * Each property in the input object becomes a control with full signal-based reactivity.
771
+ * Provides type-safe access to controls and tracks collective validation state.
772
+ *
773
+ * Features:
774
+ * - Type-safe control access via `.controls` property
775
+ * - Reactive value and error tracking across all controls
776
+ * - Collective state management (touched, dirty, valid)
777
+ * - Manual error/warning management at group level
778
+ * - Support for nested groups and arrays
779
+ * - Cross-field validation via getControl accessor
780
+ *
781
+ * @template TData - Object type defining the structure and types of all controls
782
+ *
783
+ * @param inputs - Object mapping property names to their control inputs
784
+ * @returns Fully configured SignalForm instance
785
+ *
786
+ * @example
787
+ * ```typescript
788
+ * // Simple form
789
+ * const form = createSignalFormGroup({
790
+ * name: 'John',
791
+ * age: 25
792
+ * });
793
+ *
794
+ * // With validators and nested structure
795
+ * const form = createSignalFormGroup<User>({
796
+ * email: {
797
+ * value: '',
798
+ * validators: [signalFormValidators.required, signalFormValidators.email]
799
+ * },
800
+ * age: {
801
+ * value: 25,
802
+ * validators: [signalFormValidators.min(0)],
803
+ * warnings: [signalFormValidators.max(120)]
804
+ * },
805
+ * address: {
806
+ * street: '123 Main St',
807
+ * city: 'NYC'
808
+ * },
809
+ * hobbies: ['coding', 'gaming']
810
+ * });
811
+ *
812
+ * // Access controls
813
+ * form.controls.email.value(); // Type-safe access
814
+ * form.getControl('age').setValue(30);
815
+ * ```
816
+ */
817
+ declare function createSignalFormGroup<TData extends object>(inputs: SignalFormInputs<TData>): SignalForm<TData>;
818
+ /**
819
+ * Helper function to create a standalone form control.
820
+ *
821
+ * Creates a control without sibling control access. Useful for creating
822
+ * individual controls outside of a form group context.
823
+ *
824
+ * @template TValue - The type of value the control manages
825
+ * @param input - Control input (raw value, config object, or existing control)
826
+ * @returns SignalFormControl instance
827
+ *
828
+ * @example
829
+ * ```typescript
830
+ * const nameControl = formControl('John');
831
+ * const ageControl = formControl({
832
+ * value: 25,
833
+ * validators: [signalFormValidators.min(0)]
834
+ * });
835
+ * ```
836
+ */
837
+ declare function formControl<TValue>(input: SignalFormControlInput<TValue, object>): SignalFormControl<TValue>;
838
+ /**
839
+ * Helper function to create a standalone form array.
840
+ *
841
+ * Creates an array without sibling control access. Useful for creating
842
+ * array controls outside of a form group context.
843
+ *
844
+ * @template TValue - The type of each item in the array
845
+ * @param input - Array of initial items
846
+ * @returns SignalFormArray instance
847
+ *
848
+ * @example
849
+ * ```typescript
850
+ * const tagsArray = formArray(['tag1', 'tag2', 'tag3']);
851
+ * const addressesArray = formArray<Address>([
852
+ * { street: '123 Main', city: 'NYC' }
853
+ * ]);
854
+ * ```
855
+ */
856
+ declare function formArray<TValue>(input: SignalFormInput<TValue, object>[]): SignalFormArray<TValue>;
857
+ /**
858
+ * Helper function to create a form group.
859
+ *
860
+ * Alias for createSignalFormGroup. Creates a typed form with multiple controls.
861
+ *
862
+ * @template TData - Object type defining the form structure
863
+ * @param input - Object mapping property names to control inputs
864
+ * @returns SignalForm instance
865
+ *
866
+ * @example
867
+ * ```typescript
868
+ * const form = formGroup({
869
+ * name: 'John',
870
+ * email: {
871
+ * value: 'john@example.com',
872
+ * validators: [signalFormValidators.email]
873
+ * }
874
+ * });
875
+ * ```
876
+ */
877
+ declare function formGroup<TData extends object>(input: SignalFormInputs<TData>): SignalForm<TData>;
878
+ /**
879
+ * Primary API for creating signal-based reactive forms.
880
+ *
881
+ * Alias for `formGroup`. This is the main entry point for creating forms.
882
+ * Provides type-safe, signal-based form state management with built-in validation.
883
+ *
884
+ * @example
885
+ * ```typescript
886
+ * // Basic form
887
+ * const form = signalForm({ name: 'John', age: 25 });
888
+ *
889
+ * // Complex form with validation
890
+ * const form = signalForm<Person>({
891
+ * name: {
892
+ * value: '',
893
+ * validators: [signalFormValidators.required, signalFormValidators.minLength(2)]
894
+ * },
895
+ * age: {
896
+ * value: 30,
897
+ * validators: [signalFormValidators.min(0)],
898
+ * warnings: [signalFormValidators.max(120)],
899
+ * disabled: (ctx) => ctx.getControl('name').value() === 'admin'
900
+ * },
901
+ * address: {
902
+ * street: '123 Main St',
903
+ * city: 'NYC'
904
+ * },
905
+ * hobbies: ['coding', 'gaming']
906
+ * });
907
+ *
908
+ * // Access form state
909
+ * console.log(form.value()); // { name: '', age: 30, address: {...}, hobbies: [...] }
910
+ * console.log(form.valid()); // boolean
911
+ * console.log(form.controls.name.errors()); // { required: 'This field is required' }
912
+ * ```
913
+ */
914
+ declare const signalForm: typeof formGroup;
915
+
916
+ type ValidatorFn = SignalFormValidatorFn<any, any>;
917
+ /**
918
+ * Validator that enforces a maximum string or number length.
919
+ *
920
+ * Converts the value to string and checks if its length exceeds the specified maximum.
921
+ * Works with both string and number types.
922
+ *
923
+ * @param num - Maximum allowed length (inclusive)
924
+ * @returns Validator function
925
+ *
926
+ * @example
927
+ * ```typescript
928
+ * const control = signalForm({
929
+ * username: { value: 'verylongusername', validators: [signalFormValidators.maxLength(10)] }
930
+ * });
931
+ * // control.controls.username.errors() => { maxLength: 'To long' }
932
+ * ```
933
+ */
934
+ declare function maxLength(num: number): ValidatorFn;
935
+ /**
936
+ * Validator that enforces a minimum string or number length.
937
+ *
938
+ * Converts the value to string and checks if its length is less than or equal to the specified minimum.
939
+ * Works with both string and number types.
940
+ *
941
+ * @param num - Minimum required length (inclusive)
942
+ * @returns Validator function
943
+ *
944
+ * @example
945
+ * ```typescript
946
+ * const control = signalForm({
947
+ * code: { value: 'ab', validators: [signalFormValidators.minLength(3)] }
948
+ * });
949
+ * // control.controls.code.errors() => { minLength: 'To short' }
950
+ * ```
951
+ */
952
+ declare function minLength(num: number): ValidatorFn;
953
+ /**
954
+ * Validator that enforces a minimum numeric value.
955
+ *
956
+ * Checks if a numeric value is less than or equal to the specified minimum.
957
+ * Value is coerced to a number for comparison.
958
+ *
959
+ * @param num - Minimum allowed value (exclusive - value must be greater than this)
960
+ * @returns Validator function
961
+ *
962
+ * @example
963
+ * ```typescript
964
+ * const control = signalForm({
965
+ * age: { value: -5, validators: [signalFormValidators.min(0)] }
966
+ * });
967
+ * // control.controls.age.errors() => { minLength: 'To small' }
968
+ * ```
969
+ */
970
+ declare function min(num: number): ValidatorFn;
971
+ /**
972
+ * Validator that enforces a maximum numeric value.
973
+ *
974
+ * Checks if a numeric value exceeds the specified maximum.
975
+ * Value is coerced to a number for comparison.
976
+ *
977
+ * @param num - Maximum allowed value (inclusive)
978
+ * @returns Validator function
979
+ *
980
+ * @example
981
+ * ```typescript
982
+ * const control = signalForm({
983
+ * age: { value: 150, validators: [signalFormValidators.max(120)] }
984
+ * });
985
+ * // control.controls.age.errors() => { minLength: 'To big' }
986
+ * ```
987
+ */
988
+ declare function max(num: number): ValidatorFn;
989
+ /**
990
+ * Validator that checks if a value matches a specified regular expression pattern.
991
+ *
992
+ * Accepts either a RegExp object or a string pattern. String patterns are automatically
993
+ * wrapped with ^ and $ anchors to match the entire value.
994
+ *
995
+ * Skips validation for empty values (use with `required` if needed).
996
+ *
997
+ * @param valuePattern - Regular expression or pattern string to match against
998
+ * @returns Validator function
999
+ *
1000
+ * @example
1001
+ * ```typescript
1002
+ * // Using regex
1003
+ * const control1 = signalForm({
1004
+ * code: { value: 'abc', validators: [signalFormValidators.pattern(/^[0-9]+$/)] }
1005
+ * });
1006
+ * // control1.controls.code.errors() => { pattern: 'RequiredPattern: ^[0-9]+$, ActualValue: abc' }
1007
+ *
1008
+ * // Using string pattern
1009
+ * const control2 = signalForm({
1010
+ * zipCode: { value: 'ABC', validators: [signalFormValidators.pattern('[0-9]{5}')] }
1011
+ * });
1012
+ * ```
1013
+ */
1014
+ declare function pattern(valuePattern: string | RegExp): ValidatorFn;
1015
+ /**
1016
+ * Collection of built-in validators for signal-form controls.
1017
+ *
1018
+ * Provides common validation functions that can be used in the `validators` or `warnings`
1019
+ * arrays of form controls. All validators skip empty values except `required`.
1020
+ *
1021
+ * @property required - Ensures the value is not empty (null, undefined, '', [], 0, empty Set)
1022
+ * @property maxLength - Ensures string/number length doesn't exceed maximum
1023
+ * @property minLength - Ensures string/number length meets minimum requirement
1024
+ * @property min - Ensures numeric value is greater than minimum (exclusive)
1025
+ * @property max - Ensures numeric value doesn't exceed maximum (inclusive)
1026
+ * @property email - Validates email address format using Angular-compatible regex
1027
+ * @property pattern - Validates value matches a regular expression pattern
1028
+ *
1029
+ * @example
1030
+ * ```typescript
1031
+ * const form = signalForm({
1032
+ * email: {
1033
+ * value: '',
1034
+ * validators: [signalFormValidators.required, signalFormValidators.email]
1035
+ * },
1036
+ * age: {
1037
+ * value: 25,
1038
+ * validators: [signalFormValidators.min(0), signalFormValidators.max(120)],
1039
+ * warnings: [signalFormValidators.max(100)] // Warning but doesn't invalidate
1040
+ * },
1041
+ * username: {
1042
+ * value: '',
1043
+ * validators: [
1044
+ * signalFormValidators.required,
1045
+ * signalFormValidators.minLength(3),
1046
+ * signalFormValidators.maxLength(20),
1047
+ * signalFormValidators.pattern(/^[a-zA-Z0-9_]+$/)
1048
+ * ]
1049
+ * }
1050
+ * });
1051
+ * ```
1052
+ */
1053
+ declare const signalFormValidators: {
1054
+ required: ValidatorFn;
1055
+ maxLength: typeof maxLength;
1056
+ minLength: typeof minLength;
1057
+ min: typeof min;
1058
+ max: typeof max;
1059
+ email: ValidatorFn;
1060
+ pattern: typeof pattern;
1061
+ };
1062
+
1063
+ /**
1064
+ * A function interface for a signal-based notification mechanism.
1065
+ * Calling the function returns the current notification count.
1066
+ * Calling `notify()` increments the count, triggering any listeners.
1067
+ */
1068
+ interface SignalNotifier {
1069
+ (): number;
1070
+ /**
1071
+ * Triggers a notification by incrementing the internal signal value.
1072
+ */
1073
+ notify: () => void;
1074
+ }
1075
+ /**
1076
+ * Creates a signal-based notifier function.
1077
+ *
1078
+ * Each call to the returned function returns the current notification count.
1079
+ * Calling `notify()` increments the count, triggering any listeners.
1080
+ *
1081
+ * @returns {SignalNotifier} A notifier function with a `notify` method.
1082
+ *
1083
+ * @example
1084
+ * const notifier = signalNotifier();
1085
+ * effect(() => {
1086
+ * notifier(); // Reacts to notifications
1087
+ * });
1088
+ * notifier.notify(); // Triggers the effect
1089
+ */
1090
+ declare function signalNotifier(): SignalNotifier;
1091
+
1092
+ /**
1093
+ * A writable signal enhanced with debounce capabilities.
1094
+ *
1095
+ * Extends `WritableSignal<T>` so it can be read and written like a normal signal,
1096
+ * but also exposes a `setDebounced` method that applies values after a configurable delay
1097
+ * and an `isLoading` signal that indicates whether a debounced update is pending.
1098
+ *
1099
+ * @typeParam T - The type of the signal's value.
1100
+ */
1101
+ interface SignalDebounce<T> extends WritableSignal<T> {
1102
+ /** Sets the signal value after the configured debounce delay. */
1103
+ setDebounced(value: T): void;
1104
+ /** Reactive flag that is `true` while a debounced update is pending. */
1105
+ isLoading: Signal<boolean>;
1106
+ }
1107
+ /**
1108
+ * Creates a debounced writable signal.
1109
+ *
1110
+ * The returned signal can be written to instantly via its `WritableSignal` interface
1111
+ * **or** through `setDebounced(value)` which delays the commit by `debounceTime` ms.
1112
+ * While a debounced write is pending, `isLoading()` returns `true`.
1113
+ *
1114
+ * If a reactive `params` function is supplied, the signal will also track that
1115
+ * source and debounce upstream changes (requires an injection context).
1116
+ *
1117
+ * @typeParam T - The type of the signal's value.
1118
+ * @param options - Configuration object.
1119
+ * @param options.params - Optional reactive source function whose return value
1120
+ * is tracked and debounced into the signal.
1121
+ * @param options.debounceTime - Delay in milliseconds before a debounced value
1122
+ * is committed.
1123
+ * @param options.initialValue - Optional initial value for the signal.
1124
+ * @param options.injector - Optional Angular `Injector` to use for setting up
1125
+ * reactive tracking. Required if `params` is provided and this function is called
1126
+ * outside of an injection context.
1127
+ * @returns A `SignalDebounce<T>` instance.
1128
+ *
1129
+ * @example
1130
+ * ```ts
1131
+ * // Simple debounced signal with an initial value
1132
+ * const search = signalDebounce<string>({ debounceTime: 300, initialValue: '' });
1133
+ * search.setDebounced('hello'); // commits after 300 ms
1134
+ *
1135
+ * // Tracking a reactive source
1136
+ * const query = signal('angular');
1137
+ * const debounced = signalDebounce({ params: () => query(), debounceTime: 500 });
1138
+ * ```
1139
+ */
1140
+ declare function signalDebounce<T>(options: {
1141
+ params?: () => T;
1142
+ debounceTime: number;
1143
+ initialValue?: T;
1144
+ injector?: unknown;
1145
+ }): SignalDebounce<T>;
1146
+
1147
+ /**
1148
+ * A reactive wrapper around a `Set` backed by Angular signals.
1149
+ * All mutations produce a new `Set` instance, ensuring signal-based change detection works correctly.
1150
+ *
1151
+ * @template T The type of elements stored in the set. Defaults to `number`.
1152
+ */
1153
+ interface SignalSet<T = number> {
1154
+ /** The current underlying `Set` (read via signal). */
1155
+ (): Set<T>;
1156
+ /** The number of elements in the set (reactive). */
1157
+ size: Signal<number>;
1158
+ /** A computed signal that returns the set contents as an array. */
1159
+ toArray: Signal<T[]>;
1160
+ /** Adds the element if absent, removes it if present. */
1161
+ toggle: (id: T) => void;
1162
+ /** Returns `true` if the element exists in the set. */
1163
+ has: (id: T) => boolean;
1164
+ /** Adds an element to the set. */
1165
+ add: (id: T) => void;
1166
+ /** Removes an element from the set. */
1167
+ delete: (id: T) => void;
1168
+ /** Removes all elements from the set. */
1169
+ clear: () => void;
1170
+ /** Returns a human-readable string representation, e.g. `SignalSet(1, 2, 3)`. */
1171
+ toString: () => string;
1172
+ /** Converts the set to a JSON-compatible array. e.g. `[1, 2, "a"]` */
1173
+ toJSON: () => T[];
1174
+ }
1175
+ /**
1176
+ * Creates a reactive `SignalSet` backed by Angular signals.
1177
+ *
1178
+ * Every mutation creates a new `Set`, so Angular's signal equality check triggers updates.
1179
+ *
1180
+ * @template T The element type. Defaults to `number`.
1181
+ * @param initialValue An optional iterable to seed the set with.
1182
+ * @returns A {@link SignalSet} instance.
1183
+ *
1184
+ * @example
1185
+ * ```ts
1186
+ * const selected = signalSet<number>();
1187
+ * selected.add(1);
1188
+ * selected.toggle(2);
1189
+ * console.log(selected.toArray()); // [1, 2]
1190
+ * selected.toggle(1);
1191
+ * console.log(selected.has(1)); // false
1192
+ * ```
1193
+ */
1194
+ declare function signalSet<T = number>(initialValue?: Iterable<T> | (() => Iterable<T>)): SignalSet<T>;
1195
+
1196
+ /**
1197
+ * Resolves `T` to itself when it is a valid object key (`string | number | symbol`),
1198
+ * otherwise falls back to `string`. Used to type-safe `Record` conversions.
1199
+ */
1200
+ type ToKey<T> = T extends string | number | symbol ? T : string;
1201
+ /**
1202
+ * A reactive wrapper around a `Map` backed by Angular signals.
1203
+ * All mutations produce a new `Map` instance, ensuring signal-based change detection works correctly.
1204
+ *
1205
+ * @template K The key type. Defaults to `string`.
1206
+ * @template V The value type. Defaults to `unknown`.
1207
+ */
1208
+ interface SignalMap<K = string, V = unknown> {
1209
+ /** The current underlying `Map` (read via signal). */
1210
+ (): Map<K, V>;
1211
+ /** The number of entries in the map (reactive). */
1212
+ size: Signal<number>;
1213
+ /** A computed signal that returns the map keys as an array. */
1214
+ keys: Signal<K[]>;
1215
+ /** A computed signal that returns the map values as an array. */
1216
+ values: Signal<V[]>;
1217
+ /** A computed signal that returns the map entries as an array of `[key, value]` tuples. */
1218
+ entries: Signal<[K, V][]>;
1219
+ /** Returns the value associated with `key`, or `undefined` if absent. */
1220
+ get: (key: K) => V | undefined;
1221
+ /** Returns `true` if the map contains the given `key`. */
1222
+ has: (key: K) => boolean;
1223
+ /** Sets (or overwrites) the value for `key` and returns the updated `Map`. */
1224
+ set: (key: K, value: V) => Map<K, V>;
1225
+ /** Removes the entry for `key`. Returns `true` if the key existed. */
1226
+ delete: (key: K) => boolean;
1227
+ /** Removes all entries from the map. */
1228
+ clear: () => void;
1229
+ /** Returns a human-readable string, e.g. `SignalMap(a => 1, b => 2)`. */
1230
+ toString: () => string;
1231
+ /** Converts the map to a JSON-compatible object. */
1232
+ toJSON: () => Record<ToKey<K>, V>;
1233
+ }
1234
+ /**
1235
+ * Creates a reactive `SignalMap` backed by Angular signals.
1236
+ *
1237
+ * Every mutation creates a new `Map`, so Angular's signal equality check triggers updates.
1238
+ * Accepts either an iterable of `[key, value]` pairs or a plain object as the initial value.
1239
+ *
1240
+ * @template K The key type. Defaults to `string`.
1241
+ * @template V The value type. Defaults to `unknown`.
1242
+ * @param initialValue An optional iterable of entries or a plain object to seed the map.
1243
+ * @returns A {@link SignalMap} instance.
1244
+ *
1245
+ * @example
1246
+ * ```ts
1247
+ * const cache = signalMap<string, number>({ a: 1, b: 2 });
1248
+ * cache.set('c', 3);
1249
+ * console.log(cache.keys()); // ['a', 'b', 'c']
1250
+ * cache.delete('a'); // true
1251
+ * console.log(cache.toJSON()); // {b:2,c:3}
1252
+ * ```
1253
+ */
1254
+ declare function signalMap<K = string, V = unknown>(initialValue?: Iterable<[K, V]> | Record<ToKey<K>, V> | (() => Iterable<[K, V]> | Record<ToKey<K>, V>)): SignalMap<K, V>;
1255
+
1256
+ /**
1257
+ * Creates a reactive object backed by Angular signals.
1258
+ *
1259
+ * Every property is stored as a `WritableSignal`. Reading a property
1260
+ * (e.g. `obj.name` or `obj['name']`) calls the signal — so it's
1261
+ * automatically tracked in templates, `computed()`, and `effect()`.
1262
+ * Setting a property calls `signal.set()`, which triggers reactivity.
1263
+ *
1264
+ * @example
1265
+ * // In a component:
1266
+ * protected person = signalObject({ name: 'dvirus', age: 30 });
1267
+ *
1268
+ * // In the template (reactive — updates automatically):
1269
+ * // {{ person.name }}
1270
+ *
1271
+ * // In the class:
1272
+ * // person.name = 'changed'; → triggers re-render
1273
+ * // person['age'] = 31; → triggers re-render
1274
+ */
1275
+ type SignalObject<T> = T & {
1276
+ /**
1277
+ * Call the SignalObject as a function to get a reactive snapshot.
1278
+ *
1279
+ * @example
1280
+ * const person = signalObject({ name: 'dvirus', age: 30 });
1281
+ * person(); // { name: 'dvirus', age: 30 } — tracked by Angular
1282
+ */
1283
+ (): T;
1284
+ /**
1285
+ * A computed signal that returns a plain snapshot of all properties.
1286
+ * Reading this tracks ALL properties — any property change triggers reactivity.
1287
+ *
1288
+ * @example
1289
+ * effect(() => console.log(person.$snapshot()));
1290
+ * // logs whenever ANY property changes
1291
+ *
1292
+ * const label = computed(() => {
1293
+ * const snap = person.$snapshot();
1294
+ * return `${snap.name} (${snap.age})`;
1295
+ * });
1296
+ */
1297
+ /**
1298
+ * Spreads one or more objects (plain or reactive) into this SignalObject.
1299
+ * Mimics `Object.assign(this, ...sources)` / `{ ...this, ...a, ...b }`.
1300
+ *
1301
+ * - Existing keys → updates the signal (triggers reactivity)
1302
+ * - New keys → creates a new signal and bumps the version
1303
+ * - Accepts plain objects and SignalObjects interchangeably
1304
+ *
1305
+ * @param sources - One or more plain objects or SignalObjects to merge in
1306
+ *
1307
+ * @example
1308
+ * const person = signalObject({ name: 'dvirus' });
1309
+ * person.$assign({ age: 30 }, otherSignalObj);
1310
+ */
1311
+ $assign(...sources: Partial<T>[]): void;
1312
+ };
1313
+ /**
1314
+ * Creates a reactive object backed by Angular signals.
1315
+ *
1316
+ * Every property is stored as a `WritableSignal`. Reading a property
1317
+ * (e.g. `obj.name` or `obj['name']`) calls the signal — so it's
1318
+ * automatically tracked in templates, `computed()`, and `effect()`.
1319
+ * Setting a property calls `signal.set()`, which triggers reactivity.
1320
+ *
1321
+ * @param initialValue - The plain object to make reactive
1322
+ * @returns A `SignalObject<T>` proxy with reactive property access, `$snapshot`, and `$assign`
1323
+ *
1324
+ * @example
1325
+ * // In a component:
1326
+ * protected person = signalObject({ name: 'dvirus', age: 30 });
1327
+ *
1328
+ * // In the template (reactive — updates automatically):
1329
+ * // {{ person.name }}
1330
+ *
1331
+ * // In the class:
1332
+ * person.name = 'changed'; // triggers re-render
1333
+ * person['age'] = 31; // triggers re-render
1334
+ *
1335
+ * // Spread (plain snapshot):
1336
+ * const copy = { ...person }; // { name: 'changed', age: 31 }
1337
+ *
1338
+ * // Track all properties reactively:
1339
+ * effect(() => console.log(person.$snapshot()));
1340
+ */
1341
+ declare function signalObject<T extends object>(initialValue: T): SignalObject<T>;
1342
+ /**
1343
+ * Type guard — checks if a value is a reactive SignalObject proxy.
1344
+ *
1345
+ * @example
1346
+ * isSignalObject(signalObject({ a: 1 })); // true
1347
+ * isSignalObject({ a: 1 }); // false
1348
+ * isSignalObject({ ...signalObject({ a: 1 }) }); // false (spread = plain copy)
1349
+ */
1350
+ declare function isSignalObject<T extends Record<string, unknown>>(value: unknown): value is SignalObject<T>;
1351
+ /**
1352
+ * Reactively merges multiple SignalObjects (like `{ ...a, ...b }`).
1353
+ * Returns a `Signal` that re-evaluates whenever any source property changes.
1354
+ * Later sources win on key conflicts, just like spread.
1355
+ *
1356
+ * same as `computed(() => ({ ...a, ...b }))`
1357
+ * but with proper tracking of nested properties and support for non-reactive objects as sources.
1358
+ *
1359
+ * @example
1360
+ * const objA = signalObject({ name: 'dvirus', role: 'dev' });
1361
+ * const objB = signalObject({ age: 30, role: 'admin' });
1362
+ * const merged = mergeSignalObjects(objA, objB);
1363
+ * merged(); // { name: 'dvirus', role: 'admin', age: 30 }
1364
+ */
1365
+ declare function mergeSignalObjects<T extends object[]>(...sources: [...{
1366
+ [K in keyof T]: T[K] | SignalObject<T[K]>;
1367
+ }]): Signal<UnionToIntersection<T[number]>>;
1368
+ /**
1369
+ * Extracts the plain object type `U` from a `SignalObject<U>`.
1370
+ * Returns `T` as-is if it's not a `SignalObject`.
1371
+ */
1372
+ /**
1373
+ * Converts a union of types into an intersection.
1374
+ * Used to merge multiple object types from `mergeSignalObjects` into a single combined type.
1375
+ *
1376
+ * @example
1377
+ * // UnionToIntersection<{ a: 1 } | { b: 2 }> → { a: 1 } & { b: 2 }
1378
+ */
1379
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
1380
+
1381
+ interface ControlEvent<T> {
1382
+ /**
1383
+ * Form control from which this event is originated.
1384
+ *
1385
+ * Note: the type of the control can't be inferred from T as the event can be emitted by any of child controls
1386
+ */
1387
+ readonly source: AbstractControl<unknown | T>;
1388
+ }
1389
+ /**
1390
+ * A reactive signal-based wrapper around an `AbstractControl`, exposing
1391
+ * the control's state (value, status, touched, dirty, errors, etc.) as
1392
+ * Angular signals for use in templates and computed expressions.
1393
+ *
1394
+ * @template T - The value type of the underlying form control.
1395
+ * @template TControl - The specific `AbstractControl` type being wrapped (e.g., `FormControl`, `FormGroup`, `FormArray`).
1396
+ */
1397
+ interface ControlSignal<T, TControl extends AbstractControl<unknown> = AbstractControl<T>> {
1398
+ /** Signal returning the underlying `AbstractControl` instance with its specific type. */
1399
+ control: TControl;
1400
+ /** Signal returning the current value of the control. */
1401
+ value: Signal<T | null | undefined>;
1402
+ /** Signal returning the current validation status (`VALID`, `INVALID`, `PENDING`, `DISABLED`). */
1403
+ status: Signal<FormControlStatus | null | undefined>;
1404
+ /** Signal returning the most recent `ControlEvent` emitted by the control. */
1405
+ events: Signal<ControlEvent<T> | null | undefined>;
1406
+ /** Signal that is `true` when the control status is `DISABLED`. */
1407
+ disabled: Signal<boolean>;
1408
+ /** Signal that is `true` when the control status is `VALID`. */
1409
+ valid: Signal<boolean>;
1410
+ /** Signal that is `true` when the control status is `INVALID`. */
1411
+ invalid: Signal<boolean>;
1412
+ /** Signal that is `true` when the control has been touched. */
1413
+ touched: Signal<boolean>;
1414
+ /** Signal that is `true` when the control is dirty. */
1415
+ dirty: Signal<boolean>;
1416
+ /** Signal returning the current validation errors, or `null` if there are none. */
1417
+ errors: Signal<ValidationErrors | null>;
1418
+ /** Signal returning the key of the first validation error, or `null`. */
1419
+ firstErrorKey: Signal<string | null>;
1420
+ /** Signal that is `true` when the control is both touched and invalid. */
1421
+ touchedAndInvalid: Signal<boolean>;
1422
+ /**
1423
+ * Signal returning the control's synchronous validators as a `ValidationErrors`-like object, or `null` if there are none.
1424
+ * @Note that this does not include asynchronous validators, and the shape of the returned object may differ from the actual validation errors emitted by the control.
1425
+ */
1426
+ validators: Signal<ValidationErrors | null>;
1427
+ /** Tears down all internal subscriptions and effects. */
1428
+ unsubscribe(): void;
1429
+ }
1430
+ /**
1431
+ * Creates a {@link ControlSignal} that mirrors an `AbstractControl`'s
1432
+ * reactive state as Angular signals.
1433
+ *
1434
+ * **Important:** If called outside an injection context, you must manually handle
1435
+ * un-subscription by either:
1436
+ * - Calling the `unsubscribe()` method on the returned {@link ControlSignal}, or
1437
+ * - Passing a `DestroyRef` via the `options` parameter for automatic cleanup.
1438
+ *
1439
+ * If called within an injection context without providing a `DestroyRef`, the
1440
+ * subscriptions will be automatically cleaned up on component destruction.
1441
+ *
1442
+ * @template T - The value type of the form control.
1443
+ * @param control - The form control or a signal wrapping one.
1444
+ * @param options - Optional configuration object containing:
1445
+ * - `destroyRef`: A `DestroyRef` used for automatic cleanup on destruction.
1446
+ * If not provided, the function will attempt to inject one from the current
1447
+ * injection context. If neither is available, manual un-subscription is required.
1448
+ * @returns A {@link ControlSignal} exposing the control's state as signals.
1449
+ * @throws If `control` is a signal and no `Injector` is available.
1450
+ */
1451
+ declare function controlSignal<T, TControl extends AbstractControl<unknown> = FormControl<T>>(control: TControl, options?: {
1452
+ destroyRef?: DestroyRef | null;
1453
+ }): ControlSignal<T, TControl>;
1454
+ /**
1455
+ * Extends {@link ControlSignal} with a strongly-typed `controls` map,
1456
+ * providing a `ControlSignal` for every control in the `FormGroup`.
1457
+ *
1458
+ * @template T - An object type whose keys correspond to the group's control names
1459
+ * and whose values are the respective control value types.
1460
+ */
1461
+ interface FormGroupSignal<TControls extends TypedControlMap> extends ControlSignal<ControlsValue<TControls>, FormGroup<TControls>> {
1462
+ /** The underlying `FormGroup` instance. */
1463
+ control: FormGroup<TControls>;
1464
+ /** A map of child control names to their individual {@link ControlSignal} instances. */
1465
+ controls: {
1466
+ [K in keyof TControls]: NestedControlSignal<TControls[K]>;
1467
+ };
1468
+ }
1469
+ /**
1470
+ * Creates a {@link FormGroupSignal} for a `FormGroup`. Child controls are
1471
+ * converted recursively, so nested `FormGroup` and `FormArray` structures
1472
+ * are supported.
1473
+ *
1474
+ * @template TControls - A typed map of control names to `AbstractControl` instances.
1475
+ * @param formGroup - The `FormGroup` to wrap.
1476
+ * @param options - Optional `DestroyRef` and `Injector` forwarded to
1477
+ * each underlying {@link controlSignal} call.
1478
+ * @returns A {@link FormGroupSignal} with both group-level and per-control signals.
1479
+ */
1480
+ declare function formGroupSignal<TControls extends TypedControlMap>(formGroup: FormGroup<TControls>, options?: {
1481
+ destroyRef?: DestroyRef | null;
1482
+ }): FormGroupSignal<TControls>;
1483
+ interface FormArraySignal<TControl extends AbstractControl<unknown>> extends ControlSignal<ControlValue<TControl>[], FormArray<TControl>> {
1484
+ /** The underlying `FormArray` instance. */
1485
+ control: FormArray<TControl>;
1486
+ controls: NestedControlSignal<TControl>[];
1487
+ }
1488
+ /**
1489
+ * Creates a {@link FormArraySignal} for a `FormArray`. Child controls are
1490
+ * converted recursively, so arrays of `FormGroup`, arrays of `FormArray`,
1491
+ * and arrays of `FormControl` are all supported.
1492
+ */
1493
+ declare function formArraySignal<TControl extends AbstractControl<unknown>>(formArray: FormArray<TControl>, options?: {
1494
+ destroyRef?: DestroyRef | null;
1495
+ }): FormArraySignal<TControl>;
1496
+ type TypedControlMap = Record<string, AbstractControl<unknown>>;
1497
+ type ControlValue<TControl extends AbstractControl<unknown>> = TControl extends AbstractControl<infer TValue> ? TValue : never;
1498
+ type ControlsValue<TControls extends TypedControlMap> = {
1499
+ [K in keyof TControls]: ControlValue<TControls[K]>;
1500
+ };
1501
+ type NestedControlSignal<TControl extends AbstractControl<unknown>> = TControl extends FormGroup<infer TControls> ? FormGroupSignal<TControls> : TControl extends FormArray<infer TItemControl> ? FormArraySignal<TItemControl & AbstractControl<unknown>> : ControlSignal<ControlValue<TControl>, TControl>;
1502
+
1503
+ /**
1504
+ * Types for the result tuple with discriminated union
1505
+ * @template T - Type of the successful result
1506
+ * @template E - Type of the error, defaults to Error
1507
+ */
1508
+ type TryResult<T, E = Error> = [T, null] | [null, E];
1509
+ /**
1510
+ * Main wrapper function to handle promise with try-catch
1511
+ * @template T - Type of the successful result
1512
+ * @template E - Type of the error, defaults to Error
1513
+ * @param {()=> T} fn - The function to handle
1514
+ * @returns {TryResult<T, E>} - A tuple with either the result or the error
1515
+ */
1516
+ declare function tryCatch<T, E = Error>(fn: () => T): TryResult<T, E>;
1517
+
1518
+ /**
1519
+ * Type for value equality comparison function
1520
+ */
1521
+ type ValueEqualityFn<T> = (a: T, b: T) => boolean;
1522
+ /**
1523
+ * Creates a `WritableSignal` whose value is derived from a computation function,
1524
+ * but can also be overridden manually via `.set()` / `.update()`.
1525
+ * When the reactive dependencies inside the computation change, the signal resets to the new derived value.
1526
+ *
1527
+ * Angular-16 compatible alternative to `linkedSignal` (Angular 19+).
1528
+ *
1529
+ * @overload
1530
+ * @param computation - A computation function that returns the derived value
1531
+ * @param options - Optional configuration (equal, debugName)
1532
+ * @returns A WritableSignal<D>
1533
+ */
1534
+ declare function writableSignal<D>(computation: () => D, options?: {
1535
+ equal?: ValueEqualityFn<D>;
1536
+ debugName?: string;
1537
+ }): WritableSignal<D>;
1538
+ /**
1539
+ * Creates a `WritableSignal` with explicit source tracking and computation.
1540
+ * The `source` function provides the reactive dependencies, and the `computation` function derives the value from the source.
1541
+ * Manual overrides via `.set()` / `.update()` are only valid for the specific source state they were set against.
1542
+ *
1543
+ * Angular-16 compatible alternative to `linkedSignal` (Angular 19+).
1544
+ *
1545
+ * @overload
1546
+ * @param options - Configuration object with source tracking and computation
1547
+ * @returns A WritableSignal<D>
1548
+ */
1549
+ declare function writableSignal<S, D>(options: {
1550
+ source: () => S;
1551
+ computation: (source: S, previous?: {
1552
+ source: S;
1553
+ value: D;
1554
+ }) => D;
1555
+ equal?: ValueEqualityFn<D>;
1556
+ debugName?: string;
1557
+ }): WritableSignal<D>;
1558
+
1559
+ export { controlSignal, createSignalFormArray, createSignalFormControl, createSignalFormGroup, formArray, formArraySignal, formControl, formGroup, formGroupSignal, fromSignalObj, isSignalFormArray, isSignalFormControl, isSignalFormGroup, isSignalObject, mergeSignalObjects, signalDebounce, signalForm, signalFormValidators, signalMap, signalNotifier, signalObject, signalOrFunction, signalOrValue, signalSet, toSignalObj, tryCatch, writableSignal };
1560
+ export type { ControlSignal, FirstError, FormArraySignal, FormGroupSignal, NestedControlSignal, ObjectType, SignalDebounce, SignalForm, SignalFormArray, SignalFormArrayInput, SignalFormContext, SignalFormControl, SignalFormControlConfig, SignalFormControlInput, SignalFormControlLike, SignalFormDisableOptions, SignalFormDisabledFn, SignalFormErrorFor, SignalFormGroupInput, SignalFormInput, SignalFormInputs, SignalFormSetValueOptions, SignalFormValidationError, SignalFormValidatorFn, SignalFormValueFor, SignalMap, SignalNotifier, SignalObj, SignalObjWritable, SignalObject, SignalOrValue, SignalOrValueObj, SignalSet };