@ng-forge/dynamic-forms 1.3.0-next.2 → 1.3.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs +12 -0
  2. package/fesm2022/ng-forge-dynamic-forms-active-page-initialized.event-CiKN-mcc.mjs.map +1 -0
  3. package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs +770 -0
  4. package/fesm2022/ng-forge-dynamic-forms-array-field.component-Dv9mPnJ3.mjs.map +1 -0
  5. package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs +83 -0
  6. package/fesm2022/ng-forge-dynamic-forms-array-item-registry.service-D-AxVLdk.mjs.map +1 -0
  7. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs +1887 -0
  8. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-EuYCbquo.mjs.map +1 -0
  9. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs +954 -0
  10. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-2wQK_wPp.mjs.map +1 -0
  11. package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs +117 -0
  12. package/fesm2022/ng-forge-dynamic-forms-container-field-processors-C_JRvaVt.mjs.map +1 -0
  13. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs +228 -0
  14. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Bg7Win9n.mjs.map +1 -0
  15. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs +102 -0
  16. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-R2yc-H0T.mjs.map +1 -0
  17. package/fesm2022/ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs +4 -0
  18. package/fesm2022/{ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs.map → ng-forge-dynamic-forms-debounce-CG3uP5B-.mjs.map} +1 -1
  19. package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs +77 -0
  20. package/fesm2022/ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs.map +1 -0
  21. package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs +4 -0
  22. package/fesm2022/ng-forge-dynamic-forms-dev-mode-4rbYBBo_.mjs.map +1 -0
  23. package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs +644 -0
  24. package/fesm2022/ng-forge-dynamic-forms-df-field-outlet.directive-CQsDMV-s.mjs.map +1 -0
  25. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs +56 -0
  26. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-DKgkpIpG.mjs.map +1 -0
  27. package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs +38 -0
  28. package/fesm2022/{ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs.map → ng-forge-dynamic-forms-form-schema.service-Dd-gHJ_7.mjs.map} +1 -1
  29. package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs +1522 -0
  30. package/fesm2022/ng-forge-dynamic-forms-form-state-manager-DcOXRFRL.mjs.map +1 -0
  31. package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs +292 -0
  32. package/fesm2022/ng-forge-dynamic-forms-group-field.component-BjZi0bhq.mjs.map +1 -0
  33. package/fesm2022/ng-forge-dynamic-forms-integration.mjs +1318 -843
  34. package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
  35. package/fesm2022/ng-forge-dynamic-forms-internal.mjs +3326 -3641
  36. package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
  37. package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs +295 -0
  38. package/fesm2022/ng-forge-dynamic-forms-page-field.component-BRjQmWC9.mjs.map +1 -0
  39. package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs +329 -0
  40. package/fesm2022/ng-forge-dynamic-forms-resolve-field-ByGa5cpo.mjs.map +1 -0
  41. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs +81 -0
  42. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CuFycQb-.mjs.map +1 -0
  43. package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs +400 -0
  44. package/fesm2022/ng-forge-dynamic-forms-schema-builder-C62afItJ.mjs.map +1 -0
  45. package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs +45 -0
  46. package/fesm2022/ng-forge-dynamic-forms-schema-registry.service-axBV9FBH.mjs.map +1 -0
  47. package/fesm2022/ng-forge-dynamic-forms-schema.mjs +8 -14
  48. package/fesm2022/ng-forge-dynamic-forms-schema.mjs.map +1 -1
  49. package/fesm2022/ng-forge-dynamic-forms-testing.mjs +68 -73
  50. package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -1
  51. package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs +257 -0
  52. package/fesm2022/ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs.map +1 -0
  53. package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs +8 -0
  54. package/fesm2022/ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs.map +1 -0
  55. package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs +94 -0
  56. package/fesm2022/ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs.map +1 -0
  57. package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs +115 -0
  58. package/fesm2022/ng-forge-dynamic-forms-wrapper-chain-BnntfNU1.mjs.map +1 -0
  59. package/fesm2022/ng-forge-dynamic-forms.mjs +2136 -3
  60. package/fesm2022/ng-forge-dynamic-forms.mjs.map +1 -1
  61. package/package.json +1 -1
  62. package/types/ng-forge-dynamic-forms-integration.d.ts +543 -415
  63. package/types/ng-forge-dynamic-forms-internal.d.ts +2319 -2436
  64. package/types/ng-forge-dynamic-forms-schema.d.ts +13 -16
  65. package/types/ng-forge-dynamic-forms-testing.d.ts +34 -37
  66. package/types/ng-forge-dynamic-forms.d.ts +735 -722
  67. package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs +0 -750
  68. package/fesm2022/ng-forge-dynamic-forms-array-field.component-CSCKq_1K.mjs.map +0 -1
  69. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs +0 -2394
  70. package/fesm2022/ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-CTOTwzzw.mjs.map +0 -1
  71. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs +0 -1054
  72. package/fesm2022/ng-forge-dynamic-forms-bootstrap-web-mcp-BtjqeJOj.mjs.map +0 -1
  73. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs +0 -86
  74. package/fesm2022/ng-forge-dynamic-forms-container-field.component-Dc3ROhHL.mjs.map +0 -1
  75. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs +0 -33
  76. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BzgX8lAD.mjs.map +0 -1
  77. package/fesm2022/ng-forge-dynamic-forms-debounce-C9F4v1Ke.mjs +0 -17
  78. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs +0 -25
  79. package/fesm2022/ng-forge-dynamic-forms-field-errors-wrapper.component-CIKbWqYA.mjs.map +0 -1
  80. package/fesm2022/ng-forge-dynamic-forms-form-schema.service-Dx5Dlb15.mjs +0 -24
  81. package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs +0 -177
  82. package/fesm2022/ng-forge-dynamic-forms-group-field.component-DAC3P9DC.mjs.map +0 -1
  83. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs +0 -5133
  84. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CXQe_5td.mjs.map +0 -1
  85. package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs +0 -176
  86. package/fesm2022/ng-forge-dynamic-forms-page-field.component-DPKJcwUO.mjs.map +0 -1
  87. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs +0 -19
  88. package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-DMEeKZny.mjs.map +0 -1
  89. package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs +0 -570
  90. package/fesm2022/ng-forge-dynamic-forms-schema-builder-BvDTzfdM.mjs.map +0 -1
  91. package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs +0 -126
  92. package/fesm2022/ng-forge-dynamic-forms-text-field.component-BB-jutBq.mjs.map +0 -1
@@ -1,84 +1,79 @@
1
- import { signal, EnvironmentInjector, runInInjectionContext } from '@angular/core';
2
- import { getTestBed, TestBed } from '@angular/core/testing';
3
- import { form, schema } from '@angular/forms/signals';
4
- import { DynamicFormError, DynamicFormLogger, EventBus, DEFAULT_VALIDATION_MESSAGES } from '@ng-forge/dynamic-forms/internal';
5
-
1
+ import { EnvironmentInjector, runInInjectionContext, signal } from "@angular/core";
2
+ import { TestBed, getTestBed } from "@angular/core/testing";
3
+ import { form, schema } from "@angular/forms/signals";
4
+ import { DEFAULT_VALIDATION_MESSAGES, DynamicFormError, DynamicFormLogger, EventBus } from "@ng-forge/dynamic-forms/internal";
6
5
  const fixtureLogger = {
7
- debug: (message, ...args) => console.debug('[Dynamic Forms]', message, ...args),
8
- info: (message, ...args) => console.info('[Dynamic Forms]', message, ...args),
9
- warn: (message, ...args) => console.warn('[Dynamic Forms]', message, ...args),
10
- error: (message, ...args) => console.error('[Dynamic Forms]', message, ...args),
6
+ debug: (message, ...args) => console.debug("[Dynamic Forms]", message, ...args),
7
+ info: (message, ...args) => console.info("[Dynamic Forms]", message, ...args),
8
+ warn: (message, ...args) => console.warn("[Dynamic Forms]", message, ...args),
9
+ error: (message, ...args) => console.error("[Dynamic Forms]", message, ...args)
11
10
  };
12
11
  function assertTestEnvironmentInitialized() {
13
- if (getTestBed().platform)
14
- return;
15
- throw new DynamicFormError('The Angular test environment was never initialized for the @angular/core/testing instance this fixture resolved. ' +
16
- 'Under Vitest this means your specs use a Vite-transformed copy of @angular/core/testing while the fixtures load the native one. ' +
17
- 'Fix: either remove @angular/* from server.deps.inline so everything resolves natively, or inline the whole Angular graph:\n' +
18
- "test: { server: { deps: { inline: [/@angular\\//, /@ng-forge/, 'ngxtension'] } } }\n" +
19
- "and keep import '@angular/compiler' in your test setup so the inlined bundles JIT-link.\n" +
20
- 'On Jest or Karma this instead means initTestEnvironment was never called; add it to your test setup file (e.g. getTestBed().initTestEnvironment(...)).');
12
+ if (getTestBed().platform) return;
13
+ throw new DynamicFormError("The Angular test environment was never initialized for the @angular/core/testing instance this fixture resolved. Under Vitest this means your specs use a Vite-transformed copy of @angular/core/testing while the fixtures load the native one. Fix: either remove @angular/* from server.deps.inline so everything resolves natively, or inline the whole Angular graph:\ntest: { server: { deps: { inline: [/@angular\\//, /@ng-forge/, 'ngxtension'] } } }\nand keep import '@angular/compiler' in your test setup so the inlined bundles JIT-link.\nOn Jest or Karma this instead means initTestEnvironment was never called; add it to your test setup file (e.g. getTestBed().initTestEnvironment(...)).");
21
14
  }
22
15
  function createNgForgeFieldFixture(component, options) {
23
- assertTestEnvironmentInitialized();
24
- TestBed.configureTestingModule({
25
- imports: [component],
26
- providers: [{ provide: DynamicFormLogger, useValue: fixtureLogger }, ...(options.providers ?? [])],
27
- });
28
- const key = options.key;
29
- const rootValue = signal({ [key]: options.value }, /* @ts-ignore */
30
- ...(ngDevMode ? [{ debugName: "rootValue" }] : /* istanbul ignore next */ []));
31
- const injector = TestBed.inject(EnvironmentInjector);
32
- const schemaCallback = options.schema;
33
- const root = runInInjectionContext(injector, () => {
34
- if (!schemaCallback)
35
- return form(rootValue);
36
- return form(rootValue, schema((path) => {
37
- schemaCallback(path[key]);
38
- }));
39
- });
40
- const field = root[key];
41
- if (options.touched)
42
- field().markAsTouched();
43
- const fixture = TestBed.createComponent(component);
44
- fixture.componentRef.setInput('field', field);
45
- fixture.componentRef.setInput('key', key);
46
- if (options.inputs) {
47
- for (const [name, value] of Object.entries(options.inputs)) {
48
- fixture.componentRef.setInput(name, value);
49
- }
50
- }
51
- return { fixture, field, rootValue };
16
+ assertTestEnvironmentInitialized();
17
+ TestBed.configureTestingModule({
18
+ imports: [component],
19
+ providers: [{
20
+ provide: DynamicFormLogger,
21
+ useValue: fixtureLogger
22
+ }, ...options.providers ?? []]
23
+ });
24
+ const key = options.key;
25
+ const rootValue = signal({ [key]: options.value }, ...ngDevMode ? [{ debugName: "rootValue" }] : /* istanbul ignore next */ []);
26
+ const injector = TestBed.inject(EnvironmentInjector);
27
+ const schemaCallback = options.schema;
28
+ const field = runInInjectionContext(injector, () => {
29
+ if (!schemaCallback) return form(rootValue);
30
+ return form(rootValue, schema((path) => {
31
+ schemaCallback(path[key]);
32
+ }));
33
+ })[key];
34
+ if (options.touched) field().markAsTouched();
35
+ const fixture = TestBed.createComponent(component);
36
+ fixture.componentRef.setInput("field", field);
37
+ fixture.componentRef.setInput("key", key);
38
+ if (options.inputs) for (const [name, value] of Object.entries(options.inputs)) fixture.componentRef.setInput(name, value);
39
+ return {
40
+ fixture,
41
+ field,
42
+ rootValue
43
+ };
52
44
  }
53
45
  function createNgForgeActionFixture(component, options) {
54
- assertTestEnvironmentInitialized();
55
- TestBed.configureTestingModule({
56
- imports: [component],
57
- providers: [EventBus, { provide: DynamicFormLogger, useValue: fixtureLogger }, ...(options.providers ?? [])],
58
- });
59
- const fixture = TestBed.createComponent(component);
60
- fixture.componentRef.setInput('key', options.key);
61
- fixture.componentRef.setInput('label', options.label);
62
- if (options.event)
63
- fixture.componentRef.setInput('event', options.event);
64
- if (options.eventArgs)
65
- fixture.componentRef.setInput('eventArgs', options.eventArgs);
66
- if (options.disabled !== undefined)
67
- fixture.componentRef.setInput('disabled', options.disabled);
68
- if (options.hidden !== undefined)
69
- fixture.componentRef.setInput('hidden', options.hidden);
70
- if (options.inputs) {
71
- for (const [name, value] of Object.entries(options.inputs)) {
72
- fixture.componentRef.setInput(name, value);
73
- }
74
- }
75
- return { fixture, eventBus: TestBed.inject(EventBus) };
46
+ assertTestEnvironmentInitialized();
47
+ TestBed.configureTestingModule({
48
+ imports: [component],
49
+ providers: [
50
+ EventBus,
51
+ {
52
+ provide: DynamicFormLogger,
53
+ useValue: fixtureLogger
54
+ },
55
+ ...options.providers ?? []
56
+ ]
57
+ });
58
+ const fixture = TestBed.createComponent(component);
59
+ fixture.componentRef.setInput("key", options.key);
60
+ fixture.componentRef.setInput("label", options.label);
61
+ if (options.event) fixture.componentRef.setInput("event", options.event);
62
+ if (options.eventArgs) fixture.componentRef.setInput("eventArgs", options.eventArgs);
63
+ if (options.disabled !== void 0) fixture.componentRef.setInput("disabled", options.disabled);
64
+ if (options.hidden !== void 0) fixture.componentRef.setInput("hidden", options.hidden);
65
+ if (options.inputs) for (const [name, value] of Object.entries(options.inputs)) fixture.componentRef.setInput(name, value);
66
+ return {
67
+ fixture,
68
+ eventBus: TestBed.inject(EventBus)
69
+ };
76
70
  }
77
71
  function provideTestValidationMessages(messages) {
78
- return { provide: DEFAULT_VALIDATION_MESSAGES, useValue: signal(messages) };
72
+ return {
73
+ provide: DEFAULT_VALIDATION_MESSAGES,
74
+ useValue: signal(messages)
75
+ };
79
76
  }
80
-
81
-
82
-
83
77
  export { createNgForgeActionFixture, createNgForgeFieldFixture, provideTestValidationMessages };
84
- //# sourceMappingURL=ng-forge-dynamic-forms-testing.mjs.map
78
+
79
+ //# sourceMappingURL=ng-forge-dynamic-forms-testing.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-forge-dynamic-forms-testing.mjs","mappings":";;;;;AAWA;AACE;AACA;AACA;AACA;;AAyBF;;;;;;;;AAQM;AAEN;AAOM;AAIJ;;;;AAIC;AAED;AACA;;;AAGA;AACA;AACE;AAAqB;;AAIjB;;AAGN;AAEA;;AAEqB;;;;AAKrB;AACE;;;;AAKF;AACF;AAuBM;AAIJ;;;;AAIC;;;;;;;;AAOD;;AACA;;AACA;AACE;;;;AAKF;AACF;AAGM;AACJ;AACF","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms/testing/src/create-field-fixture.ts"],"sourcesContent":["import { EnvironmentInjector, Provider, runInInjectionContext, signal, type Type, type WritableSignal } from '@angular/core';\nimport { ComponentFixture, getTestBed, TestBed } from '@angular/core/testing';\nimport { type FieldTree, form, schema, type SchemaPath } from '@angular/forms/signals';\nimport { type FormEvent, type FormEventConstructor } from '@ng-forge/dynamic-forms';\nimport { EventBus, DynamicFormError, DynamicFormLogger, type Logger } from '@ng-forge/dynamic-forms/internal';\nimport { DEFAULT_VALIDATION_MESSAGES, type DynamicText, type ValidationMessages } from '@ng-forge/dynamic-forms/internal';\n\n/** Structural copy of integration's EventArgs; importing it would cycle the entrypoints. */\ntype EventArgs = readonly (string | number | boolean | null | undefined)[];\n\n/** Default logger so fixtures work without provideDynamicForm(); override via options.providers. */\nconst fixtureLogger: Logger = {\n debug: (message, ...args) => console.debug('[Dynamic Forms]', message, ...args),\n info: (message, ...args) => console.info('[Dynamic Forms]', message, ...args),\n warn: (message, ...args) => console.warn('[Dynamic Forms]', message, ...args),\n error: (message, ...args) => console.error('[Dynamic Forms]', message, ...args),\n};\n\nexport interface CreateNgForgeFieldFixtureOptions<TValue = unknown> {\n /** Field key. Becomes the only property on the wrapping form. */\n readonly key: string;\n /** Initial value for the field. */\n readonly value?: TValue;\n /** Optional schema callback that receives the field's `SchemaPath`. Use it to attach validators (`required`, `minLength`, etc.). */\n readonly schema?: (fieldPath: SchemaPath<TValue>) => void;\n /** Mark the field as touched after creation (useful for invalid-state assertions). */\n readonly touched?: boolean;\n /** Extra inputs to set on the component before `detectChanges()`. */\n readonly inputs?: Record<string, unknown>;\n /** Extra TestBed providers. */\n readonly providers?: readonly Provider[];\n}\n\nexport interface NgForgeFieldFixture<C, TValue = unknown> {\n readonly fixture: ComponentFixture<C>;\n readonly field: FieldTree<TValue>;\n readonly rootValue: WritableSignal<Record<string, TValue>>;\n}\n\n/** Guards against a second, uninitialized @angular/core/testing instance (Vitest externalization). */\nfunction assertTestEnvironmentInitialized(): void {\n if (getTestBed().platform) return;\n throw new DynamicFormError(\n 'The Angular test environment was never initialized for the @angular/core/testing instance this fixture resolved. ' +\n 'Under Vitest this means your specs use a Vite-transformed copy of @angular/core/testing while the fixtures load the native one. ' +\n 'Fix: either remove @angular/* from server.deps.inline so everything resolves natively, or inline the whole Angular graph:\\n' +\n \"test: { server: { deps: { inline: [/@angular\\\\//, /@ng-forge/, 'ngxtension'] } } }\\n\" +\n \"and keep import '@angular/compiler' in your test setup so the inlined bundles JIT-link.\\n\" +\n 'On Jest or Karma this instead means initTestEnvironment was never called; add it to your test setup file (e.g. getTestBed().initTestEnvironment(...)).',\n );\n}\n\n/**\n * Builds a `ComponentFixture` for an `NgForgeField`-composing component with\n * `field` + `key` bound BEFORE `detectChanges()` — sidesteps the NG0950 that\n * Shell's required `key` and Field's required `field` would otherwise throw.\n */\nexport function createNgForgeFieldFixture<C, TValue = unknown>(\n component: Type<C>,\n options: CreateNgForgeFieldFixtureOptions<TValue>,\n): NgForgeFieldFixture<C, TValue> {\n assertTestEnvironmentInitialized();\n TestBed.configureTestingModule({\n imports: [component],\n providers: [{ provide: DynamicFormLogger, useValue: fixtureLogger }, ...(options.providers ?? [])],\n });\n\n const key = options.key;\n const rootValue = signal<Record<string, TValue>>({ [key]: options.value as TValue });\n\n const injector = TestBed.inject(EnvironmentInjector);\n const schemaCallback = options.schema;\n const root = runInInjectionContext(injector, () => {\n if (!schemaCallback) return form(rootValue);\n return form(\n rootValue,\n schema<Record<string, TValue>>((path) => {\n schemaCallback(path[key] as SchemaPath<TValue>);\n }),\n );\n });\n\n const field = (root as unknown as Record<string, FieldTree<TValue>>)[key];\n\n if (options.touched) field().markAsTouched();\n\n const fixture = TestBed.createComponent(component);\n fixture.componentRef.setInput('field', field);\n fixture.componentRef.setInput('key', key);\n if (options.inputs) {\n for (const [name, value] of Object.entries(options.inputs)) {\n fixture.componentRef.setInput(name, value);\n }\n }\n\n return { fixture, field, rootValue };\n}\n\nexport interface CreateNgForgeActionFixtureOptions<TEvent extends FormEvent = FormEvent> {\n readonly key: string;\n readonly label: DynamicText;\n readonly event?: FormEventConstructor<TEvent>;\n readonly eventArgs?: EventArgs;\n readonly disabled?: boolean;\n readonly hidden?: boolean;\n readonly inputs?: Record<string, unknown>;\n readonly providers?: readonly Provider[];\n}\n\nexport interface NgForgeActionFixture<C> {\n readonly fixture: ComponentFixture<C>;\n readonly eventBus: EventBus;\n}\n\n/**\n * Builds a `ComponentFixture` for an `NgForgeAction`-composing component with\n * `key` + `label` bound and `EventBus` provided. The caller calls\n * `detectChanges()`; the harness handles the NG0950-avoidance bindings.\n */\nexport function createNgForgeActionFixture<C, TEvent extends FormEvent = FormEvent>(\n component: Type<C>,\n options: CreateNgForgeActionFixtureOptions<TEvent>,\n): NgForgeActionFixture<C> {\n assertTestEnvironmentInitialized();\n TestBed.configureTestingModule({\n imports: [component],\n providers: [EventBus, { provide: DynamicFormLogger, useValue: fixtureLogger }, ...(options.providers ?? [])],\n });\n\n const fixture = TestBed.createComponent(component);\n fixture.componentRef.setInput('key', options.key);\n fixture.componentRef.setInput('label', options.label);\n if (options.event) fixture.componentRef.setInput('event', options.event);\n if (options.eventArgs) fixture.componentRef.setInput('eventArgs', options.eventArgs);\n if (options.disabled !== undefined) fixture.componentRef.setInput('disabled', options.disabled);\n if (options.hidden !== undefined) fixture.componentRef.setInput('hidden', options.hidden);\n if (options.inputs) {\n for (const [name, value] of Object.entries(options.inputs)) {\n fixture.componentRef.setInput(name, value);\n }\n }\n\n return { fixture, eventBus: TestBed.inject(EventBus) };\n}\n\n/** Provider for `DEFAULT_VALIDATION_MESSAGES` in field tests — supply the default-messages map and the directive resolves it from DI. */\nexport function provideTestValidationMessages(messages: ValidationMessages): Provider {\n return { provide: DEFAULT_VALIDATION_MESSAGES, useValue: signal(messages) };\n}\n"]}
1
+ {"version":3,"file":"ng-forge-dynamic-forms-testing.mjs","names":[],"sources":["../../../../packages/dynamic-forms/testing/src/create-field-fixture.ts"],"sourcesContent":["import { EnvironmentInjector, Provider, runInInjectionContext, signal, type Type, type WritableSignal } from '@angular/core';\nimport { ComponentFixture, getTestBed, TestBed } from '@angular/core/testing';\nimport { type FieldTree, form, schema, type SchemaPath } from '@angular/forms/signals';\nimport { type FormEvent, type FormEventConstructor } from '@ng-forge/dynamic-forms';\nimport { EventBus, DynamicFormError, DynamicFormLogger, type Logger } from '@ng-forge/dynamic-forms/internal';\nimport { DEFAULT_VALIDATION_MESSAGES, type DynamicText, type ValidationMessages } from '@ng-forge/dynamic-forms/internal';\n\n/** Structural copy of integration's EventArgs; importing it would cycle the entrypoints. */\ntype EventArgs = readonly (string | number | boolean | null | undefined)[];\n\n/** Default logger so fixtures work without provideDynamicForm(); override via options.providers. */\nconst fixtureLogger: Logger = {\n debug: (message, ...args) => console.debug('[Dynamic Forms]', message, ...args),\n info: (message, ...args) => console.info('[Dynamic Forms]', message, ...args),\n warn: (message, ...args) => console.warn('[Dynamic Forms]', message, ...args),\n error: (message, ...args) => console.error('[Dynamic Forms]', message, ...args),\n};\n\nexport interface CreateNgForgeFieldFixtureOptions<TValue = unknown> {\n /** Field key. Becomes the only property on the wrapping form. */\n readonly key: string;\n /** Initial value for the field. */\n readonly value?: TValue;\n /** Optional schema callback that receives the field's `SchemaPath`. Use it to attach validators (`required`, `minLength`, etc.). */\n readonly schema?: (fieldPath: SchemaPath<TValue>) => void;\n /** Mark the field as touched after creation (useful for invalid-state assertions). */\n readonly touched?: boolean;\n /** Extra inputs to set on the component before `detectChanges()`. */\n readonly inputs?: Record<string, unknown>;\n /** Extra TestBed providers. */\n readonly providers?: readonly Provider[];\n}\n\nexport interface NgForgeFieldFixture<C, TValue = unknown> {\n readonly fixture: ComponentFixture<C>;\n readonly field: FieldTree<TValue>;\n readonly rootValue: WritableSignal<Record<string, TValue>>;\n}\n\n/** Guards against a second, uninitialized @angular/core/testing instance (Vitest externalization). */\nfunction assertTestEnvironmentInitialized(): void {\n if (getTestBed().platform) return;\n throw new DynamicFormError(\n 'The Angular test environment was never initialized for the @angular/core/testing instance this fixture resolved. ' +\n 'Under Vitest this means your specs use a Vite-transformed copy of @angular/core/testing while the fixtures load the native one. ' +\n 'Fix: either remove @angular/* from server.deps.inline so everything resolves natively, or inline the whole Angular graph:\\n' +\n \"test: { server: { deps: { inline: [/@angular\\\\//, /@ng-forge/, 'ngxtension'] } } }\\n\" +\n \"and keep import '@angular/compiler' in your test setup so the inlined bundles JIT-link.\\n\" +\n 'On Jest or Karma this instead means initTestEnvironment was never called; add it to your test setup file (e.g. getTestBed().initTestEnvironment(...)).',\n );\n}\n\n/**\n * Builds a `ComponentFixture` for an `NgForgeField`-composing component with\n * `field` + `key` bound BEFORE `detectChanges()` — sidesteps the NG0950 that\n * Shell's required `key` and Field's required `field` would otherwise throw.\n */\nexport function createNgForgeFieldFixture<C, TValue = unknown>(\n component: Type<C>,\n options: CreateNgForgeFieldFixtureOptions<TValue>,\n): NgForgeFieldFixture<C, TValue> {\n assertTestEnvironmentInitialized();\n TestBed.configureTestingModule({\n imports: [component],\n providers: [{ provide: DynamicFormLogger, useValue: fixtureLogger }, ...(options.providers ?? [])],\n });\n\n const key = options.key;\n const rootValue = signal<Record<string, TValue>>({ [key]: options.value as TValue });\n\n const injector = TestBed.inject(EnvironmentInjector);\n const schemaCallback = options.schema;\n const root = runInInjectionContext(injector, () => {\n if (!schemaCallback) return form(rootValue);\n return form(\n rootValue,\n schema<Record<string, TValue>>((path) => {\n schemaCallback(path[key] as SchemaPath<TValue>);\n }),\n );\n });\n\n const field = (root as unknown as Record<string, FieldTree<TValue>>)[key];\n\n if (options.touched) field().markAsTouched();\n\n const fixture = TestBed.createComponent(component);\n fixture.componentRef.setInput('field', field);\n fixture.componentRef.setInput('key', key);\n if (options.inputs) {\n for (const [name, value] of Object.entries(options.inputs)) {\n fixture.componentRef.setInput(name, value);\n }\n }\n\n return { fixture, field, rootValue };\n}\n\nexport interface CreateNgForgeActionFixtureOptions<TEvent extends FormEvent = FormEvent> {\n readonly key: string;\n readonly label: DynamicText;\n readonly event?: FormEventConstructor<TEvent>;\n readonly eventArgs?: EventArgs;\n readonly disabled?: boolean;\n readonly hidden?: boolean;\n readonly inputs?: Record<string, unknown>;\n readonly providers?: readonly Provider[];\n}\n\nexport interface NgForgeActionFixture<C> {\n readonly fixture: ComponentFixture<C>;\n readonly eventBus: EventBus;\n}\n\n/**\n * Builds a `ComponentFixture` for an `NgForgeAction`-composing component with\n * `key` + `label` bound and `EventBus` provided. The caller calls\n * `detectChanges()`; the harness handles the NG0950-avoidance bindings.\n */\nexport function createNgForgeActionFixture<C, TEvent extends FormEvent = FormEvent>(\n component: Type<C>,\n options: CreateNgForgeActionFixtureOptions<TEvent>,\n): NgForgeActionFixture<C> {\n assertTestEnvironmentInitialized();\n TestBed.configureTestingModule({\n imports: [component],\n providers: [EventBus, { provide: DynamicFormLogger, useValue: fixtureLogger }, ...(options.providers ?? [])],\n });\n\n const fixture = TestBed.createComponent(component);\n fixture.componentRef.setInput('key', options.key);\n fixture.componentRef.setInput('label', options.label);\n if (options.event) fixture.componentRef.setInput('event', options.event);\n if (options.eventArgs) fixture.componentRef.setInput('eventArgs', options.eventArgs);\n if (options.disabled !== undefined) fixture.componentRef.setInput('disabled', options.disabled);\n if (options.hidden !== undefined) fixture.componentRef.setInput('hidden', options.hidden);\n if (options.inputs) {\n for (const [name, value] of Object.entries(options.inputs)) {\n fixture.componentRef.setInput(name, value);\n }\n }\n\n return { fixture, eventBus: TestBed.inject(EventBus) };\n}\n\n/** Provider for `DEFAULT_VALIDATION_MESSAGES` in field tests — supply the default-messages map and the directive resolves it from DI. */\nexport function provideTestValidationMessages(messages: ValidationMessages): Provider {\n return { provide: DEFAULT_VALIDATION_MESSAGES, useValue: signal(messages) };\n}\n"],"mappings":";;;;AAWA,MAAM,gBAAwB;CAC5B,QAAQ,SAAS,GAAG,SAAS,QAAQ,MAAM,mBAAmB,SAAS,GAAG,IAAI;CAC9E,OAAO,SAAS,GAAG,SAAS,QAAQ,KAAK,mBAAmB,SAAS,GAAG,IAAI;CAC5E,OAAO,SAAS,GAAG,SAAS,QAAQ,KAAK,mBAAmB,SAAS,GAAG,IAAI;CAC5E,QAAQ,SAAS,GAAG,SAAS,QAAQ,MAAM,mBAAmB,SAAS,GAAG,IAAI;AAC/E;AAwBD,SAAS,mCAAgC;CACvC,IAAI,WAAU,CAAE,CAAC,UAAU;CAC3B,MAAM,IAAI,iBACR,irBAK0J;AAE9J;AAOA,SAAgB,0BACd,WACA,SAAiD;CAEjD,iCAAgC;CAChC,QAAQ,uBAAuB;EAC7B,SAAS,CAAC,SAAS;EACnB,WAAW,CAAC;GAAE,SAAS;GAAmB,UAAU;EAAa,GAAI,GAAI,QAAQ,aAAa,CAAA,CAAG;CAClG,CAAA;CAED,MAAM,MAAM,QAAQ;CACpB,MAAM,YAAY,OAA+B,GAAG,MAAM,QAAQ,MAAe,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAEpF,MAAM,WAAW,QAAQ,OAAO,mBAAmB;CACnD,MAAM,iBAAiB,QAAQ;CAW/B,MAAM,QAVO,sBAAsB,gBAAe;EAChD,IAAI,CAAC,gBAAgB,OAAO,KAAK,SAAS;EAC1C,OAAO,KACL,WACA,QAAgC,SAAQ;GACtC,eAAe,KAAK,IAA0B;EAChD,CAAC,CAAC;CAEN,CAEe,CAAA,CAAsD;CAErE,IAAI,QAAQ,SAAS,MAAK,CAAE,CAAC,cAAa;CAE1C,MAAM,UAAU,QAAQ,gBAAgB,SAAS;CACjD,QAAQ,aAAa,SAAS,SAAS,KAAK;CAC5C,QAAQ,aAAa,SAAS,OAAO,GAAG;CACxC,IAAI,QAAQ,QACV,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,MAAM,GACvD,QAAQ,aAAa,SAAS,MAAM,KAAK;CAI7C,OAAO;EAAE;EAAS;EAAO;CAAS;AACpC;AAuBA,SAAgB,2BACd,WACA,SAAkD;CAElD,iCAAgC;CAChC,QAAQ,uBAAuB;EAC7B,SAAS,CAAC,SAAS;EACnB,WAAW;GAAC;GAAU;IAAE,SAAS;IAAmB,UAAU;GAAa;GAAI,GAAI,QAAQ,aAAa,CAAA;EAAG;CAC5G,CAAA;CAED,MAAM,UAAU,QAAQ,gBAAgB,SAAS;CACjD,QAAQ,aAAa,SAAS,OAAO,QAAQ,GAAG;CAChD,QAAQ,aAAa,SAAS,SAAS,QAAQ,KAAK;CACpD,IAAI,QAAQ,OAAO,QAAQ,aAAa,SAAS,SAAS,QAAQ,KAAK;CACvE,IAAI,QAAQ,WAAW,QAAQ,aAAa,SAAS,aAAa,QAAQ,SAAS;CACnF,IAAI,QAAQ,aAAa,QAAW,QAAQ,aAAa,SAAS,YAAY,QAAQ,QAAQ;CAC9F,IAAI,QAAQ,WAAW,QAAW,QAAQ,aAAa,SAAS,UAAU,QAAQ,MAAM;CACxF,IAAI,QAAQ,QACV,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,MAAM,GACvD,QAAQ,aAAa,SAAS,MAAM,KAAK;CAI7C,OAAO;EAAE;EAAS,UAAU,QAAQ,OAAO,QAAQ;CAAC;AACtD;AAGA,SAAgB,8BAA8B,UAA4B;CACxE,OAAO;EAAE,SAAS;EAA6B,UAAU,OAAO,QAAQ;CAAC;AAC3E"}
@@ -0,0 +1,257 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, computed, input } from "@angular/core";
3
+ import { DynamicTextPipe } from "@ng-forge/dynamic-forms/internal";
4
+ import { AsyncPipe } from "@angular/common";
5
+ var TextFieldComponent = class TextFieldComponent {
6
+ key = input.required(...ngDevMode ? [{ debugName: "key" }] : /* istanbul ignore next */ []);
7
+ label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
8
+ className = input(...ngDevMode ? [void 0, { debugName: "className" }] : /* istanbul ignore next */ []);
9
+ tabIndex = input(...ngDevMode ? [void 0, { debugName: "tabIndex" }] : /* istanbul ignore next */ []);
10
+ hidden = input(...ngDevMode ? [void 0, { debugName: "hidden" }] : /* istanbul ignore next */ []);
11
+ props = input(...ngDevMode ? [void 0, { debugName: "props" }] : /* istanbul ignore next */ []);
12
+ elementType = computed(() => this.props()?.elementType || "p", ...ngDevMode ? [{ debugName: "elementType" }] : /* istanbul ignore next */ []);
13
+ static ɵfac = i0.ɵɵngDeclareFactory({
14
+ minVersion: "12.0.0",
15
+ version: "22.2.5",
16
+ ngImport: i0,
17
+ type: TextFieldComponent,
18
+ deps: [],
19
+ target: i0.ɵɵFactoryTarget.Component
20
+ });
21
+ static ɵcmp = i0.ɵɵngDeclareComponent({
22
+ minVersion: "17.0.0",
23
+ version: "22.2.5",
24
+ type: TextFieldComponent,
25
+ isStandalone: true,
26
+ selector: "df-text",
27
+ inputs: {
28
+ key: {
29
+ classPropertyName: "key",
30
+ publicName: "key",
31
+ isSignal: true,
32
+ isRequired: true,
33
+ transformFunction: null
34
+ },
35
+ label: {
36
+ classPropertyName: "label",
37
+ publicName: "label",
38
+ isSignal: true,
39
+ isRequired: true,
40
+ transformFunction: null
41
+ },
42
+ className: {
43
+ classPropertyName: "className",
44
+ publicName: "className",
45
+ isSignal: true,
46
+ isRequired: false,
47
+ transformFunction: null
48
+ },
49
+ tabIndex: {
50
+ classPropertyName: "tabIndex",
51
+ publicName: "tabIndex",
52
+ isSignal: true,
53
+ isRequired: false,
54
+ transformFunction: null
55
+ },
56
+ hidden: {
57
+ classPropertyName: "hidden",
58
+ publicName: "hidden",
59
+ isSignal: true,
60
+ isRequired: false,
61
+ transformFunction: null
62
+ },
63
+ props: {
64
+ classPropertyName: "props",
65
+ publicName: "props",
66
+ isSignal: true,
67
+ isRequired: false,
68
+ transformFunction: null
69
+ }
70
+ },
71
+ host: { properties: {
72
+ "id": "`${key()}`",
73
+ "attr.data-testid": "key()",
74
+ "attr.hidden": "hidden() || null"
75
+ } },
76
+ ngImport: i0,
77
+ template: `
78
+ @switch (elementType()) {
79
+ @case ('p') {
80
+ <p class="df-text df-text-p" [class]="className() || ''">
81
+ {{ label() | dynamicText | async }}
82
+ </p>
83
+ }
84
+ @case ('h1') {
85
+ <h1 class="df-text df-text-h1" [class]="className() || ''">
86
+ {{ label() | dynamicText | async }}
87
+ </h1>
88
+ }
89
+ @case ('h2') {
90
+ <h2 class="df-text df-text-h2" [class]="className() || ''">
91
+ {{ label() | dynamicText | async }}
92
+ </h2>
93
+ }
94
+ @case ('h3') {
95
+ <h3 class="df-text df-text-h3" [class]="className() || ''">
96
+ {{ label() | dynamicText | async }}
97
+ </h3>
98
+ }
99
+ @case ('h4') {
100
+ <h4 class="df-text df-text-h4" [class]="className() || ''">
101
+ {{ label() | dynamicText | async }}
102
+ </h4>
103
+ }
104
+ @case ('h5') {
105
+ <h5 class="df-text df-text-h5" [class]="className() || ''">
106
+ {{ label() | dynamicText | async }}
107
+ </h5>
108
+ }
109
+ @case ('h6') {
110
+ <h6 class="df-text df-text-h6" [class]="className() || ''">
111
+ {{ label() | dynamicText | async }}
112
+ </h6>
113
+ }
114
+ @case ('span') {
115
+ <span class="df-text df-text-span" [class]="className() || ''">
116
+ {{ label() | dynamicText | async }}
117
+ </span>
118
+ }
119
+ @default {
120
+ never;
121
+ }
122
+ }
123
+ `,
124
+ isInline: true,
125
+ styles: [":host([hidden]){display:none!important}.df-text{font-size:var(--df-text-font-size, 1rem);font-family:var(--df-text-font-family, inherit);font-weight:var(--df-text-font-weight, normal);color:var(--df-text-color, inherit);line-height:var(--df-text-line-height, 1.5);text-align:var(--df-text-text-align, inherit);letter-spacing:var(--df-text-letter-spacing, normal);text-decoration:var(--df-text-text-decoration, none);text-transform:var(--df-text-text-transform, none);margin:var(--df-text-margin, 0);padding:var(--df-text-padding, 0)}.df-text-h1{font-size:var(--df-text-h1-font-size, 2rem);font-weight:var(--df-text-h1-font-weight, bold);margin:var(--df-text-h1-margin, 0)}.df-text-h2{font-size:var(--df-text-h2-font-size, 1.75rem);font-weight:var(--df-text-h2-font-weight, bold);margin:var(--df-text-h2-margin, 0)}.df-text-h3{font-size:var(--df-text-h3-font-size, 1.5rem);font-weight:var(--df-text-h3-font-weight, bold);margin:var(--df-text-h3-margin, 0)}.df-text-h4{font-size:var(--df-text-h4-font-size, 1.25rem);font-weight:var(--df-text-h4-font-weight, bold);margin:var(--df-text-h4-margin, 0)}.df-text-h5{font-size:var(--df-text-h5-font-size, 1.125rem);font-weight:var(--df-text-h5-font-weight, bold);margin:var(--df-text-h5-margin, 0)}.df-text-h6{font-size:var(--df-text-h6-font-size, 1rem);font-weight:var(--df-text-h6-font-weight, bold);margin:var(--df-text-h6-margin, 0)}.df-text-p{font-size:var(--df-text-p-font-size, 1rem);margin:var(--df-text-p-margin, 0)}.df-text-span{display:var(--df-text-span-display, inline)}\n"],
126
+ dependencies: [{
127
+ kind: "pipe",
128
+ type: AsyncPipe,
129
+ name: "async"
130
+ }, {
131
+ kind: "pipe",
132
+ type: DynamicTextPipe,
133
+ name: "dynamicText"
134
+ }],
135
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
136
+ });
137
+ };
138
+ i0.ɵɵngDeclareClassMetadata({
139
+ minVersion: "12.0.0",
140
+ version: "22.2.5",
141
+ ngImport: i0,
142
+ type: TextFieldComponent,
143
+ decorators: [{
144
+ type: Component,
145
+ args: [{
146
+ selector: "df-text",
147
+ template: `
148
+ @switch (elementType()) {
149
+ @case ('p') {
150
+ <p class="df-text df-text-p" [class]="className() || ''">
151
+ {{ label() | dynamicText | async }}
152
+ </p>
153
+ }
154
+ @case ('h1') {
155
+ <h1 class="df-text df-text-h1" [class]="className() || ''">
156
+ {{ label() | dynamicText | async }}
157
+ </h1>
158
+ }
159
+ @case ('h2') {
160
+ <h2 class="df-text df-text-h2" [class]="className() || ''">
161
+ {{ label() | dynamicText | async }}
162
+ </h2>
163
+ }
164
+ @case ('h3') {
165
+ <h3 class="df-text df-text-h3" [class]="className() || ''">
166
+ {{ label() | dynamicText | async }}
167
+ </h3>
168
+ }
169
+ @case ('h4') {
170
+ <h4 class="df-text df-text-h4" [class]="className() || ''">
171
+ {{ label() | dynamicText | async }}
172
+ </h4>
173
+ }
174
+ @case ('h5') {
175
+ <h5 class="df-text df-text-h5" [class]="className() || ''">
176
+ {{ label() | dynamicText | async }}
177
+ </h5>
178
+ }
179
+ @case ('h6') {
180
+ <h6 class="df-text df-text-h6" [class]="className() || ''">
181
+ {{ label() | dynamicText | async }}
182
+ </h6>
183
+ }
184
+ @case ('span') {
185
+ <span class="df-text df-text-span" [class]="className() || ''">
186
+ {{ label() | dynamicText | async }}
187
+ </span>
188
+ }
189
+ @default {
190
+ never;
191
+ }
192
+ }
193
+ `,
194
+ imports: [AsyncPipe, DynamicTextPipe],
195
+ changeDetection: ChangeDetectionStrategy.OnPush,
196
+ host: {
197
+ "[id]": "`${key()}`",
198
+ "[attr.data-testid]": "key()",
199
+ "[attr.hidden]": "hidden() || null"
200
+ },
201
+ styles: [":host([hidden]){display:none!important}.df-text{font-size:var(--df-text-font-size, 1rem);font-family:var(--df-text-font-family, inherit);font-weight:var(--df-text-font-weight, normal);color:var(--df-text-color, inherit);line-height:var(--df-text-line-height, 1.5);text-align:var(--df-text-text-align, inherit);letter-spacing:var(--df-text-letter-spacing, normal);text-decoration:var(--df-text-text-decoration, none);text-transform:var(--df-text-text-transform, none);margin:var(--df-text-margin, 0);padding:var(--df-text-padding, 0)}.df-text-h1{font-size:var(--df-text-h1-font-size, 2rem);font-weight:var(--df-text-h1-font-weight, bold);margin:var(--df-text-h1-margin, 0)}.df-text-h2{font-size:var(--df-text-h2-font-size, 1.75rem);font-weight:var(--df-text-h2-font-weight, bold);margin:var(--df-text-h2-margin, 0)}.df-text-h3{font-size:var(--df-text-h3-font-size, 1.5rem);font-weight:var(--df-text-h3-font-weight, bold);margin:var(--df-text-h3-margin, 0)}.df-text-h4{font-size:var(--df-text-h4-font-size, 1.25rem);font-weight:var(--df-text-h4-font-weight, bold);margin:var(--df-text-h4-margin, 0)}.df-text-h5{font-size:var(--df-text-h5-font-size, 1.125rem);font-weight:var(--df-text-h5-font-weight, bold);margin:var(--df-text-h5-margin, 0)}.df-text-h6{font-size:var(--df-text-h6-font-size, 1rem);font-weight:var(--df-text-h6-font-weight, bold);margin:var(--df-text-h6-margin, 0)}.df-text-p{font-size:var(--df-text-p-font-size, 1rem);margin:var(--df-text-p-margin, 0)}.df-text-span{display:var(--df-text-span-display, inline)}\n"]
202
+ }]
203
+ }],
204
+ propDecorators: {
205
+ key: [{
206
+ type: i0.Input,
207
+ args: [{
208
+ isSignal: true,
209
+ alias: "key",
210
+ required: true
211
+ }]
212
+ }],
213
+ label: [{
214
+ type: i0.Input,
215
+ args: [{
216
+ isSignal: true,
217
+ alias: "label",
218
+ required: true
219
+ }]
220
+ }],
221
+ className: [{
222
+ type: i0.Input,
223
+ args: [{
224
+ isSignal: true,
225
+ alias: "className",
226
+ required: false
227
+ }]
228
+ }],
229
+ tabIndex: [{
230
+ type: i0.Input,
231
+ args: [{
232
+ isSignal: true,
233
+ alias: "tabIndex",
234
+ required: false
235
+ }]
236
+ }],
237
+ hidden: [{
238
+ type: i0.Input,
239
+ args: [{
240
+ isSignal: true,
241
+ alias: "hidden",
242
+ required: false
243
+ }]
244
+ }],
245
+ props: [{
246
+ type: i0.Input,
247
+ args: [{
248
+ isSignal: true,
249
+ alias: "props",
250
+ required: false
251
+ }]
252
+ }]
253
+ }
254
+ });
255
+ export { TextFieldComponent as default };
256
+
257
+ //# sourceMappingURL=ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-forge-dynamic-forms-text-field.component--MAh_h4Q.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/fields/text/text-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { AsyncPipe } from '@angular/common';\nimport { DynamicTextPipe } from '@ng-forge/dynamic-forms/internal';\nimport { TextProps } from '@ng-forge/dynamic-forms/internal';\nimport { DynamicText } from '@ng-forge/dynamic-forms/internal';\n\n@Component({\n selector: 'df-text',\n template: `\n @switch (elementType()) {\n @case ('p') {\n <p class=\"df-text df-text-p\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </p>\n }\n @case ('h1') {\n <h1 class=\"df-text df-text-h1\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h1>\n }\n @case ('h2') {\n <h2 class=\"df-text df-text-h2\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h2>\n }\n @case ('h3') {\n <h3 class=\"df-text df-text-h3\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h3>\n }\n @case ('h4') {\n <h4 class=\"df-text df-text-h4\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h4>\n }\n @case ('h5') {\n <h5 class=\"df-text df-text-h5\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h5>\n }\n @case ('h6') {\n <h6 class=\"df-text df-text-h6\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h6>\n }\n @case ('span') {\n <span class=\"df-text df-text-span\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </span>\n }\n @default {\n never;\n }\n }\n `,\n styleUrl: './text-field.component.scss',\n imports: [AsyncPipe, DynamicTextPipe],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n '[attr.hidden]': 'hidden() || null',\n },\n})\nexport default class TextFieldComponent {\n readonly key = input.required<string>();\n readonly label = input.required<DynamicText>();\n readonly className = input<string>();\n readonly tabIndex = input<number>();\n readonly hidden = input<boolean>();\n readonly props = input<TextProps>();\n\n readonly elementType = computed(() => this.props()?.elementType || 'p');\n}\n"],"mappings":";;;;AAgEA,IAAqB,qBAArB,MAAqB,mBAAkB;CAC5B,MAAM,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,QAAQ,MAAM,SAAuB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACrC,YAAY,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAC3B,WAAW,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAC1B,SAAS,MAAgB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACzB,QAAQ,MAAkB,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAE1B,cAAc,eAAe,KAAK,MAAK,CAAE,EAAE,eAAe,KAAI,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CARpD,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAkB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAlB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAkB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,UAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,QAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA,EAAA,YAAA;GAAA,MAAA;GAAA,oBAAA;GAAA,eAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UAxD3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8CT,UAAA;EAAA,QAAA,CAAA,y/CAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MAES;GAAS,MAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAe,MAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAQjB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAkB,YAAA,CAAA;EA1DtC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAS,UACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CT,SAEQ,CAAC,WAAW,eAAe;GAAC,iBACpB,wBAAwB;GAAM,MACzC;IACJ,QAAQ;IACR,sBAAsB;IACtB,iBAAiB;GAClB;GAAA,QAAA,CAAA,y/CAAA;EAAA,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { InjectionToken } from "@angular/core";
2
+ const VALIDATION_EXECUTION_DEFAULTS = new InjectionToken("VALIDATION_EXECUTION_DEFAULTS", {
3
+ providedIn: "root",
4
+ factory: () => ({ validateWhenHidden: false })
5
+ });
6
+ export { VALIDATION_EXECUTION_DEFAULTS as t };
7
+
8
+ //# sourceMappingURL=ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-forge-dynamic-forms-validation-execution.token-BFyySKtp.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/providers/features/validation-execution/validation-execution.token.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { ResolvedValidationExecutionConfig } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Injection token for global validation execution defaults.\n *\n * @internal\n */\nexport const VALIDATION_EXECUTION_DEFAULTS = new InjectionToken<ResolvedValidationExecutionConfig>('VALIDATION_EXECUTION_DEFAULTS', {\n providedIn: 'root',\n factory: () => ({\n validateWhenHidden: false,\n }),\n});\n"],"mappings":";AAQA,MAAa,gCAAgC,IAAI,eAAkD,iCAAiC;CAClI,YAAY;CACZ,gBAAgB,EACd,oBAAoB,MACrB;AACF,CAAA"}
@@ -0,0 +1,94 @@
1
+ import { n as getNormalizedArrayMetadata } from "./ng-forge-dynamic-forms-default-value-D5M4MNE-.mjs";
2
+ import { InjectionToken } from "@angular/core";
3
+ import { DynamicFormLogger, NoopLogger, createDefaultDerivationLogConfig, createWarningTracker, hasChildFields, normalizeFieldsArray } from "@ng-forge/dynamic-forms/internal";
4
+ function traverseFieldsWithContext(fields, context, visitor, hooks) {
5
+ for (const field of fields) {
6
+ visitor(field, context);
7
+ if (!hasChildFields(field)) continue;
8
+ if (field.type === "array") {
9
+ const childContext = mergeContext(context, hooks?.onArrayChild?.(context, field));
10
+ traverseFieldsWithContext(collectArrayChildren(field), childContext, visitor, hooks);
11
+ continue;
12
+ }
13
+ const childContext = mergeContext(context, field.type === "group" ? hooks?.onGroupChild?.(context, field) : hooks?.onLayoutChild?.(context, field));
14
+ traverseFieldsWithContext(normalizeFieldsArray(field.fields), childContext, visitor, hooks);
15
+ }
16
+ }
17
+ function someField(fields, predicate) {
18
+ return fields.some((field) => {
19
+ if (predicate(field)) return true;
20
+ if (!hasChildFields(field)) return false;
21
+ return someField(field.type === "array" ? collectArrayChildren(field) : normalizeFieldsArray(field.fields), predicate);
22
+ });
23
+ }
24
+ function collectArrayChildren(field) {
25
+ let arrayItems = normalizeFieldsArray(field.fields);
26
+ if (arrayItems.length === 0) {
27
+ const metadataTemplate = getNormalizedArrayMetadata(field)?.template;
28
+ if (metadataTemplate) arrayItems = [Array.isArray(metadataTemplate) ? [...metadataTemplate] : metadataTemplate];
29
+ }
30
+ const flattened = [];
31
+ for (const item of arrayItems) if (Array.isArray(item)) flattened.push(...item);
32
+ else flattened.push(item);
33
+ return flattened;
34
+ }
35
+ function mergeContext(base, overrides) {
36
+ return overrides ? {
37
+ ...base,
38
+ ...overrides
39
+ } : { ...base };
40
+ }
41
+ const DERIVATION_WARNING_TRACKER = new InjectionToken("DerivationWarningTracker", {
42
+ providedIn: null,
43
+ factory: createWarningTracker
44
+ });
45
+ function isDynamicFormFeature(value) {
46
+ return typeof value === "object" && value !== null && "ɵkind" in value && typeof value.ɵkind === "string" && "ɵproviders" in value && Array.isArray(value.ɵproviders);
47
+ }
48
+ function createFeature(kind, providers) {
49
+ return {
50
+ ɵkind: kind,
51
+ ɵproviders: providers
52
+ };
53
+ }
54
+ var ConsoleLogger = class {
55
+ prefix = "[Dynamic Forms]";
56
+ debug(message, ...args) {
57
+ console.debug(this.prefix, message, ...args);
58
+ }
59
+ info(message, ...args) {
60
+ console.info(this.prefix, message, ...args);
61
+ }
62
+ warn(message, ...args) {
63
+ console.warn(this.prefix, message, ...args);
64
+ }
65
+ error(message, ...args) {
66
+ console.error(this.prefix, message, ...args);
67
+ }
68
+ };
69
+ const DERIVATION_LOG_CONFIG = new InjectionToken("DERIVATION_LOG_CONFIG", {
70
+ providedIn: "root",
71
+ factory: createDefaultDerivationLogConfig
72
+ });
73
+ function withLoggerConfig(config = true) {
74
+ if (typeof config === "boolean" || typeof config === "function") {
75
+ const logger = (typeof config === "function" ? config() : config) ? new ConsoleLogger() : new NoopLogger();
76
+ return createFeature("logger", [{
77
+ provide: DynamicFormLogger,
78
+ useValue: logger
79
+ }]);
80
+ }
81
+ const logger = config.enabled !== false ? new ConsoleLogger() : new NoopLogger();
82
+ const providers = [{
83
+ provide: DynamicFormLogger,
84
+ useValue: logger
85
+ }];
86
+ if (config.derivations !== void 0) providers.push({
87
+ provide: DERIVATION_LOG_CONFIG,
88
+ useValue: { level: config.derivations }
89
+ });
90
+ return createFeature("logger", providers);
91
+ }
92
+ export { isDynamicFormFeature as a, traverseFieldsWithContext as c, createFeature as i, withLoggerConfig as n, DERIVATION_WARNING_TRACKER as o, ConsoleLogger as r, someField as s, DERIVATION_LOG_CONFIG as t };
93
+
94
+ //# sourceMappingURL=ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-forge-dynamic-forms-with-logger-config-BAATqYY0.mjs","names":[],"sources":["../../../../packages/dynamic-forms/src/lib/core/derivation/field-traversal.ts","../../../../packages/dynamic-forms/src/lib/core/derivation/derivation-warning-tracker.ts","../../../../packages/dynamic-forms/src/lib/providers/features/dynamic-form-feature.ts","../../../../packages/dynamic-forms/src/lib/providers/features/logger/console-logger.ts","../../../../packages/dynamic-forms/src/lib/providers/features/logger/with-logger-config.ts"],"sourcesContent":["import { FieldDef } from '@ng-forge/dynamic-forms/internal';\nimport { hasChildFields } from '@ng-forge/dynamic-forms/internal';\nimport { getNormalizedArrayMetadata } from '../../utils/array-field/normalized-array-metadata';\nimport { normalizeFieldsArray } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Visitor invoked for every field encountered during traversal.\n *\n * @internal\n */\nexport type FieldVisitor<TContext> = (field: FieldDef<unknown>, context: TContext) => void;\n\n/**\n * Hooks for mutating the traversal context when crossing container boundaries.\n *\n * @internal\n */\nexport interface FieldTraversalHooks<TContext> {\n /** Called when descending into an `array` field. */\n onArrayChild?: (parent: TContext, field: FieldDef<unknown>) => Partial<TContext>;\n /** Called when descending into a `group` field. */\n onGroupChild?: (parent: TContext, field: FieldDef<unknown>) => Partial<TContext>;\n /** Called when descending into a layout container (page, row, container). */\n onLayoutChild?: (parent: TContext, field: FieldDef<unknown>) => Partial<TContext>;\n}\n\n/**\n * Recursively walks a field-definition tree, invoking `visitor` for each field.\n *\n * @internal\n */\nexport function traverseFieldsWithContext<TContext>(\n fields: FieldDef<unknown>[],\n context: TContext,\n visitor: FieldVisitor<TContext>,\n hooks?: FieldTraversalHooks<TContext>,\n): void {\n for (const field of fields) {\n visitor(field, context);\n\n if (!hasChildFields(field)) continue;\n\n if (field.type === 'array') {\n const childContext = mergeContext(context, hooks?.onArrayChild?.(context, field));\n const arrayChildren = collectArrayChildren(field);\n traverseFieldsWithContext(arrayChildren, childContext, visitor, hooks);\n continue;\n }\n\n const overrides = field.type === 'group' ? hooks?.onGroupChild?.(context, field) : hooks?.onLayoutChild?.(context, field);\n const childContext = mergeContext(context, overrides);\n traverseFieldsWithContext(normalizeFieldsArray(field.fields) as FieldDef<unknown>[], childContext, visitor, hooks);\n }\n}\n\n/**\n * Returns `true` as soon as `predicate` holds for any field in the tree,\n * short-circuiting the walk. Resolves children exactly like\n * {@link traverseFieldsWithContext} (including array-item templates), so a\n * presence check stays in lockstep with the full traversal.\n *\n * @internal\n */\nexport function someField(fields: readonly FieldDef<unknown>[], predicate: (field: FieldDef<unknown>) => boolean): boolean {\n return fields.some((field) => {\n if (predicate(field)) return true;\n if (!hasChildFields(field)) return false;\n const children = field.type === 'array' ? collectArrayChildren(field) : (normalizeFieldsArray(field.fields) as FieldDef<unknown>[]);\n return someField(children, predicate);\n });\n}\n\n/**\n * Returns the flattened list of children for an array field, falling back\n * to the Symbol metadata template when `fields` is empty.\n *\n * @internal\n */\nfunction collectArrayChildren(\n field: FieldDef<unknown> & { fields: FieldDef<unknown>[] | Record<string, FieldDef<unknown>> },\n): FieldDef<unknown>[] {\n let arrayItems = normalizeFieldsArray(field.fields) as (FieldDef<unknown> | FieldDef<unknown>[])[];\n\n if (arrayItems.length === 0) {\n const metadataTemplate = getNormalizedArrayMetadata(field)?.template;\n if (metadataTemplate) {\n arrayItems = [\n Array.isArray(metadataTemplate) ? [...(metadataTemplate as readonly FieldDef<unknown>[])] : (metadataTemplate as FieldDef<unknown>),\n ];\n }\n }\n\n const flattened: FieldDef<unknown>[] = [];\n for (const item of arrayItems) {\n if (Array.isArray(item)) {\n flattened.push(...item);\n } else {\n flattened.push(item);\n }\n }\n return flattened;\n}\n\n/** @internal */\nfunction mergeContext<TContext>(base: TContext, overrides: Partial<TContext> | undefined): TContext {\n return overrides ? { ...base, ...overrides } : { ...base };\n}\n","import { InjectionToken } from '@angular/core';\nimport { createWarningTracker, type WarningTracker } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Injection token for the derivation warning tracker.\n * Provided at form component level for instance-scoped tracking of derivation warnings\n * (keyed by field path) so the same warning fires once per form rather than every render.\n *\n * @internal\n */\nexport const DERIVATION_WARNING_TRACKER = new InjectionToken<WarningTracker>('DerivationWarningTracker', {\n providedIn: null,\n factory: createWarningTracker,\n});\n","import { Provider } from '@angular/core';\n\n/**\n * Base interface for dynamic form features.\n * Features are configuration options that can be passed to provideDynamicForm\n * alongside field type definitions.\n */\nexport interface DynamicFormFeature<TKind extends string = string> {\n /** Internal marker to identify this as a feature, not a field type */\n ɵkind: TKind;\n /** Providers to register for this feature */\n ɵproviders: Provider[];\n}\n\n/**\n * Known feature kinds for type safety. Adapter feature modules (and the\n * addon system) contribute their own discriminants via module augmentation.\n */\nexport type DynamicFormFeatureKind =\n | 'logger'\n | 'event-form-value'\n | 'value-exclusion'\n | 'validation-execution'\n | 'legacy-status-classes'\n | 'page-preload'\n | 'field-windowing'\n | 'web-mcp'\n | 'addons'\n | 'addon-actions';\n\n/** Type guard to check if a value is a DynamicFormFeature */\nexport function isDynamicFormFeature(value: unknown): value is DynamicFormFeature {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'ɵkind' in value &&\n typeof (value as DynamicFormFeature).ɵkind === 'string' &&\n 'ɵproviders' in value &&\n Array.isArray((value as DynamicFormFeature).ɵproviders)\n );\n}\n\n/** Helper to create a feature with proper typing. */\nexport function createFeature<TKind extends string>(kind: TKind, providers: Provider[]): DynamicFormFeature<TKind> {\n return {\n ɵkind: kind,\n ɵproviders: providers,\n };\n}\n","import type { Logger } from '@ng-forge/dynamic-forms/internal';\n\n/** Console-based logger implementation. */\nexport class ConsoleLogger implements Logger {\n private readonly prefix = '[Dynamic Forms]';\n\n debug(message: string, ...args: unknown[]): void {\n console.debug(this.prefix, message, ...args);\n }\n\n info(message: string, ...args: unknown[]): void {\n console.info(this.prefix, message, ...args);\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(this.prefix, message, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(this.prefix, message, ...args);\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport { createFeature, DynamicFormFeature } from '../dynamic-form-feature';\nimport { DynamicFormLogger } from '@ng-forge/dynamic-forms/internal';\nimport { ConsoleLogger } from './console-logger';\nimport { NoopLogger } from '@ng-forge/dynamic-forms/internal';\nimport { DerivationLogConfig, DerivationLogLevel, createDefaultDerivationLogConfig } from '@ng-forge/dynamic-forms/internal';\n\n/**\n * Injection token for derivation logging configuration.\n *\n * @internal\n */\nexport const DERIVATION_LOG_CONFIG = new InjectionToken<DerivationLogConfig>('DERIVATION_LOG_CONFIG', {\n providedIn: 'root',\n factory: createDefaultDerivationLogConfig,\n});\n\n/** Configuration options for the logger feature. */\nexport interface LoggerConfigOptions {\n /**\n * Whether general logging is enabled.\n *\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Derivation logging level.\n *\n * @default 'none'\n */\n derivations?: DerivationLogLevel;\n}\n\n/**\n * Configure logging for dynamic forms.\n *\n * @param config - Boolean to enable/disable logging, a function returning boolean, or a config object\n * @returns A DynamicFormFeature that configures logging\n */\nexport function withLoggerConfig(config: boolean | (() => boolean) | LoggerConfigOptions = true): DynamicFormFeature<'logger'> {\n // Handle boolean or function\n if (typeof config === 'boolean' || typeof config === 'function') {\n const isEnabled = typeof config === 'function' ? config() : config;\n const logger = isEnabled ? new ConsoleLogger() : new NoopLogger();\n return createFeature('logger', [{ provide: DynamicFormLogger, useValue: logger }]);\n }\n\n // Handle config object\n const isEnabled = config.enabled !== false;\n const logger = isEnabled ? new ConsoleLogger() : new NoopLogger();\n\n const providers: { provide: InjectionToken<unknown>; useValue: unknown }[] = [{ provide: DynamicFormLogger, useValue: logger }];\n\n // Add derivation log config if specified\n if (config.derivations !== undefined) {\n providers.push({\n provide: DERIVATION_LOG_CONFIG,\n useValue: { level: config.derivations },\n });\n }\n\n return createFeature('logger', providers);\n}\n"],"mappings":";;;AA+BA,SAAgB,0BACd,QACA,SACA,SACA,OAAqC;CAErC,KAAK,MAAM,SAAS,QAAQ;EAC1B,QAAQ,OAAO,OAAO;EAEtB,IAAI,CAAC,eAAe,KAAK,GAAG;EAE5B,IAAI,MAAM,SAAS,SAAS;GAC1B,MAAM,eAAe,aAAa,SAAS,OAAO,eAAe,SAAS,KAAK,CAAC;GAEhF,0BADsB,qBAAqB,KACjB,GAAe,cAAc,SAAS,KAAK;GACrE;EACF;EAGA,MAAM,eAAe,aAAa,SADhB,MAAM,SAAS,UAAU,OAAO,eAAe,SAAS,KAAK,IAAI,OAAO,gBAAgB,SAAS,KAAK,CACpE;EACpD,0BAA0B,qBAAqB,MAAM,MAAM,GAA0B,cAAc,SAAS,KAAK;CACnH;AACF;AAUA,SAAgB,UAAU,QAAsC,WAAgD;CAC9G,OAAO,OAAO,MAAM,UAAS;EAC3B,IAAI,UAAU,KAAK,GAAG,OAAO;EAC7B,IAAI,CAAC,eAAe,KAAK,GAAG,OAAO;EAEnC,OAAO,UADU,MAAM,SAAS,UAAU,qBAAqB,KAAK,IAAK,qBAAqB,MAAM,MAAM,GAC/E,SAAS;CACtC,CAAC;AACH;AAQA,SAAS,qBACP,OAA8F;CAE9F,IAAI,aAAa,qBAAqB,MAAM,MAAM;CAElD,IAAI,WAAW,WAAW,GAAG;EAC3B,MAAM,mBAAmB,2BAA2B,KAAK,CAAC,EAAE;EAC5D,IAAI,kBACF,aAAa,CACX,MAAM,QAAQ,gBAAgB,IAAI,CAAC,GAAI,gBAAiD,IAAK,gBAC9F;CAEL;CAEA,MAAM,YAAiC,CAAA;CACvC,KAAK,MAAM,QAAQ,YACjB,IAAI,MAAM,QAAQ,IAAI,GACpB,UAAU,KAAK,GAAG,IAAI;MAEtB,UAAU,KAAK,IAAI;CAGvB,OAAO;AACT;AAGA,SAAS,aAAuB,MAAgB,WAAwC;CACtF,OAAO,YAAY;EAAE,GAAG;EAAM,GAAG;CAAS,IAAK,EAAE,GAAG,KAAI;AAC1D;AChGA,MAAa,6BAA6B,IAAI,eAA+B,4BAA4B;CACvG,YAAY;CACZ,SAAS;AACV,CAAA;ACkBD,SAAgB,qBAAqB,OAAc;CACjD,OACE,OAAO,UAAU,YACjB,UAAU,QACV,WAAW,SACX,OAAQ,MAA6B,UAAU,YAC/C,gBAAgB,SAChB,MAAM,QAAS,MAA6B,UAAU;AAE1D;AAGA,SAAgB,cAAoC,MAAa,WAAqB;CACpF,OAAO;EACL,OAAO;EACP,YAAY;CACb;AACH;AC7CA,IAAa,gBAAb,MAA0B;CACP,SAAS;CAE1B,MAAM,SAAiB,GAAG,MAAe;EACvC,QAAQ,MAAM,KAAK,QAAQ,SAAS,GAAG,IAAI;CAC7C;CAEA,KAAK,SAAiB,GAAG,MAAe;EACtC,QAAQ,KAAK,KAAK,QAAQ,SAAS,GAAG,IAAI;CAC5C;CAEA,KAAK,SAAiB,GAAG,MAAe;EACtC,QAAQ,KAAK,KAAK,QAAQ,SAAS,GAAG,IAAI;CAC5C;CAEA,MAAM,SAAiB,GAAG,MAAe;EACvC,QAAQ,MAAM,KAAK,QAAQ,SAAS,GAAG,IAAI;CAC7C;AACD;ACTD,MAAa,wBAAwB,IAAI,eAAoC,yBAAyB;CACpG,YAAY;CACZ,SAAS;AACV,CAAA;AAyBD,SAAgB,iBAAiB,SAA0D,MAAI;CAE7F,IAAI,OAAO,WAAW,aAAa,OAAO,WAAW,YAAY;EAE/D,MAAM,UADY,OAAO,WAAW,aAAa,OAAM,IAAK,UACjC,IAAI,cAAa,IAAK,IAAI,WAAU;EAC/D,OAAO,cAAc,UAAU,CAAC;GAAE,SAAS;GAAmB,UAAU;EAAM,CAAE,CAAC;CACnF;CAIA,MAAM,SADY,OAAO,YAAY,QACV,IAAI,cAAa,IAAK,IAAI,WAAU;CAE/D,MAAM,YAAuE,CAAC;EAAE,SAAS;EAAmB,UAAU;CAAM,CAAE;CAG9H,IAAI,OAAO,gBAAgB,QACzB,UAAU,KAAK;EACb,SAAS;EACT,UAAU,EAAE,OAAO,OAAO,YAAW;CACtC,CAAA;CAGH,OAAO,cAAc,UAAU,SAAS;AAC1C"}