@forge-form/angular 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,853 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Inject, Injectable, inject, input, DestroyRef, signal, computed, ChangeDetectionStrategy, Component, effect, Input, output, Directive } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { ReactiveFormsModule, FormControl, FormGroup, Validators } from '@angular/forms';
5
+ import { NgComponentOutlet } from '@angular/common';
6
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
+ import { distinctUntilChanged, debounceTime } from 'rxjs';
8
+
9
+ const RENDERERS = new InjectionToken('RENDERERS');
10
+ class RendererRegistry {
11
+ map = new Map();
12
+ // eslint-disable-next-line @angular-eslint/prefer-inject
13
+ constructor(renderers = []) {
14
+ renderers.flat().forEach((r) => {
15
+ this.map.set(r.type, r.component);
16
+ });
17
+ }
18
+ get(type) {
19
+ const cmp = this.map.get(type);
20
+ if (!cmp) {
21
+ throw new Error(`No renderer for type: ${type}`);
22
+ }
23
+ return cmp;
24
+ }
25
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: RendererRegistry, deps: [{ token: RENDERERS }], target: i0.ɵɵFactoryTarget.Injectable });
26
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: RendererRegistry });
27
+ }
28
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: RendererRegistry, decorators: [{
29
+ type: Injectable
30
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
31
+ type: Inject,
32
+ args: [RENDERERS]
33
+ }] }] });
34
+
35
+ const FORM_OPTIONS = new InjectionToken('FORM_OPTIONS');
36
+
37
+ const ORIENTATION_OPTIONS = {
38
+ row: 'row',
39
+ column: 'column',
40
+ };
41
+ const THEMES = {
42
+ none: 'none',
43
+ default: 'default',
44
+ };
45
+
46
+ const debouncedValueChanges = (valueChanges, time = 0, destroyRef) => valueChanges.pipe(distinctUntilChanged(), takeUntilDestroyed(destroyRef), debounceTime(time));
47
+
48
+ const UPDATE_ON = {
49
+ change: 'change',
50
+ blur: 'blur',
51
+ submit: 'submit',
52
+ };
53
+
54
+ const VALIDATOR_TYPES = {
55
+ required: 'required',
56
+ minlength: 'minlength',
57
+ maxlength: 'maxlength',
58
+ min: 'min',
59
+ max: 'max',
60
+ custom: 'custom',
61
+ };
62
+
63
+ const ERROR_MESSAGES = new InjectionToken('ERROR_MESSAGES');
64
+ const DEFAULT_ERROR_FALLBACK = new InjectionToken('DEFAULT_ERROR_FALLBACK');
65
+ const DEFAULT_ERROR_MESSAGES = [
66
+ {
67
+ type: VALIDATOR_TYPES.required,
68
+ message: () => 'This field is required',
69
+ },
70
+ {
71
+ type: VALIDATOR_TYPES.minlength,
72
+ message: (err) => `Minimum length is ${err['requiredLength']}`,
73
+ },
74
+ {
75
+ type: VALIDATOR_TYPES.maxlength,
76
+ message: (err) => `Maximum length is ${err['requiredLength']}`,
77
+ },
78
+ {
79
+ type: VALIDATOR_TYPES.min,
80
+ message: (err) => `Minimum value is ${err['min']}`,
81
+ },
82
+ {
83
+ type: VALIDATOR_TYPES.max,
84
+ message: (err) => `Maximum value is ${err['max']}`,
85
+ },
86
+ ];
87
+ class ErrorMessageRegistry {
88
+ map = new Map();
89
+ // eslint-disable-next-line @angular-eslint/prefer-inject
90
+ constructor(defs = []) {
91
+ defs.flat().forEach((def) => {
92
+ this.map.set(def.type, def.message);
93
+ });
94
+ }
95
+ get(type) {
96
+ return this.map.get(type) ?? null;
97
+ }
98
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorMessageRegistry, deps: [{ token: ERROR_MESSAGES }], target: i0.ɵɵFactoryTarget.Injectable });
99
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorMessageRegistry });
100
+ }
101
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorMessageRegistry, decorators: [{
102
+ type: Injectable
103
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
104
+ type: Inject,
105
+ args: [ERROR_MESSAGES]
106
+ }] }] });
107
+
108
+ class ErrorMessageService {
109
+ registry = inject(ErrorMessageRegistry);
110
+ defaultFallback = inject(DEFAULT_ERROR_FALLBACK);
111
+ getErrors(control, validators) {
112
+ if (!control.errors)
113
+ return [];
114
+ return Object.entries(control.errors).map(([errorKey, errorValue]) => {
115
+ const validatorSchema = this.getValidatorSchema(errorKey, validators);
116
+ const content = validatorSchema?.errorMessage ??
117
+ this.registry.get(errorKey);
118
+ if (!content) {
119
+ return { type: 'text', message: this.defaultFallback };
120
+ }
121
+ return this.resolveContent(content, errorValue);
122
+ });
123
+ }
124
+ getValidatorSchema(errorKey, validators) {
125
+ return validators.find((validator) => validator.type !== VALIDATOR_TYPES.custom
126
+ ? validator.type === errorKey
127
+ : validator.key === errorKey);
128
+ }
129
+ resolveContent(content, errorValue) {
130
+ if (typeof content === 'string') {
131
+ return { type: 'text', message: content };
132
+ }
133
+ if (typeof content === 'function') {
134
+ return { type: 'text', message: content(errorValue) };
135
+ }
136
+ return {
137
+ type: 'component',
138
+ component: content.component,
139
+ inputs: content.inputs?.(errorValue),
140
+ };
141
+ }
142
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
143
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorMessageService });
144
+ }
145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorMessageService, decorators: [{
146
+ type: Injectable
147
+ }] });
148
+
149
+ class ErrorRendererComponent {
150
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
151
+ controlSchema = input.required(...(ngDevMode ? [{ debugName: "controlSchema" }] : []));
152
+ destroyRef = inject(DestroyRef);
153
+ errorMessageService = inject(ErrorMessageService);
154
+ controlErrors = signal(null, ...(ngDevMode ? [{ debugName: "controlErrors" }] : []));
155
+ resolvedErrors = computed(() => {
156
+ const errors = this.controlErrors();
157
+ return !!errors && !!this.controlSchema().validators
158
+ ? this.errorMessageService.getErrors(this.control(), this.controlSchema().validators)
159
+ : null;
160
+ }, ...(ngDevMode ? [{ debugName: "resolvedErrors" }] : []));
161
+ ngOnInit() {
162
+ this.control()
163
+ .statusChanges.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
164
+ .subscribe(() => this.controlErrors.set(this.control().errors));
165
+ }
166
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
167
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: ErrorRendererComponent, isStandalone: true, selector: "forge-form-error-renderer", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, controlSchema: { classPropertyName: "controlSchema", publicName: "controlSchema", isSignal: true, isRequired: true, transformFunction: null } }, providers: [ErrorMessageService, ErrorMessageRegistry], ngImport: i0, template: "@for (resolvedError of resolvedErrors(); track resolvedError) {\r\n @if (resolvedError.type === 'text') {\r\n <span class=\"forge-form-error\" data-test=\"error-text\">\r\n {{ resolvedError.message }}\r\n </span>\r\n }\r\n\r\n @if (resolvedError.type === 'component') {\r\n <ng-container\r\n *ngComponentOutlet=\"\r\n resolvedError.component;\r\n inputs: {\r\n ...resolvedError.inputs,\r\n }\r\n \" />\r\n }\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
168
+ }
169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorRendererComponent, decorators: [{
170
+ type: Component,
171
+ args: [{ selector: 'forge-form-error-renderer', imports: [ReactiveFormsModule, NgComponentOutlet], providers: [ErrorMessageService, ErrorMessageRegistry], changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (resolvedError of resolvedErrors(); track resolvedError) {\r\n @if (resolvedError.type === 'text') {\r\n <span class=\"forge-form-error\" data-test=\"error-text\">\r\n {{ resolvedError.message }}\r\n </span>\r\n }\r\n\r\n @if (resolvedError.type === 'component') {\r\n <ng-container\r\n *ngComponentOutlet=\"\r\n resolvedError.component;\r\n inputs: {\r\n ...resolvedError.inputs,\r\n }\r\n \" />\r\n }\r\n}\r\n" }]
172
+ }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }], controlSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlSchema", required: true }] }] } });
173
+
174
+ class HintMessageService {
175
+ getHint(hint) {
176
+ if (!hint)
177
+ return undefined;
178
+ return hint instanceof Object && 'component' in hint
179
+ ? {
180
+ type: 'component',
181
+ component: hint.component,
182
+ inputs: hint.inputs,
183
+ }
184
+ : { type: 'text', message: hint };
185
+ }
186
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: HintMessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
187
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: HintMessageService });
188
+ }
189
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: HintMessageService, decorators: [{
190
+ type: Injectable
191
+ }] });
192
+
193
+ class HintRendererComponent {
194
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
195
+ controlSchema = input.required(...(ngDevMode ? [{ debugName: "controlSchema" }] : []));
196
+ destroyRef = inject(DestroyRef);
197
+ hintMessageService = inject(HintMessageService);
198
+ controlErrors = signal(null, ...(ngDevMode ? [{ debugName: "controlErrors" }] : []));
199
+ controlValue = signal(null, ...(ngDevMode ? [{ debugName: "controlValue" }] : []));
200
+ resolvedHint = computed(() => {
201
+ const errors = this.controlErrors();
202
+ return !errors && !!this.controlSchema().hint
203
+ ? this.hintMessageService.getHint(this.controlSchema().hint)
204
+ : null;
205
+ }, ...(ngDevMode ? [{ debugName: "resolvedHint" }] : []));
206
+ mergedInputs = computed(() => {
207
+ const hint = this.resolvedHint();
208
+ if (!hint || hint.type !== 'component') {
209
+ return {};
210
+ }
211
+ return {
212
+ control: this.control(),
213
+ controlValue: this.controlValue(),
214
+ controlErrors: this.controlErrors(),
215
+ controlSchema: this.controlSchema(),
216
+ ...hint.inputs,
217
+ };
218
+ }, ...(ngDevMode ? [{ debugName: "mergedInputs" }] : []));
219
+ ngOnInit() {
220
+ this.controlValue.set(this.control().value);
221
+ this.control()
222
+ .valueChanges.pipe(takeUntilDestroyed(this.destroyRef))
223
+ .subscribe((value) => {
224
+ this.controlValue.set(value);
225
+ });
226
+ this.control()
227
+ .statusChanges.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
228
+ .subscribe(() => this.controlErrors.set(this.control().errors));
229
+ }
230
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: HintRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
231
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: HintRendererComponent, isStandalone: true, selector: "forge-form-hint-renderer", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, controlSchema: { classPropertyName: "controlSchema", publicName: "controlSchema", isSignal: true, isRequired: true, transformFunction: null } }, providers: [HintMessageService], ngImport: i0, template: "@if (resolvedHint(); as hint) {\r\n @if (hint.type === 'text') {\r\n <span class=\"forge-form-hint\" data-test=\"hint-text\">\r\n {{ hint.message }}\r\n </span>\r\n }\r\n\r\n @if (hint.type === 'component') {\r\n <ng-container *ngComponentOutlet=\"hint.component; inputs: mergedInputs()\" />\r\n }\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
232
+ }
233
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: HintRendererComponent, decorators: [{
234
+ type: Component,
235
+ args: [{ selector: 'forge-form-hint-renderer', imports: [ReactiveFormsModule, NgComponentOutlet], providers: [HintMessageService], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (resolvedHint(); as hint) {\r\n @if (hint.type === 'text') {\r\n <span class=\"forge-form-hint\" data-test=\"hint-text\">\r\n {{ hint.message }}\r\n </span>\r\n }\r\n\r\n @if (hint.type === 'component') {\r\n <ng-container *ngComponentOutlet=\"hint.component; inputs: mergedInputs()\" />\r\n }\r\n}\r\n" }]
236
+ }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }], controlSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlSchema", required: true }] }] } });
237
+
238
+ class FormBuilderService {
239
+ buildForm(schema) {
240
+ const controls = {};
241
+ const collectControls = (node) => {
242
+ for (const item of node.controls) {
243
+ if (this.isGroupFieldSchema(item)) {
244
+ collectControls(item);
245
+ }
246
+ else {
247
+ controls[item.controlName] = new FormControl(item.initialValue ?? null, {
248
+ updateOn: item.updateOn ?? schema.updateOn,
249
+ validators: this.mapSchemaValidators(item.validators),
250
+ });
251
+ }
252
+ }
253
+ };
254
+ collectControls(schema);
255
+ return new FormGroup(controls, { updateOn: schema.updateOn });
256
+ }
257
+ mapSchemaValidators(validators) {
258
+ if (!validators?.length) {
259
+ return null;
260
+ }
261
+ return validators.map((validator) => {
262
+ switch (validator.type) {
263
+ case VALIDATOR_TYPES.required:
264
+ return Validators.required;
265
+ case VALIDATOR_TYPES.minlength:
266
+ return Validators.minLength(validator.value);
267
+ case VALIDATOR_TYPES.maxlength:
268
+ return Validators.maxLength(validator.value);
269
+ case VALIDATOR_TYPES.min:
270
+ return Validators.min(validator.value);
271
+ case VALIDATOR_TYPES.max:
272
+ return Validators.max(validator.value);
273
+ case VALIDATOR_TYPES.custom:
274
+ return validator.fn;
275
+ default:
276
+ return () => null;
277
+ }
278
+ });
279
+ }
280
+ isGroupFieldSchema(obj) {
281
+ return 'controls' in obj;
282
+ }
283
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormBuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
284
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormBuilderService });
285
+ }
286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormBuilderService, decorators: [{
287
+ type: Injectable
288
+ }] });
289
+
290
+ const VISIBILITY_BEHAVIORS = {
291
+ hide: 'hide',
292
+ disable: 'disable',
293
+ };
294
+
295
+ class FormService {
296
+ destroyRef = inject(DestroyRef);
297
+ formBuilder = inject(FormBuilderService);
298
+ form = signal(null, ...(ngDevMode ? [{ debugName: "form" }] : []));
299
+ value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
300
+ disabledByVisibility = new Set();
301
+ valueChangesSubscription;
302
+ init(formSchema) {
303
+ if (!formSchema) {
304
+ return;
305
+ }
306
+ this.valueChangesSubscription?.unsubscribe();
307
+ const form = this.formBuilder.buildForm(formSchema);
308
+ this.form.set(form);
309
+ this.valueChangesSubscription = this.form()
310
+ .valueChanges.pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
311
+ .subscribe(() => this.value.set(this.form().value));
312
+ }
313
+ applyVisibility(controlSchema, visible, clearOnHide) {
314
+ const visibilitySchema = controlSchema.visibility;
315
+ if (!visibilitySchema) {
316
+ return;
317
+ }
318
+ if (visibilitySchema.behavior === VISIBILITY_BEHAVIORS.disable) {
319
+ if (visible) {
320
+ this.disableControlByVisibility(controlSchema.controlName, clearOnHide);
321
+ }
322
+ else {
323
+ this.enableControlByVisibility(controlSchema.controlName);
324
+ }
325
+ }
326
+ }
327
+ getControl(controlName) {
328
+ if (!this.form()) {
329
+ console.error("Couldn't get control. Form is not initialized!");
330
+ return null;
331
+ }
332
+ const control = this.form().get(controlName);
333
+ if (!control) {
334
+ console.error(`Couldn't get control. Control with name "${controlName}" not found!`);
335
+ return null;
336
+ }
337
+ return control;
338
+ }
339
+ disableControlByVisibility(controlName, clearOnHide) {
340
+ const control = this.getControl(controlName);
341
+ if (!control)
342
+ return;
343
+ if (clearOnHide && !this.disabledByVisibility.has(controlName)) {
344
+ control.reset(null, { emitEvent: false });
345
+ }
346
+ if (control.enabled) {
347
+ control.disable({ emitEvent: false });
348
+ this.disabledByVisibility.add(controlName);
349
+ }
350
+ }
351
+ enableControlByVisibility(controlName) {
352
+ const control = this.getControl(controlName);
353
+ if (!control)
354
+ return;
355
+ if (this.disabledByVisibility.has(controlName)) {
356
+ control.enable({ emitEvent: false });
357
+ this.disabledByVisibility.delete(controlName);
358
+ }
359
+ }
360
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
361
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormService });
362
+ }
363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormService, decorators: [{
364
+ type: Injectable
365
+ }] });
366
+
367
+ class FormFieldComponent {
368
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
369
+ controlSchema = input.required(...(ngDevMode ? [{ debugName: "controlSchema" }] : []));
370
+ VALUE_CHANGE_DELAY = 300;
371
+ registry = inject(RendererRegistry);
372
+ formOptions = inject(FORM_OPTIONS, { optional: true });
373
+ destroyRef = inject(DestroyRef);
374
+ formService = inject((FormService));
375
+ wasVisible = true;
376
+ formSignal = this.formService.form;
377
+ componentType = computed(() => this.registry.get(this.controlSchema().type), ...(ngDevMode ? [{ debugName: "componentType" }] : []));
378
+ labelOrientation = computed(() => this.controlSchema().options?.labelOrientation ??
379
+ this.formOptions?.labelOrientation ??
380
+ ORIENTATION_OPTIONS.column, ...(ngDevMode ? [{ debugName: "labelOrientation" }] : []));
381
+ valueChanges = signal(null, ...(ngDevMode ? [{ debugName: "valueChanges" }] : []));
382
+ shouldApplyDelay = computed(() => this.controlSchema().updateOn === UPDATE_ON.change &&
383
+ this.controlSchema().type !== 'checkbox', ...(ngDevMode ? [{ debugName: "shouldApplyDelay" }] : []));
384
+ visibilityResolved = computed(() => {
385
+ const visibilitySchema = this.controlSchema().visibility;
386
+ const formValue = this.formService.value();
387
+ const visible = visibilitySchema?.fn({
388
+ value: formValue,
389
+ form: this.formSignal(),
390
+ control: this.control(),
391
+ });
392
+ return visibilitySchema ? visible : true;
393
+ }, ...(ngDevMode ? [{ debugName: "visibilityResolved" }] : []));
394
+ showControl = computed(() => {
395
+ const visibilitySchema = this.controlSchema().visibility;
396
+ return ((!this.visibilityResolved() &&
397
+ visibilitySchema?.behavior === VISIBILITY_BEHAVIORS.hide) ||
398
+ !visibilitySchema ||
399
+ visibilitySchema?.behavior !== VISIBILITY_BEHAVIORS.hide);
400
+ }, ...(ngDevMode ? [{ debugName: "showControl" }] : []));
401
+ constructor() {
402
+ effect(() => {
403
+ const visibilitySchema = this.controlSchema().visibility;
404
+ const visible = !!this.visibilityResolved();
405
+ const becameHidden = this.wasVisible && !visible;
406
+ if (!visibilitySchema) {
407
+ return;
408
+ }
409
+ this.formService.applyVisibility(this.controlSchema(), visible, becameHidden && !!visibilitySchema.clearOnHide);
410
+ this.wasVisible = !!visible;
411
+ });
412
+ }
413
+ ngOnInit() {
414
+ debouncedValueChanges(this.control().valueChanges, this.shouldApplyDelay() ? this.VALUE_CHANGE_DELAY : 0, this.destroyRef).subscribe((value) => this.valueChanges.set(value));
415
+ }
416
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
417
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FormFieldComponent, isStandalone: true, selector: "forge-form-field", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, controlSchema: { classPropertyName: "controlSchema", publicName: "controlSchema", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (showControl()) {\r\n <div\r\n data-test=\"forge-form-field-container\"\r\n [class]=\"\r\n 'forge-form-field-container forge-form-field-container--' +\r\n labelOrientation()\r\n \"\r\n [style.width]=\"controlSchema().options?.width || 'auto'\">\r\n @if (controlSchema().label) {\r\n <span class=\"forge-form-field-label\" data-test=\"forge-form-field-label\">\r\n {{ controlSchema().label }}\r\n </span>\r\n }\r\n\r\n <ng-container\r\n *ngComponentOutlet=\"\r\n componentType();\r\n inputs: {\r\n control: control(),\r\n controlSchema: controlSchema(),\r\n }\r\n \" />\r\n\r\n <forge-form-hint-renderer\r\n [control]=\"control()\"\r\n [controlSchema]=\"controlSchema()\" />\r\n\r\n <forge-form-error-renderer\r\n [control]=\"control()\"\r\n [controlSchema]=\"controlSchema()\" />\r\n </div>\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: ErrorRendererComponent, selector: "forge-form-error-renderer", inputs: ["control", "controlSchema"] }, { kind: "component", type: HintRendererComponent, selector: "forge-form-hint-renderer", inputs: ["control", "controlSchema"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
418
+ }
419
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormFieldComponent, decorators: [{
420
+ type: Component,
421
+ args: [{ selector: 'forge-form-field', imports: [
422
+ ReactiveFormsModule,
423
+ NgComponentOutlet,
424
+ ErrorRendererComponent,
425
+ HintRendererComponent,
426
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (showControl()) {\r\n <div\r\n data-test=\"forge-form-field-container\"\r\n [class]=\"\r\n 'forge-form-field-container forge-form-field-container--' +\r\n labelOrientation()\r\n \"\r\n [style.width]=\"controlSchema().options?.width || 'auto'\">\r\n @if (controlSchema().label) {\r\n <span class=\"forge-form-field-label\" data-test=\"forge-form-field-label\">\r\n {{ controlSchema().label }}\r\n </span>\r\n }\r\n\r\n <ng-container\r\n *ngComponentOutlet=\"\r\n componentType();\r\n inputs: {\r\n control: control(),\r\n controlSchema: controlSchema(),\r\n }\r\n \" />\r\n\r\n <forge-form-hint-renderer\r\n [control]=\"control()\"\r\n [controlSchema]=\"controlSchema()\" />\r\n\r\n <forge-form-error-renderer\r\n [control]=\"control()\"\r\n [controlSchema]=\"controlSchema()\" />\r\n </div>\r\n}\r\n" }]
427
+ }], ctorParameters: () => [], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }], controlSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlSchema", required: true }] }] } });
428
+
429
+ class TextRendererComponent {
430
+ control;
431
+ controlSchema;
432
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: TextRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
433
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: TextRendererComponent, isStandalone: true, selector: "forge-form-text-renderer", inputs: { control: "control", controlSchema: "controlSchema" }, ngImport: i0, template: `
434
+ <input
435
+ class="forge-form-input"
436
+ data-test="text-input"
437
+ [attr.id]="controlSchema.controlName"
438
+ [formControl]="control"
439
+ [placeholder]="controlSchema.placeholder || controlSchema.label" />
440
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
441
+ }
442
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: TextRendererComponent, decorators: [{
443
+ type: Component,
444
+ args: [{
445
+ selector: 'forge-form-text-renderer',
446
+ template: `
447
+ <input
448
+ class="forge-form-input"
449
+ data-test="text-input"
450
+ [attr.id]="controlSchema.controlName"
451
+ [formControl]="control"
452
+ [placeholder]="controlSchema.placeholder || controlSchema.label" />
453
+ `,
454
+ standalone: true,
455
+ imports: [ReactiveFormsModule],
456
+ }]
457
+ }], propDecorators: { control: [{
458
+ type: Input
459
+ }], controlSchema: [{
460
+ type: Input
461
+ }] } });
462
+
463
+ class NumberRendererComponent {
464
+ control;
465
+ controlSchema;
466
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NumberRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
467
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: NumberRendererComponent, isStandalone: true, selector: "forge-form-number-renderer", inputs: { control: "control", controlSchema: "controlSchema" }, ngImport: i0, template: `
468
+ <input
469
+ class="forge-form-input"
470
+ data-test="number-input"
471
+ type="number"
472
+ [attr.id]="controlSchema.controlName"
473
+ [formControl]="control"
474
+ [attr.min]="controlSchema.min"
475
+ [attr.max]="controlSchema.max"
476
+ [placeholder]="controlSchema.placeholder || controlSchema.label" />
477
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
478
+ }
479
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: NumberRendererComponent, decorators: [{
480
+ type: Component,
481
+ args: [{
482
+ selector: 'forge-form-number-renderer',
483
+ template: `
484
+ <input
485
+ class="forge-form-input"
486
+ data-test="number-input"
487
+ type="number"
488
+ [attr.id]="controlSchema.controlName"
489
+ [formControl]="control"
490
+ [attr.min]="controlSchema.min"
491
+ [attr.max]="controlSchema.max"
492
+ [placeholder]="controlSchema.placeholder || controlSchema.label" />
493
+ `,
494
+ standalone: true,
495
+ imports: [ReactiveFormsModule],
496
+ }]
497
+ }], propDecorators: { control: [{
498
+ type: Input
499
+ }], controlSchema: [{
500
+ type: Input
501
+ }] } });
502
+
503
+ class CheckboxRendererComponent {
504
+ control;
505
+ controlSchema;
506
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CheckboxRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
507
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: CheckboxRendererComponent, isStandalone: true, selector: "forge-form-checkbox-renderer", inputs: { control: "control", controlSchema: "controlSchema" }, ngImport: i0, template: `
508
+ <input
509
+ class="forge-form-checkbox"
510
+ data-test="checkbox-input"
511
+ type="checkbox"
512
+ [attr.id]="controlSchema.controlName"
513
+ [formControl]="control" />
514
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
515
+ }
516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: CheckboxRendererComponent, decorators: [{
517
+ type: Component,
518
+ args: [{
519
+ selector: 'forge-form-checkbox-renderer',
520
+ template: `
521
+ <input
522
+ class="forge-form-checkbox"
523
+ data-test="checkbox-input"
524
+ type="checkbox"
525
+ [attr.id]="controlSchema.controlName"
526
+ [formControl]="control" />
527
+ `,
528
+ standalone: true,
529
+ imports: [ReactiveFormsModule],
530
+ }]
531
+ }], propDecorators: { control: [{
532
+ type: Input
533
+ }], controlSchema: [{
534
+ type: Input
535
+ }] } });
536
+
537
+ class SelectRendererComponent {
538
+ control;
539
+ controlSchema;
540
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SelectRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
541
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: SelectRendererComponent, isStandalone: true, selector: "forge-form-select-renderer", inputs: { control: "control", controlSchema: "controlSchema" }, ngImport: i0, template: `
542
+ <select
543
+ class="forge-form-select"
544
+ data-test="select-input"
545
+ [attr.id]="controlSchema.controlName"
546
+ [formControl]="control">
547
+ @if (controlSchema.placeholder || controlSchema.label) {
548
+ <option data-test="select-placeholder" [ngValue]="null" disabled>
549
+ {{ controlSchema.placeholder || controlSchema.label }}
550
+ </option>
551
+ }
552
+
553
+ @for (option of controlSchema.items; track option.value) {
554
+ <option data-test="select-option" [value]="option.value">
555
+ {{ option.label }}
556
+ </option>
557
+ }
558
+ </select>
559
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
560
+ }
561
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: SelectRendererComponent, decorators: [{
562
+ type: Component,
563
+ args: [{
564
+ selector: 'forge-form-select-renderer',
565
+ template: `
566
+ <select
567
+ class="forge-form-select"
568
+ data-test="select-input"
569
+ [attr.id]="controlSchema.controlName"
570
+ [formControl]="control">
571
+ @if (controlSchema.placeholder || controlSchema.label) {
572
+ <option data-test="select-placeholder" [ngValue]="null" disabled>
573
+ {{ controlSchema.placeholder || controlSchema.label }}
574
+ </option>
575
+ }
576
+
577
+ @for (option of controlSchema.items; track option.value) {
578
+ <option data-test="select-option" [value]="option.value">
579
+ {{ option.label }}
580
+ </option>
581
+ }
582
+ </select>
583
+ `,
584
+ standalone: true,
585
+ imports: [ReactiveFormsModule],
586
+ }]
587
+ }], propDecorators: { control: [{
588
+ type: Input
589
+ }], controlSchema: [{
590
+ type: Input
591
+ }] } });
592
+
593
+ class GroupRendererComponent {
594
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
595
+ schema = input.required(...(ngDevMode ? [{ debugName: "schema" }] : []));
596
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
597
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: GroupRendererComponent, isStandalone: true, selector: "forge-form-group-renderer", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, schema: { classPropertyName: "schema", publicName: "schema", isSignal: true, isRequired: true, transformFunction: null } }, providers: [
598
+ FormBuilderService,
599
+ RendererRegistry,
600
+ {
601
+ provide: RENDERERS,
602
+ multi: true,
603
+ useValue: {
604
+ type: 'text',
605
+ component: TextRendererComponent,
606
+ },
607
+ },
608
+ {
609
+ provide: RENDERERS,
610
+ multi: true,
611
+ useValue: {
612
+ type: 'number',
613
+ component: NumberRendererComponent,
614
+ },
615
+ },
616
+ {
617
+ provide: RENDERERS,
618
+ multi: true,
619
+ useValue: {
620
+ type: 'checkbox',
621
+ component: CheckboxRendererComponent,
622
+ },
623
+ },
624
+ {
625
+ provide: RENDERERS,
626
+ multi: true,
627
+ useValue: {
628
+ type: 'select',
629
+ component: SelectRendererComponent,
630
+ },
631
+ },
632
+ ], ngImport: i0, template: "<div\r\n data-test=\"group-container\"\r\n [class]=\"\r\n 'forge-form-group forge-form-group--' + schema().options?.orientation\r\n \">\r\n @for (subjectSchema of schema().controls; track subjectSchema) {\r\n @if (subjectSchema.type === 'group') {\r\n <forge-form-group-renderer\r\n data-test=\"nested-group\"\r\n [form]=\"form()\"\r\n [schema]=\"subjectSchema\" />\r\n } @else {\r\n <forge-form-field\r\n data-test=\"group-field\"\r\n [controlSchema]=\"subjectSchema\"\r\n [control]=\"form().get(subjectSchema.controlName)!\" />\r\n }\r\n }\r\n</div>\r\n", dependencies: [{ kind: "component", type: GroupRendererComponent, selector: "forge-form-group-renderer", inputs: ["form", "schema"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: FormFieldComponent, selector: "forge-form-field", inputs: ["control", "controlSchema"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
633
+ }
634
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: GroupRendererComponent, decorators: [{
635
+ type: Component,
636
+ args: [{ selector: 'forge-form-group-renderer', imports: [ReactiveFormsModule, FormFieldComponent], providers: [
637
+ FormBuilderService,
638
+ RendererRegistry,
639
+ {
640
+ provide: RENDERERS,
641
+ multi: true,
642
+ useValue: {
643
+ type: 'text',
644
+ component: TextRendererComponent,
645
+ },
646
+ },
647
+ {
648
+ provide: RENDERERS,
649
+ multi: true,
650
+ useValue: {
651
+ type: 'number',
652
+ component: NumberRendererComponent,
653
+ },
654
+ },
655
+ {
656
+ provide: RENDERERS,
657
+ multi: true,
658
+ useValue: {
659
+ type: 'checkbox',
660
+ component: CheckboxRendererComponent,
661
+ },
662
+ },
663
+ {
664
+ provide: RENDERERS,
665
+ multi: true,
666
+ useValue: {
667
+ type: 'select',
668
+ component: SelectRendererComponent,
669
+ },
670
+ },
671
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n data-test=\"group-container\"\r\n [class]=\"\r\n 'forge-form-group forge-form-group--' + schema().options?.orientation\r\n \">\r\n @for (subjectSchema of schema().controls; track subjectSchema) {\r\n @if (subjectSchema.type === 'group') {\r\n <forge-form-group-renderer\r\n data-test=\"nested-group\"\r\n [form]=\"form()\"\r\n [schema]=\"subjectSchema\" />\r\n } @else {\r\n <forge-form-field\r\n data-test=\"group-field\"\r\n [controlSchema]=\"subjectSchema\"\r\n [control]=\"form().get(subjectSchema.controlName)!\" />\r\n }\r\n }\r\n</div>\r\n" }]
672
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], schema: [{ type: i0.Input, args: [{ isSignal: true, alias: "schema", required: true }] }] } });
673
+
674
+ class FormRendererComponent {
675
+ formService = inject((FormService));
676
+ schema = input.required(...(ngDevMode ? [{ debugName: "schema" }] : []));
677
+ formSubmit = output();
678
+ THEMES = THEMES;
679
+ formSignal = this.formService.form;
680
+ constructor() {
681
+ effect(() => {
682
+ this.formService.init(this.schema());
683
+ });
684
+ }
685
+ getControl(name) {
686
+ return this.formSignal().get(name);
687
+ }
688
+ onSubmit() {
689
+ if (this.formSignal().valid) {
690
+ this.formSubmit.emit(this.formSignal().value);
691
+ }
692
+ }
693
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
694
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FormRendererComponent, isStandalone: true, selector: "forge-form-angular", inputs: { schema: { classPropertyName: "schema", publicName: "schema", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { formSubmit: "formSubmit" }, providers: [
695
+ FormBuilderService,
696
+ RendererRegistry,
697
+ FormService,
698
+ {
699
+ provide: RENDERERS,
700
+ multi: true,
701
+ useValue: {
702
+ type: 'text',
703
+ component: TextRendererComponent,
704
+ },
705
+ },
706
+ {
707
+ provide: RENDERERS,
708
+ multi: true,
709
+ useValue: {
710
+ type: 'number',
711
+ component: NumberRendererComponent,
712
+ },
713
+ },
714
+ {
715
+ provide: RENDERERS,
716
+ multi: true,
717
+ useValue: {
718
+ type: 'checkbox',
719
+ component: CheckboxRendererComponent,
720
+ },
721
+ },
722
+ {
723
+ provide: RENDERERS,
724
+ multi: true,
725
+ useValue: {
726
+ type: 'select',
727
+ component: SelectRendererComponent,
728
+ },
729
+ },
730
+ {
731
+ provide: FORM_OPTIONS,
732
+ useFactory: (component) => component.schema().options,
733
+ deps: [FormRendererComponent],
734
+ },
735
+ {
736
+ provide: ERROR_MESSAGES,
737
+ useValue: DEFAULT_ERROR_MESSAGES,
738
+ multi: true,
739
+ },
740
+ { provide: DEFAULT_ERROR_FALLBACK, useValue: 'Invalid field', multi: true },
741
+ ], ngImport: i0, template: "@if (!!formSignal()) {\r\n <form\r\n [class]=\"'forge-form forge-form--' + schema().options?.orientation\"\r\n [class.forge-theme-default]=\"schema().options?.theme === THEMES.default\"\r\n [formGroup]=\"formSignal()!\"\r\n (ngSubmit)=\"onSubmit()\"\r\n data-test=\"form\">\r\n @for (subjectSchema of schema().controls; track subjectSchema) {\r\n @if (subjectSchema.type === 'group') {\r\n <forge-form-group-renderer\r\n data-test=\"group-renderer\"\r\n [form]=\"formSignal()!\"\r\n [schema]=\"subjectSchema\" />\r\n } @else {\r\n <forge-form-field\r\n data-test=\"form-field\"\r\n [controlSchema]=\"subjectSchema\"\r\n [control]=\"formSignal()!.get(subjectSchema.controlName)!\" />\r\n }\r\n }\r\n\r\n <button\r\n class=\"forge-form-button\"\r\n [disabled]=\"!formSignal()?.valid\"\r\n data-test=\"submit-button\"\r\n type=\"submit\">\r\n Submit\r\n </button>\r\n </form>\r\n}\r\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormFieldComponent, selector: "forge-form-field", inputs: ["control", "controlSchema"] }, { kind: "component", type: GroupRendererComponent, selector: "forge-form-group-renderer", inputs: ["form", "schema"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
742
+ }
743
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormRendererComponent, decorators: [{
744
+ type: Component,
745
+ args: [{ selector: 'forge-form-angular', imports: [ReactiveFormsModule, FormFieldComponent, GroupRendererComponent], providers: [
746
+ FormBuilderService,
747
+ RendererRegistry,
748
+ FormService,
749
+ {
750
+ provide: RENDERERS,
751
+ multi: true,
752
+ useValue: {
753
+ type: 'text',
754
+ component: TextRendererComponent,
755
+ },
756
+ },
757
+ {
758
+ provide: RENDERERS,
759
+ multi: true,
760
+ useValue: {
761
+ type: 'number',
762
+ component: NumberRendererComponent,
763
+ },
764
+ },
765
+ {
766
+ provide: RENDERERS,
767
+ multi: true,
768
+ useValue: {
769
+ type: 'checkbox',
770
+ component: CheckboxRendererComponent,
771
+ },
772
+ },
773
+ {
774
+ provide: RENDERERS,
775
+ multi: true,
776
+ useValue: {
777
+ type: 'select',
778
+ component: SelectRendererComponent,
779
+ },
780
+ },
781
+ {
782
+ provide: FORM_OPTIONS,
783
+ useFactory: (component) => component.schema().options,
784
+ deps: [FormRendererComponent],
785
+ },
786
+ {
787
+ provide: ERROR_MESSAGES,
788
+ useValue: DEFAULT_ERROR_MESSAGES,
789
+ multi: true,
790
+ },
791
+ { provide: DEFAULT_ERROR_FALLBACK, useValue: 'Invalid field', multi: true },
792
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!!formSignal()) {\r\n <form\r\n [class]=\"'forge-form forge-form--' + schema().options?.orientation\"\r\n [class.forge-theme-default]=\"schema().options?.theme === THEMES.default\"\r\n [formGroup]=\"formSignal()!\"\r\n (ngSubmit)=\"onSubmit()\"\r\n data-test=\"form\">\r\n @for (subjectSchema of schema().controls; track subjectSchema) {\r\n @if (subjectSchema.type === 'group') {\r\n <forge-form-group-renderer\r\n data-test=\"group-renderer\"\r\n [form]=\"formSignal()!\"\r\n [schema]=\"subjectSchema\" />\r\n } @else {\r\n <forge-form-field\r\n data-test=\"form-field\"\r\n [controlSchema]=\"subjectSchema\"\r\n [control]=\"formSignal()!.get(subjectSchema.controlName)!\" />\r\n }\r\n }\r\n\r\n <button\r\n class=\"forge-form-button\"\r\n [disabled]=\"!formSignal()?.valid\"\r\n data-test=\"submit-button\"\r\n type=\"submit\">\r\n Submit\r\n </button>\r\n </form>\r\n}\r\n" }]
793
+ }], ctorParameters: () => [], propDecorators: { schema: [{ type: i0.Input, args: [{ isSignal: true, alias: "schema", required: true }] }], formSubmit: [{ type: i0.Output, args: ["formSubmit"] }] } });
794
+
795
+ class FormFieldContextComponent {
796
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
797
+ controlValue = input.required(...(ngDevMode ? [{ debugName: "controlValue" }] : []));
798
+ controlErrors = input(null, ...(ngDevMode ? [{ debugName: "controlErrors" }] : []));
799
+ controlSchema = input.required(...(ngDevMode ? [{ debugName: "controlSchema" }] : []));
800
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormFieldContextComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
801
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.1", type: FormFieldContextComponent, isStandalone: true, inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, controlValue: { classPropertyName: "controlValue", publicName: "controlValue", isSignal: true, isRequired: true, transformFunction: null }, controlErrors: { classPropertyName: "controlErrors", publicName: "controlErrors", isSignal: true, isRequired: false, transformFunction: null }, controlSchema: { classPropertyName: "controlSchema", publicName: "controlSchema", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
802
+ }
803
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FormFieldContextComponent, decorators: [{
804
+ type: Directive
805
+ }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }], controlValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlValue", required: true }] }], controlErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlErrors", required: false }] }], controlSchema: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlSchema", required: true }] }] } });
806
+
807
+ const required = (credentials) => ({
808
+ type: VALIDATOR_TYPES.required,
809
+ errorMessage: credentials?.errorMessage,
810
+ });
811
+ const minLength = ({ value, errorMessage, }) => ({
812
+ type: VALIDATOR_TYPES.minlength,
813
+ value: +value,
814
+ errorMessage,
815
+ });
816
+ const maxLength = ({ value, errorMessage, }) => ({
817
+ type: VALIDATOR_TYPES.maxlength,
818
+ value: +value,
819
+ errorMessage,
820
+ });
821
+ const min = ({ value, errorMessage, }) => ({
822
+ type: VALIDATOR_TYPES.min,
823
+ value: +value,
824
+ errorMessage,
825
+ });
826
+ const max = ({ value, errorMessage, }) => ({
827
+ type: VALIDATOR_TYPES.max,
828
+ value: +value,
829
+ errorMessage,
830
+ });
831
+ const customValidator = ({ key, fn, errorMessage, }) => ({
832
+ type: VALIDATOR_TYPES.custom,
833
+ key: key ?? '',
834
+ fn: fn ?? (() => null),
835
+ errorMessage,
836
+ });
837
+
838
+ const HINT_TYPES = {
839
+ text: 'text',
840
+ custom: 'custom',
841
+ };
842
+
843
+ /*
844
+ * Public API Surface of @forge-form/angular
845
+ */
846
+ // Main entry component
847
+
848
+ /**
849
+ * Generated bundle index. Do not edit.
850
+ */
851
+
852
+ export { DEFAULT_ERROR_FALLBACK, DEFAULT_ERROR_MESSAGES, ERROR_MESSAGES, FORM_OPTIONS, FormFieldContextComponent, FormRendererComponent, HINT_TYPES, ORIENTATION_OPTIONS, RENDERERS, RendererRegistry, THEMES, UPDATE_ON, VALIDATOR_TYPES, VISIBILITY_BEHAVIORS, customValidator, max, maxLength, min, minLength, required };
853
+ //# sourceMappingURL=forge-form-angular.mjs.map