@ng-forge/dynamic-forms 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +269 -0
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-Dcd04rfS.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-B_676NHl.mjs} +989 -1211
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-B_676NHl.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-page-field.component-DjrahUgb.mjs → ng-forge-dynamic-forms-page-field.component-YHFQcpCS.mjs} +31 -29
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-YHFQcpCS.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-testing-test-button.harness-BenmCFcM.mjs +31 -0
- package/fesm2022/ng-forge-dynamic-forms-testing-test-button.harness-BenmCFcM.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs +968 -0
- package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-7QVNm95W.mjs → ng-forge-dynamic-forms-text-field.component-CiYq73aF.mjs} +2 -2
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-7QVNm95W.mjs.map → ng-forge-dynamic-forms-text-field.component-CiYq73aF.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
- package/package.json +17 -3
- package/types/ng-forge-dynamic-forms-integration.d.ts +315 -0
- package/types/ng-forge-dynamic-forms-testing.d.ts +565 -0
- package/types/ng-forge-dynamic-forms.d.ts +353 -549
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-Dcd04rfS.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-DjrahUgb.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -7,8 +7,20 @@
|
|
|
7
7
|
Core library for building type-safe, dynamic Angular forms with signal forms integration.
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@ng-forge/dynamic-forms)
|
|
10
|
+
[](https://www.npmjs.com/package/@ng-forge/dynamic-forms)
|
|
11
|
+
[](https://angular.dev)
|
|
10
12
|
[](https://opensource.org/licenses/MIT)
|
|
11
13
|
|
|
14
|
+
> **Experimental API Notice:** This library uses Angular's experimental Signal Forms API.
|
|
15
|
+
> Angular may introduce breaking changes in patch releases. Check the [compatibility matrix](#compatibility) below.
|
|
16
|
+
|
|
17
|
+
## Compatibility
|
|
18
|
+
|
|
19
|
+
| @ng-forge/dynamic-forms | Angular | Notes |
|
|
20
|
+
| ----------------------- | ------------- | ---------------------------------- |
|
|
21
|
+
| 0.1.1+ | >=21.0.2 | Signal forms API signature changed |
|
|
22
|
+
| 0.1.0 | 21.0.0-21.0.1 | Initial release |
|
|
23
|
+
|
|
12
24
|
## Installation
|
|
13
25
|
|
|
14
26
|
```bash
|
|
@@ -61,6 +73,19 @@ export class UserFormComponent {
|
|
|
61
73
|
- **i18n Ready** - Observable/Signal support for labels and messages
|
|
62
74
|
- **Event System** - Custom events for buttons and form actions
|
|
63
75
|
|
|
76
|
+
## UI Integrations
|
|
77
|
+
|
|
78
|
+
This core library requires a UI integration. Choose one:
|
|
79
|
+
|
|
80
|
+
| Package | UI Library |
|
|
81
|
+
| ---------------------------------------------------------------------------------------------------- | ---------------- |
|
|
82
|
+
| [@ng-forge/dynamic-forms-material](https://www.npmjs.com/package/@ng-forge/dynamic-forms-material) | Angular Material |
|
|
83
|
+
| [@ng-forge/dynamic-forms-bootstrap](https://www.npmjs.com/package/@ng-forge/dynamic-forms-bootstrap) | Bootstrap 5 |
|
|
84
|
+
| [@ng-forge/dynamic-forms-primeng](https://www.npmjs.com/package/@ng-forge/dynamic-forms-primeng) | PrimeNG |
|
|
85
|
+
| [@ng-forge/dynamic-forms-ionic](https://www.npmjs.com/package/@ng-forge/dynamic-forms-ionic) | Ionic |
|
|
86
|
+
|
|
87
|
+
Or [create your own](https://ng-forge.com/dynamic-forms/deep-dive/custom-integrations).
|
|
88
|
+
|
|
64
89
|
## Documentation
|
|
65
90
|
|
|
66
91
|
- [Installation](https://ng-forge.com/dynamic-forms/installation)
|
|
@@ -72,6 +97,14 @@ export class UserFormComponent {
|
|
|
72
97
|
- [i18n](https://ng-forge.com/dynamic-forms/core/i18n)
|
|
73
98
|
- [Custom Integrations](https://ng-forge.com/dynamic-forms/deep-dive/custom-integrations)
|
|
74
99
|
|
|
100
|
+
## Changelog
|
|
101
|
+
|
|
102
|
+
See [GitHub Releases](https://github.com/ng-forge/ng-forge/releases).
|
|
103
|
+
|
|
104
|
+
## Contributing
|
|
105
|
+
|
|
106
|
+
Contributions are welcome! Please read our [Contributing Guide](https://github.com/ng-forge/ng-forge/blob/main/CONTRIBUTING.md).
|
|
107
|
+
|
|
75
108
|
## License
|
|
76
109
|
|
|
77
110
|
MIT © ng-forge
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { inject, computed, signal, Injector } from '@angular/core';
|
|
2
|
+
import { FIELD_SIGNAL_CONTEXT, omit, buildBaseInputs, DYNAMIC_FORM_LOGGER, dynamicTextToObservable, interpolateParams } from '@ng-forge/dynamic-forms';
|
|
3
|
+
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { combineLatest, of } from 'rxjs';
|
|
5
|
+
import { switchMap, map } from 'rxjs/operators';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the field tree and default validation messages from the form context.
|
|
9
|
+
* Must be called within an injection context.
|
|
10
|
+
*
|
|
11
|
+
* Uses type-safe field tree utilities to access child FieldTrees from the parent form.
|
|
12
|
+
*
|
|
13
|
+
* @param fieldKey The key of the field to resolve
|
|
14
|
+
* @returns The resolved context with field tree and validation messages
|
|
15
|
+
*/
|
|
16
|
+
function resolveValueFieldContext(fieldKey) {
|
|
17
|
+
const context = inject(FIELD_SIGNAL_CONTEXT);
|
|
18
|
+
const defaultValidationMessages = context.defaultValidationMessages;
|
|
19
|
+
const formRoot = context.form;
|
|
20
|
+
const fieldTree = formRoot[fieldKey];
|
|
21
|
+
return { fieldTree, defaultValidationMessages };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Builds the base inputs for a value field.
|
|
25
|
+
* This is a helper function used by valueFieldMapper and specialized mappers.
|
|
26
|
+
*
|
|
27
|
+
* @param fieldDef The value field definition
|
|
28
|
+
* @param ctx The resolved value field context
|
|
29
|
+
* @returns Record of input names to values
|
|
30
|
+
*/
|
|
31
|
+
function buildValueFieldInputs(fieldDef, ctx) {
|
|
32
|
+
const omittedFields = omit(fieldDef, ['value']);
|
|
33
|
+
const baseInputs = buildBaseInputs(omittedFields);
|
|
34
|
+
const inputs = {
|
|
35
|
+
...baseInputs,
|
|
36
|
+
validationMessages: fieldDef.validationMessages ?? {},
|
|
37
|
+
};
|
|
38
|
+
if (fieldDef.placeholder !== undefined) {
|
|
39
|
+
inputs['placeholder'] = fieldDef.placeholder;
|
|
40
|
+
}
|
|
41
|
+
if (ctx.defaultValidationMessages !== undefined) {
|
|
42
|
+
inputs['defaultValidationMessages'] = ctx.defaultValidationMessages;
|
|
43
|
+
}
|
|
44
|
+
if (ctx.fieldTree !== undefined) {
|
|
45
|
+
inputs['field'] = ctx.fieldTree;
|
|
46
|
+
}
|
|
47
|
+
return inputs;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Maps a value field definition to component inputs.
|
|
51
|
+
*
|
|
52
|
+
* Value fields are input fields that contribute to the form's value (text, number, etc.).
|
|
53
|
+
* This mapper injects FIELD_SIGNAL_CONTEXT to access the form structure and retrieve the field proxy.
|
|
54
|
+
*
|
|
55
|
+
* For fields with specific properties (select, datepicker, textarea, slider), use the specialized mappers:
|
|
56
|
+
* - selectFieldMapper: for fields with options (select, radio, multi-checkbox)
|
|
57
|
+
* - datepickerFieldMapper: for fields with minDate, maxDate, startAt
|
|
58
|
+
* - textareaFieldMapper: for fields with rows, cols
|
|
59
|
+
* - sliderFieldMapper: for fields with minValue, maxValue, step
|
|
60
|
+
*
|
|
61
|
+
* @param fieldDef The value field definition
|
|
62
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
63
|
+
*/
|
|
64
|
+
function valueFieldMapper(fieldDef) {
|
|
65
|
+
const ctx = resolveValueFieldContext(fieldDef.key);
|
|
66
|
+
return computed(() => buildValueFieldInputs(fieldDef, ctx));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Maps a checkbox/toggle field definition to component inputs.
|
|
71
|
+
*
|
|
72
|
+
* Checkbox fields are checked fields that contribute to the form's value as boolean.
|
|
73
|
+
* This mapper injects FIELD_SIGNAL_CONTEXT to access the form structure and retrieve the field tree.
|
|
74
|
+
*
|
|
75
|
+
* @param fieldDef The checkbox field definition
|
|
76
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
77
|
+
*/
|
|
78
|
+
function checkboxFieldMapper(fieldDef) {
|
|
79
|
+
const context = inject(FIELD_SIGNAL_CONTEXT);
|
|
80
|
+
const omittedFields = omit(fieldDef, ['value']);
|
|
81
|
+
const baseInputs = buildBaseInputs(omittedFields);
|
|
82
|
+
const defaultValidationMessages = context.defaultValidationMessages;
|
|
83
|
+
const formRoot = context.form;
|
|
84
|
+
const fieldTree = formRoot[fieldDef.key];
|
|
85
|
+
return computed(() => {
|
|
86
|
+
const inputs = {
|
|
87
|
+
...baseInputs,
|
|
88
|
+
validationMessages: fieldDef.validationMessages ?? {},
|
|
89
|
+
};
|
|
90
|
+
if (fieldDef.placeholder !== undefined) {
|
|
91
|
+
inputs['placeholder'] = fieldDef.placeholder;
|
|
92
|
+
}
|
|
93
|
+
if (defaultValidationMessages !== undefined) {
|
|
94
|
+
inputs['defaultValidationMessages'] = defaultValidationMessages;
|
|
95
|
+
}
|
|
96
|
+
if (fieldTree !== undefined) {
|
|
97
|
+
inputs['field'] = fieldTree;
|
|
98
|
+
}
|
|
99
|
+
return inputs;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Maps a datepicker field to component inputs.
|
|
105
|
+
*
|
|
106
|
+
* Extends the base value field mapper by adding datepicker-specific properties:
|
|
107
|
+
* - minDate: Minimum selectable date
|
|
108
|
+
* - maxDate: Maximum selectable date
|
|
109
|
+
* - startAt: Initial date to display when opening the picker
|
|
110
|
+
*
|
|
111
|
+
* @param fieldDef The datepicker field definition
|
|
112
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
113
|
+
*/
|
|
114
|
+
function datepickerFieldMapper(fieldDef) {
|
|
115
|
+
const ctx = resolveValueFieldContext(fieldDef.key);
|
|
116
|
+
return computed(() => {
|
|
117
|
+
const inputs = buildValueFieldInputs(fieldDef, ctx);
|
|
118
|
+
// Add datepicker-specific properties
|
|
119
|
+
if (fieldDef.minDate !== undefined) {
|
|
120
|
+
inputs['minDate'] = fieldDef.minDate;
|
|
121
|
+
}
|
|
122
|
+
if (fieldDef.maxDate !== undefined) {
|
|
123
|
+
inputs['maxDate'] = fieldDef.maxDate;
|
|
124
|
+
}
|
|
125
|
+
if (fieldDef.startAt !== undefined) {
|
|
126
|
+
inputs['startAt'] = fieldDef.startAt;
|
|
127
|
+
}
|
|
128
|
+
return inputs;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Maps a field with options (select, radio, multi-checkbox) to component inputs.
|
|
134
|
+
*
|
|
135
|
+
* Extends the base value field mapper by adding the options property.
|
|
136
|
+
*
|
|
137
|
+
* @param fieldDef The field definition with options
|
|
138
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
139
|
+
*/
|
|
140
|
+
function optionsFieldMapper(fieldDef) {
|
|
141
|
+
const ctx = resolveValueFieldContext(fieldDef.key);
|
|
142
|
+
return computed(() => {
|
|
143
|
+
// Cast to BaseValueField - safe because all FieldWithOptions types extend BaseValueField
|
|
144
|
+
const inputs = buildValueFieldInputs(fieldDef, ctx);
|
|
145
|
+
// Add options property
|
|
146
|
+
inputs['options'] = fieldDef.options;
|
|
147
|
+
return inputs;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// UI-specific field mappers
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Factory function that creates a signal of resolved validation errors
|
|
155
|
+
* Handles async resolution of DynamicText validation messages
|
|
156
|
+
*
|
|
157
|
+
* @param field - Signal containing FieldTree
|
|
158
|
+
* @param validationMessages - Signal containing custom field-level validation messages
|
|
159
|
+
* @param defaultValidationMessages - Signal containing default validation messages (fallback)
|
|
160
|
+
* @param injector - Optional injector for DynamicText resolution
|
|
161
|
+
* @returns Signal<ResolvedError[]> - Reactively resolved error messages
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* readonly resolvedErrors = createResolvedErrorsSignal(
|
|
166
|
+
* this.field,
|
|
167
|
+
* this.validationMessages,
|
|
168
|
+
* this.defaultValidationMessages
|
|
169
|
+
* );
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
function createResolvedErrorsSignal(field, validationMessages, defaultValidationMessages = signal(undefined), injector = inject(Injector)) {
|
|
173
|
+
// Get logger from injector
|
|
174
|
+
const logger = injector.get(DYNAMIC_FORM_LOGGER);
|
|
175
|
+
// Ensure validationMessages is never undefined (mappers pass {} if not defined)
|
|
176
|
+
const messages = computed(() => validationMessages() ?? {}, ...(ngDevMode ? [{ debugName: "messages" }] : []));
|
|
177
|
+
const defaultMessages = computed(() => defaultValidationMessages() ?? {}, ...(ngDevMode ? [{ debugName: "defaultMessages" }] : []));
|
|
178
|
+
// Create a computed signal that reads the actual errors from the field
|
|
179
|
+
// This ensures the signal tracks changes to field().errors(), not just the field reference
|
|
180
|
+
const errors = computed(() => {
|
|
181
|
+
const control = field()();
|
|
182
|
+
return control.errors();
|
|
183
|
+
}, ...(ngDevMode ? [{ debugName: "errors" }] : []));
|
|
184
|
+
// Convert signals to observables using toObservable with injector
|
|
185
|
+
const errors$ = toObservable(errors, { injector });
|
|
186
|
+
const messages$ = toObservable(messages, { injector });
|
|
187
|
+
const defaultMessages$ = toObservable(defaultMessages, { injector });
|
|
188
|
+
// Combine observables and process errors
|
|
189
|
+
const resolvedErrors$ = combineLatest([errors$, messages$, defaultMessages$]).pipe(switchMap(([currentErrors, msgs, defaultMsgs]) => {
|
|
190
|
+
// No errors - return empty array
|
|
191
|
+
if (!currentErrors || currentErrors.length === 0) {
|
|
192
|
+
return of([]);
|
|
193
|
+
}
|
|
194
|
+
// Create observable for each error's resolved message
|
|
195
|
+
const errorResolvers = currentErrors.map((error) => resolveErrorMessage(error, msgs, defaultMsgs, injector, logger));
|
|
196
|
+
// Combine all error message observables into single array emission, filtering out nulls
|
|
197
|
+
return errorResolvers.length > 0
|
|
198
|
+
? combineLatest(errorResolvers).pipe(map((errors) => errors.filter((e) => e !== null)))
|
|
199
|
+
: of([]);
|
|
200
|
+
}));
|
|
201
|
+
// Convert observable back to signal using toSignal with injector
|
|
202
|
+
// toSignal properly handles the injection context and manages subscriptions
|
|
203
|
+
return toSignal(resolvedErrors$, { initialValue: [], injector });
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Resolves a single error message from DynamicText sources with fallback logic
|
|
207
|
+
* Priority: field-level message → default message → no message (logs warning)
|
|
208
|
+
* @internal
|
|
209
|
+
*/
|
|
210
|
+
function resolveErrorMessage(error, fieldMessages, defaultMessages, injector, logger) {
|
|
211
|
+
// Check for field-level custom message first
|
|
212
|
+
const fieldMessage = fieldMessages[error.kind];
|
|
213
|
+
// Fall back to default message if no field-level message exists
|
|
214
|
+
const defaultMessage = defaultMessages[error.kind];
|
|
215
|
+
// Determine which message to use: field-level → default
|
|
216
|
+
const messageToUse = fieldMessage ?? defaultMessage;
|
|
217
|
+
// If no message found, log warning and return null (will be filtered out)
|
|
218
|
+
if (!messageToUse) {
|
|
219
|
+
logger.warn(`No validation message found for error kind "${error.kind}". ` +
|
|
220
|
+
`Please provide a message via field-level validationMessages or form-level defaultValidationMessages.`);
|
|
221
|
+
return of(null);
|
|
222
|
+
}
|
|
223
|
+
// Convert DynamicText to Observable
|
|
224
|
+
const messageObservable = dynamicTextToObservable(messageToUse, injector);
|
|
225
|
+
// Apply parameter interpolation to support {{param}} syntax
|
|
226
|
+
return messageObservable.pipe(map((msg) => ({
|
|
227
|
+
kind: error.kind,
|
|
228
|
+
message: interpolateParams(msg, error),
|
|
229
|
+
})));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Computed signal that determines if errors should be displayed
|
|
234
|
+
* Based on field's invalid, touched, and error count
|
|
235
|
+
*
|
|
236
|
+
* @param field - Signal containing FieldTree
|
|
237
|
+
* @returns Signal<boolean> - True if errors should be displayed
|
|
238
|
+
*/
|
|
239
|
+
function shouldShowErrors(field) {
|
|
240
|
+
return computed(() => {
|
|
241
|
+
const fieldTree = field();
|
|
242
|
+
const control = fieldTree();
|
|
243
|
+
return control.invalid() && control.touched() && control.errors().length > 0;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Error display utilities for field components
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @ng-forge/dynamic-forms/integration
|
|
251
|
+
*
|
|
252
|
+
* Integration API for UI library authors building field implementations
|
|
253
|
+
* (Material, Bootstrap, PrimeNG, Ionic, etc.)
|
|
254
|
+
*
|
|
255
|
+
* This entrypoint provides:
|
|
256
|
+
* - Specific field type definitions (InputField, SelectField, etc.)
|
|
257
|
+
* - Field mappers for creating FieldTypeDefinition
|
|
258
|
+
* - Error display utilities for field components
|
|
259
|
+
*/
|
|
260
|
+
// =============================================================================
|
|
261
|
+
// Field Mappers
|
|
262
|
+
// =============================================================================
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Generated bundle index. Do not edit.
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
export { buildValueFieldInputs, checkboxFieldMapper, createResolvedErrorsSignal, datepickerFieldMapper, optionsFieldMapper, resolveValueFieldContext, shouldShowErrors, valueFieldMapper };
|
|
269
|
+
//# sourceMappingURL=ng-forge-dynamic-forms-integration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-forge-dynamic-forms-integration.mjs","sources":["../../../../packages/dynamic-forms/integration/src/mappers/value/value-field.mapper.ts","../../../../packages/dynamic-forms/integration/src/mappers/checkbox/checkbox-field-mapper.ts","../../../../packages/dynamic-forms/integration/src/mappers/datepicker/datepicker-field-mapper.ts","../../../../packages/dynamic-forms/integration/src/mappers/select/options-field-mapper.ts","../../../../packages/dynamic-forms/integration/src/mappers/index.ts","../../../../packages/dynamic-forms/integration/src/utils/create-resolved-errors-signal.ts","../../../../packages/dynamic-forms/integration/src/utils/should-show-errors.ts","../../../../packages/dynamic-forms/integration/src/utils/index.ts","../../../../packages/dynamic-forms/integration/src/public_api.ts","../../../../packages/dynamic-forms/integration/src/ng-forge-dynamic-forms-integration.ts"],"sourcesContent":["import { BaseValueField } from '@ng-forge/dynamic-forms';\nimport { computed, inject, Signal } from '@angular/core';\nimport { FieldTree } from '@angular/forms/signals';\nimport { buildBaseInputs } from '@ng-forge/dynamic-forms';\nimport { FIELD_SIGNAL_CONTEXT } from '@ng-forge/dynamic-forms';\nimport { omit } from '@ng-forge/dynamic-forms';\nimport { ValidationMessages } from '@ng-forge/dynamic-forms';\n\n/**\n * Context for value field mapping, containing resolved field tree and default validation messages.\n * Used by specialized mappers to avoid duplicate context resolution.\n */\nexport interface ValueFieldContext {\n fieldTree: FieldTree<unknown> | undefined;\n defaultValidationMessages: ValidationMessages | undefined;\n}\n\n/**\n * Resolves the field tree and default validation messages from the form context.\n * Must be called within an injection context.\n *\n * Uses type-safe field tree utilities to access child FieldTrees from the parent form.\n *\n * @param fieldKey The key of the field to resolve\n * @returns The resolved context with field tree and validation messages\n */\nexport function resolveValueFieldContext(fieldKey: string): ValueFieldContext {\n const context = inject(FIELD_SIGNAL_CONTEXT);\n const defaultValidationMessages = context.defaultValidationMessages;\n const formRoot = context.form as Record<string, FieldTree<unknown> | undefined>;\n const fieldTree = formRoot[fieldKey];\n return { fieldTree, defaultValidationMessages };\n}\n\n/**\n * Builds the base inputs for a value field.\n * This is a helper function used by valueFieldMapper and specialized mappers.\n *\n * @param fieldDef The value field definition\n * @param ctx The resolved value field context\n * @returns Record of input names to values\n */\nexport function buildValueFieldInputs<TProps, TValue = unknown>(\n fieldDef: BaseValueField<TProps, TValue>,\n ctx: ValueFieldContext,\n): Record<string, unknown> {\n const omittedFields = omit(fieldDef, ['value']);\n const baseInputs = buildBaseInputs(omittedFields);\n\n const inputs: Record<string, unknown> = {\n ...baseInputs,\n validationMessages: fieldDef.validationMessages ?? {},\n };\n\n if (fieldDef.placeholder !== undefined) {\n inputs['placeholder'] = fieldDef.placeholder;\n }\n\n if (ctx.defaultValidationMessages !== undefined) {\n inputs['defaultValidationMessages'] = ctx.defaultValidationMessages;\n }\n\n if (ctx.fieldTree !== undefined) {\n inputs['field'] = ctx.fieldTree;\n }\n\n return inputs;\n}\n\n/**\n * Maps a value field definition to component inputs.\n *\n * Value fields are input fields that contribute to the form's value (text, number, etc.).\n * This mapper injects FIELD_SIGNAL_CONTEXT to access the form structure and retrieve the field proxy.\n *\n * For fields with specific properties (select, datepicker, textarea, slider), use the specialized mappers:\n * - selectFieldMapper: for fields with options (select, radio, multi-checkbox)\n * - datepickerFieldMapper: for fields with minDate, maxDate, startAt\n * - textareaFieldMapper: for fields with rows, cols\n * - sliderFieldMapper: for fields with minValue, maxValue, step\n *\n * @param fieldDef The value field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function valueFieldMapper<TProps = unknown, TValue = unknown>(\n fieldDef: BaseValueField<TProps, TValue>,\n): Signal<Record<string, unknown>> {\n const ctx = resolveValueFieldContext(fieldDef.key);\n\n return computed(() => buildValueFieldInputs(fieldDef, ctx));\n}\n","import { BaseCheckedField } from '@ng-forge/dynamic-forms';\nimport { FieldDef } from '@ng-forge/dynamic-forms';\nimport { computed, inject, Signal } from '@angular/core';\nimport { FieldTree } from '@angular/forms/signals';\nimport { buildBaseInputs } from '@ng-forge/dynamic-forms';\nimport { FIELD_SIGNAL_CONTEXT } from '@ng-forge/dynamic-forms';\nimport { omit } from '@ng-forge/dynamic-forms';\n\n/**\n * Maps a checkbox/toggle field definition to component inputs.\n *\n * Checkbox fields are checked fields that contribute to the form's value as boolean.\n * This mapper injects FIELD_SIGNAL_CONTEXT to access the form structure and retrieve the field tree.\n *\n * @param fieldDef The checkbox field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function checkboxFieldMapper(fieldDef: BaseCheckedField<unknown>): Signal<Record<string, unknown>> {\n const context = inject(FIELD_SIGNAL_CONTEXT);\n const omittedFields = omit(fieldDef, ['value']) as FieldDef<unknown>;\n const baseInputs = buildBaseInputs(omittedFields);\n const defaultValidationMessages = context.defaultValidationMessages;\n const formRoot = context.form as Record<string, FieldTree<unknown> | undefined>;\n const fieldTree = formRoot[fieldDef.key];\n\n return computed(() => {\n const inputs: Record<string, unknown> = {\n ...baseInputs,\n validationMessages: fieldDef.validationMessages ?? {},\n };\n\n if (fieldDef.placeholder !== undefined) {\n inputs['placeholder'] = fieldDef.placeholder;\n }\n\n if (defaultValidationMessages !== undefined) {\n inputs['defaultValidationMessages'] = defaultValidationMessages;\n }\n\n if (fieldTree !== undefined) {\n inputs['field'] = fieldTree;\n }\n\n return inputs;\n });\n}\n","import { computed, Signal } from '@angular/core';\nimport { DatepickerField } from '../../definitions';\nimport { resolveValueFieldContext, buildValueFieldInputs } from '../value/value-field.mapper';\n\n/**\n * Maps a datepicker field to component inputs.\n *\n * Extends the base value field mapper by adding datepicker-specific properties:\n * - minDate: Minimum selectable date\n * - maxDate: Maximum selectable date\n * - startAt: Initial date to display when opening the picker\n *\n * @param fieldDef The datepicker field definition\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function datepickerFieldMapper<TProps>(fieldDef: DatepickerField<TProps>): Signal<Record<string, unknown>> {\n const ctx = resolveValueFieldContext(fieldDef.key);\n\n return computed(() => {\n const inputs = buildValueFieldInputs(fieldDef, ctx);\n\n // Add datepicker-specific properties\n if (fieldDef.minDate !== undefined) {\n inputs['minDate'] = fieldDef.minDate;\n }\n if (fieldDef.maxDate !== undefined) {\n inputs['maxDate'] = fieldDef.maxDate;\n }\n if (fieldDef.startAt !== undefined) {\n inputs['startAt'] = fieldDef.startAt;\n }\n\n return inputs;\n });\n}\n","import { computed, Signal } from '@angular/core';\nimport { SelectField } from '../../definitions';\nimport { RadioField } from '../../definitions';\nimport { MultiCheckboxField } from '../../definitions';\nimport { BaseValueField } from '@ng-forge/dynamic-forms';\nimport { resolveValueFieldContext, buildValueFieldInputs } from '../value/value-field.mapper';\n\n/**\n * Field types that have an options property.\n */\nexport type FieldWithOptions<T = unknown, TProps = unknown> =\n | SelectField<T, TProps>\n | RadioField<T, TProps>\n | MultiCheckboxField<T, TProps>;\n\n/**\n * Maps a field with options (select, radio, multi-checkbox) to component inputs.\n *\n * Extends the base value field mapper by adding the options property.\n *\n * @param fieldDef The field definition with options\n * @returns Signal containing Record of input names to values for ngComponentOutlet\n */\nexport function optionsFieldMapper<T, TProps>(fieldDef: FieldWithOptions<T, TProps>): Signal<Record<string, unknown>> {\n const ctx = resolveValueFieldContext(fieldDef.key);\n\n return computed(() => {\n // Cast to BaseValueField - safe because all FieldWithOptions types extend BaseValueField\n const inputs = buildValueFieldInputs(fieldDef as BaseValueField<TProps, unknown>, ctx);\n\n // Add options property\n inputs['options'] = fieldDef.options;\n\n return inputs;\n });\n}\n","// UI-specific field mappers\nexport { valueFieldMapper, buildValueFieldInputs, resolveValueFieldContext } from './value/value-field.mapper';\nexport type { ValueFieldContext } from './value/value-field.mapper';\nexport { checkboxFieldMapper } from './checkbox/checkbox-field-mapper';\nexport { datepickerFieldMapper } from './datepicker/datepicker-field-mapper';\nexport { optionsFieldMapper } from './select/options-field-mapper';\nexport type { FieldWithOptions } from './select/options-field-mapper';\n","import { computed, inject, Injector, signal, Signal } from '@angular/core';\nimport { toObservable, toSignal } from '@angular/core/rxjs-interop';\nimport { FieldTree, ValidationError } from '@angular/forms/signals';\nimport { combineLatest, Observable, of } from 'rxjs';\nimport { map, switchMap } from 'rxjs/operators';\nimport { ValidationMessages } from '@ng-forge/dynamic-forms';\nimport { dynamicTextToObservable } from '@ng-forge/dynamic-forms';\nimport { interpolateParams } from '@ng-forge/dynamic-forms';\nimport { DYNAMIC_FORM_LOGGER, DynamicFormLogger } from '@ng-forge/dynamic-forms';\n\n/**\n * Resolved validation error with interpolated message\n */\nexport interface ResolvedError {\n kind: string;\n message: string;\n}\n\n/**\n * Factory function that creates a signal of resolved validation errors\n * Handles async resolution of DynamicText validation messages\n *\n * @param field - Signal containing FieldTree\n * @param validationMessages - Signal containing custom field-level validation messages\n * @param defaultValidationMessages - Signal containing default validation messages (fallback)\n * @param injector - Optional injector for DynamicText resolution\n * @returns Signal<ResolvedError[]> - Reactively resolved error messages\n *\n * @example\n * ```typescript\n * readonly resolvedErrors = createResolvedErrorsSignal(\n * this.field,\n * this.validationMessages,\n * this.defaultValidationMessages\n * );\n * ```\n */\nexport function createResolvedErrorsSignal<T>(\n field: Signal<FieldTree<T>>,\n validationMessages: Signal<ValidationMessages | undefined>,\n defaultValidationMessages: Signal<ValidationMessages | undefined> = signal(undefined),\n injector = inject(Injector),\n): Signal<ResolvedError[]> {\n // Get logger from injector\n const logger = injector.get(DYNAMIC_FORM_LOGGER);\n\n // Ensure validationMessages is never undefined (mappers pass {} if not defined)\n const messages = computed(() => validationMessages() ?? {});\n const defaultMessages = computed(() => defaultValidationMessages() ?? {});\n\n // Create a computed signal that reads the actual errors from the field\n // This ensures the signal tracks changes to field().errors(), not just the field reference\n const errors = computed(() => {\n const control = field()();\n return control.errors();\n });\n\n // Convert signals to observables using toObservable with injector\n const errors$ = toObservable(errors, { injector });\n const messages$ = toObservable(messages, { injector });\n const defaultMessages$ = toObservable(defaultMessages, { injector });\n\n // Combine observables and process errors\n const resolvedErrors$ = combineLatest([errors$, messages$, defaultMessages$]).pipe(\n switchMap(([currentErrors, msgs, defaultMsgs]) => {\n // No errors - return empty array\n if (!currentErrors || currentErrors.length === 0) {\n return of([]);\n }\n\n // Create observable for each error's resolved message\n const errorResolvers = currentErrors.map((error: ValidationError) => resolveErrorMessage(error, msgs, defaultMsgs, injector, logger));\n\n // Combine all error message observables into single array emission, filtering out nulls\n return errorResolvers.length > 0\n ? combineLatest(errorResolvers).pipe(map((errors) => errors.filter((e): e is ResolvedError => e !== null)))\n : of([]);\n }),\n );\n\n // Convert observable back to signal using toSignal with injector\n // toSignal properly handles the injection context and manages subscriptions\n return toSignal(resolvedErrors$, { initialValue: [] as ResolvedError[], injector });\n}\n\n/**\n * Resolves a single error message from DynamicText sources with fallback logic\n * Priority: field-level message → default message → no message (logs warning)\n * @internal\n */\nfunction resolveErrorMessage(\n error: ValidationError,\n fieldMessages: ValidationMessages,\n defaultMessages: ValidationMessages,\n injector: Injector,\n logger: DynamicFormLogger,\n): Observable<ResolvedError | null> {\n // Check for field-level custom message first\n const fieldMessage = fieldMessages[error.kind];\n\n // Fall back to default message if no field-level message exists\n const defaultMessage = defaultMessages[error.kind];\n\n // Determine which message to use: field-level → default\n const messageToUse = fieldMessage ?? defaultMessage;\n\n // If no message found, log warning and return null (will be filtered out)\n if (!messageToUse) {\n logger.warn(\n `No validation message found for error kind \"${error.kind}\". ` +\n `Please provide a message via field-level validationMessages or form-level defaultValidationMessages.`,\n );\n return of(null);\n }\n\n // Convert DynamicText to Observable\n const messageObservable = dynamicTextToObservable(messageToUse, injector);\n\n // Apply parameter interpolation to support {{param}} syntax\n return messageObservable.pipe(\n map((msg) => ({\n kind: error.kind,\n message: interpolateParams(msg, error),\n })),\n );\n}\n","import { Signal, computed } from '@angular/core';\nimport { FieldTree } from '@angular/forms/signals';\n\n/**\n * Computed signal that determines if errors should be displayed\n * Based on field's invalid, touched, and error count\n *\n * @param field - Signal containing FieldTree\n * @returns Signal<boolean> - True if errors should be displayed\n */\nexport function shouldShowErrors<T>(field: Signal<FieldTree<T>>): Signal<boolean> {\n return computed(() => {\n const fieldTree = field();\n const control = fieldTree();\n return control.invalid() && control.touched() && control.errors().length > 0;\n });\n}\n","// Error display utilities for field components\nexport { createResolvedErrorsSignal } from './create-resolved-errors-signal';\nexport type { ResolvedError } from './create-resolved-errors-signal';\nexport { shouldShowErrors } from './should-show-errors';\n","/**\n * @ng-forge/dynamic-forms/integration\n *\n * Integration API for UI library authors building field implementations\n * (Material, Bootstrap, PrimeNG, Ionic, etc.)\n *\n * This entrypoint provides:\n * - Specific field type definitions (InputField, SelectField, etc.)\n * - Field mappers for creating FieldTypeDefinition\n * - Error display utilities for field components\n */\n\n// =============================================================================\n// Field Type Definitions\n// =============================================================================\n\nexport type {\n ButtonField,\n EventArgs,\n CheckboxField,\n DatepickerField,\n DatepickerProps,\n InputField,\n InputProps,\n InputType,\n InputTypeToValueType,\n StringInputType,\n MultiCheckboxField,\n RadioField,\n SelectField,\n SelectProps,\n SliderField,\n TextareaField,\n TextareaProps,\n ToggleField,\n} from './definitions';\n\n// =============================================================================\n// Field Mappers\n// =============================================================================\n\nexport {\n valueFieldMapper,\n buildValueFieldInputs,\n resolveValueFieldContext,\n checkboxFieldMapper,\n datepickerFieldMapper,\n optionsFieldMapper,\n} from './mappers';\n\nexport type { ValueFieldContext, FieldWithOptions } from './mappers';\n\n// =============================================================================\n// Error Display Utilities\n// =============================================================================\n\nexport { createResolvedErrorsSignal, shouldShowErrors } from './utils';\nexport type { ResolvedError } from './utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|