@ng-forge/dynamic-forms 0.9.0-next.12 → 0.9.0-next.14
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/fesm2022/{ng-forge-dynamic-forms-array-field.component-BgCrTME1.mjs → ng-forge-dynamic-forms-array-field.component-Tw49K5kz.mjs} +9 -9
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-Tw49K5kz.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-container-field.component-VHaBk_1l.mjs → ng-forge-dynamic-forms-container-field.component-CrOIZEL_.mjs} +6 -6
- package/fesm2022/{ng-forge-dynamic-forms-container-field.component-VHaBk_1l.mjs.map → ng-forge-dynamic-forms-container-field.component-CrOIZEL_.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-container-utils-CGJiiKBY.mjs → ng-forge-dynamic-forms-container-utils-Bx1A5tg-.mjs} +2 -2
- package/fesm2022/{ng-forge-dynamic-forms-container-utils-CGJiiKBY.mjs.map → ng-forge-dynamic-forms-container-utils-Bx1A5tg-.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-css-wrapper.component-BOdw40ZF.mjs → ng-forge-dynamic-forms-css-wrapper.component-Q2g56KUM.mjs} +5 -5
- package/fesm2022/{ng-forge-dynamic-forms-css-wrapper.component-BOdw40ZF.mjs.map → ng-forge-dynamic-forms-css-wrapper.component-Q2g56KUM.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-emit-initialization-D72mQxlX.mjs → ng-forge-dynamic-forms-emit-initialization-9l5gPNQc.mjs} +2 -2
- package/fesm2022/{ng-forge-dynamic-forms-emit-initialization-D72mQxlX.mjs.map → ng-forge-dynamic-forms-emit-initialization-9l5gPNQc.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-group-field.component-BvTQwoLg.mjs → ng-forge-dynamic-forms-group-field.component-DqnhddRH.mjs} +9 -9
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-DqnhddRH.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +334 -27
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-BAPGCjUs.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-Be1Lk0qR.mjs} +1558 -172
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-Be1Lk0qR.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-n4KTMOTm.mjs +114 -0
- package/fesm2022/{ng-forge-dynamic-forms-page-field.component-DDzmhJNn.mjs.map → ng-forge-dynamic-forms-page-field.component-n4KTMOTm.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-CFtnatYj.mjs +34 -0
- package/fesm2022/{ng-forge-dynamic-forms-row-wrapper.component-BIvEUoia.mjs.map → ng-forge-dynamic-forms-row-wrapper.component-CFtnatYj.mjs.map} +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-Bo4zNJXY.mjs → ng-forge-dynamic-forms-text-field.component-C14mlROS.mjs} +5 -5
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-Bo4zNJXY.mjs.map → ng-forge-dynamic-forms-text-field.component-C14mlROS.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
- package/package.json +1 -1
- package/types/ng-forge-dynamic-forms-integration.d.ts +244 -40
- package/types/ng-forge-dynamic-forms.d.ts +1719 -545
- package/fesm2022/ng-forge-dynamic-forms-array-field.component-BgCrTME1.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-group-field.component-BvTQwoLg.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-BAPGCjUs.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DDzmhJNn.mjs +0 -114
- package/fesm2022/ng-forge-dynamic-forms-row-wrapper.component-BIvEUoia.mjs +0 -34
|
@@ -1,13 +1,155 @@
|
|
|
1
1
|
import * as rxjs from 'rxjs';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import * as _angular_core from '@angular/core';
|
|
4
|
-
import { Signal,
|
|
4
|
+
import { Signal, Type, ResourceRef, ViewContainerRef, InjectionToken, Injector, WritableSignal, EnvironmentInjector, Provider, EnvironmentProviders, TemplateRef, Resource, PipeTransform } from '@angular/core';
|
|
5
5
|
import * as _ng_forge_dynamic_forms from '@ng-forge/dynamic-forms';
|
|
6
6
|
import * as _angular_forms_signals from '@angular/forms/signals';
|
|
7
7
|
import { FieldContext, TreeValidationResult, ValidationError as ValidationError$1, FieldTree, SchemaPath, SchemaPathTree } from '@angular/forms/signals';
|
|
8
8
|
import { FormSchema } from '@ng-forge/dynamic-forms/schema';
|
|
9
9
|
import * as _angular_forms from '@angular/forms';
|
|
10
10
|
|
|
11
|
+
type DynamicText = string | Observable<string> | Signal<string>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generic reactive value — a static value, an Angular Signal, or an RxJS Observable.
|
|
15
|
+
*
|
|
16
|
+
* Generalises {@link DynamicText} for arbitrary value types. Used by
|
|
17
|
+
* cross-cutting properties that need to react to form state without forcing
|
|
18
|
+
* every consumer to deal with reactivity (e.g., `hidden` / `disabled` on
|
|
19
|
+
* addons).
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const a: DynamicValue<boolean> = true;
|
|
24
|
+
* const b: DynamicValue<boolean> = signal(false);
|
|
25
|
+
* const c: DynamicValue<boolean> = isValid$;
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
type DynamicValue<T> = T | Signal<T> | Observable<T>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Universal addon slot names supported by every adapter.
|
|
32
|
+
*
|
|
33
|
+
* Adapters render `prefix` to the leading edge of a field and `suffix` to
|
|
34
|
+
* the trailing edge (mirrored in RTL). Additional slots may be contributed
|
|
35
|
+
* via {@link DynamicFormAddonSlotRegistry} module augmentation.
|
|
36
|
+
*/
|
|
37
|
+
type CommonAddonSlot = 'prefix' | 'suffix';
|
|
38
|
+
/**
|
|
39
|
+
* Module-augmentable registry of adapter-specific addon slot names.
|
|
40
|
+
*
|
|
41
|
+
* Adapters that expose slots beyond the universal `prefix` / `suffix` (e.g.,
|
|
42
|
+
* an "error overlay" slot specific to one design system) declare them here.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
47
|
+
* interface DynamicFormAddonSlotRegistry {
|
|
48
|
+
* 'mat-error-overlay': true;
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
interface DynamicFormAddonSlotRegistry {
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Union of every valid addon slot — universal slots plus any registered via
|
|
57
|
+
* {@link DynamicFormAddonSlotRegistry} module augmentation.
|
|
58
|
+
*/
|
|
59
|
+
type AddonSlot = CommonAddonSlot | keyof DynamicFormAddonSlotRegistry;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Base shape every addon kind extends.
|
|
63
|
+
*
|
|
64
|
+
* Public contract:
|
|
65
|
+
* - `slot` chooses where the addon renders (prefix / suffix / adapter-specific).
|
|
66
|
+
* - `hidden` / `disabled` are reactive — re-evaluated when their underlying
|
|
67
|
+
* signals or observables emit.
|
|
68
|
+
* - Multiple addons in the same slot render in array order, left-to-right
|
|
69
|
+
* within the slot (LTR; mirrored in RTL).
|
|
70
|
+
*
|
|
71
|
+
* Note: `meta` is intentionally absent — adapters declare addon-specific
|
|
72
|
+
* fields via module augmentation rather than an untyped escape hatch.
|
|
73
|
+
*/
|
|
74
|
+
interface BaseAddon<TSlot extends AddonSlot = AddonSlot> {
|
|
75
|
+
/** Slot to render this addon in. */
|
|
76
|
+
readonly slot: TSlot;
|
|
77
|
+
/** CSS class applied to the addon host element. */
|
|
78
|
+
readonly className?: string;
|
|
79
|
+
/** Reactive visibility — when `true`, the addon is removed from layout. */
|
|
80
|
+
readonly hidden?: DynamicValue<boolean>;
|
|
81
|
+
/** Reactive disabled state — primarily relevant for interactive kinds. */
|
|
82
|
+
readonly disabled?: DynamicValue<boolean>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Module-augmentable registry of addon kinds.
|
|
86
|
+
*
|
|
87
|
+
* Each key is the kind discriminant; each value is the addon's full shape
|
|
88
|
+
* (extending {@link BaseAddon}). Core ships `text`, `template`, and
|
|
89
|
+
* `component`; adapters add their own (e.g., `prime-icon`, `prime-button`).
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
94
|
+
* interface DynamicFormAddonRegistry {
|
|
95
|
+
* 'prime-icon': PrimeIconAddon;
|
|
96
|
+
* 'prime-button': PrimeButtonAddon;
|
|
97
|
+
* }
|
|
98
|
+
* }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
interface DynamicFormAddonRegistry {
|
|
102
|
+
text: TextAddon;
|
|
103
|
+
template: TemplateAddon;
|
|
104
|
+
component: ComponentAddon;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Union of every registered addon shape.
|
|
108
|
+
*/
|
|
109
|
+
type AnyAddon = DynamicFormAddonRegistry[keyof DynamicFormAddonRegistry];
|
|
110
|
+
/**
|
|
111
|
+
* Renders text content inline.
|
|
112
|
+
*
|
|
113
|
+
* `text` is `DynamicText`, supporting plain strings, observables, and
|
|
114
|
+
* signals — so values like `'$'`, `'.com'`, or interpolated counters
|
|
115
|
+
* (`'42/100'`) all work uniformly.
|
|
116
|
+
*/
|
|
117
|
+
interface TextAddon extends BaseAddon {
|
|
118
|
+
readonly kind: 'text';
|
|
119
|
+
readonly text: DynamicText;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Renders a named `<ng-template>` projected into the host `<df-dynamic-form>`.
|
|
123
|
+
*
|
|
124
|
+
* JSON-safe — backends ship the key, FE supplies the template definition.
|
|
125
|
+
* Use the `templateAddon(ref)` helper for rename-safe authoring in code.
|
|
126
|
+
*/
|
|
127
|
+
interface TemplateAddon extends BaseAddon {
|
|
128
|
+
readonly kind: 'template';
|
|
129
|
+
readonly templateKey: string;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Renders an arbitrary Angular component as the addon body.
|
|
133
|
+
*
|
|
134
|
+
* The loader returns either a component class directly or a module with a
|
|
135
|
+
* `default` export. For non-default exports, unwrap with `.then(m => m.X)`:
|
|
136
|
+
*
|
|
137
|
+
* ```ts
|
|
138
|
+
* { kind: 'component', component: () => import('./my').then(m => m.MyComponent) }
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* @codeOnly The `component` loader is a function and cannot survive
|
|
142
|
+
* `JSON.stringify`/`parse`. The lenient validator drops this kind when the
|
|
143
|
+
* config originated from JSON (set via `sanitizeFormConfig({ source: 'json' })`).
|
|
144
|
+
*/
|
|
145
|
+
interface ComponentAddon extends BaseAddon {
|
|
146
|
+
readonly kind: 'component';
|
|
147
|
+
readonly component: () => Promise<Type<unknown> | {
|
|
148
|
+
default: Type<unknown>;
|
|
149
|
+
}>;
|
|
150
|
+
readonly inputs?: Record<string, unknown>;
|
|
151
|
+
}
|
|
152
|
+
|
|
11
153
|
type WithInputSignals<T> = {
|
|
12
154
|
readonly [K in keyof T]-?: Signal<T[K]>;
|
|
13
155
|
};
|
|
@@ -725,19 +867,32 @@ type Widen<T, D extends number = 5> = [D] extends [never] ? T : T extends string
|
|
|
725
867
|
-readonly [K in keyof T]: Widen<T[K], Depth[D]>;
|
|
726
868
|
} : T;
|
|
727
869
|
/**
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
*
|
|
870
|
+
* Resolves the "underlying" non-null value type for a field, based on its `type`
|
|
871
|
+
* discriminator and (where it matters) its `value` literal. Used when we need a
|
|
872
|
+
* base type independent of whether the literal happens to be `null` — i.e., when
|
|
873
|
+
* computing the nullable widening for `value: null, nullable: true`.
|
|
732
874
|
*/
|
|
733
|
-
type
|
|
875
|
+
type ResolveBaseValueType<T, V> = T extends {
|
|
734
876
|
type: 'slider';
|
|
735
877
|
} ? number : T extends {
|
|
736
878
|
type: 'input';
|
|
737
879
|
props: {
|
|
738
880
|
type: 'number';
|
|
739
881
|
};
|
|
740
|
-
} ? number :
|
|
882
|
+
} ? number : T extends {
|
|
883
|
+
type: 'checkbox' | 'toggle';
|
|
884
|
+
} ? boolean : [V] extends [null] ? string : Widen<V>;
|
|
885
|
+
/**
|
|
886
|
+
* Infer value type based on field type, value literal, and the `nullable` flag.
|
|
887
|
+
* - Slider fields: always number
|
|
888
|
+
* - Input fields with props.type: 'number': number
|
|
889
|
+
* - Checkbox / toggle fields: always boolean
|
|
890
|
+
* - Other fields: widen the literal value type (default to string when value is null)
|
|
891
|
+
* - When `nullable: true` is declared, widens the result to `T | null`.
|
|
892
|
+
*/
|
|
893
|
+
type InferValueType<T, V> = T extends {
|
|
894
|
+
nullable: true;
|
|
895
|
+
} ? ResolveBaseValueType<T, V> | null : ResolveBaseValueType<T, V>;
|
|
741
896
|
/**
|
|
742
897
|
* Make type optional if field is not required.
|
|
743
898
|
* Hidden fields are never optional since they require a value property.
|
|
@@ -749,9 +904,11 @@ type MaybeOptional<T, V> = T extends {
|
|
|
749
904
|
} ? V : V | undefined;
|
|
750
905
|
/**
|
|
751
906
|
* Infers the value type from a single template field (for primitive arrays).
|
|
752
|
-
* Mirrors InferValueType logic: slider → number, input[number] → number,
|
|
907
|
+
* Mirrors InferValueType logic: slider → number, input[number] → number,
|
|
908
|
+
* checkbox/toggle → boolean, else widen `value` (string fallback). Widens to
|
|
909
|
+
* `T | null` when `nullable: true` is declared on the template field.
|
|
753
910
|
*/
|
|
754
|
-
type
|
|
911
|
+
type InferSingleTemplateValueBase<T, D extends number> = T extends {
|
|
755
912
|
type: 'slider';
|
|
756
913
|
} ? number : T extends {
|
|
757
914
|
type: 'input';
|
|
@@ -762,7 +919,10 @@ type InferSingleTemplateValue<T, D extends number> = T extends {
|
|
|
762
919
|
type: 'checkbox' | 'toggle';
|
|
763
920
|
} ? boolean : T extends {
|
|
764
921
|
value: infer V;
|
|
765
|
-
} ? Widen<V, Depth[D]> : string;
|
|
922
|
+
} ? [V] extends [null] ? string : Widen<V, Depth[D]> : string;
|
|
923
|
+
type InferSingleTemplateValue<T, D extends number> = T extends {
|
|
924
|
+
nullable: true;
|
|
925
|
+
} ? InferSingleTemplateValueBase<T, D> | null : InferSingleTemplateValueBase<T, D>;
|
|
766
926
|
/**
|
|
767
927
|
* Infers the value type for an array field.
|
|
768
928
|
* Handles four cases:
|
|
@@ -810,7 +970,9 @@ type ProcessField<T, D extends number = 5> = [D] extends [never] ? Record<string
|
|
|
810
970
|
} : never : T extends {
|
|
811
971
|
key: infer K;
|
|
812
972
|
} ? K extends string ? {
|
|
813
|
-
[P in K]: MaybeOptional<T,
|
|
973
|
+
[P in K]: MaybeOptional<T, T extends {
|
|
974
|
+
nullable: true;
|
|
975
|
+
} ? string | null : string>;
|
|
814
976
|
} : never : never;
|
|
815
977
|
/**
|
|
816
978
|
* Internal helper with depth tracking
|
|
@@ -2098,8 +2260,6 @@ interface SchemaDefinition {
|
|
|
2098
2260
|
subSchemas?: SchemaApplicationConfig[];
|
|
2099
2261
|
}
|
|
2100
2262
|
|
|
2101
|
-
type DynamicText = string | Observable<string> | Signal<string>;
|
|
2102
|
-
|
|
2103
2263
|
/**
|
|
2104
2264
|
* Re-export Angular's ValidationError for consistency
|
|
2105
2265
|
* This replaces our custom ValidationError interface
|
|
@@ -4195,6 +4355,24 @@ interface FieldDef<TProps, TMeta extends FieldMeta = FieldMeta> {
|
|
|
4195
4355
|
* and any field-level `wrappers`.
|
|
4196
4356
|
*/
|
|
4197
4357
|
skipDefaultWrappers?: boolean;
|
|
4358
|
+
/**
|
|
4359
|
+
* Addons rendered inside this field's slots (typically `prefix` / `suffix`).
|
|
4360
|
+
*
|
|
4361
|
+
* Each addon declares its kind, slot, and kind-specific configuration.
|
|
4362
|
+
* Whether a field type accepts addons — and which slots / kinds — is
|
|
4363
|
+
* declared at registration via `FieldTypeDefinition.addons`. Field types
|
|
4364
|
+
* without that registration ("Tier 3", e.g., toggle, radio) drop any
|
|
4365
|
+
* `addons` value with a lenient warning at config init.
|
|
4366
|
+
*
|
|
4367
|
+
* @example
|
|
4368
|
+
* ```typescript
|
|
4369
|
+
* addons: [
|
|
4370
|
+
* { slot: 'prefix', kind: 'prime-icon', icon: 'search' },
|
|
4371
|
+
* { slot: 'suffix', kind: 'prime-button', preset: 'clear', ariaLabel: 'Clear' },
|
|
4372
|
+
* ]
|
|
4373
|
+
* ```
|
|
4374
|
+
*/
|
|
4375
|
+
addons?: ReadonlyArray<AnyAddon>;
|
|
4198
4376
|
}
|
|
4199
4377
|
type IncludedKeys = 'label' | 'className' | 'hidden' | 'tabIndex';
|
|
4200
4378
|
/**
|
|
@@ -4289,6 +4467,103 @@ interface GroupContext {
|
|
|
4289
4467
|
*/
|
|
4290
4468
|
type MapperFn<T extends FieldDef<unknown>> = (input: T) => Signal<Record<string, unknown>>;
|
|
4291
4469
|
|
|
4470
|
+
/**
|
|
4471
|
+
* Minimal JSON Schema fragment used by the MCP server to surface an addon
|
|
4472
|
+
* kind's shape to AI form generators. Covers the common subset
|
|
4473
|
+
* (`type`/`properties`/`required`/`enum`/etc.) without pulling in a full JSON
|
|
4474
|
+
* Schema dependency. Extra keys are allowed via the `[key: string]` index so
|
|
4475
|
+
* vendor-specific annotations (`x-foo`, `markdownDescription`) still typecheck.
|
|
4476
|
+
*
|
|
4477
|
+
* Tooling-only: the runtime addon validator does NOT consult `schema` — it
|
|
4478
|
+
* relies on each kind's `validate?(addon, fieldKey)` callback for shape
|
|
4479
|
+
* enforcement. `schema` exists exclusively so the MCP server (and any other
|
|
4480
|
+
* AI-driven form authoring tool) can describe the kind to a model without
|
|
4481
|
+
* hand-maintaining a parallel registry.
|
|
4482
|
+
*/
|
|
4483
|
+
interface AddonKindSchema {
|
|
4484
|
+
readonly $ref?: string;
|
|
4485
|
+
readonly $schema?: string;
|
|
4486
|
+
readonly title?: string;
|
|
4487
|
+
readonly description?: string;
|
|
4488
|
+
readonly type?: 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null' | ReadonlyArray<'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'>;
|
|
4489
|
+
readonly enum?: ReadonlyArray<unknown>;
|
|
4490
|
+
readonly const?: unknown;
|
|
4491
|
+
readonly properties?: Readonly<Record<string, AddonKindSchema>>;
|
|
4492
|
+
readonly required?: ReadonlyArray<string>;
|
|
4493
|
+
readonly additionalProperties?: boolean | AddonKindSchema;
|
|
4494
|
+
readonly items?: AddonKindSchema | ReadonlyArray<AddonKindSchema>;
|
|
4495
|
+
readonly oneOf?: ReadonlyArray<AddonKindSchema>;
|
|
4496
|
+
readonly anyOf?: ReadonlyArray<AddonKindSchema>;
|
|
4497
|
+
readonly allOf?: ReadonlyArray<AddonKindSchema>;
|
|
4498
|
+
readonly not?: AddonKindSchema;
|
|
4499
|
+
readonly default?: unknown;
|
|
4500
|
+
readonly examples?: ReadonlyArray<unknown>;
|
|
4501
|
+
readonly minimum?: number;
|
|
4502
|
+
readonly maximum?: number;
|
|
4503
|
+
readonly minLength?: number;
|
|
4504
|
+
readonly maxLength?: number;
|
|
4505
|
+
readonly pattern?: string;
|
|
4506
|
+
readonly format?: string;
|
|
4507
|
+
/** Vendor extensions and unrecognised keywords pass through untyped. */
|
|
4508
|
+
readonly [key: string]: unknown;
|
|
4509
|
+
}
|
|
4510
|
+
/**
|
|
4511
|
+
* Optional shape validator a kind ships to enforce its required fields at
|
|
4512
|
+
* runtime. Throws are caught by the validator and converted into lenient
|
|
4513
|
+
* warnings; the offending addon is dropped and the form keeps rendering.
|
|
4514
|
+
*/
|
|
4515
|
+
type AddonShapeValidator<T extends BaseAddon = BaseAddon> = (addon: T, fieldKey: string) => void;
|
|
4516
|
+
/**
|
|
4517
|
+
* Per-kind registration metadata.
|
|
4518
|
+
*
|
|
4519
|
+
* Registered via `withCustomAddon(...)` features (or adapter feature
|
|
4520
|
+
* helpers like `withPrimeNGAddons()`); resolved at render time by
|
|
4521
|
+
* `<df-addon-slot>`.
|
|
4522
|
+
*/
|
|
4523
|
+
interface AddonKindDefinition<T extends BaseAddon = BaseAddon> {
|
|
4524
|
+
/** Discriminant matching `addon.kind`. */
|
|
4525
|
+
readonly kind: string;
|
|
4526
|
+
/** Lazy loader for the kind's renderer component. */
|
|
4527
|
+
readonly loadComponent: LazyComponentLoader;
|
|
4528
|
+
/** Optional shape validator — throw `DynamicFormError` to drop the addon with a warning. */
|
|
4529
|
+
readonly validate?: AddonShapeValidator<T>;
|
|
4530
|
+
/** Optional JSON Schema fragment for MCP / pre-flight tooling. */
|
|
4531
|
+
readonly schema?: AddonKindSchema;
|
|
4532
|
+
/**
|
|
4533
|
+
* Whether the kind survives `JSON.stringify` / `JSON.parse`. Kinds whose
|
|
4534
|
+
* shape includes a function payload (e.g., the built-in `'component'`
|
|
4535
|
+
* loader, inline `prime-button` `action` handlers) declare `jsonSafe: false`
|
|
4536
|
+
* so the validator drops them when the config was loaded from a JSON
|
|
4537
|
+
* source (`sanitizeFormConfig(config, { source: 'json' })`). Defaults to
|
|
4538
|
+
* `true` — kinds are JSON-safe unless explicitly opted out.
|
|
4539
|
+
*/
|
|
4540
|
+
readonly jsonSafe?: boolean;
|
|
4541
|
+
}
|
|
4542
|
+
/**
|
|
4543
|
+
* Per-field-type addon-support metadata declared at field registration.
|
|
4544
|
+
*
|
|
4545
|
+
* Source of truth for the runtime validator: which slots are valid for a
|
|
4546
|
+
* field type, which kinds are accepted (optional whitelist).
|
|
4547
|
+
*
|
|
4548
|
+
* Field types that do not declare `addons` on their `FieldTypeDefinition`
|
|
4549
|
+
* are treated as Tier 3 — addons configured on such fields are dropped
|
|
4550
|
+
* with a warning at config init.
|
|
4551
|
+
*/
|
|
4552
|
+
interface FieldAddonSupport {
|
|
4553
|
+
/** Slots a field of this type accepts. */
|
|
4554
|
+
readonly slots: readonly AddonSlot[];
|
|
4555
|
+
/** Optional whitelist of allowed addon kinds. Omitted = any registered kind. */
|
|
4556
|
+
readonly allowedKinds?: readonly string[];
|
|
4557
|
+
}
|
|
4558
|
+
/**
|
|
4559
|
+
* Global registry of addon kinds.
|
|
4560
|
+
*
|
|
4561
|
+
* Populated by `withCustomAddon(...)` features and adapter feature helpers
|
|
4562
|
+
* (e.g., `withPrimeNGAddons()`). Read by `<df-addon-slot>` to resolve a
|
|
4563
|
+
* kind discriminant to its renderer component.
|
|
4564
|
+
*/
|
|
4565
|
+
declare const ADDON_KIND_REGISTRY: InjectionToken<Map<string, AddonKindDefinition<BaseAddon<AddonSlot>>>>;
|
|
4566
|
+
|
|
4292
4567
|
/**
|
|
4293
4568
|
* Defines how a field type handles form values and data collection.
|
|
4294
4569
|
*
|
|
@@ -4382,6 +4657,23 @@ interface FieldTypeDefinition<T extends FieldDef<any> = any> {
|
|
|
4382
4657
|
scope?: FieldScope | FieldScope[];
|
|
4383
4658
|
/** Mapped component inputs that must exist before the renderer instantiates the component */
|
|
4384
4659
|
renderReadyWhen?: readonly RenderReadyInput[];
|
|
4660
|
+
/**
|
|
4661
|
+
* Declares which addon slots this field accepts and (optionally) the
|
|
4662
|
+
* subset of kinds allowed.
|
|
4663
|
+
*
|
|
4664
|
+
* Source of truth for the runtime addon validator. Field types that
|
|
4665
|
+
* omit this property are treated as Tier 3 — any `addons` configured
|
|
4666
|
+
* on such a field are dropped with a warning at config init.
|
|
4667
|
+
*
|
|
4668
|
+
* @example
|
|
4669
|
+
* ```typescript
|
|
4670
|
+
* {
|
|
4671
|
+
* name: 'prime-input',
|
|
4672
|
+
* addons: { slots: ['prefix', 'suffix'] },
|
|
4673
|
+
* }
|
|
4674
|
+
* ```
|
|
4675
|
+
*/
|
|
4676
|
+
addons?: FieldAddonSupport;
|
|
4385
4677
|
}
|
|
4386
4678
|
/**
|
|
4387
4679
|
* Injection token for the global field type registry.
|
|
@@ -4626,12 +4918,22 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
4626
4918
|
formOptions: _angular_core.InputSignal<FormOptions | undefined>;
|
|
4627
4919
|
/** Form values for two-way data binding. */
|
|
4628
4920
|
value: _angular_core.ModelSignal<Partial<TModel> | undefined>;
|
|
4921
|
+
/**
|
|
4922
|
+
* How lenient the addon validator is on `config.fields[...].addons`.
|
|
4923
|
+
* `'inline'` (default) keeps everything; `'json'` drops code-only kinds
|
|
4924
|
+
* with a warning. Read at form init and on every config swap — change
|
|
4925
|
+
* `source` AND the config to force re-validation mid-flight.
|
|
4926
|
+
*/
|
|
4927
|
+
source: _angular_core.InputSignal<"json" | "inline">;
|
|
4629
4928
|
private destroyRef;
|
|
4630
4929
|
private injector;
|
|
4631
4930
|
protected environmentInjector: EnvironmentInjector;
|
|
4632
4931
|
private eventBus;
|
|
4633
4932
|
private logger;
|
|
4634
4933
|
private dispatcher;
|
|
4934
|
+
private templateRegistry;
|
|
4935
|
+
/** All `<ng-template dfTemplate="...">` instances projected into this form. */
|
|
4936
|
+
private readonly _projectedTemplates;
|
|
4635
4937
|
/** State manager that owns all form state. Initialized via connectDeps() to guarantee
|
|
4636
4938
|
* FORM_STATE_DEPS is populated before FormStateManager is injected. */
|
|
4637
4939
|
private readonly stateManager;
|
|
@@ -4745,7 +5047,7 @@ declare class DynamicForm<TFields extends RegisteredFieldTypes[] = RegisteredFie
|
|
|
4745
5047
|
private connectDeps;
|
|
4746
5048
|
private setupEventHandlers;
|
|
4747
5049
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DynamicForm<any, any>, never>;
|
|
4748
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicForm<any, any>, "form[dynamic-form]", never, { "config": { "alias": "dynamic-form"; "required": true; "isSignal": true; }; "formOptions": { "alias": "formOptions"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "validityChange": "validityChange"; "dirtyChange": "dirtyChange"; "submitted": "submitted"; "reset": "reset"; "cleared": "cleared"; "events": "events"; "initialized": "initialized"; "onPageChange": "onPageChange"; "onPageNavigationStateChange": "onPageNavigationStateChange"; },
|
|
5050
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicForm<any, any>, "form[dynamic-form]", never, { "config": { "alias": "dynamic-form"; "required": true; "isSignal": true; }; "formOptions": { "alias": "formOptions"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "source": { "alias": "source"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "validityChange": "validityChange"; "dirtyChange": "dirtyChange"; "submitted": "submitted"; "reset": "reset"; "cleared": "cleared"; "events": "events"; "initialized": "initialized"; "onPageChange": "onPageChange"; "onPageNavigationStateChange": "onPageNavigationStateChange"; }, ["_projectedTemplates"], never, true, never>;
|
|
4749
5051
|
}
|
|
4750
5052
|
|
|
4751
5053
|
declare class EventBus {
|
|
@@ -4920,178 +5222,99 @@ interface DynamicFormFeature<TKind extends string = string> {
|
|
|
4920
5222
|
ɵproviders: Provider[];
|
|
4921
5223
|
}
|
|
4922
5224
|
|
|
4923
|
-
interface FieldOption<T = unknown> {
|
|
4924
|
-
label: DynamicText;
|
|
4925
|
-
value: T;
|
|
4926
|
-
disabled?: boolean;
|
|
4927
|
-
[key: string]: unknown;
|
|
4928
|
-
}
|
|
4929
|
-
|
|
4930
5225
|
/**
|
|
4931
|
-
*
|
|
4932
|
-
*
|
|
4933
|
-
* Provides a Signal of the `defaultWrappers` array from FormConfig. Consumed by
|
|
4934
|
-
* `DfFieldOutlet` / `ContainerFieldComponent` to merge into each field's
|
|
4935
|
-
* effective wrapper chain (lowest priority after auto-associations, higher
|
|
4936
|
-
* than field-level `wrappers`).
|
|
5226
|
+
* User-facing wrapper registration shape used with `createWrappers(...)`.
|
|
4937
5227
|
*
|
|
4938
|
-
*
|
|
4939
|
-
*
|
|
5228
|
+
* Extends `WrapperTypeDefinition` with an optional `props` field that
|
|
5229
|
+
* carries the wrapper's config type (via `wrapperProps`) for later
|
|
5230
|
+
* inference by `InferWrapperRegistry`.
|
|
4940
5231
|
*/
|
|
4941
|
-
|
|
5232
|
+
interface WrapperRegistration<TName extends string = string, TConfig = unknown> {
|
|
5233
|
+
/** Unique identifier for the wrapper type */
|
|
5234
|
+
readonly wrapperName: TName;
|
|
5235
|
+
/** Lazy-loader for the wrapper component */
|
|
5236
|
+
readonly loadComponent: LazyComponentLoader;
|
|
5237
|
+
/** Field types this wrapper auto-applies to (merged lowest-priority during wrapper resolution) */
|
|
5238
|
+
readonly types?: readonly string[];
|
|
5239
|
+
/**
|
|
5240
|
+
* Type carrier only — runtime value is always `undefined`.
|
|
5241
|
+
* Use `wrapperProps<YourConfig>()` to thread the config type.
|
|
5242
|
+
*/
|
|
5243
|
+
readonly props?: TConfig;
|
|
5244
|
+
}
|
|
4942
5245
|
/**
|
|
4943
|
-
*
|
|
4944
|
-
*
|
|
4945
|
-
* The field signal context is the "nervous system" of the dynamic form library,
|
|
4946
|
-
* providing access to:
|
|
4947
|
-
* - The form instance and structure
|
|
4948
|
-
* - Current form values (as signals)
|
|
4949
|
-
* - Default values
|
|
4950
|
-
* - Validation messages
|
|
4951
|
-
* - The injector for creating components
|
|
5246
|
+
* Branded bundle returned by `createWrappers(...)`.
|
|
4952
5247
|
*
|
|
4953
|
-
*
|
|
4954
|
-
*
|
|
5248
|
+
* Carries:
|
|
5249
|
+
* - `ɵkind: 'wrappers'` — discriminant recognised by `provideDynamicForm(...)`
|
|
5250
|
+
* - `ɵregistrations` — the original registrations (type-level use for `InferWrapperRegistry`)
|
|
5251
|
+
* - `ɵdefinitions` — the `WrapperTypeDefinition[]` extracted for `WRAPPER_REGISTRY`
|
|
5252
|
+
*/
|
|
5253
|
+
interface WrappersBundle<T extends readonly WrapperRegistration[] = readonly WrapperRegistration[]> {
|
|
5254
|
+
readonly ɵkind: 'wrappers';
|
|
5255
|
+
readonly ɵregistrations: T;
|
|
5256
|
+
readonly ɵdefinitions: readonly WrapperTypeDefinition[];
|
|
5257
|
+
}
|
|
5258
|
+
/**
|
|
5259
|
+
* Bundle wrapper registrations into a single object that can be passed to
|
|
5260
|
+
* `provideDynamicForm(...)`.
|
|
4955
5261
|
*
|
|
4956
5262
|
* @example
|
|
4957
5263
|
* ```typescript
|
|
4958
|
-
*
|
|
4959
|
-
*
|
|
4960
|
-
*
|
|
4961
|
-
*
|
|
4962
|
-
*
|
|
4963
|
-
*
|
|
5264
|
+
* const appWrappers = createWrappers(
|
|
5265
|
+
* {
|
|
5266
|
+
* wrapperName: 'section',
|
|
5267
|
+
* loadComponent: () => import('./section-wrapper'),
|
|
5268
|
+
* props: wrapperProps<SectionWrapper>(),
|
|
5269
|
+
* },
|
|
5270
|
+
* {
|
|
5271
|
+
* wrapperName: 'highlight',
|
|
5272
|
+
* loadComponent: () => import('./highlight-wrapper'),
|
|
5273
|
+
* types: ['input', 'select'],
|
|
5274
|
+
* props: wrapperProps<HighlightWrapper>(),
|
|
5275
|
+
* },
|
|
5276
|
+
* );
|
|
4964
5277
|
*
|
|
4965
|
-
*
|
|
4966
|
-
*
|
|
4967
|
-
* private context = inject(FIELD_SIGNAL_CONTEXT);
|
|
5278
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
5279
|
+
* interface FieldRegistryWrappers extends InferWrapperRegistry<typeof appWrappers> {}
|
|
4968
5280
|
* }
|
|
5281
|
+
*
|
|
5282
|
+
* bootstrapApplication(AppComponent, {
|
|
5283
|
+
* providers: [provideDynamicForm(appWrappers)],
|
|
5284
|
+
* });
|
|
4969
5285
|
* ```
|
|
4970
5286
|
*/
|
|
4971
|
-
declare const
|
|
5287
|
+
declare function createWrappers<const T extends readonly WrapperRegistration[]>(...registrations: T): WrappersBundle<T>;
|
|
5288
|
+
/** Type guard for a `WrappersBundle`. */
|
|
5289
|
+
declare function isWrappersBundle(value: unknown): value is WrappersBundle;
|
|
4972
5290
|
/**
|
|
4973
|
-
*
|
|
4974
|
-
*
|
|
4975
|
-
* This token is optionally provided by ArrayFieldComponent when creating injectors
|
|
4976
|
-
* for array items. It contains metadata about the array item's position and parent.
|
|
5291
|
+
* Derive the `FieldRegistryWrappers` augmentation shape from a wrapper bundle.
|
|
4977
5292
|
*
|
|
4978
|
-
*
|
|
5293
|
+
* Maps each registration's `wrapperName` to its `props` type (the config carried
|
|
5294
|
+
* by `wrapperProps<T>()`). If a registration has no `props`, falls back to the
|
|
5295
|
+
* minimal discriminant shape `{ readonly type: wrapperName }`.
|
|
4979
5296
|
*
|
|
4980
5297
|
* @example
|
|
4981
5298
|
* ```typescript
|
|
4982
|
-
*
|
|
4983
|
-
*
|
|
4984
|
-
* const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
4985
|
-
* if (arrayContext) {
|
|
4986
|
-
* // Use arrayContext.index, arrayContext.arrayKey, etc.
|
|
4987
|
-
* }
|
|
5299
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
5300
|
+
* interface FieldRegistryWrappers extends InferWrapperRegistry<typeof appWrappers> {}
|
|
4988
5301
|
* }
|
|
4989
5302
|
* ```
|
|
4990
5303
|
*/
|
|
4991
|
-
|
|
5304
|
+
type InferWrapperRegistry<T> = T extends WrappersBundle<infer R> ? {
|
|
5305
|
+
[Reg in R[number] as Reg['wrapperName']]: Reg extends {
|
|
5306
|
+
props: infer P;
|
|
5307
|
+
} ? Exclude<P, undefined> : {
|
|
5308
|
+
readonly type: Reg['wrapperName'];
|
|
5309
|
+
};
|
|
5310
|
+
} : never;
|
|
5311
|
+
|
|
4992
5312
|
/**
|
|
4993
|
-
*
|
|
4994
|
-
*
|
|
4995
|
-
*
|
|
4996
|
-
* 1. `GroupFieldComponent` provides a context whose `groupPath()` is the
|
|
4997
|
-
* parent path extended by its own key (e.g. `'address'` or `'user.address'`).
|
|
4998
|
-
* 2. `createArrayItemInjector` provides a sentinel with an empty `groupPath`,
|
|
4999
|
-
* resetting the chain at array boundaries — descendants of an array item
|
|
5000
|
-
* that re-enter a group compose paths INSIDE the array item, matching the
|
|
5001
|
-
* property-derivation collector's keying.
|
|
5002
|
-
*
|
|
5003
|
-
* `mapFieldToInputs` reads this to scope DOM IDs and override-store keys so
|
|
5004
|
-
* the same leaf key can appear in different groups without colliding (#401).
|
|
5005
|
-
*
|
|
5006
|
-
* Inject with `{ optional: true }` because top-level fields with no group
|
|
5007
|
-
* ancestor (and no enclosing array) won't have the token provided. The token
|
|
5008
|
-
* IS present for fields inside an array even when no inner group exists — the
|
|
5009
|
-
* array-boundary sentinel makes injection succeed with an empty `groupPath`.
|
|
5313
|
+
* Type guard to check if a field is a container field (page, row, group, or array)
|
|
5314
|
+
* Container fields have a 'fields' property and don't contribute values directly.
|
|
5315
|
+
* This overload works with RegisteredFieldTypes for full type narrowing.
|
|
5010
5316
|
*/
|
|
5011
|
-
declare
|
|
5012
|
-
/**
|
|
5013
|
-
* Injection token for form-level default props.
|
|
5014
|
-
*
|
|
5015
|
-
* Default props are form-wide property defaults that are merged with field-level props.
|
|
5016
|
-
* Field props take precedence over default props.
|
|
5017
|
-
*
|
|
5018
|
-
* Unlike FIELD_SIGNAL_CONTEXT which is re-provided by container components (Group, Array),
|
|
5019
|
-
* DEFAULT_PROPS is provided ONCE at the DynamicForm level and inherited by all children
|
|
5020
|
-
* via Angular's hierarchical injector.
|
|
5021
|
-
*
|
|
5022
|
-
* The token provides a Signal to enable reactivity - when config changes, mappers
|
|
5023
|
-
* that read the signal inside their computed() will automatically update.
|
|
5024
|
-
*
|
|
5025
|
-
* @example
|
|
5026
|
-
* ```typescript
|
|
5027
|
-
* // In a mapper function
|
|
5028
|
-
* const defaultPropsSignal = inject(DEFAULT_PROPS);
|
|
5029
|
-
*
|
|
5030
|
-
* return computed(() => {
|
|
5031
|
-
* const defaultProps = defaultPropsSignal?.(); // Read inside computed for reactivity
|
|
5032
|
-
* const baseInputs = buildBaseInputs(fieldDef, defaultProps);
|
|
5033
|
-
* // ...
|
|
5034
|
-
* });
|
|
5035
|
-
* ```
|
|
5036
|
-
*/
|
|
5037
|
-
declare const DEFAULT_PROPS: InjectionToken<Signal<Record<string, unknown> | undefined>>;
|
|
5038
|
-
/**
|
|
5039
|
-
* Injection token for form-level default validation messages.
|
|
5040
|
-
*
|
|
5041
|
-
* Default validation messages act as fallbacks when fields have validation
|
|
5042
|
-
* errors but no field-level `validationMessages` defined.
|
|
5043
|
-
*
|
|
5044
|
-
* Like DEFAULT_PROPS, this token is provided ONCE at the DynamicForm level
|
|
5045
|
-
* and inherited by all children via Angular's hierarchical injector.
|
|
5046
|
-
*
|
|
5047
|
-
* The token provides a Signal to enable reactivity - when config changes, mappers
|
|
5048
|
-
* that read the signal inside their computed() will automatically update.
|
|
5049
|
-
*
|
|
5050
|
-
* @example
|
|
5051
|
-
* ```typescript
|
|
5052
|
-
* // In a mapper or component
|
|
5053
|
-
* const defaultMessagesSignal = inject(DEFAULT_VALIDATION_MESSAGES);
|
|
5054
|
-
*
|
|
5055
|
-
* return computed(() => {
|
|
5056
|
-
* const defaultMessages = defaultMessagesSignal?.(); // Read inside computed for reactivity
|
|
5057
|
-
* const message = defaultMessages?.required ?? 'Field is required';
|
|
5058
|
-
* // ...
|
|
5059
|
-
* });
|
|
5060
|
-
* ```
|
|
5061
|
-
*/
|
|
5062
|
-
declare const DEFAULT_VALIDATION_MESSAGES: InjectionToken<Signal<ValidationMessages | undefined>>;
|
|
5063
|
-
/**
|
|
5064
|
-
* Injection token for form-level options.
|
|
5065
|
-
*
|
|
5066
|
-
* Form options control form-wide behavior including button disabled states.
|
|
5067
|
-
* Used by button mappers to determine default disabled behavior.
|
|
5068
|
-
*
|
|
5069
|
-
* Like DEFAULT_PROPS, this token is provided ONCE at the DynamicForm level
|
|
5070
|
-
* and inherited by all children via Angular's hierarchical injector.
|
|
5071
|
-
*
|
|
5072
|
-
* The token provides a Signal to enable reactivity - when config changes, mappers
|
|
5073
|
-
* that read the signal inside their computed() will automatically update.
|
|
5074
|
-
*
|
|
5075
|
-
* @example
|
|
5076
|
-
* ```typescript
|
|
5077
|
-
* // In a button mapper
|
|
5078
|
-
* const formOptionsSignal = inject(FORM_OPTIONS);
|
|
5079
|
-
*
|
|
5080
|
-
* return computed(() => {
|
|
5081
|
-
* const formOptions = formOptionsSignal?.(); // Read inside computed for reactivity
|
|
5082
|
-
* const disableWhenInvalid = formOptions?.submitButton?.disableWhenInvalid ?? true;
|
|
5083
|
-
* // ...
|
|
5084
|
-
* });
|
|
5085
|
-
* ```
|
|
5086
|
-
*/
|
|
5087
|
-
declare const FORM_OPTIONS: InjectionToken<Signal<FormOptions | undefined>>;
|
|
5088
|
-
|
|
5089
|
-
/**
|
|
5090
|
-
* Type guard to check if a field is a container field (page, row, group, or array)
|
|
5091
|
-
* Container fields have a 'fields' property and don't contribute values directly.
|
|
5092
|
-
* This overload works with RegisteredFieldTypes for full type narrowing.
|
|
5093
|
-
*/
|
|
5094
|
-
declare function isContainerField(field: RegisteredFieldTypes): field is ContainerFieldTypes;
|
|
5317
|
+
declare function isContainerField(field: RegisteredFieldTypes): field is ContainerFieldTypes;
|
|
5095
5318
|
/**
|
|
5096
5319
|
* Type guard to check if a field is a container field (page, row, group, or array).
|
|
5097
5320
|
* This overload works with any FieldDef for looser type checking.
|
|
@@ -5128,93 +5351,6 @@ type FieldPathAccess<TValue> = {
|
|
|
5128
5351
|
[K in keyof TValue]: SchemaPath<TValue[K]> | SchemaPathTree<TValue[K]>;
|
|
5129
5352
|
};
|
|
5130
5353
|
|
|
5131
|
-
/**
|
|
5132
|
-
* User-facing wrapper registration shape used with `createWrappers(...)`.
|
|
5133
|
-
*
|
|
5134
|
-
* Extends `WrapperTypeDefinition` with an optional `props` field that
|
|
5135
|
-
* carries the wrapper's config type (via `wrapperProps`) for later
|
|
5136
|
-
* inference by `InferWrapperRegistry`.
|
|
5137
|
-
*/
|
|
5138
|
-
interface WrapperRegistration<TName extends string = string, TConfig = unknown> {
|
|
5139
|
-
/** Unique identifier for the wrapper type */
|
|
5140
|
-
readonly wrapperName: TName;
|
|
5141
|
-
/** Lazy-loader for the wrapper component */
|
|
5142
|
-
readonly loadComponent: LazyComponentLoader;
|
|
5143
|
-
/** Field types this wrapper auto-applies to (merged lowest-priority during wrapper resolution) */
|
|
5144
|
-
readonly types?: readonly string[];
|
|
5145
|
-
/**
|
|
5146
|
-
* Type carrier only — runtime value is always `undefined`.
|
|
5147
|
-
* Use `wrapperProps<YourConfig>()` to thread the config type.
|
|
5148
|
-
*/
|
|
5149
|
-
readonly props?: TConfig;
|
|
5150
|
-
}
|
|
5151
|
-
/**
|
|
5152
|
-
* Branded bundle returned by `createWrappers(...)`.
|
|
5153
|
-
*
|
|
5154
|
-
* Carries:
|
|
5155
|
-
* - `ɵkind: 'wrappers'` — discriminant recognised by `provideDynamicForm(...)`
|
|
5156
|
-
* - `ɵregistrations` — the original registrations (type-level use for `InferWrapperRegistry`)
|
|
5157
|
-
* - `ɵdefinitions` — the `WrapperTypeDefinition[]` extracted for `WRAPPER_REGISTRY`
|
|
5158
|
-
*/
|
|
5159
|
-
interface WrappersBundle<T extends readonly WrapperRegistration[] = readonly WrapperRegistration[]> {
|
|
5160
|
-
readonly ɵkind: 'wrappers';
|
|
5161
|
-
readonly ɵregistrations: T;
|
|
5162
|
-
readonly ɵdefinitions: readonly WrapperTypeDefinition[];
|
|
5163
|
-
}
|
|
5164
|
-
/**
|
|
5165
|
-
* Bundle wrapper registrations into a single object that can be passed to
|
|
5166
|
-
* `provideDynamicForm(...)`.
|
|
5167
|
-
*
|
|
5168
|
-
* @example
|
|
5169
|
-
* ```typescript
|
|
5170
|
-
* const appWrappers = createWrappers(
|
|
5171
|
-
* {
|
|
5172
|
-
* wrapperName: 'section',
|
|
5173
|
-
* loadComponent: () => import('./section-wrapper'),
|
|
5174
|
-
* props: wrapperProps<SectionWrapper>(),
|
|
5175
|
-
* },
|
|
5176
|
-
* {
|
|
5177
|
-
* wrapperName: 'highlight',
|
|
5178
|
-
* loadComponent: () => import('./highlight-wrapper'),
|
|
5179
|
-
* types: ['input', 'select'],
|
|
5180
|
-
* props: wrapperProps<HighlightWrapper>(),
|
|
5181
|
-
* },
|
|
5182
|
-
* );
|
|
5183
|
-
*
|
|
5184
|
-
* declare module '@ng-forge/dynamic-forms' {
|
|
5185
|
-
* interface FieldRegistryWrappers extends InferWrapperRegistry<typeof appWrappers> {}
|
|
5186
|
-
* }
|
|
5187
|
-
*
|
|
5188
|
-
* bootstrapApplication(AppComponent, {
|
|
5189
|
-
* providers: [provideDynamicForm(appWrappers)],
|
|
5190
|
-
* });
|
|
5191
|
-
* ```
|
|
5192
|
-
*/
|
|
5193
|
-
declare function createWrappers<const T extends readonly WrapperRegistration[]>(...registrations: T): WrappersBundle<T>;
|
|
5194
|
-
/** Type guard for a `WrappersBundle`. */
|
|
5195
|
-
declare function isWrappersBundle(value: unknown): value is WrappersBundle;
|
|
5196
|
-
/**
|
|
5197
|
-
* Derive the `FieldRegistryWrappers` augmentation shape from a wrapper bundle.
|
|
5198
|
-
*
|
|
5199
|
-
* Maps each registration's `wrapperName` to its `props` type (the config carried
|
|
5200
|
-
* by `wrapperProps<T>()`). If a registration has no `props`, falls back to the
|
|
5201
|
-
* minimal discriminant shape `{ readonly type: wrapperName }`.
|
|
5202
|
-
*
|
|
5203
|
-
* @example
|
|
5204
|
-
* ```typescript
|
|
5205
|
-
* declare module '@ng-forge/dynamic-forms' {
|
|
5206
|
-
* interface FieldRegistryWrappers extends InferWrapperRegistry<typeof appWrappers> {}
|
|
5207
|
-
* }
|
|
5208
|
-
* ```
|
|
5209
|
-
*/
|
|
5210
|
-
type InferWrapperRegistry<T> = T extends WrappersBundle<infer R> ? {
|
|
5211
|
-
[Reg in R[number] as Reg['wrapperName']]: Reg extends {
|
|
5212
|
-
props: infer P;
|
|
5213
|
-
} ? Exclude<P, undefined> : {
|
|
5214
|
-
readonly type: Reg['wrapperName'];
|
|
5215
|
-
};
|
|
5216
|
-
} : never;
|
|
5217
|
-
|
|
5218
5354
|
/**
|
|
5219
5355
|
* Extract FieldDef type from FieldTypeDefinition
|
|
5220
5356
|
*/
|
|
@@ -5307,336 +5443,1425 @@ type ExtractFormValue<T> = T extends {
|
|
|
5307
5443
|
} ? V : never;
|
|
5308
5444
|
|
|
5309
5445
|
/**
|
|
5310
|
-
*
|
|
5446
|
+
* Type representing a FieldTree for an array.
|
|
5447
|
+
* Extends FieldTree to add numeric indexing for accessing item FieldTrees.
|
|
5448
|
+
*/
|
|
5449
|
+
type ArrayFieldTree<T> = FieldTree<T[]> & {
|
|
5450
|
+
readonly [index: number]: FieldTree<T> | undefined;
|
|
5451
|
+
};
|
|
5452
|
+
/**
|
|
5453
|
+
* Get the length of an array FieldTree.
|
|
5454
|
+
*/
|
|
5455
|
+
declare function getArrayLength<T>(arrayFieldTree: ArrayFieldTree<T>): number;
|
|
5456
|
+
/**
|
|
5457
|
+
* Read-only view of a single field's observable state.
|
|
5311
5458
|
*
|
|
5312
|
-
*
|
|
5313
|
-
*
|
|
5314
|
-
*
|
|
5459
|
+
* Whitelisted read signals copied from Angular Signal Forms' `FieldState` so wrappers
|
|
5460
|
+
* can observe a field without being able to mutate it. New write-capable members
|
|
5461
|
+
* added in future Angular versions are excluded by default (the `Pick` list stays
|
|
5462
|
+
* the source of truth).
|
|
5463
|
+
*
|
|
5464
|
+
* `value` is narrowed from `WritableSignal<TValue>` to `Signal<TValue>` so consumers
|
|
5465
|
+
* cannot write through it.
|
|
5315
5466
|
*/
|
|
5316
|
-
|
|
5467
|
+
interface ReadonlyFieldTree<TValue = unknown> {
|
|
5468
|
+
readonly value: Signal<TValue>;
|
|
5469
|
+
readonly valid: Signal<boolean>;
|
|
5470
|
+
readonly invalid: Signal<boolean>;
|
|
5471
|
+
readonly touched: Signal<boolean>;
|
|
5472
|
+
readonly dirty: Signal<boolean>;
|
|
5473
|
+
readonly required: Signal<boolean>;
|
|
5474
|
+
readonly disabled: Signal<boolean>;
|
|
5475
|
+
readonly hidden: Signal<boolean>;
|
|
5476
|
+
readonly errors: Signal<readonly unknown[]>;
|
|
5477
|
+
}
|
|
5478
|
+
/**
|
|
5479
|
+
* Build a `ReadonlyFieldTree` by extracting the whitelisted read signals from a
|
|
5480
|
+
* Signal Forms `FieldTree`. Returns a fresh plain object — no casting, no proxying,
|
|
5481
|
+
* so consumers only see the narrow surface and Angular's `WritableSignal` capability
|
|
5482
|
+
* on `value` is hidden.
|
|
5483
|
+
*/
|
|
5484
|
+
declare function toReadonlyFieldTree<TValue>(field: FieldTree<TValue>): ReadonlyFieldTree<TValue>;
|
|
5485
|
+
/**
|
|
5486
|
+
* Write a value into a FieldTree's underlying signal. Signal Forms stores
|
|
5487
|
+
* `FieldState.value` as a `WritableSignal`; this helper centralises the cast
|
|
5488
|
+
* and warns if that contract ever changes (vs a silent no-op).
|
|
5489
|
+
*/
|
|
5490
|
+
declare function writeToFieldValue<T>(value: Signal<T>, next: T, logger?: {
|
|
5491
|
+
warn: (msg: string) => void;
|
|
5492
|
+
}): boolean;
|
|
5317
5493
|
|
|
5318
5494
|
/**
|
|
5319
|
-
*
|
|
5320
|
-
*
|
|
5321
|
-
* @public
|
|
5495
|
+
* Fields every addon-action context carries, regardless of whether the
|
|
5496
|
+
* addon is bound to a host field or rendered orphaned.
|
|
5322
5497
|
*/
|
|
5323
|
-
interface
|
|
5498
|
+
interface AddonActionContextBase<TValue> {
|
|
5324
5499
|
/**
|
|
5325
|
-
*
|
|
5326
|
-
*
|
|
5327
|
-
* @
|
|
5500
|
+
* Identity of the host field this addon is attached to. Empty strings
|
|
5501
|
+
* indicate the addon is rendered outside an active field context (rare).
|
|
5502
|
+
* Use {@link isFieldBoundContext} or the `form !== null` check to
|
|
5503
|
+
* narrow before relying on field identity.
|
|
5328
5504
|
*/
|
|
5329
|
-
|
|
5505
|
+
readonly field: {
|
|
5506
|
+
readonly key: string;
|
|
5507
|
+
readonly type: string;
|
|
5508
|
+
};
|
|
5330
5509
|
/**
|
|
5331
|
-
*
|
|
5332
|
-
*
|
|
5333
|
-
*
|
|
5334
|
-
* - `'summary'`: Log cycle completion with counts
|
|
5335
|
-
* - `'verbose'`: Log individual derivation evaluations with details
|
|
5336
|
-
*
|
|
5337
|
-
* @default 'none'
|
|
5510
|
+
* Current value of the host field at the time the action fires.
|
|
5511
|
+
* `undefined` when the host field has no value yet (initial render before
|
|
5512
|
+
* defaultValue resolution) or when the addon is rendered outside a field.
|
|
5338
5513
|
*/
|
|
5339
|
-
|
|
5514
|
+
readonly value: TValue | undefined;
|
|
5340
5515
|
}
|
|
5341
5516
|
/**
|
|
5342
|
-
*
|
|
5517
|
+
* Field-bound variant — the addon is attached to a real field and has a
|
|
5518
|
+
* working value-writer. The common case for `pi-button` / `mat-button` /
|
|
5519
|
+
* `bs-button` / `ion-button` inside an adapter input field.
|
|
5343
5520
|
*
|
|
5344
|
-
*
|
|
5345
|
-
*
|
|
5521
|
+
* `setValue` is non-optional here; the optional chain (`ctx.setValue?.()`)
|
|
5522
|
+
* is unnecessary noise once you've narrowed via {@link isFieldBoundContext}.
|
|
5523
|
+
*/
|
|
5524
|
+
interface FieldBoundAddonActionContext<TValue = unknown> extends AddonActionContextBase<TValue> {
|
|
5525
|
+
/** Read-only view of the host field's tree — same view wrappers receive. */
|
|
5526
|
+
readonly form: ReadonlyFieldTree<TValue>;
|
|
5527
|
+
/** Push a new value into the host field. */
|
|
5528
|
+
readonly setValue: (next: TValue) => void;
|
|
5529
|
+
}
|
|
5530
|
+
/**
|
|
5531
|
+
* Orphan variant — the addon is rendered outside any field component (rare;
|
|
5532
|
+
* happens when consumers compose `<df-addon-slot>` directly without a host
|
|
5533
|
+
* field). No writer is reachable; reading `value` may also yield `undefined`.
|
|
5534
|
+
*/
|
|
5535
|
+
interface OrphanAddonActionContext<TValue = unknown> extends AddonActionContextBase<TValue> {
|
|
5536
|
+
readonly form: null;
|
|
5537
|
+
/** Always absent in the orphan variant — distinguishes the union members. */
|
|
5538
|
+
readonly setValue?: undefined;
|
|
5539
|
+
}
|
|
5540
|
+
/**
|
|
5541
|
+
* Context handed to inline addon actions and registered handler functions.
|
|
5542
|
+
*
|
|
5543
|
+
* Discriminated by `form`: field-bound contexts have a non-null `form` and a
|
|
5544
|
+
* required `setValue`; orphan contexts have `form: null` and no `setValue`.
|
|
5545
|
+
* Use {@link isFieldBoundContext} when the handler needs to write back.
|
|
5346
5546
|
*
|
|
5347
5547
|
* @example
|
|
5348
5548
|
* ```typescript
|
|
5349
|
-
*
|
|
5350
|
-
*
|
|
5351
|
-
*
|
|
5352
|
-
*
|
|
5353
|
-
* )
|
|
5549
|
+
* provideAddonActions({
|
|
5550
|
+
* submit: (ctx) => {
|
|
5551
|
+
* if (!isFieldBoundContext(ctx)) return;
|
|
5552
|
+
* // ctx.setValue is now `(next: TValue) => void` — no optional chain.
|
|
5553
|
+
* myService.send(ctx.field.key, ctx.value, ctx.setValue);
|
|
5554
|
+
* },
|
|
5555
|
+
* });
|
|
5556
|
+
* ```
|
|
5557
|
+
*/
|
|
5558
|
+
type AddonActionContext<TValue = unknown> = FieldBoundAddonActionContext<TValue> | OrphanAddonActionContext<TValue>;
|
|
5559
|
+
/** Type guard narrowing {@link AddonActionContext} to its field-bound variant. */
|
|
5560
|
+
declare function isFieldBoundContext<TValue>(ctx: AddonActionContext<TValue>): ctx is FieldBoundAddonActionContext<TValue>;
|
|
5561
|
+
/**
|
|
5562
|
+
* Built-in preset actions shared across adapters.
|
|
5354
5563
|
*
|
|
5355
|
-
*
|
|
5356
|
-
*
|
|
5357
|
-
* ...withMaterialFields(),
|
|
5358
|
-
* withLoggerConfig({ derivations: 'verbose' })
|
|
5359
|
-
* )
|
|
5564
|
+
* Adapter kinds that accept a `preset` field render the corresponding
|
|
5565
|
+
* behaviour:
|
|
5360
5566
|
*
|
|
5361
|
-
*
|
|
5362
|
-
*
|
|
5363
|
-
*
|
|
5364
|
-
*
|
|
5365
|
-
*
|
|
5567
|
+
* - `'clear'`: empties the field value.
|
|
5568
|
+
* - `'reset'`: restores the field's configured default value (resolved
|
|
5569
|
+
* from the form's `defaultValues` map at click time); falls back to
|
|
5570
|
+
* empty when no default is reachable.
|
|
5571
|
+
* - `'paste'`: reads from the system clipboard and writes the result.
|
|
5572
|
+
* - `'copy'`: writes the field's current value to the system clipboard.
|
|
5573
|
+
* - `'toggle-password-visibility'`: flips a host input's `type` between
|
|
5574
|
+
* `password` and `text` (requires the host field to provide a type
|
|
5575
|
+
* override token, e.g., `PRIME_INPUT_TYPE_OVERRIDE`).
|
|
5576
|
+
*
|
|
5577
|
+
* Form submission is intentionally NOT exposed as a button-addon preset —
|
|
5578
|
+
* use the dedicated `'submit'` field type instead.
|
|
5579
|
+
*/
|
|
5580
|
+
type CommonAddonActionPreset = 'clear' | 'reset' | 'paste' | 'copy' | 'toggle-password-visibility';
|
|
5581
|
+
/**
|
|
5582
|
+
* Module-augmentable registry of adapter-specific preset names.
|
|
5583
|
+
*
|
|
5584
|
+
* Adapters add their canonical actions (e.g., Material's
|
|
5585
|
+
* `'mat-datepicker-open'`) without forking the `AddonActionPreset` union.
|
|
5586
|
+
*
|
|
5587
|
+
* @example
|
|
5588
|
+
* ```typescript
|
|
5589
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
5590
|
+
* interface DynamicFormAddonActionPresetRegistry {
|
|
5591
|
+
* 'mat-datepicker-open': true;
|
|
5592
|
+
* }
|
|
5593
|
+
* }
|
|
5594
|
+
* ```
|
|
5595
|
+
*/
|
|
5596
|
+
interface DynamicFormAddonActionPresetRegistry {
|
|
5597
|
+
}
|
|
5598
|
+
/**
|
|
5599
|
+
* Union of every preset name an addon may reference — universal presets
|
|
5600
|
+
* plus any contributed via {@link DynamicFormAddonActionPresetRegistry}.
|
|
5601
|
+
*
|
|
5602
|
+
* The `(string & {})` escape hatch keeps autocomplete on the known +
|
|
5603
|
+
* augmented presets while accepting arbitrary strings for one-off adapter
|
|
5604
|
+
* presets that don't warrant a module-augmentation. The runtime preset
|
|
5605
|
+
* runner already handles unknown names gracefully via its `default:` arm
|
|
5606
|
+
* (logs a warning, no throw). Mirrors `FieldDef.type`'s
|
|
5607
|
+
* `RegisteredFieldTypes['type'] | (string & {})` shape.
|
|
5608
|
+
*/
|
|
5609
|
+
type AddonActionPreset = CommonAddonActionPreset | keyof DynamicFormAddonActionPresetRegistry | (string & {});
|
|
5610
|
+
/**
|
|
5611
|
+
* Module-augmentable registry of user-defined named action handlers.
|
|
5612
|
+
*
|
|
5613
|
+
* Users register handlers once at bootstrap with `provideAddonActions({...})`
|
|
5614
|
+
* and reference them from JSON-driven configs via `actionRef: 'handlerName'`.
|
|
5615
|
+
*
|
|
5616
|
+
* @example
|
|
5617
|
+
* ```typescript
|
|
5618
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
5619
|
+
* interface DynamicFormActionRegistry {
|
|
5620
|
+
* openProfile: true;
|
|
5621
|
+
* runWorkflow: true;
|
|
5622
|
+
* }
|
|
5623
|
+
* }
|
|
5624
|
+
* ```
|
|
5625
|
+
*/
|
|
5626
|
+
interface DynamicFormActionRegistry {
|
|
5627
|
+
}
|
|
5628
|
+
/**
|
|
5629
|
+
* Typed string handle to a registered action handler. The empty registry
|
|
5630
|
+
* resolves to `never`; augmenting `DynamicFormActionRegistry` populates the
|
|
5631
|
+
* union and unlocks autocomplete.
|
|
5632
|
+
*/
|
|
5633
|
+
type RegisteredActionRef = keyof DynamicFormActionRegistry;
|
|
5634
|
+
|
|
5635
|
+
/**
|
|
5636
|
+
* Map of named `TemplateRef`s collected by `<df-dynamic-form>` from
|
|
5637
|
+
* `<ng-template dfTemplate="...">` children projected into its content.
|
|
5638
|
+
* The directive selector is `dfTemplate` (see `DfTemplate`); the input
|
|
5639
|
+
* value is the name addons reference via `templateKey`.
|
|
5640
|
+
*
|
|
5641
|
+
* The `template` addon kind looks up its `templateKey` in this map at
|
|
5642
|
+
* render time. Exposed as a `Signal` so projections can be added or
|
|
5643
|
+
* removed reactively (e.g., when the host conditionally projects).
|
|
5644
|
+
*
|
|
5645
|
+
* Provided at the form-component level (not root) so multiple
|
|
5646
|
+
* `<df-dynamic-form>` instances on the same page have independent
|
|
5647
|
+
* template scopes.
|
|
5648
|
+
*/
|
|
5649
|
+
declare const DF_FIELD_TEMPLATES: InjectionToken<Signal<ReadonlyMap<string, TemplateRef<unknown>>>>;
|
|
5650
|
+
|
|
5651
|
+
interface FieldOption<T = unknown> {
|
|
5652
|
+
label: DynamicText;
|
|
5653
|
+
value: T;
|
|
5654
|
+
disabled?: boolean;
|
|
5655
|
+
[key: string]: unknown;
|
|
5656
|
+
}
|
|
5657
|
+
|
|
5658
|
+
/**
|
|
5659
|
+
* Injection token for form-level default wrappers.
|
|
5660
|
+
*
|
|
5661
|
+
* Provides a Signal of the `defaultWrappers` array from FormConfig. Consumed by
|
|
5662
|
+
* `DfFieldOutlet` / `ContainerFieldComponent` to merge into each field's
|
|
5663
|
+
* effective wrapper chain (lowest priority after auto-associations, higher
|
|
5664
|
+
* than field-level `wrappers`).
|
|
5665
|
+
*
|
|
5666
|
+
* Provided once at the DynamicForm level and inherited via Angular's
|
|
5667
|
+
* hierarchical injector.
|
|
5668
|
+
*/
|
|
5669
|
+
declare const DEFAULT_WRAPPERS: InjectionToken<Signal<readonly WrapperConfig[] | undefined>>;
|
|
5670
|
+
/**
|
|
5671
|
+
* Injection token for providing field signal context to mappers and components.
|
|
5672
|
+
*
|
|
5673
|
+
* The field signal context is the "nervous system" of the dynamic form library,
|
|
5674
|
+
* providing access to:
|
|
5675
|
+
* - The form instance and structure
|
|
5676
|
+
* - Current form values (as signals)
|
|
5677
|
+
* - Default values
|
|
5678
|
+
* - Validation messages
|
|
5679
|
+
* - The injector for creating components
|
|
5680
|
+
*
|
|
5681
|
+
* This token is provided by the DynamicForm component and can be scoped
|
|
5682
|
+
* for nested forms (Groups, Arrays) via child injectors.
|
|
5683
|
+
*
|
|
5684
|
+
* @example
|
|
5685
|
+
* ```typescript
|
|
5686
|
+
* // In a mapper function — prefer the helper for required access (descriptive error).
|
|
5687
|
+
* export function mapValueField(fieldDef: BaseValueField<any, any>): Binding[] {
|
|
5688
|
+
* const context = injectFieldSignalContext();
|
|
5689
|
+
* const form = context.form();
|
|
5690
|
+
* // ... use context
|
|
5691
|
+
* }
|
|
5692
|
+
*
|
|
5693
|
+
* // Optional access — token directly, returns null if not provided.
|
|
5694
|
+
* const ctx = inject(FIELD_SIGNAL_CONTEXT, { optional: true });
|
|
5695
|
+
* if (ctx) {
|
|
5696
|
+
* // ...
|
|
5697
|
+
* }
|
|
5698
|
+
* ```
|
|
5699
|
+
*/
|
|
5700
|
+
declare const FIELD_SIGNAL_CONTEXT: InjectionToken<FieldSignalContext<Record<string, unknown>>>;
|
|
5701
|
+
/**
|
|
5702
|
+
* Throwing accessor for {@link FIELD_SIGNAL_CONTEXT}.
|
|
5703
|
+
*
|
|
5704
|
+
* Use when the consumer requires the context — group/array containers and
|
|
5705
|
+
* mappers that depend on form structure. Throws a descriptive
|
|
5706
|
+
* `DynamicFormError` instead of Angular's generic `NullInjectorError` when
|
|
5707
|
+
* the token isn't provided.
|
|
5708
|
+
*
|
|
5709
|
+
* Consumers that may legitimately run outside a `DynamicForm` should keep
|
|
5710
|
+
* using `inject(FIELD_SIGNAL_CONTEXT, { optional: true })`.
|
|
5711
|
+
*/
|
|
5712
|
+
declare function injectFieldSignalContext<TModel extends Record<string, unknown> = Record<string, unknown>>(): FieldSignalContext<TModel>;
|
|
5713
|
+
/**
|
|
5714
|
+
* Injection token for providing array context metadata to mappers and components.
|
|
5715
|
+
*
|
|
5716
|
+
* This token is optionally provided by ArrayFieldComponent when creating injectors
|
|
5717
|
+
* for array items. It contains metadata about the array item's position and parent.
|
|
5718
|
+
*
|
|
5719
|
+
* Mappers can inject this token with {optional: true} to access array context:
|
|
5720
|
+
*
|
|
5721
|
+
* @example
|
|
5722
|
+
* ```typescript
|
|
5723
|
+
* // In a mapper function
|
|
5724
|
+
* export function buttonMapper(fieldDef: FieldDef<any>): Binding[] {
|
|
5725
|
+
* const arrayContext = inject(ARRAY_CONTEXT, { optional: true });
|
|
5726
|
+
* if (arrayContext) {
|
|
5727
|
+
* // Use arrayContext.index, arrayContext.arrayKey, etc.
|
|
5728
|
+
* }
|
|
5729
|
+
* }
|
|
5730
|
+
* ```
|
|
5731
|
+
*/
|
|
5732
|
+
declare const ARRAY_CONTEXT: InjectionToken<ArrayContext>;
|
|
5733
|
+
/**
|
|
5734
|
+
* Injection token for providing group ancestry to mappers and components.
|
|
5735
|
+
*
|
|
5736
|
+
* Re-provided in two places:
|
|
5737
|
+
* 1. `GroupFieldComponent` provides a context whose `groupPath()` is the
|
|
5738
|
+
* parent path extended by its own key (e.g. `'address'` or `'user.address'`).
|
|
5739
|
+
* 2. `createArrayItemInjector` provides a sentinel with an empty `groupPath`,
|
|
5740
|
+
* resetting the chain at array boundaries — descendants of an array item
|
|
5741
|
+
* that re-enter a group compose paths INSIDE the array item, matching the
|
|
5742
|
+
* property-derivation collector's keying.
|
|
5743
|
+
*
|
|
5744
|
+
* `mapFieldToInputs` reads this to scope DOM IDs and override-store keys so
|
|
5745
|
+
* the same leaf key can appear in different groups without colliding (#401).
|
|
5746
|
+
*
|
|
5747
|
+
* Inject with `{ optional: true }` because top-level fields with no group
|
|
5748
|
+
* ancestor (and no enclosing array) won't have the token provided. The token
|
|
5749
|
+
* IS present for fields inside an array even when no inner group exists — the
|
|
5750
|
+
* array-boundary sentinel makes injection succeed with an empty `groupPath`.
|
|
5751
|
+
*/
|
|
5752
|
+
declare const GROUP_CONTEXT: InjectionToken<GroupContext>;
|
|
5753
|
+
/**
|
|
5754
|
+
* Injection token for form-level default props.
|
|
5755
|
+
*
|
|
5756
|
+
* Default props are form-wide property defaults that are merged with field-level props.
|
|
5757
|
+
* Field props take precedence over default props.
|
|
5758
|
+
*
|
|
5759
|
+
* Unlike FIELD_SIGNAL_CONTEXT which is re-provided by container components (Group, Array),
|
|
5760
|
+
* DEFAULT_PROPS is provided ONCE at the DynamicForm level and inherited by all children
|
|
5761
|
+
* via Angular's hierarchical injector.
|
|
5762
|
+
*
|
|
5763
|
+
* The token provides a Signal to enable reactivity - when config changes, mappers
|
|
5764
|
+
* that read the signal inside their computed() will automatically update.
|
|
5765
|
+
*
|
|
5766
|
+
* @example
|
|
5767
|
+
* ```typescript
|
|
5768
|
+
* // In a mapper function
|
|
5769
|
+
* const defaultPropsSignal = inject(DEFAULT_PROPS);
|
|
5770
|
+
*
|
|
5771
|
+
* return computed(() => {
|
|
5772
|
+
* const defaultProps = defaultPropsSignal?.(); // Read inside computed for reactivity
|
|
5773
|
+
* const baseInputs = buildBaseInputs(fieldDef, defaultProps);
|
|
5774
|
+
* // ...
|
|
5775
|
+
* });
|
|
5776
|
+
* ```
|
|
5777
|
+
*/
|
|
5778
|
+
declare const DEFAULT_PROPS: InjectionToken<Signal<Record<string, unknown> | undefined>>;
|
|
5779
|
+
/**
|
|
5780
|
+
* Injection token for form-level default validation messages.
|
|
5781
|
+
*
|
|
5782
|
+
* Default validation messages act as fallbacks when fields have validation
|
|
5783
|
+
* errors but no field-level `validationMessages` defined.
|
|
5784
|
+
*
|
|
5785
|
+
* Like DEFAULT_PROPS, this token is provided ONCE at the DynamicForm level
|
|
5786
|
+
* and inherited by all children via Angular's hierarchical injector.
|
|
5787
|
+
*
|
|
5788
|
+
* The token provides a Signal to enable reactivity - when config changes, mappers
|
|
5789
|
+
* that read the signal inside their computed() will automatically update.
|
|
5790
|
+
*
|
|
5791
|
+
* @example
|
|
5792
|
+
* ```typescript
|
|
5793
|
+
* // In a mapper or component
|
|
5794
|
+
* const defaultMessagesSignal = inject(DEFAULT_VALIDATION_MESSAGES);
|
|
5795
|
+
*
|
|
5796
|
+
* return computed(() => {
|
|
5797
|
+
* const defaultMessages = defaultMessagesSignal?.(); // Read inside computed for reactivity
|
|
5798
|
+
* const message = defaultMessages?.required ?? 'Field is required';
|
|
5799
|
+
* // ...
|
|
5800
|
+
* });
|
|
5801
|
+
* ```
|
|
5802
|
+
*/
|
|
5803
|
+
declare const DEFAULT_VALIDATION_MESSAGES: InjectionToken<Signal<ValidationMessages | undefined>>;
|
|
5804
|
+
/**
|
|
5805
|
+
* Injection token for form-level options.
|
|
5806
|
+
*
|
|
5807
|
+
* Form options control form-wide behavior including button disabled states.
|
|
5808
|
+
* Used by button mappers to determine default disabled behavior.
|
|
5809
|
+
*
|
|
5810
|
+
* Like DEFAULT_PROPS, this token is provided ONCE at the DynamicForm level
|
|
5811
|
+
* and inherited by all children via Angular's hierarchical injector.
|
|
5812
|
+
*
|
|
5813
|
+
* The token provides a Signal to enable reactivity - when config changes, mappers
|
|
5814
|
+
* that read the signal inside their computed() will automatically update.
|
|
5815
|
+
*
|
|
5816
|
+
* @example
|
|
5817
|
+
* ```typescript
|
|
5818
|
+
* // In a button mapper
|
|
5819
|
+
* const formOptionsSignal = inject(FORM_OPTIONS);
|
|
5820
|
+
*
|
|
5821
|
+
* return computed(() => {
|
|
5822
|
+
* const formOptions = formOptionsSignal?.(); // Read inside computed for reactivity
|
|
5823
|
+
* const disableWhenInvalid = formOptions?.submitButton?.disableWhenInvalid ?? true;
|
|
5824
|
+
* // ...
|
|
5825
|
+
* });
|
|
5826
|
+
* ```
|
|
5827
|
+
*/
|
|
5828
|
+
declare const FORM_OPTIONS: InjectionToken<Signal<FormOptions | undefined>>;
|
|
5829
|
+
|
|
5830
|
+
/**
|
|
5831
|
+
* Built-in field types provided by the dynamic form library.
|
|
5832
|
+
*
|
|
5833
|
+
* Each field type is validated at compile time using satisfies, ensuring
|
|
5834
|
+
* type safety of the mapper function while allowing the array to be typed
|
|
5835
|
+
* as FieldTypeDefinition[] for consumer flexibility.
|
|
5836
|
+
*/
|
|
5837
|
+
declare const BUILT_IN_FIELDS: FieldTypeDefinition[];
|
|
5838
|
+
|
|
5839
|
+
/**
|
|
5840
|
+
* Configuration options for the logger feature.
|
|
5841
|
+
*
|
|
5842
|
+
* @public
|
|
5843
|
+
*/
|
|
5844
|
+
interface LoggerConfigOptions {
|
|
5845
|
+
/**
|
|
5846
|
+
* Whether general logging is enabled.
|
|
5847
|
+
*
|
|
5848
|
+
* @default true
|
|
5849
|
+
*/
|
|
5850
|
+
enabled?: boolean;
|
|
5851
|
+
/**
|
|
5852
|
+
* Derivation logging level.
|
|
5853
|
+
*
|
|
5854
|
+
* - `'none'`: No derivation debug logging (default)
|
|
5855
|
+
* - `'summary'`: Log cycle completion with counts
|
|
5856
|
+
* - `'verbose'`: Log individual derivation evaluations with details
|
|
5857
|
+
*
|
|
5858
|
+
* @default 'none'
|
|
5859
|
+
*/
|
|
5860
|
+
derivations?: DerivationLogLevel;
|
|
5861
|
+
}
|
|
5862
|
+
/**
|
|
5863
|
+
* Configure logging for dynamic forms.
|
|
5864
|
+
*
|
|
5865
|
+
* By default, general logging is enabled (ConsoleLogger) and derivation
|
|
5866
|
+
* logging is disabled ('none'). Use this feature to enable derivation debugging.
|
|
5867
|
+
*
|
|
5868
|
+
* @example
|
|
5869
|
+
* ```typescript
|
|
5870
|
+
* // Disable all logging
|
|
5871
|
+
* provideDynamicForm(
|
|
5872
|
+
* ...withMaterialFields(),
|
|
5873
|
+
* withLoggerConfig(false)
|
|
5874
|
+
* )
|
|
5875
|
+
*
|
|
5876
|
+
* // Enable verbose derivation logging
|
|
5877
|
+
* provideDynamicForm(
|
|
5878
|
+
* ...withMaterialFields(),
|
|
5879
|
+
* withLoggerConfig({ derivations: 'verbose' })
|
|
5880
|
+
* )
|
|
5881
|
+
*
|
|
5882
|
+
* // Disable derivation logging but keep general logging
|
|
5883
|
+
* provideDynamicForm(
|
|
5884
|
+
* ...withMaterialFields(),
|
|
5885
|
+
* withLoggerConfig({ derivations: 'none' })
|
|
5886
|
+
* )
|
|
5366
5887
|
*
|
|
5367
5888
|
* // Conditional logging (e.g., only in dev mode)
|
|
5368
5889
|
* provideDynamicForm(
|
|
5369
5890
|
* ...withMaterialFields(),
|
|
5370
|
-
* withLoggerConfig(() => isDevMode())
|
|
5891
|
+
* withLoggerConfig(() => isDevMode())
|
|
5892
|
+
* )
|
|
5893
|
+
* ```
|
|
5894
|
+
*
|
|
5895
|
+
* @param config - Boolean to enable/disable logging, a function returning boolean, or a config object
|
|
5896
|
+
* @returns A DynamicFormFeature that configures logging
|
|
5897
|
+
*
|
|
5898
|
+
* @public
|
|
5899
|
+
*/
|
|
5900
|
+
declare function withLoggerConfig(config?: boolean | (() => boolean) | LoggerConfigOptions): DynamicFormFeature<'logger'>;
|
|
5901
|
+
|
|
5902
|
+
/**
|
|
5903
|
+
* Injection token for the dynamic forms logger.
|
|
5904
|
+
*
|
|
5905
|
+
* Provided by provideDynamicForm() with ConsoleLogger as default.
|
|
5906
|
+
* Override with withLoggerConfig(false) to disable logging.
|
|
5907
|
+
*/
|
|
5908
|
+
declare const DynamicFormLogger: InjectionToken<Logger>;
|
|
5909
|
+
|
|
5910
|
+
/**
|
|
5911
|
+
* Console-based logger implementation.
|
|
5912
|
+
*/
|
|
5913
|
+
declare class ConsoleLogger implements Logger {
|
|
5914
|
+
private readonly prefix;
|
|
5915
|
+
debug(message: string, ...args: unknown[]): void;
|
|
5916
|
+
info(message: string, ...args: unknown[]): void;
|
|
5917
|
+
warn(message: string, ...args: unknown[]): void;
|
|
5918
|
+
error(message: string, ...args: unknown[]): void;
|
|
5919
|
+
}
|
|
5920
|
+
|
|
5921
|
+
/**
|
|
5922
|
+
* No-operation logger implementation.
|
|
5923
|
+
* All methods are no-ops - used in production by default.
|
|
5924
|
+
*/
|
|
5925
|
+
declare class NoopLogger implements Logger {
|
|
5926
|
+
debug(): void;
|
|
5927
|
+
info(): void;
|
|
5928
|
+
warn(): void;
|
|
5929
|
+
error(): void;
|
|
5930
|
+
}
|
|
5931
|
+
|
|
5932
|
+
/**
|
|
5933
|
+
* Enables automatic form value attachment to all events dispatched through the EventBus.
|
|
5934
|
+
*
|
|
5935
|
+
* When this feature is enabled, events dispatched via `eventBus.dispatch()` will include
|
|
5936
|
+
* the current form value in the `formValue` property. This is useful for event handlers
|
|
5937
|
+
* that need access to the complete form state at the time of the event.
|
|
5938
|
+
*
|
|
5939
|
+
* @example Global opt-in
|
|
5940
|
+
* ```typescript
|
|
5941
|
+
* provideDynamicForm(
|
|
5942
|
+
* ...withMaterialFields(),
|
|
5943
|
+
* withEventFormValue()
|
|
5944
|
+
* )
|
|
5945
|
+
* ```
|
|
5946
|
+
*
|
|
5947
|
+
* @example Consumer usage
|
|
5948
|
+
* ```typescript
|
|
5949
|
+
* eventBus.on<SubmitEvent>('submit').subscribe(event => {
|
|
5950
|
+
* if (hasFormValue(event)) {
|
|
5951
|
+
* console.log('Form value:', event.formValue);
|
|
5952
|
+
* }
|
|
5953
|
+
* });
|
|
5954
|
+
* ```
|
|
5955
|
+
*
|
|
5956
|
+
* @example Per-form disable (when globally enabled)
|
|
5957
|
+
* ```typescript
|
|
5958
|
+
* const config: FormConfig = {
|
|
5959
|
+
* fields: [...],
|
|
5960
|
+
* options: { emitFormValueOnEvents: false }
|
|
5961
|
+
* };
|
|
5962
|
+
* ```
|
|
5963
|
+
*
|
|
5964
|
+
* @remarks
|
|
5965
|
+
* **Precedence rules:**
|
|
5966
|
+
* 1. Per-form `false` - Disables for this form, regardless of global setting
|
|
5967
|
+
* 2. Per-form `true` - Enables for this form, regardless of global setting
|
|
5968
|
+
* 3. Per-form `undefined` - Uses global setting
|
|
5969
|
+
* 4. Global `withEventFormValue()` - Enables globally
|
|
5970
|
+
* 5. No global feature - Disabled globally (default)
|
|
5971
|
+
*
|
|
5972
|
+
* @returns A DynamicFormFeature that enables form value attachment to events
|
|
5973
|
+
*
|
|
5974
|
+
* @public
|
|
5975
|
+
*/
|
|
5976
|
+
declare function withEventFormValue(): DynamicFormFeature<'event-form-value'>;
|
|
5977
|
+
|
|
5978
|
+
/**
|
|
5979
|
+
* Configuration for excluding field values from form submission output
|
|
5980
|
+
* based on their reactive state (hidden, disabled, readonly).
|
|
5981
|
+
*
|
|
5982
|
+
* Supports a 3-tier configuration hierarchy: Field > Form > Global.
|
|
5983
|
+
* The most specific level wins for each property.
|
|
5984
|
+
*
|
|
5985
|
+
* @public
|
|
5986
|
+
*/
|
|
5987
|
+
interface ValueExclusionConfig {
|
|
5988
|
+
/**
|
|
5989
|
+
* Whether to exclude the value of hidden fields from submission output.
|
|
5990
|
+
*
|
|
5991
|
+
* When `true`, fields whose `hidden()` state is `true` will have their
|
|
5992
|
+
* values omitted from the submitted form value.
|
|
5993
|
+
*
|
|
5994
|
+
* @remarks
|
|
5995
|
+
* This does NOT affect HiddenField (`type: 'hidden'`) — those fields
|
|
5996
|
+
* store values without UI and their `hidden()` state is always `false`.
|
|
5997
|
+
*/
|
|
5998
|
+
readonly excludeValueIfHidden?: boolean;
|
|
5999
|
+
/**
|
|
6000
|
+
* Whether to exclude the value of disabled fields from submission output.
|
|
6001
|
+
*
|
|
6002
|
+
* When `true`, fields whose `disabled()` state is `true` will have their
|
|
6003
|
+
* values omitted from the submitted form value.
|
|
6004
|
+
*/
|
|
6005
|
+
readonly excludeValueIfDisabled?: boolean;
|
|
6006
|
+
/**
|
|
6007
|
+
* Whether to exclude the value of readonly fields from submission output.
|
|
6008
|
+
*
|
|
6009
|
+
* When `true`, fields whose `readonly()` state is `true` will have their
|
|
6010
|
+
* values omitted from the submitted form value.
|
|
6011
|
+
*/
|
|
6012
|
+
readonly excludeValueIfReadonly?: boolean;
|
|
6013
|
+
}
|
|
6014
|
+
/**
|
|
6015
|
+
* Fully resolved exclusion config with all properties required.
|
|
6016
|
+
* Produced by the 3-tier resolution: `field ?? form ?? global`.
|
|
6017
|
+
*
|
|
6018
|
+
* @public
|
|
6019
|
+
*/
|
|
6020
|
+
type ResolvedValueExclusionConfig = Required<ValueExclusionConfig>;
|
|
6021
|
+
|
|
6022
|
+
/**
|
|
6023
|
+
* Configures global value exclusion defaults for form submission output.
|
|
6024
|
+
*
|
|
6025
|
+
* Value exclusion is **enabled by default** — field values are excluded from the
|
|
6026
|
+
* `(submitted)` output based on their reactive state. Use this feature to
|
|
6027
|
+
* override those defaults. This does NOT affect two-way binding (`value` model /
|
|
6028
|
+
* `entity`) — fields retain their values internally.
|
|
6029
|
+
*
|
|
6030
|
+
* @example Default behavior (all exclusions enabled)
|
|
6031
|
+
* ```typescript
|
|
6032
|
+
* provideDynamicForm(
|
|
6033
|
+
* ...withMaterialFields(),
|
|
6034
|
+
* withValueExclusionDefaults()
|
|
6035
|
+
* )
|
|
6036
|
+
* ```
|
|
6037
|
+
*
|
|
6038
|
+
* @example Disable specific exclusions
|
|
6039
|
+
* ```typescript
|
|
6040
|
+
* provideDynamicForm(
|
|
6041
|
+
* ...withMaterialFields(),
|
|
6042
|
+
* withValueExclusionDefaults({ excludeValueIfReadonly: false })
|
|
6043
|
+
* )
|
|
6044
|
+
* ```
|
|
6045
|
+
*
|
|
6046
|
+
* @example Disable all exclusions (restore pre-v1 behavior)
|
|
6047
|
+
* ```typescript
|
|
6048
|
+
* provideDynamicForm(
|
|
6049
|
+
* ...withMaterialFields(),
|
|
6050
|
+
* withValueExclusionDefaults({
|
|
6051
|
+
* excludeValueIfHidden: false,
|
|
6052
|
+
* excludeValueIfDisabled: false,
|
|
6053
|
+
* excludeValueIfReadonly: false,
|
|
6054
|
+
* })
|
|
6055
|
+
* )
|
|
6056
|
+
* ```
|
|
6057
|
+
*
|
|
6058
|
+
* @remarks
|
|
6059
|
+
* **Precedence rules:**
|
|
6060
|
+
* 1. Per-field `excludeValueIf*` on `FieldDef` — wins for that field
|
|
6061
|
+
* 2. Per-form `excludeValueIf*` on `FormOptions` — wins for all fields in that form
|
|
6062
|
+
* 3. Global `withValueExclusionDefaults()` — baseline default
|
|
6063
|
+
* 4. No global feature — uses token default (all enabled)
|
|
6064
|
+
*
|
|
6065
|
+
* @param config - Partial override of exclusion rules. Unspecified properties default to `true`.
|
|
6066
|
+
* @returns A DynamicFormFeature that configures value exclusion defaults
|
|
6067
|
+
*
|
|
6068
|
+
* @public
|
|
6069
|
+
*/
|
|
6070
|
+
declare function withValueExclusionDefaults(config?: Partial<ValueExclusionConfig>): DynamicFormFeature<'value-exclusion'>;
|
|
6071
|
+
|
|
6072
|
+
/**
|
|
6073
|
+
* Configuration for when validation runs based on a field's reactive state.
|
|
6074
|
+
*
|
|
6075
|
+
* Currently controls whether hidden fields are validated. Resolved through a
|
|
6076
|
+
* tree-aware hierarchy: per-field overrides inherit down to descendants, with
|
|
6077
|
+
* per-form `FormOptions` and global `withValidationExecutionDefaults()` providing
|
|
6078
|
+
* the root inherited value.
|
|
6079
|
+
*
|
|
6080
|
+
* @public
|
|
6081
|
+
*/
|
|
6082
|
+
interface ValidationExecutionConfig {
|
|
6083
|
+
/**
|
|
6084
|
+
* Whether validators run while a field is hidden (statically, via `hidden`
|
|
6085
|
+
* logic, or because any ancestor is hidden).
|
|
6086
|
+
*
|
|
6087
|
+
* When `false`, all validators on a hidden field are skipped — the field is
|
|
6088
|
+
* effectively inert until shown. State logic (hidden/disabled/readonly) and
|
|
6089
|
+
* value derivations continue to apply.
|
|
6090
|
+
*/
|
|
6091
|
+
readonly validateWhenHidden?: boolean;
|
|
6092
|
+
}
|
|
6093
|
+
/**
|
|
6094
|
+
* Fully resolved validation execution config — every property defined.
|
|
6095
|
+
*
|
|
6096
|
+
* @public
|
|
6097
|
+
*/
|
|
6098
|
+
type ResolvedValidationExecutionConfig = Required<ValidationExecutionConfig>;
|
|
6099
|
+
|
|
6100
|
+
/**
|
|
6101
|
+
* Configures global validation execution defaults — when validators should run
|
|
6102
|
+
* relative to a field's reactive state.
|
|
6103
|
+
*
|
|
6104
|
+
* By default, validators are **skipped** for hidden fields (`validateWhenHidden: false`),
|
|
6105
|
+
* matching what most users expect: a hidden field is inert. Use this feature to
|
|
6106
|
+
* restore the legacy behavior where hidden fields still validate.
|
|
6107
|
+
*
|
|
6108
|
+
* @example Default behavior — no feature needed
|
|
6109
|
+
* ```typescript
|
|
6110
|
+
* provideDynamicForm(...withMaterialFields())
|
|
6111
|
+
* // hidden fields skip validation
|
|
6112
|
+
* ```
|
|
6113
|
+
*
|
|
6114
|
+
* @example Restore legacy validation-on-hidden behavior
|
|
6115
|
+
* ```typescript
|
|
6116
|
+
* provideDynamicForm(
|
|
6117
|
+
* ...withMaterialFields(),
|
|
6118
|
+
* withValidationExecutionDefaults({ validateWhenHidden: true })
|
|
5371
6119
|
* )
|
|
5372
6120
|
* ```
|
|
5373
6121
|
*
|
|
5374
|
-
* @
|
|
5375
|
-
*
|
|
6122
|
+
* @remarks
|
|
6123
|
+
* **Precedence rules:**
|
|
6124
|
+
* 1. Per-field `FieldDef.validateWhenHidden` — wins for that field; inherits down to descendants
|
|
6125
|
+
* that don't override.
|
|
6126
|
+
* 2. Per-form `FormOptions.validateWhenHidden` — root inherited value for the form.
|
|
6127
|
+
* 3. Global `withValidationExecutionDefaults()` — fallback when no form/field setting.
|
|
6128
|
+
* 4. No feature configured — uses token default (`validateWhenHidden: false`).
|
|
6129
|
+
*
|
|
6130
|
+
* @param config - Partial override. Unspecified properties keep their defaults.
|
|
6131
|
+
* @returns A `DynamicFormFeature` that configures validation execution defaults.
|
|
5376
6132
|
*
|
|
5377
6133
|
* @public
|
|
5378
6134
|
*/
|
|
5379
|
-
declare function
|
|
6135
|
+
declare function withValidationExecutionDefaults(config?: Partial<ValidationExecutionConfig>): DynamicFormFeature<'validation-execution'>;
|
|
5380
6136
|
|
|
5381
6137
|
/**
|
|
5382
|
-
*
|
|
6138
|
+
* Opt into Angular Signal Forms' legacy `.ng-touched` / `.ng-invalid` /
|
|
6139
|
+
* `.ng-dirty` / `.ng-pristine` / `.ng-untouched` / `.ng-pending` /
|
|
6140
|
+
* `.ng-valid` CSS classes on form-bound elements.
|
|
5383
6141
|
*
|
|
5384
|
-
*
|
|
5385
|
-
*
|
|
6142
|
+
* Wires Angular's `@angular/forms/signals/compat` `NG_STATUS_CLASSES` strategy
|
|
6143
|
+
* via `provideSignalFormsConfig`. Without this feature the modern Signal Forms
|
|
6144
|
+
* class strategy is active, which omits the legacy `ng-*` classes.
|
|
6145
|
+
*
|
|
6146
|
+
* @example Opt in once at the application root
|
|
6147
|
+
* ```typescript
|
|
6148
|
+
* bootstrapApplication(AppComponent, {
|
|
6149
|
+
* providers: [
|
|
6150
|
+
* provideDynamicForm(
|
|
6151
|
+
* ...withMaterialFields(),
|
|
6152
|
+
* withLegacyStatusClasses()
|
|
6153
|
+
* )
|
|
6154
|
+
* ]
|
|
6155
|
+
* });
|
|
6156
|
+
* ```
|
|
6157
|
+
*
|
|
6158
|
+
* @returns A DynamicFormFeature that enables the legacy `ng-*` class strategy
|
|
6159
|
+
*
|
|
6160
|
+
* @public
|
|
5386
6161
|
*/
|
|
5387
|
-
declare
|
|
6162
|
+
declare function withLegacyStatusClasses(): DynamicFormFeature<'legacy-status-classes'>;
|
|
5388
6163
|
|
|
5389
6164
|
/**
|
|
5390
|
-
*
|
|
6165
|
+
* Zero-cost type carrier used in wrapper registrations.
|
|
6166
|
+
*
|
|
6167
|
+
* Returns `undefined` at runtime but is typed as `T`, so TypeScript can
|
|
6168
|
+
* thread a wrapper's config type through `createWrappers(...)` into the
|
|
6169
|
+
* `InferWrapperRegistry<typeof ...>` utility without requiring users to
|
|
6170
|
+
* hand-write the augmentation shape.
|
|
6171
|
+
*
|
|
6172
|
+
* @example
|
|
6173
|
+
* ```typescript
|
|
6174
|
+
* const wrappers = createWrappers(
|
|
6175
|
+
* {
|
|
6176
|
+
* wrapperName: 'section',
|
|
6177
|
+
* loadComponent: () => import('./section-wrapper'),
|
|
6178
|
+
* props: wrapperProps<SectionWrapper>(),
|
|
6179
|
+
* },
|
|
6180
|
+
* );
|
|
6181
|
+
*
|
|
6182
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
6183
|
+
* interface FieldRegistryWrappers extends InferWrapperRegistry<typeof wrappers> {}
|
|
6184
|
+
* }
|
|
6185
|
+
* ```
|
|
5391
6186
|
*/
|
|
5392
|
-
declare
|
|
5393
|
-
private readonly prefix;
|
|
5394
|
-
debug(message: string, ...args: unknown[]): void;
|
|
5395
|
-
info(message: string, ...args: unknown[]): void;
|
|
5396
|
-
warn(message: string, ...args: unknown[]): void;
|
|
5397
|
-
error(message: string, ...args: unknown[]): void;
|
|
5398
|
-
}
|
|
6187
|
+
declare function wrapperProps<T>(): T;
|
|
5399
6188
|
|
|
5400
6189
|
/**
|
|
5401
|
-
*
|
|
5402
|
-
*
|
|
6190
|
+
* Input shape passed to a wrapper component via the `fieldInputs` input.
|
|
6191
|
+
*
|
|
6192
|
+
* Carries the wrapped field's mapper outputs plus an optional `field`
|
|
6193
|
+
* read-only view. Wrappers reached through a container path (which has
|
|
6194
|
+
* no FieldTree of its own) receive `fieldInputs === undefined`, so any
|
|
6195
|
+
* wrapper that reads `fieldInputs.field` must guard for it.
|
|
6196
|
+
*
|
|
6197
|
+
* Mappers must emit new rawInputs objects per tick rather than mutating
|
|
6198
|
+
* the previous one — this bag is a shallow spread, so mutations to shared
|
|
6199
|
+
* nested values leak to downstream wrappers.
|
|
5403
6200
|
*/
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
6201
|
+
interface WrapperFieldInputs {
|
|
6202
|
+
readonly key: string;
|
|
6203
|
+
/** Field-type discriminant (mirrors `FieldDef.type`) — useful for kind-aware addons. */
|
|
6204
|
+
readonly type?: string;
|
|
6205
|
+
readonly label?: string;
|
|
6206
|
+
readonly placeholder?: string;
|
|
6207
|
+
readonly className?: string;
|
|
6208
|
+
readonly props?: Record<string, unknown>;
|
|
6209
|
+
readonly validationMessages?: Record<string, string>;
|
|
6210
|
+
readonly defaultValidationMessages?: Record<string, string>;
|
|
6211
|
+
readonly field?: ReadonlyFieldTree;
|
|
6212
|
+
/**
|
|
6213
|
+
* Write a value into the wrapped field's tree. Provided by `buildFieldInputs`
|
|
6214
|
+
* when a `FieldTree` is present. Addons (e.g., `prime-button` presets) use this
|
|
6215
|
+
* to mutate the host field; wrappers should treat the field as read-only.
|
|
6216
|
+
*/
|
|
6217
|
+
readonly setValue?: (next: unknown) => void;
|
|
6218
|
+
readonly [key: string]: unknown;
|
|
5409
6219
|
}
|
|
5410
6220
|
|
|
5411
6221
|
/**
|
|
5412
|
-
*
|
|
6222
|
+
* Dispatcher component that renders an addon by looking up its `kind` in
|
|
6223
|
+
* `ADDON_KIND_REGISTRY` and instantiating the registered component.
|
|
5413
6224
|
*
|
|
5414
|
-
*
|
|
5415
|
-
* the current form value in the `formValue` property. This is useful for event handlers
|
|
5416
|
-
* that need access to the complete form state at the time of the event.
|
|
6225
|
+
* Used by every adapter's field component to render slot content:
|
|
5417
6226
|
*
|
|
5418
|
-
*
|
|
5419
|
-
*
|
|
5420
|
-
*
|
|
5421
|
-
*
|
|
5422
|
-
* withEventFormValue()
|
|
5423
|
-
* )
|
|
6227
|
+
* ```html
|
|
6228
|
+
* \@for (a of addonsAt('prefix'); track $index) {
|
|
6229
|
+
* <df-addon-slot [addon]="a" />
|
|
6230
|
+
* }
|
|
5424
6231
|
* ```
|
|
5425
6232
|
*
|
|
5426
|
-
*
|
|
5427
|
-
*
|
|
5428
|
-
*
|
|
5429
|
-
*
|
|
5430
|
-
*
|
|
5431
|
-
*
|
|
5432
|
-
*
|
|
6233
|
+
* Behaviour:
|
|
6234
|
+
* - Resolves and caches the kind's component asynchronously on first render.
|
|
6235
|
+
* - Forwards the `slot` HTML attribute on the host so Ionic shadow-DOM
|
|
6236
|
+
* projection works (`<ion-input>` projects children with `slot="start"`
|
|
6237
|
+
* into its native start slot).
|
|
6238
|
+
* - Honours the addon's reactive `hidden` flag — when `true`, the host is
|
|
6239
|
+
* `display: none` so it occupies no layout but stays in DOM (cheaper than
|
|
6240
|
+
* tearing down the component).
|
|
6241
|
+
* - Forwards `className` to the host element.
|
|
6242
|
+
* - ARIA semantics are owned by individual kind components — decorative
|
|
6243
|
+
* kinds (icons, text) set `aria-hidden="true"` on themselves; interactive
|
|
6244
|
+
* kinds (buttons) handle their own `aria-label`.
|
|
6245
|
+
*
|
|
6246
|
+
* If the kind cannot be resolved (registry miss, load failure), the
|
|
6247
|
+
* dispatcher logs a warning and renders nothing — never throws. The
|
|
6248
|
+
* runtime addon validator should have caught unknown kinds at config init,
|
|
6249
|
+
* but this provides a defence-in-depth fallback for misconfigured registries.
|
|
6250
|
+
*/
|
|
6251
|
+
declare class DfAddonSlot {
|
|
6252
|
+
private readonly registry;
|
|
6253
|
+
private readonly logger;
|
|
6254
|
+
private readonly hostInjector;
|
|
6255
|
+
readonly addon: _angular_core.InputSignal<AnyAddon>;
|
|
6256
|
+
/**
|
|
6257
|
+
* Optional read-only view of the host field's mapped inputs — same shape
|
|
6258
|
+
* wrappers receive (`field?: ReadonlyFieldTree`, `key`, `props`, etc.).
|
|
6259
|
+
* Forwarded to kind components so they can read field state without
|
|
6260
|
+
* re-injecting `FIELD_SIGNAL_CONTEXT` and rebuilding context themselves.
|
|
6261
|
+
*
|
|
6262
|
+
* `undefined` when the addon is rendered outside a field (rare).
|
|
6263
|
+
*/
|
|
6264
|
+
readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
|
|
6265
|
+
/**
|
|
6266
|
+
* Pre-resolved `hidden` signal supplied by the host field. When provided,
|
|
6267
|
+
* the dispatcher reads this instead of re-resolving `addon.hidden` —
|
|
6268
|
+
* lets the host (e.g., `prime-input`) share a single subscription per
|
|
6269
|
+
* Observable-typed `hidden` between its own visibility filter and the
|
|
6270
|
+
* slot's `[style.display]` binding.
|
|
6271
|
+
*/
|
|
6272
|
+
readonly hidden: _angular_core.InputSignal<Signal<boolean> | undefined>;
|
|
6273
|
+
/** `slot` HTML attribute forwarded to host — needed for Ionic shadow projection. */
|
|
6274
|
+
protected readonly slotAttr: Signal<_ng_forge_dynamic_forms.AddonSlot>;
|
|
6275
|
+
protected readonly className: Signal<string | null>;
|
|
6276
|
+
/**
|
|
6277
|
+
* Locally-resolved `hidden` signal — always reflects `addon.hidden`
|
|
6278
|
+
* regardless of whether the host supplied a pre-resolved signal.
|
|
6279
|
+
* Populated via `explicitEffect` so `resolveDynamicValue` (which may call
|
|
6280
|
+
* `toSignal` for Observable-typed values) does NOT run inside a reactive
|
|
6281
|
+
* context (NG0602). The WeakMap caches per `hidden`-value identity, so
|
|
6282
|
+
* swapping `addon` inputs that share the same Observable reuses the
|
|
6283
|
+
* subscription instead of leaking a fresh one per swap.
|
|
6284
|
+
*
|
|
6285
|
+
* Resolved unconditionally (not gated on host `hidden()` presence) so a
|
|
6286
|
+
* transition from `host hidden = Signal` → `undefined` doesn't expose a
|
|
6287
|
+
* brief window where neither value is current — the upstream effect
|
|
6288
|
+
* re-runs eventually, but the computed read can happen in between.
|
|
6289
|
+
*/
|
|
6290
|
+
private readonly _hiddenByValue;
|
|
6291
|
+
private readonly _resolvedHidden;
|
|
6292
|
+
/**
|
|
6293
|
+
* `hidden` resolved from `DynamicValue<boolean>` to a flat `Signal<boolean>`.
|
|
6294
|
+
* Prefers the host-supplied signal when present (avoids duplicate `toSignal`
|
|
6295
|
+
* subscriptions for Observable-typed `hidden`); falls back to the locally-
|
|
6296
|
+
* resolved signal, which is always populated by the addon-tracking effect.
|
|
6297
|
+
*/
|
|
6298
|
+
protected readonly isHidden: Signal<boolean>;
|
|
6299
|
+
/**
|
|
6300
|
+
* Latest async-loaded `{ kind, component }` pair. Tagging the result with
|
|
6301
|
+
* its kind lets `resolvedComponent` filter stale loads structurally — no
|
|
6302
|
+
* monotonic token needed. When `addon.kind` changes mid-load, the prior
|
|
6303
|
+
* load still completes and writes here, but the computed ignores it
|
|
6304
|
+
* because the recorded kind no longer matches the current one.
|
|
6305
|
+
*/
|
|
6306
|
+
private readonly asyncLoaded;
|
|
6307
|
+
/**
|
|
6308
|
+
* Resolved kind component — composed declaratively from two sources of
|
|
6309
|
+
* truth: the registry's synchronous cache (warm hits, e.g., a second
|
|
6310
|
+
* `<df-addon-slot>` for an already-loaded kind) and the kind-tagged async
|
|
6311
|
+
* loader result. Reading `addon().kind` first makes the computed react to
|
|
6312
|
+
* addon swaps and naturally invalidate stale async-load results.
|
|
6313
|
+
*/
|
|
6314
|
+
protected readonly resolvedComponent: Signal<Type<unknown> | undefined>;
|
|
6315
|
+
/** Inputs passed to the kind component — addon plus the wrapper-style host bag. */
|
|
6316
|
+
protected readonly kindInputs: Signal<{
|
|
6317
|
+
addon: AnyAddon;
|
|
6318
|
+
fieldInputs: WrapperFieldInputs | undefined;
|
|
6319
|
+
}>;
|
|
6320
|
+
constructor();
|
|
6321
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DfAddonSlot, never>;
|
|
6322
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DfAddonSlot, "df-addon-slot", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
6323
|
+
}
|
|
6324
|
+
|
|
6325
|
+
/**
|
|
6326
|
+
* Marks an `<ng-template>` projected into `<df-dynamic-form>` content as
|
|
6327
|
+
* available to template addons by name.
|
|
6328
|
+
*
|
|
6329
|
+
* The host form collects all `DfTemplate` instances via `contentChildren`
|
|
6330
|
+
* and exposes them through {@link DF_FIELD_TEMPLATES}, where the template
|
|
6331
|
+
* addon kind looks them up by `templateKey` at render time.
|
|
6332
|
+
*
|
|
6333
|
+
* @example
|
|
6334
|
+
* ```html
|
|
6335
|
+
* <df-dynamic-form [config]="config">
|
|
6336
|
+
* <ng-template dfTemplate="searchIcon" let-field>
|
|
6337
|
+
* <my-icon [field]="field" />
|
|
6338
|
+
* </ng-template>
|
|
6339
|
+
* </df-dynamic-form>
|
|
5433
6340
|
* ```
|
|
5434
6341
|
*
|
|
5435
|
-
*
|
|
5436
|
-
* ```
|
|
5437
|
-
*
|
|
5438
|
-
* fields: [...],
|
|
5439
|
-
* options: { emitFormValueOnEvents: false }
|
|
5440
|
-
* };
|
|
6342
|
+
* In the field config:
|
|
6343
|
+
* ```ts
|
|
6344
|
+
* { slot: 'prefix', kind: 'template', templateKey: 'searchIcon' }
|
|
5441
6345
|
* ```
|
|
6346
|
+
*/
|
|
6347
|
+
declare class DfTemplate {
|
|
6348
|
+
/** Name this template registers under — referenced from `TemplateAddon.templateKey`. */
|
|
6349
|
+
readonly dfTemplate: _angular_core.InputSignal<string>;
|
|
6350
|
+
/** The wrapped template, captured for registration and `NgTemplateOutlet` rendering. */
|
|
6351
|
+
readonly templateRef: TemplateRef<unknown>;
|
|
6352
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DfTemplate, never>;
|
|
6353
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<DfTemplate, "ng-template[dfTemplate]", ["dfTemplate"], { "dfTemplate": { "alias": "dfTemplate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
6354
|
+
}
|
|
6355
|
+
|
|
6356
|
+
/**
|
|
6357
|
+
* Renderer for the universal `text` addon kind.
|
|
5442
6358
|
*
|
|
5443
|
-
*
|
|
5444
|
-
*
|
|
5445
|
-
*
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
6359
|
+
* Renders the addon's `text` (a `DynamicText`) inside a span. Decorative —
|
|
6360
|
+
* sets `aria-hidden="true"` on the host so screen readers skip it; users
|
|
6361
|
+
* who need announcement should use a `*-button` kind with `ariaLabel` instead.
|
|
6362
|
+
*/
|
|
6363
|
+
declare class TextAddonComponent {
|
|
6364
|
+
readonly addon: _angular_core.InputSignal<TextAddon>;
|
|
6365
|
+
/** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */
|
|
6366
|
+
readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
|
|
6367
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TextAddonComponent, never>;
|
|
6368
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TextAddonComponent, "df-text-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
6369
|
+
}
|
|
6370
|
+
|
|
6371
|
+
/**
|
|
6372
|
+
* Renderer for the universal `template` addon kind.
|
|
5450
6373
|
*
|
|
5451
|
-
*
|
|
6374
|
+
* Resolves the addon's `templateKey` against {@link DF_FIELD_TEMPLATES}
|
|
6375
|
+
* (populated by `<df-dynamic-form>` from `<ng-template dfTemplate="...">`
|
|
6376
|
+
* children) and renders via `NgTemplateOutlet`. The wrapper-style host bag
|
|
6377
|
+
* (`fieldInputs`) is forwarded as the template's implicit context — author
|
|
6378
|
+
* the template as `<ng-template dfTemplate="..." let-fi>{{ fi.key }}</ng-template>`.
|
|
5452
6379
|
*
|
|
5453
|
-
*
|
|
6380
|
+
* If the key is unresolved, logs a warning and renders nothing — keeps the
|
|
6381
|
+
* form alive when a backend references a template the FE has not registered.
|
|
5454
6382
|
*/
|
|
5455
|
-
declare
|
|
6383
|
+
declare class TemplateAddonComponent {
|
|
6384
|
+
private readonly templates;
|
|
6385
|
+
private readonly logger;
|
|
6386
|
+
readonly addon: _angular_core.InputSignal<TemplateAddon>;
|
|
6387
|
+
/** Forwarded by `df-addon-slot`; surfaced to the template as its implicit `$implicit` context. */
|
|
6388
|
+
readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
|
|
6389
|
+
protected readonly template: _angular_core.Signal<_angular_core.TemplateRef<unknown> | null>;
|
|
6390
|
+
/** Implicit context payload — template authors bind via `let-fi`. */
|
|
6391
|
+
protected readonly outletContext: _angular_core.Signal<{
|
|
6392
|
+
$implicit: WrapperFieldInputs | undefined;
|
|
6393
|
+
}>;
|
|
6394
|
+
constructor();
|
|
6395
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TemplateAddonComponent, never>;
|
|
6396
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TemplateAddonComponent, "df-template-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
6397
|
+
}
|
|
5456
6398
|
|
|
5457
6399
|
/**
|
|
5458
|
-
*
|
|
5459
|
-
* based on their reactive state (hidden, disabled, readonly).
|
|
6400
|
+
* Renderer for the universal `component` addon kind.
|
|
5460
6401
|
*
|
|
5461
|
-
*
|
|
5462
|
-
*
|
|
6402
|
+
* Loads the user-supplied component lazily (`addon.component()`) and renders
|
|
6403
|
+
* it via `NgComponentOutlet` with `addon.inputs` forwarded as input bindings.
|
|
6404
|
+
* The wrapper-style `fieldInputs` bag is not propagated — user components
|
|
6405
|
+
* receive only what `addon.inputs` declares. Authors that need field state
|
|
6406
|
+
* should switch to the `template` kind or build a wrapper.
|
|
5463
6407
|
*
|
|
5464
|
-
* @
|
|
6408
|
+
* @codeOnly The `component` loader is a function; this kind is dropped in
|
|
6409
|
+
* lenient validation when the config originated from JSON.
|
|
5465
6410
|
*/
|
|
5466
|
-
|
|
6411
|
+
declare class ComponentAddonComponent {
|
|
6412
|
+
private readonly logger;
|
|
6413
|
+
readonly addon: _angular_core.InputSignal<ComponentAddon>;
|
|
6414
|
+
/** Accepted for contract uniformity — `NgComponentOutlet` setInput is strict; every kind must declare it. */
|
|
6415
|
+
readonly fieldInputs: _angular_core.InputSignal<WrapperFieldInputs | undefined>;
|
|
6416
|
+
protected readonly inputs: _angular_core.Signal<Record<string, unknown>>;
|
|
6417
|
+
/**
|
|
6418
|
+
* Latest async-loaded `{ addon, component }` pair. Tagging the result with
|
|
6419
|
+
* its source addon lets `resolvedComponent` filter stale loads structurally
|
|
6420
|
+
* — same kind-tagging pattern `DfAddonSlot` uses. When `addon` swaps
|
|
6421
|
+
* mid-load, the prior loader still completes and writes here, but the
|
|
6422
|
+
* computed ignores it because the recorded addon no longer matches the
|
|
6423
|
+
* current one.
|
|
6424
|
+
*/
|
|
6425
|
+
private readonly asyncLoaded;
|
|
6426
|
+
protected readonly resolvedComponent: _angular_core.Signal<Type<unknown> | undefined>;
|
|
6427
|
+
constructor();
|
|
6428
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ComponentAddonComponent, never>;
|
|
6429
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ComponentAddonComponent, "df-component-addon", never, { "addon": { "alias": "addon"; "required": true; "isSignal": true; }; "fieldInputs": { "alias": "fieldInputs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
6430
|
+
}
|
|
6431
|
+
|
|
6432
|
+
/**
|
|
6433
|
+
* Optional collaborators a preset may need beyond the base context. Passed
|
|
6434
|
+
* by the button kind component which has access to its own DI scope.
|
|
6435
|
+
*
|
|
6436
|
+
* Adapter input components fill in the collaborators their preset semantics
|
|
6437
|
+
* require:
|
|
6438
|
+
* - `mat-input` / `bs-input` / `prime-input` / `ion-input` populate
|
|
6439
|
+
* `typeOverride` + `fieldValueSetter` + `fieldDefaultValueGetter` +
|
|
6440
|
+
* `baselineType` from their own DI scope.
|
|
6441
|
+
* - Addons rendered outside any input field receive `{ logger }` only and
|
|
6442
|
+
* the input-specific presets warn-and-no-op.
|
|
6443
|
+
*/
|
|
6444
|
+
interface PresetCollaborators {
|
|
6445
|
+
/** Per-field input-type override signal — populated only inside an input field. */
|
|
6446
|
+
readonly typeOverride?: WritableSignal<string | undefined>;
|
|
6447
|
+
/** Writer that pushes a value into the host field's tree. */
|
|
6448
|
+
readonly fieldValueSetter?: (next: unknown) => void;
|
|
5467
6449
|
/**
|
|
5468
|
-
*
|
|
5469
|
-
*
|
|
5470
|
-
*
|
|
5471
|
-
*
|
|
5472
|
-
*
|
|
5473
|
-
* @remarks
|
|
5474
|
-
* This does NOT affect HiddenField (`type: 'hidden'`) — those fields
|
|
5475
|
-
* store values without UI and their `hidden()` state is always `false`.
|
|
6450
|
+
* Read the host field's configured default value (from the form's
|
|
6451
|
+
* `defaultValues` map keyed by `field.key`). Used by the `'reset'`
|
|
6452
|
+
* preset; absent when the addon is rendered outside an active field
|
|
6453
|
+
* context, in which case `'reset'` falls back to clearing.
|
|
5476
6454
|
*/
|
|
5477
|
-
readonly
|
|
6455
|
+
readonly fieldDefaultValueGetter?: () => unknown;
|
|
5478
6456
|
/**
|
|
5479
|
-
*
|
|
5480
|
-
*
|
|
5481
|
-
*
|
|
5482
|
-
*
|
|
6457
|
+
* Baseline configured input type (from `props().type`), read at preset-run
|
|
6458
|
+
* time. Used by `toggle-password-visibility` to refuse to corrupt
|
|
6459
|
+
* `'email'`/`'number'`/etc. inputs into `'password'` when no override is
|
|
6460
|
+
* yet set.
|
|
5483
6461
|
*/
|
|
5484
|
-
readonly
|
|
6462
|
+
readonly baselineType?: () => string | undefined;
|
|
5485
6463
|
/**
|
|
5486
|
-
*
|
|
6464
|
+
* Logger for warnings about presets that can't be fulfilled in this context.
|
|
5487
6465
|
*
|
|
5488
|
-
*
|
|
5489
|
-
*
|
|
6466
|
+
* Passed via collaborators (rather than injected) because `runPresetAction`
|
|
6467
|
+
* is a DI-free pure function shared across adapters — each adapter's
|
|
6468
|
+
* `ADDON_PRESET_HANDLER` factory injects `DynamicFormLogger` itself and
|
|
6469
|
+
* forwards it here. The `[Dynamic Forms]` prefix comes from
|
|
6470
|
+
* `ConsoleLogger`'s implementation, so the final console line is identical
|
|
6471
|
+
* to one logged directly via `inject(DynamicFormLogger)`.
|
|
5490
6472
|
*/
|
|
5491
|
-
readonly
|
|
6473
|
+
readonly logger: Logger;
|
|
6474
|
+
}
|
|
6475
|
+
/**
|
|
6476
|
+
* Apply a built-in preset action against the addon's host field. Shared
|
|
6477
|
+
* across all adapters — each adapter's `ADDON_PRESET_HANDLER` provider
|
|
6478
|
+
* delegates here.
|
|
6479
|
+
*
|
|
6480
|
+
* Presets that require adapter-specific UI mechanics (clipboard, type
|
|
6481
|
+
* override) are best-effort — they no-op with a warning when the necessary
|
|
6482
|
+
* collaborator isn't available (e.g., toggle-password-visibility outside an
|
|
6483
|
+
* input field).
|
|
6484
|
+
*
|
|
6485
|
+
* @param adapterLabel Used in warnings — `'Material'` / `'Bootstrap'` / etc.
|
|
6486
|
+
* @param fieldLabel Used in warnings — `'mat-input'` / `'bs-input'` / etc.
|
|
6487
|
+
*/
|
|
6488
|
+
declare function runPresetAction(preset: AddonActionPreset, ctx: AddonActionContext, collaborators: PresetCollaborators, adapterLabel: string, fieldLabel: string): Promise<void>;
|
|
6489
|
+
|
|
6490
|
+
/**
|
|
6491
|
+
* Cache for resolved addon-kind components.
|
|
6492
|
+
*
|
|
6493
|
+
* Provided per-form by `provideDynamicFormDI()` so two `<df-dynamic-form>`
|
|
6494
|
+
* instances with conflicting `loadComponent` factories for the same kind
|
|
6495
|
+
* never share a stale entry. Has no `providedIn: 'root'` factory — the
|
|
6496
|
+
* registry consumer is always inside a form scope, and a root fallback
|
|
6497
|
+
* would only hide misconfiguration (an SSR cross-request hit if a future
|
|
6498
|
+
* code path forgot to provide it locally).
|
|
6499
|
+
*
|
|
6500
|
+
* Mirrors `COMPONENT_CACHE` (field types) and `WRAPPER_COMPONENT_CACHE`
|
|
6501
|
+
* (wrappers).
|
|
6502
|
+
*
|
|
6503
|
+
* @internal
|
|
6504
|
+
*/
|
|
6505
|
+
declare const ADDON_KIND_COMPONENT_CACHE: InjectionToken<Map<string, Type<unknown>>>;
|
|
6506
|
+
/**
|
|
6507
|
+
* Public shape returned by {@link injectAddonKindRegistry}. Pinned explicitly
|
|
6508
|
+
* so the API extractor doesn't churn between versions when the inner factory
|
|
6509
|
+
* gets refactored.
|
|
6510
|
+
*/
|
|
6511
|
+
interface AddonKindRegistryRef {
|
|
6512
|
+
getKind(kind: string): AddonKindDefinition | undefined;
|
|
6513
|
+
hasKind(kind: string): boolean;
|
|
6514
|
+
getKindNames(): string[];
|
|
6515
|
+
loadKindComponent(kind: string): Promise<Type<unknown>>;
|
|
6516
|
+
getLoadedKindComponent(kind: string): Type<unknown> | undefined;
|
|
6517
|
+
readonly raw: ReadonlyMap<string, AddonKindDefinition>;
|
|
5492
6518
|
}
|
|
5493
6519
|
/**
|
|
5494
|
-
*
|
|
5495
|
-
*
|
|
6520
|
+
* Injection function for accessing the addon kind registry.
|
|
6521
|
+
*
|
|
6522
|
+
* Usage parallels {@link injectFieldRegistry}: lookup, lazy load, cache.
|
|
6523
|
+
* Must be called within an injection context.
|
|
6524
|
+
*
|
|
6525
|
+
* @example
|
|
6526
|
+
* ```typescript
|
|
6527
|
+
* const addonKinds = injectAddonKindRegistry();
|
|
6528
|
+
* const Component = await addonKinds.loadKindComponent('prime-icon');
|
|
6529
|
+
* ```
|
|
6530
|
+
*/
|
|
6531
|
+
declare function injectAddonKindRegistry(): AddonKindRegistryRef;
|
|
6532
|
+
|
|
6533
|
+
/**
|
|
6534
|
+
* One entry per field type that declares addon support.
|
|
5496
6535
|
*
|
|
5497
|
-
*
|
|
6536
|
+
* `name` is the field-type discriminant; `slots` and `allowedKinds` mirror
|
|
6537
|
+
* the `FieldTypeDefinition.addons` registration.
|
|
5498
6538
|
*/
|
|
5499
|
-
|
|
5500
|
-
|
|
6539
|
+
interface FieldAddonSupportEntry {
|
|
6540
|
+
readonly name: string;
|
|
6541
|
+
readonly slots: FieldAddonSupport['slots'];
|
|
6542
|
+
readonly allowedKinds: FieldAddonSupport['allowedKinds'];
|
|
6543
|
+
}
|
|
5501
6544
|
/**
|
|
5502
|
-
*
|
|
6545
|
+
* Walk `FIELD_REGISTRY` and return every field type that opted into addons
|
|
6546
|
+
* (i.e., declared `addons` on its `FieldTypeDefinition`).
|
|
5503
6547
|
*
|
|
5504
|
-
*
|
|
5505
|
-
*
|
|
5506
|
-
*
|
|
5507
|
-
* `entity`) — fields retain their values internally.
|
|
6548
|
+
* Useful for tooling — admin UIs surfacing "which fields can carry addons?",
|
|
6549
|
+
* docs generators, MCP server cross-checks. Field types without an `addons`
|
|
6550
|
+
* registration ("Tier 3" — toggle, checkbox, radio, slider) are excluded.
|
|
5508
6551
|
*
|
|
5509
|
-
*
|
|
6552
|
+
* Must be called within an injection context.
|
|
6553
|
+
*
|
|
6554
|
+
* @example
|
|
5510
6555
|
* ```typescript
|
|
5511
|
-
*
|
|
5512
|
-
*
|
|
5513
|
-
*
|
|
5514
|
-
*
|
|
6556
|
+
* @Component({ ... })
|
|
6557
|
+
* class FormBuilder {
|
|
6558
|
+
* protected readonly addonable = injectFieldsSupportingAddons();
|
|
6559
|
+
*
|
|
6560
|
+
* constructor() {
|
|
6561
|
+
* // -> [{ name: 'prime-input', slots: ['prefix', 'suffix'], allowedKinds: [...] }, ...]
|
|
6562
|
+
* }
|
|
6563
|
+
* }
|
|
5515
6564
|
* ```
|
|
6565
|
+
*/
|
|
6566
|
+
declare function injectFieldsSupportingAddons(): FieldAddonSupportEntry[];
|
|
6567
|
+
|
|
6568
|
+
/**
|
|
6569
|
+
* Normalises a {@link DynamicValue} into a `Signal<T>`.
|
|
5516
6570
|
*
|
|
5517
|
-
*
|
|
6571
|
+
* Accepts a static value, a `Signal<T>`, or an `Observable<T>`. The result
|
|
6572
|
+
* is a `Signal<T>` that reactively reflects the current value, suitable
|
|
6573
|
+
* for direct use in Angular templates.
|
|
6574
|
+
*
|
|
6575
|
+
* Static values yield a `computed` that always returns the same constant —
|
|
6576
|
+
* preferable to wrapping in `signal()` because the computed never causes
|
|
6577
|
+
* change-detection invalidation.
|
|
6578
|
+
*
|
|
6579
|
+
* Pass an `injector` when calling outside an Angular injection context
|
|
6580
|
+
* (e.g., from inside a `computed`). `toSignal` needs a `DestroyRef` to
|
|
6581
|
+
* unsubscribe — without an injector it falls back to `inject(DestroyRef)`,
|
|
6582
|
+
* which throws when called outside injection context.
|
|
6583
|
+
*
|
|
6584
|
+
* @example
|
|
5518
6585
|
* ```typescript
|
|
5519
|
-
*
|
|
5520
|
-
*
|
|
5521
|
-
* withValueExclusionDefaults({ excludeValueIfReadonly: false })
|
|
5522
|
-
* )
|
|
6586
|
+
* const isHidden = resolveDynamicValue(addon().hidden, false);
|
|
6587
|
+
* // template: \@if (isHidden()) { ... }
|
|
5523
6588
|
* ```
|
|
6589
|
+
*/
|
|
6590
|
+
declare function resolveDynamicValue<T>(value: DynamicValue<T> | undefined, fallback: T, injector?: Injector): Signal<T>;
|
|
6591
|
+
|
|
6592
|
+
/**
|
|
6593
|
+
* Register a custom addon kind with the form.
|
|
5524
6594
|
*
|
|
5525
|
-
*
|
|
6595
|
+
* The provided definition is added to `ADDON_KIND_REGISTRY` at form
|
|
6596
|
+
* initialisation, alongside the built-in `text` / `template` / `component`
|
|
6597
|
+
* kinds and any kinds contributed by adapter feature helpers
|
|
6598
|
+
* (`withPrimeNGAddons()` etc.).
|
|
6599
|
+
*
|
|
6600
|
+
* @example
|
|
5526
6601
|
* ```typescript
|
|
5527
6602
|
* provideDynamicForm(
|
|
5528
6603
|
* ...withMaterialFields(),
|
|
5529
|
-
*
|
|
5530
|
-
*
|
|
5531
|
-
*
|
|
5532
|
-
*
|
|
5533
|
-
*
|
|
5534
|
-
* )
|
|
6604
|
+
* withCustomAddon({
|
|
6605
|
+
* kind: 'lucide-icon',
|
|
6606
|
+
* // Match how field types register: a default-exported component lets
|
|
6607
|
+
* // `loadComponent` return the import promise directly.
|
|
6608
|
+
* loadComponent: () => import('./lucide-icon-addon.component'),
|
|
6609
|
+
* validate: (addon) => {
|
|
6610
|
+
* if (typeof addon.icon !== 'string') {
|
|
6611
|
+
* throw new Error('lucide-icon: icon string is required');
|
|
6612
|
+
* }
|
|
6613
|
+
* },
|
|
6614
|
+
* }),
|
|
6615
|
+
* );
|
|
5535
6616
|
* ```
|
|
5536
6617
|
*
|
|
5537
|
-
*
|
|
5538
|
-
*
|
|
5539
|
-
* 1. Per-field `excludeValueIf*` on `FieldDef` — wins for that field
|
|
5540
|
-
* 2. Per-form `excludeValueIf*` on `FormOptions` — wins for all fields in that form
|
|
5541
|
-
* 3. Global `withValueExclusionDefaults()` — baseline default
|
|
5542
|
-
* 4. No global feature — uses token default (all enabled)
|
|
5543
|
-
*
|
|
5544
|
-
* @param config - Partial override of exclusion rules. Unspecified properties default to `true`.
|
|
5545
|
-
* @returns A DynamicFormFeature that configures value exclusion defaults
|
|
5546
|
-
*
|
|
5547
|
-
* @public
|
|
6618
|
+
* Multiple `withCustomAddon(...)` calls are supported; later registrations
|
|
6619
|
+
* for the same kind override earlier ones (with a warning logged).
|
|
5548
6620
|
*/
|
|
5549
|
-
declare function
|
|
6621
|
+
declare function withCustomAddon<T extends BaseAddon>(definition: AddonKindDefinition<T>): DynamicFormFeature<'addons'>;
|
|
5550
6622
|
|
|
5551
6623
|
/**
|
|
5552
|
-
*
|
|
5553
|
-
*
|
|
5554
|
-
* Currently controls whether hidden fields are validated. Resolved through a
|
|
5555
|
-
* tree-aware hierarchy: per-field overrides inherit down to descendants, with
|
|
5556
|
-
* per-form `FormOptions` and global `withValidationExecutionDefaults()` providing
|
|
5557
|
-
* the root inherited value.
|
|
6624
|
+
* Handler signature for user-registered addon actions.
|
|
5558
6625
|
*
|
|
5559
|
-
*
|
|
6626
|
+
* Backends reference handlers by name via `actionRef: 'name'` on button-style
|
|
6627
|
+
* addons; the dispatcher invokes the registered function with the addon's
|
|
6628
|
+
* action context.
|
|
5560
6629
|
*/
|
|
5561
|
-
|
|
5562
|
-
/**
|
|
5563
|
-
* Whether validators run while a field is hidden (statically, via `hidden`
|
|
5564
|
-
* logic, or because any ancestor is hidden).
|
|
5565
|
-
*
|
|
5566
|
-
* When `false`, all validators on a hidden field are skipped — the field is
|
|
5567
|
-
* effectively inert until shown. State logic (hidden/disabled/readonly) and
|
|
5568
|
-
* value derivations continue to apply.
|
|
5569
|
-
*/
|
|
5570
|
-
readonly validateWhenHidden?: boolean;
|
|
5571
|
-
}
|
|
6630
|
+
type AddonActionHandler<TValue = unknown> = (ctx: AddonActionContext<TValue>) => void;
|
|
5572
6631
|
/**
|
|
5573
|
-
*
|
|
6632
|
+
* Multi-provider token populated by `provideAddonActions({...})` calls.
|
|
6633
|
+
* `ADDON_ACTION_REGISTRY` aggregates these into a single name → handler map.
|
|
5574
6634
|
*
|
|
5575
|
-
* @
|
|
6635
|
+
* @internal
|
|
5576
6636
|
*/
|
|
5577
|
-
|
|
6637
|
+
declare const ADDON_ACTION_HANDLERS: InjectionToken<readonly Record<string, AddonActionHandler<unknown>>[]>;
|
|
6638
|
+
/**
|
|
6639
|
+
* Form-scoped name → handler map. Read by adapter button kinds at click
|
|
6640
|
+
* time for `actionRef: 'name'` lookups. Provided at form scope (not root)
|
|
6641
|
+
* because `ADDON_ACTION_HANDLERS` is form-scoped via `provideAddonActions`.
|
|
6642
|
+
*/
|
|
6643
|
+
declare const ADDON_ACTION_REGISTRY: InjectionToken<ReadonlyMap<string, AddonActionHandler<unknown>>>;
|
|
5578
6644
|
|
|
5579
6645
|
/**
|
|
5580
|
-
*
|
|
5581
|
-
*
|
|
6646
|
+
* Typed feature returned by {@link provideAddonActions}. Carries the
|
|
6647
|
+
* registered handler keys as a phantom type so consumers can derive the
|
|
6648
|
+
* `DynamicFormActionRegistry` augmentation in one line instead of hand-typing
|
|
6649
|
+
* every key.
|
|
5582
6650
|
*
|
|
5583
|
-
*
|
|
5584
|
-
*
|
|
5585
|
-
|
|
6651
|
+
* Phantom field is `__handlerKeys` (the leading underscores signal "internal,
|
|
6652
|
+
* type-only — not for runtime access").
|
|
6653
|
+
*/
|
|
6654
|
+
type AddonActionsFeature<K extends string = string> = DynamicFormFeature<'addon-actions'> & {
|
|
6655
|
+
/** @internal Phantom field carrying the registered keys; never read at runtime. */
|
|
6656
|
+
readonly __handlerKeys?: K;
|
|
6657
|
+
};
|
|
6658
|
+
/**
|
|
6659
|
+
* Register named action handlers reachable via JSON-driven addon configs.
|
|
5586
6660
|
*
|
|
5587
|
-
*
|
|
5588
|
-
*
|
|
5589
|
-
*
|
|
5590
|
-
*
|
|
5591
|
-
*
|
|
6661
|
+
* Once registered, a backend can ship
|
|
6662
|
+
* `{ kind: 'prime-button', actionRef: 'openProfile' }` and the FE will invoke
|
|
6663
|
+
* the corresponding handler at click time.
|
|
6664
|
+
*
|
|
6665
|
+
* Define handlers once and augment the registry from the same object:
|
|
5592
6666
|
*
|
|
5593
|
-
* @example Restore legacy validation-on-hidden behavior
|
|
5594
6667
|
* ```typescript
|
|
5595
|
-
*
|
|
5596
|
-
*
|
|
5597
|
-
*
|
|
5598
|
-
* )
|
|
6668
|
+
* export const appActions = provideAddonActions({
|
|
6669
|
+
* openProfile: (ctx) => modalService.open(ProfileModal, { data: ctx.value }),
|
|
6670
|
+
* runWorkflow: (ctx) => workflowService.run(ctx.field.key, ctx.value),
|
|
6671
|
+
* });
|
|
6672
|
+
*
|
|
6673
|
+
* declare module '@ng-forge/dynamic-forms' {
|
|
6674
|
+
* // Pulls the keys straight off `appActions` — no manual list to keep in sync.
|
|
6675
|
+
* interface DynamicFormActionRegistry extends Record<NonNullable<typeof appActions['__handlerKeys']>, true> {}
|
|
6676
|
+
* }
|
|
6677
|
+
*
|
|
6678
|
+
* // Then in your bootstrap:
|
|
6679
|
+
* provideDynamicForm(...withPrimeNGFields(), appActions);
|
|
5599
6680
|
* ```
|
|
5600
6681
|
*
|
|
5601
|
-
*
|
|
5602
|
-
*
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
*
|
|
6682
|
+
* Multiple `provideAddonActions(...)` calls are merged; later names override
|
|
6683
|
+
* earlier ones for the same key.
|
|
6684
|
+
*/
|
|
6685
|
+
declare function provideAddonActions<const H extends Record<string, AddonActionHandler>>(handlers: H): AddonActionsFeature<keyof H & string>;
|
|
6686
|
+
|
|
6687
|
+
/**
|
|
6688
|
+
* Multi-provider token used by `withCustomAddon(...)` features to contribute
|
|
6689
|
+
* addon kind definitions. `provideDynamicForm` aggregates all values into
|
|
6690
|
+
* the form-scoped `ADDON_KIND_REGISTRY` map.
|
|
5608
6691
|
*
|
|
5609
|
-
* @
|
|
5610
|
-
|
|
6692
|
+
* @internal
|
|
6693
|
+
*/
|
|
6694
|
+
declare const ADDON_KIND_DEFINITIONS: InjectionToken<readonly AddonKindDefinition<_ng_forge_dynamic_forms.BaseAddon<_ng_forge_dynamic_forms.AddonSlot>>[]>;
|
|
6695
|
+
|
|
6696
|
+
/**
|
|
6697
|
+
* Reason an addon was dropped during validation.
|
|
5611
6698
|
*
|
|
5612
|
-
*
|
|
6699
|
+
* Each variant carries its own context fields so log messages can be both
|
|
6700
|
+
* actionable (registered kinds enumerated, fix suggestion present) and
|
|
6701
|
+
* machine-readable (admin UIs surfacing per-error guidance).
|
|
5613
6702
|
*/
|
|
5614
|
-
|
|
6703
|
+
type AddonWarning = {
|
|
6704
|
+
type: 'unknown-field-type';
|
|
6705
|
+
fieldKey: string;
|
|
6706
|
+
fieldType: string;
|
|
6707
|
+
} | {
|
|
6708
|
+
type: 'field-type-no-addon-support';
|
|
6709
|
+
fieldKey: string;
|
|
6710
|
+
fieldType: string;
|
|
6711
|
+
} | {
|
|
6712
|
+
type: 'unknown-slot';
|
|
6713
|
+
fieldKey: string;
|
|
6714
|
+
fieldType: string;
|
|
6715
|
+
slot: string;
|
|
6716
|
+
allowedSlots: readonly string[];
|
|
6717
|
+
} | {
|
|
6718
|
+
type: 'unknown-kind';
|
|
6719
|
+
fieldKey: string;
|
|
6720
|
+
kind: string;
|
|
6721
|
+
registeredKinds: readonly string[];
|
|
6722
|
+
} | {
|
|
6723
|
+
type: 'kind-not-allowed';
|
|
6724
|
+
fieldKey: string;
|
|
6725
|
+
fieldType: string;
|
|
6726
|
+
kind: string;
|
|
6727
|
+
allowedKinds: readonly string[];
|
|
6728
|
+
} | {
|
|
6729
|
+
type: 'shape-violation';
|
|
6730
|
+
fieldKey: string;
|
|
6731
|
+
kind: string;
|
|
6732
|
+
reason: string;
|
|
6733
|
+
} | {
|
|
6734
|
+
type: 'code-only-kind-in-json';
|
|
6735
|
+
fieldKey: string;
|
|
6736
|
+
kind: string;
|
|
6737
|
+
} | {
|
|
6738
|
+
type: 'code-only-action-in-json';
|
|
6739
|
+
fieldKey: string;
|
|
6740
|
+
reason: string;
|
|
6741
|
+
};
|
|
6742
|
+
/**
|
|
6743
|
+
* Render an `AddonWarning` to a developer-friendly message.
|
|
6744
|
+
*
|
|
6745
|
+
* Returns the bare message — the `[Dynamic Forms]` prefix is added by the
|
|
6746
|
+
* library's logger (`ConsoleLogger`) and by `DynamicFormError`. Pass the
|
|
6747
|
+
* result of this function directly into `logger.warn(...)` to get the
|
|
6748
|
+
* standard prefixed line; use `logAddonWarnings()` for direct
|
|
6749
|
+
* `console.warn` output (which prefixes manually).
|
|
6750
|
+
*
|
|
6751
|
+
* Messages are designed to be actionable: they enumerate the relevant set
|
|
6752
|
+
* (registered kinds, allowed slots) and suggest a likely fix.
|
|
6753
|
+
*/
|
|
6754
|
+
declare function formatAddonWarning(w: AddonWarning): string;
|
|
5615
6755
|
|
|
5616
6756
|
/**
|
|
5617
|
-
*
|
|
6757
|
+
* Walk a field's addons; return the survivors plus a list of warnings for
|
|
6758
|
+
* anything dropped.
|
|
5618
6759
|
*
|
|
5619
|
-
*
|
|
5620
|
-
*
|
|
5621
|
-
*
|
|
5622
|
-
*
|
|
6760
|
+
* Pure: receives the registries as arguments (so the function is reusable
|
|
6761
|
+
* outside Angular's DI — tests, server-side validation, etc.).
|
|
6762
|
+
*
|
|
6763
|
+
* @param field The field to validate.
|
|
6764
|
+
* @param fieldRegistry Snapshot of `FIELD_REGISTRY` map.
|
|
6765
|
+
* @param kindRegistry Snapshot of `ADDON_KIND_REGISTRY` map.
|
|
6766
|
+
* @param source Whether the config originated from JSON (lenient drop
|
|
6767
|
+
* of code-only kinds) or inline TypeScript.
|
|
6768
|
+
*/
|
|
6769
|
+
declare function validateFieldAddons(field: FieldDef<unknown>, fieldRegistry: ReadonlyMap<string, FieldTypeDefinition>, kindRegistry: ReadonlyMap<string, AddonKindDefinition>, source: 'json' | 'inline'): {
|
|
6770
|
+
addons: AnyAddon[];
|
|
6771
|
+
warnings: AddonWarning[];
|
|
6772
|
+
};
|
|
6773
|
+
/**
|
|
6774
|
+
* Recursively walk a field tree, validating each field's addons. Returns a
|
|
6775
|
+
* sanitized copy of the input field array plus accumulated warnings.
|
|
6776
|
+
*/
|
|
6777
|
+
declare function walkAndValidateAddons(fields: readonly FieldDef<unknown>[], fieldRegistry: ReadonlyMap<string, FieldTypeDefinition>, kindRegistry: ReadonlyMap<string, AddonKindDefinition>, source: 'json' | 'inline'): {
|
|
6778
|
+
fields: FieldDef<unknown>[];
|
|
6779
|
+
warnings: AddonWarning[];
|
|
6780
|
+
};
|
|
6781
|
+
|
|
6782
|
+
/**
|
|
6783
|
+
* Options accepted by {@link sanitizeFormConfig}.
|
|
6784
|
+
*/
|
|
6785
|
+
interface SanitizeFormConfigOptions {
|
|
6786
|
+
/**
|
|
6787
|
+
* Whether the config originated from JSON (server-driven) or inline
|
|
6788
|
+
* TypeScript code.
|
|
6789
|
+
*
|
|
6790
|
+
* - `'inline'` (default): keeps everything; assumes the config is
|
|
6791
|
+
* authored in code and code-only constructs (inline `action`
|
|
6792
|
+
* functions, `component` kind) are intentional. The default avoids
|
|
6793
|
+
* silently stripping inline behaviour during in-process authoring.
|
|
6794
|
+
* - `'json'`: drops code-only addon kinds (`component`, inline
|
|
6795
|
+
* `action: function`) with a warning, since they cannot survive
|
|
6796
|
+
* serialization. Use this when sanitising configs received from a
|
|
6797
|
+
* backend / form-builder UI.
|
|
6798
|
+
*/
|
|
6799
|
+
source?: 'json' | 'inline';
|
|
6800
|
+
}
|
|
6801
|
+
/**
|
|
6802
|
+
* Result of a `sanitizeFormConfig` call.
|
|
6803
|
+
*/
|
|
6804
|
+
interface SanitizedFormConfig {
|
|
6805
|
+
/** Sanitized config — invalid addons stripped from the field tree. */
|
|
6806
|
+
sanitized: FormConfig;
|
|
6807
|
+
/** Structured list of every addon that was dropped, and why. */
|
|
6808
|
+
warnings: readonly AddonWarning[];
|
|
6809
|
+
}
|
|
6810
|
+
/**
|
|
6811
|
+
* Walk a `FormConfig`, validate every field's addons against the active
|
|
6812
|
+
* `FIELD_REGISTRY` and `ADDON_KIND_REGISTRY`, and return a sanitized copy
|
|
6813
|
+
* plus a list of dropped-addon warnings.
|
|
6814
|
+
*
|
|
6815
|
+
* Distinct from the INTERNAL `validateFormConfig` in
|
|
6816
|
+
* `utils/config-validation/config-validator.ts` (which throws on
|
|
6817
|
+
* structural errors like duplicate keys / unknown field types). This
|
|
6818
|
+
* helper is the PUBLIC, lenient addon-shape pass — renamed to
|
|
6819
|
+
* `sanitizeFormConfig` to avoid the name collision.
|
|
6820
|
+
*
|
|
6821
|
+
* Lenient by design: invalid addons are dropped (with warnings) rather than
|
|
6822
|
+
* thrown. The form keeps rendering even when the backend ships an addon the
|
|
6823
|
+
* FE doesn't understand.
|
|
6824
|
+
*
|
|
6825
|
+
* `<df-dynamic-form>` already runs this internally at form init — calling
|
|
6826
|
+
* the public helper AND passing the original config to the form will
|
|
6827
|
+
* double-emit warnings. Use this entry point only when you need the
|
|
6828
|
+
* sanitized config or warning list outside the form (e.g., admin-UI
|
|
6829
|
+
* diagnostics, build-time lints).
|
|
6830
|
+
*
|
|
6831
|
+
* Must be called within an Angular injection context — typically inside
|
|
6832
|
+
* an admin-UI component or a `runInInjectionContext()` block on the server.
|
|
5623
6833
|
*
|
|
5624
6834
|
* @example
|
|
5625
6835
|
* ```typescript
|
|
5626
|
-
*
|
|
5627
|
-
*
|
|
5628
|
-
*
|
|
5629
|
-
*
|
|
5630
|
-
*
|
|
5631
|
-
*
|
|
5632
|
-
*
|
|
5633
|
-
*
|
|
5634
|
-
*
|
|
5635
|
-
* interface FieldRegistryWrappers extends InferWrapperRegistry<typeof wrappers> {}
|
|
6836
|
+
* @Component({ ... })
|
|
6837
|
+
* class AdminFormBuilder {
|
|
6838
|
+
* private readonly check = (cfg: FormConfig) => {
|
|
6839
|
+
* const { sanitized, warnings } = sanitizeFormConfig(cfg, { source: 'json' });
|
|
6840
|
+
* if (warnings.length > 0) {
|
|
6841
|
+
* this.diagnostics.set(warnings);
|
|
6842
|
+
* }
|
|
6843
|
+
* return sanitized;
|
|
6844
|
+
* };
|
|
5636
6845
|
* }
|
|
5637
6846
|
* ```
|
|
5638
6847
|
*/
|
|
5639
|
-
declare function
|
|
6848
|
+
declare function sanitizeFormConfig(config: FormConfig, options?: SanitizeFormConfigOptions): SanitizedFormConfig;
|
|
6849
|
+
/**
|
|
6850
|
+
* Default warning sink. Pass a `DynamicFormLogger` to route through the
|
|
6851
|
+
* form's configured logger (respects `NoopLogger` opt-out); omit it to
|
|
6852
|
+
* fall back to `console.warn` for build-time / admin-UI use cases that
|
|
6853
|
+
* run outside an Angular injection context.
|
|
6854
|
+
*/
|
|
6855
|
+
declare function logAddonWarnings(warnings: readonly AddonWarning[], logger?: Logger): void;
|
|
6856
|
+
/**
|
|
6857
|
+
* DI-free variant of {@link sanitizeFormConfig} for tooling that lives
|
|
6858
|
+
* outside Angular's injector — build-time linters, MCP-side checks, CLI
|
|
6859
|
+
* scripts.
|
|
6860
|
+
*
|
|
6861
|
+
* Caller passes the registries explicitly; the result has the same shape
|
|
6862
|
+
* as the DI-bound version.
|
|
6863
|
+
*/
|
|
6864
|
+
declare function sanitizeFormConfigPure(config: FormConfig, fieldRegistry: ReadonlyMap<string, FieldTypeDefinition>, kindRegistry: ReadonlyMap<string, AddonKindDefinition>, options?: SanitizeFormConfigOptions): SanitizedFormConfig;
|
|
5640
6865
|
|
|
5641
6866
|
interface FieldWithValidation {
|
|
5642
6867
|
readonly required?: boolean;
|
|
@@ -5722,21 +6947,35 @@ interface BaseValueField<TProps, TValue, TMeta extends FieldMeta = FieldMeta, TN
|
|
|
5722
6947
|
nullable?: TNullable;
|
|
5723
6948
|
}
|
|
5724
6949
|
declare function isValueField<TProps, TMeta extends FieldMeta = FieldMeta>(field: FieldDef<TProps, TMeta>): field is BaseValueField<TProps, ValueType, TMeta, boolean>;
|
|
5725
|
-
type ExcludedKeys$1 = 'type' | 'conditionals' | 'value' | 'valueType' | 'nullable' | 'disabled' | 'readonly' | 'hidden' | 'col' | 'minValue' | 'maxValue' | 'step' | 'required' | 'email' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern' | 'validators' | 'logic' | 'derivation' | 'schemas' | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly' | 'validateWhenHidden' | 'wrappers' | 'skipAutoWrappers' | 'skipDefaultWrappers';
|
|
6950
|
+
type ExcludedKeys$1 = 'type' | 'conditionals' | 'value' | 'valueType' | 'nullable' | 'disabled' | 'readonly' | 'hidden' | 'col' | 'minValue' | 'maxValue' | 'step' | 'required' | 'email' | 'min' | 'max' | 'minLength' | 'maxLength' | 'pattern' | 'validators' | 'logic' | 'derivation' | 'schemas' | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly' | 'validateWhenHidden' | 'wrappers' | 'skipAutoWrappers' | 'skipDefaultWrappers' | 'addons';
|
|
5726
6951
|
type ValueFieldComponent<T extends BaseValueField<Record<string, unknown> | unknown, unknown, FieldMeta, boolean>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys$1>>>;
|
|
5727
6952
|
|
|
5728
|
-
interface BaseCheckedField<TProps, TMeta extends FieldMeta = FieldMeta> extends FieldDef<TProps, TMeta>, FieldWithValidation {
|
|
5729
|
-
value?: boolean;
|
|
6953
|
+
interface BaseCheckedField<TProps, TMeta extends FieldMeta = FieldMeta, TNullable extends boolean = false> extends FieldDef<TProps, TMeta>, FieldWithValidation {
|
|
6954
|
+
value?: TNullable extends true ? boolean | null : boolean;
|
|
5730
6955
|
/**
|
|
5731
6956
|
* Placeholder text displayed when the field is empty.
|
|
5732
6957
|
* Supports static strings, Observables, and Signals for dynamic content.
|
|
5733
6958
|
*/
|
|
5734
6959
|
placeholder?: DynamicText;
|
|
5735
6960
|
required?: boolean;
|
|
6961
|
+
/**
|
|
6962
|
+
* Whether the field accepts `null` as a valid value.
|
|
6963
|
+
*
|
|
6964
|
+
* When `true`, `value` may be `null` and an omitted `value` resolves to `null`
|
|
6965
|
+
* (rather than the type-specific empty default of `false`). Orthogonal to `required`.
|
|
6966
|
+
*
|
|
6967
|
+
* The data model is decoupled from the UI: a null value is a legitimate
|
|
6968
|
+
* "undecided" state at the storage / OpenAPI layer. Whether the rendered
|
|
6969
|
+
* checkbox shows an indeterminate visual is controlled separately via
|
|
6970
|
+
* `props.indeterminate` and is not driven by this flag.
|
|
6971
|
+
*
|
|
6972
|
+
* @default false
|
|
6973
|
+
*/
|
|
6974
|
+
nullable?: TNullable;
|
|
5736
6975
|
}
|
|
5737
|
-
declare function isCheckedField<TProps, TMeta extends FieldMeta = FieldMeta>(field: FieldDef<TProps, TMeta>): field is BaseCheckedField<TProps, TMeta>;
|
|
5738
|
-
type ExcludedKeys = 'type' | 'conditionals' | 'value' | 'disabled' | 'readonly' | 'hidden' | 'col' | keyof FieldWithValidation | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly' | 'validateWhenHidden' | 'wrappers' | 'skipAutoWrappers' | 'skipDefaultWrappers';
|
|
5739
|
-
type CheckedFieldComponent<T extends BaseCheckedField<Record<string, unknown> | unknown>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys>>>;
|
|
6976
|
+
declare function isCheckedField<TProps, TMeta extends FieldMeta = FieldMeta>(field: FieldDef<TProps, TMeta>): field is BaseCheckedField<TProps, TMeta, boolean>;
|
|
6977
|
+
type ExcludedKeys = 'type' | 'conditionals' | 'value' | 'nullable' | 'disabled' | 'readonly' | 'hidden' | 'col' | keyof FieldWithValidation | 'excludeValueIfHidden' | 'excludeValueIfDisabled' | 'excludeValueIfReadonly' | 'validateWhenHidden' | 'wrappers' | 'skipAutoWrappers' | 'skipDefaultWrappers' | 'addons';
|
|
6978
|
+
type CheckedFieldComponent<T extends BaseCheckedField<Record<string, unknown> | unknown, FieldMeta, boolean>> = Prettify<WithInputSignals<Omit<T, ExcludedKeys>>>;
|
|
5740
6979
|
|
|
5741
6980
|
declare function applyValidator(config: ValidatorConfig, fieldPath: SchemaPath<any> | SchemaPathTree<any>): void;
|
|
5742
6981
|
declare function applyValidators(configs: ValidatorConfig[], fieldPath: SchemaPath<any> | SchemaPathTree<any>): void;
|
|
@@ -6852,71 +8091,6 @@ declare class ContainerFieldComponent {
|
|
|
6852
8091
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContainerFieldComponent, "div[container-field]", never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "key": { "alias": "key"; "required": true; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
6853
8092
|
}
|
|
6854
8093
|
|
|
6855
|
-
/**
|
|
6856
|
-
* Type representing a FieldTree for an array.
|
|
6857
|
-
* Extends FieldTree to add numeric indexing for accessing item FieldTrees.
|
|
6858
|
-
*/
|
|
6859
|
-
type ArrayFieldTree<T> = FieldTree<T[]> & {
|
|
6860
|
-
readonly [index: number]: FieldTree<T> | undefined;
|
|
6861
|
-
};
|
|
6862
|
-
/**
|
|
6863
|
-
* Get the length of an array FieldTree.
|
|
6864
|
-
*/
|
|
6865
|
-
declare function getArrayLength<T>(arrayFieldTree: ArrayFieldTree<T>): number;
|
|
6866
|
-
/**
|
|
6867
|
-
* Read-only view of a single field's observable state.
|
|
6868
|
-
*
|
|
6869
|
-
* Whitelisted read signals copied from Angular Signal Forms' `FieldState` so wrappers
|
|
6870
|
-
* can observe a field without being able to mutate it. New write-capable members
|
|
6871
|
-
* added in future Angular versions are excluded by default (the `Pick` list stays
|
|
6872
|
-
* the source of truth).
|
|
6873
|
-
*
|
|
6874
|
-
* `value` is narrowed from `WritableSignal<TValue>` to `Signal<TValue>` so consumers
|
|
6875
|
-
* cannot write through it.
|
|
6876
|
-
*/
|
|
6877
|
-
interface ReadonlyFieldTree<TValue = unknown> {
|
|
6878
|
-
readonly value: Signal<TValue>;
|
|
6879
|
-
readonly valid: Signal<boolean>;
|
|
6880
|
-
readonly invalid: Signal<boolean>;
|
|
6881
|
-
readonly touched: Signal<boolean>;
|
|
6882
|
-
readonly dirty: Signal<boolean>;
|
|
6883
|
-
readonly required: Signal<boolean>;
|
|
6884
|
-
readonly disabled: Signal<boolean>;
|
|
6885
|
-
readonly hidden: Signal<boolean>;
|
|
6886
|
-
readonly errors: Signal<readonly unknown[]>;
|
|
6887
|
-
}
|
|
6888
|
-
/**
|
|
6889
|
-
* Build a `ReadonlyFieldTree` by extracting the whitelisted read signals from a
|
|
6890
|
-
* Signal Forms `FieldTree`. Returns a fresh plain object — no casting, no proxying,
|
|
6891
|
-
* so consumers only see the narrow surface and Angular's `WritableSignal` capability
|
|
6892
|
-
* on `value` is hidden.
|
|
6893
|
-
*/
|
|
6894
|
-
declare function toReadonlyFieldTree<TValue>(field: FieldTree<TValue>): ReadonlyFieldTree<TValue>;
|
|
6895
|
-
|
|
6896
|
-
/**
|
|
6897
|
-
* Input shape passed to a wrapper component via the `fieldInputs` input.
|
|
6898
|
-
*
|
|
6899
|
-
* Carries the wrapped field's mapper outputs plus an optional `field`
|
|
6900
|
-
* read-only view. Wrappers reached through a container path (which has
|
|
6901
|
-
* no FieldTree of its own) receive `fieldInputs === undefined`, so any
|
|
6902
|
-
* wrapper that reads `fieldInputs.field` must guard for it.
|
|
6903
|
-
*
|
|
6904
|
-
* Mappers must emit new rawInputs objects per tick rather than mutating
|
|
6905
|
-
* the previous one — this bag is a shallow spread, so mutations to shared
|
|
6906
|
-
* nested values leak to downstream wrappers.
|
|
6907
|
-
*/
|
|
6908
|
-
interface WrapperFieldInputs {
|
|
6909
|
-
readonly key: string;
|
|
6910
|
-
readonly label?: string;
|
|
6911
|
-
readonly placeholder?: string;
|
|
6912
|
-
readonly className?: string;
|
|
6913
|
-
readonly props?: Record<string, unknown>;
|
|
6914
|
-
readonly validationMessages?: Record<string, string>;
|
|
6915
|
-
readonly defaultValidationMessages?: Record<string, string>;
|
|
6916
|
-
readonly field?: ReadonlyFieldTree;
|
|
6917
|
-
readonly [key: string]: unknown;
|
|
6918
|
-
}
|
|
6919
|
-
|
|
6920
8094
|
/**
|
|
6921
8095
|
* Native JavaScript utility functions to replace lodash-es
|
|
6922
8096
|
* These are simple implementations for common object manipulation patterns
|
|
@@ -6995,5 +8169,5 @@ declare class RootFormRegistryService {
|
|
|
6995
8169
|
*/
|
|
6996
8170
|
declare const INITIALIZATION_TIMEOUT_MS: InjectionToken<number>;
|
|
6997
8171
|
|
|
6998
|
-
export { ARRAY_CONTEXT, AppendArrayItemEvent, ArrayFieldComponent, BUILT_IN_FIELDS, ConsoleLogger, ContainerFieldComponent, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DEFAULT_WRAPPERS, DynamicForm, DynamicFormError, DynamicFormLogger, DynamicTextPipe, EventBus, EventDispatcher, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_OPTIONS, FormClearEvent, FormResetEvent, GROUP_CONTEXT, GroupFieldComponent, INITIALIZATION_TIMEOUT_MS, InsertArrayItemEvent, MoveArrayItemEvent, NextPageEvent, NoopLogger, PageChangeEvent, PopArrayItemEvent, PrependArrayItemEvent, PreviousPageEvent, RemoveAtIndexEvent, RootFormRegistryService, ShiftArrayItemEvent, SubmitEvent, WRAPPER_REGISTRY, applyMetaToElement, applyValidator, applyValidators, arrayEvent, arrayFieldMapper, baseFieldMapper, buildBaseInputs, containerFieldMapper, createField, createWrappers, dynamicTextToObservable, evaluateNonFieldDisabled, evaluateNonFieldHidden, field, formConfig, getArrayLength, groupFieldMapper, hasFormValue, interpolateParams, isArrayField, isCheckedField, isContainerField, isContainerTypedField, isDisplayOnlyField, isEqual, isFormStateCondition, isGroupField, isLeafField, isPageField, isRowField, isSimplifiedArrayField, isValueBearingField, isValueField, isWrapperTypeDefinition, isWrappersBundle, omit, pageFieldMapper, provideDynamicForm, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, textFieldMapper, toReadonlyFieldTree, withEventFormValue, withLoggerConfig, withPreviousValue, withValidationExecutionDefaults, withValueExclusionDefaults, wrapperProps };
|
|
6999
|
-
export type { ArrayAllowedChildren, ArrayButtonConfig, ArrayContext, ArrayField, ArrayFieldTree, ArrayItemContext, ArrayItemDefinitionTemplate, ArrayItemTemplate, AsyncCondition, AsyncConditionFunction, AsyncCustomValidator, AsyncDerivationFunction, AsyncValidatorConfig, AvailableFieldTypes, BaseCheckedField, BaseValidatorConfig, BaseValueField, BuiltInValidatorConfig, ButtonLogicContext, CheckedFieldComponent, ConditionalExpression, ContainerAllowedChildren, ContainerField, ContainerFieldTypes, CssWrapper, CustomFnConfig, CustomFunction, CustomValidator, CustomValidatorConfig, DeclarativeHttpValidatorConfig, DynamicFormFieldRegistry, DynamicText, EvaluationContext, ExtractField, ExtractFieldDefs, ExtractFormValue, FieldComponent, FieldDef, FieldMeta, FieldOption, FieldPathAccess, FieldRegistryContainers, FieldRegistryLeaves, FieldRegistryWrappers, FieldScope, FieldSignalContext, FieldStateContext, FieldStateInfo, FieldTypeDefinition, FieldWithValidation, FieldWrapper, FormConfig, FormEvent, FormEventConstructor, FormFieldStateMap, FormMode, FormModeDetectionResult, FormOptions, FormStateCondition, GroupAllowedChildren, GroupField, HttpCondition, HttpCustomValidator, HttpRequestConfig, HttpResourceRequest, HttpValidationResponseMapping, InferFormValue$1 as InferFormValue, InferWrapperRegistry, LeafFieldTypes, Logger, LogicConfig, MapperFn, NarrowField, NarrowFields, NextButtonOptions, NonFieldLogicConfig, NonFieldLogicContext, NonFieldLogicType, PageAllowedChildren, PageField, Prettify, ReadonlyFieldTree, RegisteredFieldTypes, ResolvedValidationExecutionConfig, ResolvedValueExclusionConfig, RowAllowedChildren, RowField, SchemaApplicationConfig, SchemaDefinition, SimplifiedArrayField, StateLogicConfig, SubmissionActionResult, SubmissionConfig, SubmitButtonOptions, TextElementType, TextField, TextProps, TokenContext, ValidationError, ValidationExecutionConfig, ValidationMessages, ValidatorConfig, ValueExclusionConfig, ValueFieldComponent, ValueHandlingMode, ValueType, WithInputSignals, WrapperConfig, WrapperFieldInputs, WrapperRegistration, WrapperTypeDefinition, WrappersBundle };
|
|
8172
|
+
export { ADDON_ACTION_HANDLERS, ADDON_ACTION_REGISTRY, ADDON_KIND_COMPONENT_CACHE, ADDON_KIND_DEFINITIONS, ADDON_KIND_REGISTRY, ARRAY_CONTEXT, AppendArrayItemEvent, ArrayFieldComponent, BUILT_IN_FIELDS, ComponentAddonComponent, ConsoleLogger, ContainerFieldComponent, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DEFAULT_WRAPPERS, DF_FIELD_TEMPLATES, DfAddonSlot, DfTemplate, DynamicForm, DynamicFormError, DynamicFormLogger, DynamicTextPipe, EventBus, EventDispatcher, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_OPTIONS, FormClearEvent, FormResetEvent, GROUP_CONTEXT, GroupFieldComponent, INITIALIZATION_TIMEOUT_MS, InsertArrayItemEvent, MoveArrayItemEvent, NextPageEvent, NoopLogger, PageChangeEvent, PopArrayItemEvent, PrependArrayItemEvent, PreviousPageEvent, RemoveAtIndexEvent, RootFormRegistryService, ShiftArrayItemEvent, SubmitEvent, TemplateAddonComponent, TextAddonComponent, WRAPPER_REGISTRY, applyMetaToElement, applyValidator, applyValidators, arrayEvent, arrayFieldMapper, baseFieldMapper, buildBaseInputs, containerFieldMapper, createField, createWrappers, dynamicTextToObservable, evaluateNonFieldDisabled, evaluateNonFieldHidden, field, formConfig, formatAddonWarning, getArrayLength, groupFieldMapper, hasFormValue, injectAddonKindRegistry, injectFieldSignalContext, injectFieldsSupportingAddons, interpolateParams, isArrayField, isCheckedField, isContainerField, isContainerTypedField, isDisplayOnlyField, isEqual, isFieldBoundContext, isFormStateCondition, isGroupField, isLeafField, isPageField, isRowField, isSimplifiedArrayField, isValueBearingField, isValueField, isWrapperTypeDefinition, isWrappersBundle, logAddonWarnings, omit, pageFieldMapper, provideAddonActions, provideDynamicForm, resolveDynamicValue, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, runPresetAction, sanitizeFormConfig, sanitizeFormConfigPure, textFieldMapper, toReadonlyFieldTree, validateFieldAddons, walkAndValidateAddons, withCustomAddon, withEventFormValue, withLegacyStatusClasses, withLoggerConfig, withPreviousValue, withValidationExecutionDefaults, withValueExclusionDefaults, wrapperProps, writeToFieldValue };
|
|
8173
|
+
export type { AddonActionContext, AddonActionHandler, AddonActionPreset, AddonActionsFeature, AddonKindDefinition, AddonKindSchema, AddonShapeValidator, AddonSlot, AddonWarning, AnyAddon, ArrayAllowedChildren, ArrayButtonConfig, ArrayContext, ArrayField, ArrayFieldTree, ArrayItemContext, ArrayItemDefinitionTemplate, ArrayItemTemplate, AsyncCondition, AsyncConditionFunction, AsyncCustomValidator, AsyncDerivationFunction, AsyncValidatorConfig, AvailableFieldTypes, BaseAddon, BaseCheckedField, BaseValidatorConfig, BaseValueField, BuiltInValidatorConfig, ButtonLogicContext, CheckedFieldComponent, CommonAddonActionPreset, CommonAddonSlot, ComponentAddon, ConditionalExpression, ContainerAllowedChildren, ContainerField, ContainerFieldTypes, CssWrapper, CustomFnConfig, CustomFunction, CustomValidator, CustomValidatorConfig, DeclarativeHttpValidatorConfig, DynamicFormActionRegistry, DynamicFormAddonActionPresetRegistry, DynamicFormAddonRegistry, DynamicFormAddonSlotRegistry, DynamicFormFieldRegistry, DynamicText, DynamicValue, EvaluationContext, ExtractField, ExtractFieldDefs, ExtractFormValue, FieldAddonSupport, FieldAddonSupportEntry, FieldBoundAddonActionContext, FieldComponent, FieldDef, FieldMeta, FieldOption, FieldPathAccess, FieldRegistryContainers, FieldRegistryLeaves, FieldRegistryWrappers, FieldScope, FieldSignalContext, FieldStateContext, FieldStateInfo, FieldTypeDefinition, FieldWithValidation, FieldWrapper, FormConfig, FormEvent, FormEventConstructor, FormFieldStateMap, FormMode, FormModeDetectionResult, FormOptions, FormStateCondition, GroupAllowedChildren, GroupField, HttpCondition, HttpCustomValidator, HttpRequestConfig, HttpResourceRequest, HttpValidationResponseMapping, InferFormValue$1 as InferFormValue, InferWrapperRegistry, LeafFieldTypes, Logger, LogicConfig, MapperFn, NarrowField, NarrowFields, NextButtonOptions, NonFieldLogicConfig, NonFieldLogicContext, NonFieldLogicType, OrphanAddonActionContext, PageAllowedChildren, PageField, PresetCollaborators, Prettify, ReadonlyFieldTree, RegisteredActionRef, RegisteredFieldTypes, ResolvedValidationExecutionConfig, ResolvedValueExclusionConfig, RowAllowedChildren, RowField, SanitizeFormConfigOptions, SanitizedFormConfig, SchemaApplicationConfig, SchemaDefinition, SimplifiedArrayField, StateLogicConfig, SubmissionActionResult, SubmissionConfig, SubmitButtonOptions, TemplateAddon, TextAddon, TextElementType, TextField, TextProps, TokenContext, ValidationError, ValidationExecutionConfig, ValidationMessages, ValidatorConfig, ValueExclusionConfig, ValueFieldComponent, ValueHandlingMode, ValueType, WithInputSignals, WrapperConfig, WrapperFieldInputs, WrapperRegistration, WrapperTypeDefinition, WrappersBundle };
|