@ng-forge/dynamic-forms 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +121 -4
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-B_676NHl.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-CMSmISSp.mjs} +561 -331
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CMSmISSp.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-page-field.component-YHFQcpCS.mjs → ng-forge-dynamic-forms-page-field.component-rdGD8A9d.mjs} +6 -6
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-rdGD8A9d.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-testing-test-button.harness-BenmCFcM.mjs → ng-forge-dynamic-forms-testing-test-button.harness-0iXHLraC.mjs} +7 -7
- package/fesm2022/ng-forge-dynamic-forms-testing-test-button.harness-0iXHLraC.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs +41 -38
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-CiYq73aF.mjs → ng-forge-dynamic-forms-text-field.component-CDxka2KD.mjs} +5 -5
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-CiYq73aF.mjs.map → ng-forge-dynamic-forms-text-field.component-CDxka2KD.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
- package/package.json +4 -4
- package/types/ng-forge-dynamic-forms-integration.d.ts +237 -9
- package/types/ng-forge-dynamic-forms-testing.d.ts +67 -35
- package/types/ng-forge-dynamic-forms.d.ts +263 -99
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-B_676NHl.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-YHFQcpCS.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-testing-test-button.harness-BenmCFcM.mjs.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { FormEvent, FieldDef, FormEventConstructor, BaseCheckedField, BaseValueField, DynamicText, FieldOption, ValidationMessages } from '@ng-forge/dynamic-forms';
|
|
2
|
-
import
|
|
1
|
+
import { FormEvent, FieldDef, FormEventConstructor, BaseCheckedField, BaseValueField, DynamicText, FieldMeta, FieldOption, ValidationMessages } from '@ng-forge/dynamic-forms';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { Signal, Injector, ElementRef, PipeTransform } from '@angular/core';
|
|
3
4
|
import { FieldTree } from '@angular/forms/signals';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -42,6 +43,94 @@ interface DatepickerField<TProps> extends BaseValueField<TProps, Date | string>
|
|
|
42
43
|
startAt?: Date | null;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Autocomplete values for HTML input elements.
|
|
48
|
+
* Based on the WHATWG HTML specification for autofill.
|
|
49
|
+
*
|
|
50
|
+
* @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill
|
|
51
|
+
*/
|
|
52
|
+
type AutocompleteValue = 'off' | 'on' | 'name' | 'honorific-prefix' | 'given-name' | 'additional-name' | 'family-name' | 'honorific-suffix' | 'nickname' | 'email' | 'username' | 'new-password' | 'current-password' | 'one-time-code' | 'organization-title' | 'organization' | 'street-address' | 'address-line1' | 'address-line2' | 'address-line3' | 'address-level4' | 'address-level3' | 'address-level2' | 'address-level1' | 'country' | 'country-name' | 'postal-code' | 'cc-name' | 'cc-given-name' | 'cc-additional-name' | 'cc-family-name' | 'cc-number' | 'cc-exp' | 'cc-exp-month' | 'cc-exp-year' | 'cc-csc' | 'cc-type' | 'transaction-currency' | 'transaction-amount' | 'language' | 'bday' | 'bday-day' | 'bday-month' | 'bday-year' | 'sex' | 'tel' | 'tel-country-code' | 'tel-national' | 'tel-area-code' | 'tel-local' | 'tel-extension' | 'impp' | 'url' | 'photo';
|
|
53
|
+
/**
|
|
54
|
+
* Input mode hints for virtual keyboards on mobile devices.
|
|
55
|
+
*
|
|
56
|
+
* @see https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute
|
|
57
|
+
*/
|
|
58
|
+
type InputMode = 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
|
|
59
|
+
/**
|
|
60
|
+
* Enter key hints for virtual keyboards.
|
|
61
|
+
*
|
|
62
|
+
* @see https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-enterkeyhint-attribute
|
|
63
|
+
*/
|
|
64
|
+
type EnterKeyHint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
|
|
65
|
+
/**
|
|
66
|
+
* Autocapitalization hints for virtual keyboards.
|
|
67
|
+
*
|
|
68
|
+
* @see https://html.spec.whatwg.org/multipage/interaction.html#attr-autocapitalize
|
|
69
|
+
*/
|
|
70
|
+
type Autocapitalize = 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';
|
|
71
|
+
/**
|
|
72
|
+
* Meta attributes specific to HTML input elements.
|
|
73
|
+
*
|
|
74
|
+
* Extends FieldMeta with input-specific native attributes that can be passed through
|
|
75
|
+
* to the underlying input element.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* // Input field with meta attributes
|
|
80
|
+
* {
|
|
81
|
+
* type: 'input',
|
|
82
|
+
* key: 'email',
|
|
83
|
+
* meta: {
|
|
84
|
+
* autocomplete: 'email',
|
|
85
|
+
* inputmode: 'email',
|
|
86
|
+
* enterkeyhint: 'next',
|
|
87
|
+
* spellcheck: false,
|
|
88
|
+
* 'data-testid': 'email-input'
|
|
89
|
+
* }
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
interface InputMeta extends FieldMeta {
|
|
96
|
+
/**
|
|
97
|
+
* Hint for form autofill behavior.
|
|
98
|
+
*/
|
|
99
|
+
autocomplete?: AutocompleteValue;
|
|
100
|
+
/**
|
|
101
|
+
* Hint for virtual keyboard type on mobile devices.
|
|
102
|
+
*/
|
|
103
|
+
inputmode?: InputMode;
|
|
104
|
+
/**
|
|
105
|
+
* Hint for the enter key label on virtual keyboards.
|
|
106
|
+
*/
|
|
107
|
+
enterkeyhint?: EnterKeyHint;
|
|
108
|
+
/**
|
|
109
|
+
* Whether to enable spellchecking for the input.
|
|
110
|
+
*/
|
|
111
|
+
spellcheck?: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Hint for autocapitalization behavior on virtual keyboards.
|
|
114
|
+
*/
|
|
115
|
+
autocapitalize?: Autocapitalize;
|
|
116
|
+
/**
|
|
117
|
+
* Pattern for client-side validation (regex).
|
|
118
|
+
*/
|
|
119
|
+
pattern?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Size hint for the input element (character count).
|
|
122
|
+
*/
|
|
123
|
+
size?: number;
|
|
124
|
+
/**
|
|
125
|
+
* Maximum number of characters allowed.
|
|
126
|
+
*/
|
|
127
|
+
maxlength?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Minimum number of characters required.
|
|
130
|
+
*/
|
|
131
|
+
minlength?: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
45
134
|
/**
|
|
46
135
|
* HTML input types supported by input fields
|
|
47
136
|
*/
|
|
@@ -76,7 +165,7 @@ interface NumberInputField<TProps extends {
|
|
|
76
165
|
type?: string;
|
|
77
166
|
} = InputProps> extends BaseValueField<TProps & {
|
|
78
167
|
type: 'number';
|
|
79
|
-
}, number> {
|
|
168
|
+
}, number, InputMeta> {
|
|
80
169
|
type: 'input';
|
|
81
170
|
props: TProps & {
|
|
82
171
|
type: 'number';
|
|
@@ -91,7 +180,7 @@ interface StringInputField<TProps extends {
|
|
|
91
180
|
type?: string;
|
|
92
181
|
} = InputProps> extends BaseValueField<TProps & {
|
|
93
182
|
type?: StringInputType;
|
|
94
|
-
}, string> {
|
|
183
|
+
}, string, InputMeta> {
|
|
95
184
|
type: 'input';
|
|
96
185
|
props?: TProps & {
|
|
97
186
|
type?: StringInputType;
|
|
@@ -155,12 +244,12 @@ type InputField<TProps extends {
|
|
|
155
244
|
*/
|
|
156
245
|
interface MultiCheckboxField<TValue, TProps = object> extends BaseValueField<TProps, TValue[]> {
|
|
157
246
|
type: 'multi-checkbox';
|
|
158
|
-
options: FieldOption<TValue>[];
|
|
247
|
+
readonly options: readonly FieldOption<TValue>[];
|
|
159
248
|
}
|
|
160
249
|
|
|
161
250
|
interface RadioField<T, TProps> extends BaseValueField<TProps, T> {
|
|
162
251
|
type: 'radio';
|
|
163
|
-
options: FieldOption<T>[];
|
|
252
|
+
readonly options: readonly FieldOption<T>[];
|
|
164
253
|
}
|
|
165
254
|
|
|
166
255
|
interface SelectProps {
|
|
@@ -178,12 +267,75 @@ interface SliderField<TProps> extends BaseValueField<TProps, number> {
|
|
|
178
267
|
step?: number;
|
|
179
268
|
}
|
|
180
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Text wrapping behavior for textarea elements.
|
|
272
|
+
*
|
|
273
|
+
* @see https://html.spec.whatwg.org/multipage/form-elements.html#attr-textarea-wrap
|
|
274
|
+
*/
|
|
275
|
+
type TextareaWrap = 'hard' | 'soft' | 'off';
|
|
276
|
+
/**
|
|
277
|
+
* Meta attributes specific to HTML textarea elements.
|
|
278
|
+
*
|
|
279
|
+
* Extends FieldMeta with textarea-specific native attributes that can be passed through
|
|
280
|
+
* to the underlying textarea element.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* // Textarea field with meta attributes
|
|
285
|
+
* {
|
|
286
|
+
* type: 'textarea',
|
|
287
|
+
* key: 'description',
|
|
288
|
+
* meta: {
|
|
289
|
+
* wrap: 'soft',
|
|
290
|
+
* spellcheck: true,
|
|
291
|
+
* autocomplete: 'off',
|
|
292
|
+
* 'data-testid': 'description-textarea'
|
|
293
|
+
* }
|
|
294
|
+
* }
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
297
|
+
* @public
|
|
298
|
+
*/
|
|
299
|
+
interface TextareaMeta extends FieldMeta {
|
|
300
|
+
/**
|
|
301
|
+
* How text should wrap when submitted.
|
|
302
|
+
* - 'hard': Line breaks are inserted to wrap text at cols width
|
|
303
|
+
* - 'soft': Text is wrapped for display but not in submitted value
|
|
304
|
+
* - 'off': No wrapping, horizontal scrolling if needed
|
|
305
|
+
*/
|
|
306
|
+
wrap?: TextareaWrap;
|
|
307
|
+
/**
|
|
308
|
+
* Whether to enable spellchecking for the textarea.
|
|
309
|
+
*/
|
|
310
|
+
spellcheck?: boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Hint for form autofill behavior.
|
|
313
|
+
*/
|
|
314
|
+
autocomplete?: AutocompleteValue;
|
|
315
|
+
/**
|
|
316
|
+
* Hint for autocapitalization behavior on virtual keyboards.
|
|
317
|
+
*/
|
|
318
|
+
autocapitalize?: Autocapitalize;
|
|
319
|
+
/**
|
|
320
|
+
* Hint for the enter key label on virtual keyboards.
|
|
321
|
+
*/
|
|
322
|
+
enterkeyhint?: EnterKeyHint;
|
|
323
|
+
/**
|
|
324
|
+
* Maximum number of characters allowed.
|
|
325
|
+
*/
|
|
326
|
+
maxlength?: number;
|
|
327
|
+
/**
|
|
328
|
+
* Minimum number of characters required.
|
|
329
|
+
*/
|
|
330
|
+
minlength?: number;
|
|
331
|
+
}
|
|
332
|
+
|
|
181
333
|
interface TextareaProps {
|
|
182
334
|
placeholder?: DynamicText;
|
|
183
335
|
rows?: number;
|
|
184
336
|
cols?: number | undefined;
|
|
185
337
|
}
|
|
186
|
-
interface TextareaField<TProps = TextareaProps> extends BaseValueField<TProps, string> {
|
|
338
|
+
interface TextareaField<TProps = TextareaProps> extends BaseValueField<TProps, string, TextareaMeta> {
|
|
187
339
|
type: 'textarea';
|
|
188
340
|
maxLength?: number | undefined;
|
|
189
341
|
}
|
|
@@ -311,5 +463,81 @@ declare function createResolvedErrorsSignal<T>(field: Signal<FieldTree<T>>, vali
|
|
|
311
463
|
*/
|
|
312
464
|
declare function shouldShowErrors<T>(field: Signal<FieldTree<T>>): Signal<boolean>;
|
|
313
465
|
|
|
314
|
-
|
|
315
|
-
|
|
466
|
+
/**
|
|
467
|
+
* Performs a deep equality comparison between two values
|
|
468
|
+
*/
|
|
469
|
+
declare function isEqual(a: unknown, b: unknown): boolean;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Configuration options for setupMetaTracking.
|
|
473
|
+
*/
|
|
474
|
+
interface MetaTrackingOptions {
|
|
475
|
+
/**
|
|
476
|
+
* CSS selector for target elements within the host.
|
|
477
|
+
* If not provided, meta attributes are applied directly to the host element.
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* // Apply to internal radio inputs
|
|
481
|
+
* selector: 'input[type="radio"]'
|
|
482
|
+
*
|
|
483
|
+
* // Apply to host element (for Shadow DOM components)
|
|
484
|
+
* selector: undefined
|
|
485
|
+
*/
|
|
486
|
+
selector?: string;
|
|
487
|
+
/**
|
|
488
|
+
* Additional signals to track that should trigger re-application of meta.
|
|
489
|
+
* Useful for components where DOM elements are dynamically created (e.g., radio options).
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* // Re-apply when options change
|
|
493
|
+
* dependents: [this.options]
|
|
494
|
+
*/
|
|
495
|
+
dependents?: Signal<unknown>[];
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Sets up automatic meta attribute tracking and application for wrapped components.
|
|
499
|
+
*
|
|
500
|
+
* This utility creates an `afterRenderEffect` that applies meta attributes to DOM elements
|
|
501
|
+
* after Angular's render cycle. It efficiently tracks signal dependencies and only re-applies
|
|
502
|
+
* when the meta signal or any dependent signals change.
|
|
503
|
+
*
|
|
504
|
+
* Use this instead of MutationObserver for better performance and integration with Angular's
|
|
505
|
+
* change detection.
|
|
506
|
+
*
|
|
507
|
+
* @param elementRef - Reference to the host element
|
|
508
|
+
* @param meta - Signal containing meta attributes to apply
|
|
509
|
+
* @param options - Configuration options
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* ```typescript
|
|
513
|
+
* // For a radio group with dynamic options
|
|
514
|
+
* constructor() {
|
|
515
|
+
* setupMetaTracking(inject(ElementRef), this.meta, {
|
|
516
|
+
* selector: 'input[type="radio"]',
|
|
517
|
+
* dependents: [this.options]
|
|
518
|
+
* });
|
|
519
|
+
* }
|
|
520
|
+
*
|
|
521
|
+
* // For a simple checkbox
|
|
522
|
+
* constructor() {
|
|
523
|
+
* setupMetaTracking(inject(ElementRef), this.meta, {
|
|
524
|
+
* selector: 'input[type="checkbox"]'
|
|
525
|
+
* });
|
|
526
|
+
* }
|
|
527
|
+
*
|
|
528
|
+
* // For Shadow DOM components (apply to host)
|
|
529
|
+
* constructor() {
|
|
530
|
+
* setupMetaTracking(inject(ElementRef), this.meta);
|
|
531
|
+
* }
|
|
532
|
+
* ```
|
|
533
|
+
*/
|
|
534
|
+
declare function setupMetaTracking(elementRef: ElementRef<HTMLElement>, meta: Signal<FieldMeta | undefined>, options?: MetaTrackingOptions): void;
|
|
535
|
+
|
|
536
|
+
declare class ValueInArrayPipe implements PipeTransform {
|
|
537
|
+
transform<T>(element: T, array: T[] | undefined): boolean;
|
|
538
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ValueInArrayPipe, never>;
|
|
539
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<ValueInArrayPipe, "inArray", true>;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export { ValueInArrayPipe, buildValueFieldInputs, checkboxFieldMapper, createResolvedErrorsSignal, datepickerFieldMapper, isEqual, optionsFieldMapper, resolveValueFieldContext, setupMetaTracking, shouldShowErrors, valueFieldMapper };
|
|
543
|
+
export type { Autocapitalize, AutocompleteValue, ButtonField, CheckboxField, DatepickerField, DatepickerProps, EnterKeyHint, EventArgs, FieldWithOptions, InputField, InputMeta, InputMode, InputProps, InputType, InputTypeToValueType, MetaTrackingOptions, MultiCheckboxField, RadioField, ResolvedError, SelectField, SelectProps, SliderField, StringInputType, TextareaField, TextareaMeta, TextareaProps, TextareaWrap, ToggleField, ValueFieldContext };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { Provider, Injector, WritableSignal, Type } from '@angular/core';
|
|
1
3
|
import { Mock } from 'vitest';
|
|
2
|
-
import {
|
|
4
|
+
import { Logger, FieldDef, FormConfig, DynamicForm, ValidationMessages, FieldSignalContext, RegisteredFieldTypes } from '@ng-forge/dynamic-forms';
|
|
3
5
|
import { ComponentFixture } from '@angular/core/testing';
|
|
4
6
|
import { ValidationError, form, FieldTree } from '@angular/forms/signals';
|
|
5
|
-
import * as _angular_core from '@angular/core';
|
|
6
|
-
import { Injector, WritableSignal, Type } from '@angular/core';
|
|
7
7
|
import { Observable } from 'rxjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -31,7 +31,7 @@ declare function delay(ms?: number): Promise<void>;
|
|
|
31
31
|
/**
|
|
32
32
|
* Mock logger with vitest spies for testing.
|
|
33
33
|
*/
|
|
34
|
-
interface MockLogger extends
|
|
34
|
+
interface MockLogger extends Logger {
|
|
35
35
|
debug: Mock;
|
|
36
36
|
info: Mock;
|
|
37
37
|
warn: Mock;
|
|
@@ -43,10 +43,10 @@ interface MockLogger extends DynamicFormLogger {
|
|
|
43
43
|
*/
|
|
44
44
|
declare function createMockLogger(): MockLogger;
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
46
|
+
* Provider for a console logger in tests.
|
|
47
|
+
* Add this to TestBed.configureTestingModule providers when not using provideDynamicForm().
|
|
48
48
|
*/
|
|
49
|
-
declare function
|
|
49
|
+
declare function provideTestLogger(): Provider;
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Configuration for creating a dynamic form test
|
|
@@ -68,7 +68,7 @@ interface DynamicFormTestResult {
|
|
|
68
68
|
*/
|
|
69
69
|
declare class FormConfigBuilder {
|
|
70
70
|
private fields;
|
|
71
|
-
field(field: FieldDef<
|
|
71
|
+
field(field: FieldDef<unknown>): FormConfigBuilder;
|
|
72
72
|
inputField(key: string, props?: Record<string, unknown>): FormConfigBuilder;
|
|
73
73
|
requiredInputField(key: string, props?: Record<string, unknown>): FormConfigBuilder;
|
|
74
74
|
selectField(key: string, options: Array<{
|
|
@@ -76,10 +76,10 @@ declare class FormConfigBuilder {
|
|
|
76
76
|
label: string;
|
|
77
77
|
}>, props?: Record<string, unknown>): FormConfigBuilder;
|
|
78
78
|
checkboxField(key: string, props?: Record<string, unknown>): FormConfigBuilder;
|
|
79
|
-
rowField(key: string, fields: FieldDef<
|
|
80
|
-
groupField(key: string, fields: FieldDef<
|
|
79
|
+
rowField(key: string, fields: FieldDef<unknown>[]): FormConfigBuilder;
|
|
80
|
+
groupField(key: string, fields: FieldDef<unknown>[]): FormConfigBuilder;
|
|
81
81
|
buttonField(key: string, props?: Record<string, unknown>): FormConfigBuilder;
|
|
82
|
-
pageField(key: string, fields: FieldDef<
|
|
82
|
+
pageField(key: string, fields: FieldDef<unknown>[], title?: string): FormConfigBuilder;
|
|
83
83
|
build(): FormConfig;
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
@@ -257,7 +257,7 @@ declare function createTestFieldContext<TModel extends Record<string, unknown> =
|
|
|
257
257
|
* Simple form configuration interface for testing
|
|
258
258
|
*/
|
|
259
259
|
interface TestFormConfig$1 {
|
|
260
|
-
fields: FieldDef<
|
|
260
|
+
fields: FieldDef<unknown>[];
|
|
261
261
|
}
|
|
262
262
|
/**
|
|
263
263
|
* Configuration for creating a dynamic form test
|
|
@@ -267,18 +267,19 @@ interface SimpleTestConfig<T = Record<string, unknown>> {
|
|
|
267
267
|
initialValue?: T;
|
|
268
268
|
}
|
|
269
269
|
/**
|
|
270
|
-
* Result of creating a dynamic form test
|
|
270
|
+
* Result of creating a dynamic form test.
|
|
271
|
+
* Uses the base DynamicForm type without generic constraints for flexibility in tests.
|
|
271
272
|
*/
|
|
272
273
|
interface SimpleTestResult {
|
|
273
|
-
component:
|
|
274
|
-
fixture:
|
|
274
|
+
component: DynamicForm<RegisteredFieldTypes[]>;
|
|
275
|
+
fixture: ComponentFixture<DynamicForm<RegisteredFieldTypes[]>>;
|
|
275
276
|
}
|
|
276
277
|
/**
|
|
277
278
|
* Fluent API for building form configurations using existing field structure
|
|
278
279
|
*/
|
|
279
280
|
declare class TestFormConfigBuilder<T = Record<string, unknown>> {
|
|
280
281
|
private fields;
|
|
281
|
-
field(field: FieldDef<
|
|
282
|
+
field(field: FieldDef<unknown>): TestFormConfigBuilder<T>;
|
|
282
283
|
inputField(key: string, props?: Record<string, unknown>): TestFormConfigBuilder<T>;
|
|
283
284
|
requiredInputField(key: string, props?: Record<string, unknown>): TestFormConfigBuilder<T>;
|
|
284
285
|
checkboxField(key: string, props?: Record<string, unknown>): TestFormConfigBuilder<T>;
|
|
@@ -299,58 +300,58 @@ declare class SimpleTestUtils {
|
|
|
299
300
|
/**
|
|
300
301
|
* Waits for the dynamic form to initialize
|
|
301
302
|
*/
|
|
302
|
-
static waitForInit(fixture:
|
|
303
|
+
static waitForInit(fixture: ComponentFixture<DynamicForm>): Promise<void>;
|
|
303
304
|
/**
|
|
304
305
|
* Simulates user input on a field element
|
|
305
306
|
*/
|
|
306
|
-
static simulateInput(fixture:
|
|
307
|
+
static simulateInput(fixture: ComponentFixture<DynamicForm>, selector: string, value: string): Promise<void>;
|
|
307
308
|
/**
|
|
308
309
|
* Simulates checkbox toggle
|
|
309
310
|
*/
|
|
310
|
-
static simulateCheckbox(fixture:
|
|
311
|
+
static simulateCheckbox(fixture: ComponentFixture<DynamicForm>, selector: string, checked: boolean): Promise<void>;
|
|
311
312
|
/**
|
|
312
313
|
* Gets the current form value from the component
|
|
313
314
|
*/
|
|
314
|
-
static getFormValue(component:
|
|
315
|
+
static getFormValue(component: DynamicForm): Record<string, unknown> | undefined;
|
|
315
316
|
/**
|
|
316
317
|
* Checks if the form is valid
|
|
317
318
|
*/
|
|
318
|
-
static isFormValid(component:
|
|
319
|
+
static isFormValid(component: DynamicForm): boolean;
|
|
319
320
|
/**
|
|
320
321
|
* Asserts that the form has a specific value
|
|
321
322
|
*/
|
|
322
|
-
static assertFormValue(component:
|
|
323
|
+
static assertFormValue(component: DynamicForm, expectedValue: Record<string, unknown>): void;
|
|
323
324
|
}
|
|
324
325
|
declare class TestFieldComponent {
|
|
325
|
-
|
|
326
|
+
field: _angular_core.InputSignal<unknown>;
|
|
326
327
|
key: _angular_core.InputSignal<string>;
|
|
327
328
|
label: _angular_core.InputSignal<string>;
|
|
328
329
|
className: _angular_core.InputSignal<string>;
|
|
329
330
|
tabIndex: _angular_core.InputSignal<number | undefined>;
|
|
330
331
|
props: _angular_core.InputSignal<Record<string, unknown> | undefined>;
|
|
331
332
|
placeholder: _angular_core.InputSignal<string>;
|
|
332
|
-
fields: _angular_core.InputSignal<unknown[]>;
|
|
333
333
|
arrayContext: _angular_core.InputSignal<unknown>;
|
|
334
|
+
fields: _angular_core.InputSignal<unknown[]>;
|
|
334
335
|
validationMessages: _angular_core.InputSignal<Record<string, string> | undefined>;
|
|
335
336
|
defaultValidationMessages: _angular_core.InputSignal<Record<string, string> | undefined>;
|
|
336
|
-
|
|
337
|
+
value: _angular_core.WritableSignal<string>;
|
|
337
338
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TestFieldComponent, never>;
|
|
338
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TestFieldComponent, "df-test-field", never, { "
|
|
339
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TestFieldComponent, "df-test-field", never, { "field": { "alias": "field"; "required": false; "isSignal": true; }; "key": { "alias": "key"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; "isSignal": true; }; "props": { "alias": "props"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "arrayContext": { "alias": "arrayContext"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "validationMessages": { "alias": "validationMessages"; "required": false; "isSignal": true; }; "defaultValidationMessages": { "alias": "defaultValidationMessages"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
339
340
|
}
|
|
340
341
|
/**
|
|
341
342
|
* Configuration for setting up a simple component test
|
|
342
343
|
*/
|
|
343
|
-
interface SimpleComponentTestConfig<T =
|
|
344
|
-
field: FieldDef<
|
|
344
|
+
interface SimpleComponentTestConfig<T = unknown> {
|
|
345
|
+
field: FieldDef<unknown>;
|
|
345
346
|
value?: T;
|
|
346
347
|
pageIndex?: number;
|
|
347
348
|
isVisible?: boolean;
|
|
348
|
-
[key: string]:
|
|
349
|
+
[key: string]: unknown;
|
|
349
350
|
}
|
|
350
351
|
/**
|
|
351
352
|
* Result of setting up a simple component test
|
|
352
353
|
*/
|
|
353
|
-
interface SimpleComponentTestResult<T =
|
|
354
|
+
interface SimpleComponentTestResult<T = unknown> {
|
|
354
355
|
component: T;
|
|
355
356
|
fixture: ComponentFixture<T>;
|
|
356
357
|
}
|
|
@@ -361,13 +362,13 @@ declare function setupSimpleTest<T>(componentType: Type<T>, config: SimpleCompon
|
|
|
361
362
|
/**
|
|
362
363
|
* Creates a simple test field definition
|
|
363
364
|
*/
|
|
364
|
-
declare function createSimpleTestField(key: string, label: string): FieldDef<
|
|
365
|
+
declare function createSimpleTestField(key: string, label: string): FieldDef<unknown>;
|
|
365
366
|
|
|
366
367
|
/**
|
|
367
368
|
* Simple form configuration interface for testing
|
|
368
369
|
*/
|
|
369
370
|
interface TestFormConfig {
|
|
370
|
-
fields: FieldDef<
|
|
371
|
+
fields: FieldDef<unknown>[];
|
|
371
372
|
}
|
|
372
373
|
/**
|
|
373
374
|
* Unified configuration for creating dynamic form tests
|
|
@@ -390,7 +391,7 @@ interface TestResult<T = unknown> {
|
|
|
390
391
|
* Configuration for setting up individual field component tests
|
|
391
392
|
*/
|
|
392
393
|
interface ComponentTestConfig<T = unknown> {
|
|
393
|
-
field: FieldDef<
|
|
394
|
+
field: FieldDef<unknown>;
|
|
394
395
|
value?: T;
|
|
395
396
|
}
|
|
396
397
|
/**
|
|
@@ -401,6 +402,37 @@ interface ComponentTestResult<T = unknown> {
|
|
|
401
402
|
fixture: ComponentFixture<T>;
|
|
402
403
|
}
|
|
403
404
|
|
|
405
|
+
/**
|
|
406
|
+
* Type utilities for exhaustive whitelist type testing.
|
|
407
|
+
*
|
|
408
|
+
* These utilities help ensure that type definitions remain stable by detecting
|
|
409
|
+
* when properties are added, removed, or changed.
|
|
410
|
+
*/
|
|
411
|
+
/**
|
|
412
|
+
* Extracts only the required keys from a type.
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* ```typescript
|
|
416
|
+
* interface Example { a: string; b?: number; }
|
|
417
|
+
* type Required = RequiredKeys<Example>; // 'a'
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
type RequiredKeys<T> = {
|
|
421
|
+
[K in keyof T]-?: object extends Pick<T, K> ? never : K;
|
|
422
|
+
}[keyof T];
|
|
423
|
+
/**
|
|
424
|
+
* Extracts only the optional keys from a type.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```typescript
|
|
428
|
+
* interface Example { a: string; b?: number; }
|
|
429
|
+
* type Optional = OptionalKeys<Example>; // 'b'
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
type OptionalKeys<T> = {
|
|
433
|
+
[K in keyof T]-?: object extends Pick<T, K> ? K : never;
|
|
434
|
+
}[keyof T];
|
|
435
|
+
|
|
404
436
|
declare class TestInputHarness {
|
|
405
437
|
readonly field: _angular_core.InputSignal<FieldTree<string>>;
|
|
406
438
|
readonly key: _angular_core.InputSignal<string>;
|
|
@@ -561,5 +593,5 @@ declare const SPANISH_TEST_TRANSLATIONS: {
|
|
|
561
593
|
*/
|
|
562
594
|
declare function createTestTranslationService(initialTranslations?: Record<string, string>): FakeTranslationService;
|
|
563
595
|
|
|
564
|
-
export { DEFAULT_TEST_TRANSLATIONS, DynamicFormTestUtils, FakeTranslationService, FormConfigBuilder, SPANISH_TEST_TRANSLATIONS, TestFormConfigBuilder as SimpleFormConfigBuilder, SimpleTestUtils, TestCheckboxHarness as TestCheckboxHarnessComponent, TestFieldComponent, TestInputHarness as TestInputHarnessComponent, TestSelectHarness as TestSelectHarnessComponent, createMockLogger,
|
|
565
|
-
export type { ComponentTestConfig, ComponentTestResult, DynamicFormTestConfig, DynamicFormTestResult, MockLogger, SimpleComponentTestConfig, SimpleComponentTestResult, SimpleTestConfig, SimpleTestResult, TestConfig, TestFieldContextConfig, TestFormConfig, TestResult };
|
|
596
|
+
export { DEFAULT_TEST_TRANSLATIONS, DynamicFormTestUtils, FakeTranslationService, FormConfigBuilder, SPANISH_TEST_TRANSLATIONS, TestFormConfigBuilder as SimpleFormConfigBuilder, SimpleTestUtils, TestCheckboxHarness as TestCheckboxHarnessComponent, TestFieldComponent, TestInputHarness as TestInputHarnessComponent, TestSelectHarness as TestSelectHarnessComponent, createMockLogger, createSimpleTestField, createTestFieldContext, createTestFormInjector, createTestTranslationService, delay, provideTestLogger, setupSimpleTest, testMapper };
|
|
597
|
+
export type { ComponentTestConfig, ComponentTestResult, DynamicFormTestConfig, DynamicFormTestResult, MockLogger, OptionalKeys, RequiredKeys, SimpleComponentTestConfig, SimpleComponentTestResult, SimpleTestConfig, SimpleTestResult, TestConfig, TestFieldContextConfig, TestFormConfig, TestResult };
|