@vipsolucoes/dynamic-form 1.0.2

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,678 @@
1
+ import * as i1$1 from '@angular/common';
2
+ import { CommonModule, NgComponentOutlet } from '@angular/common';
3
+ import * as i0 from '@angular/core';
4
+ import { InjectionToken, input, inject, Component, computed, ChangeDetectionStrategy, signal, Injectable, DestroyRef, output } from '@angular/core';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import * as i1 from '@angular/forms';
7
+ import { ReactiveFormsModule, FormGroup, FormControl } from '@angular/forms';
8
+ import * as i3 from 'primeng/datepicker';
9
+ import { DatePickerModule } from 'primeng/datepicker';
10
+ import * as i2 from 'primeng/iftalabel';
11
+ import { IftaLabelModule } from 'primeng/iftalabel';
12
+ import * as i3$1 from 'primeng/inputtext';
13
+ import { InputTextModule } from 'primeng/inputtext';
14
+ import * as i3$2 from 'primeng/inputnumber';
15
+ import { InputNumberModule } from 'primeng/inputnumber';
16
+ import * as i3$3 from 'primeng/password';
17
+ import { PasswordModule } from 'primeng/password';
18
+ import * as i3$4 from 'primeng/select';
19
+ import { SelectModule } from 'primeng/select';
20
+ import * as i3$5 from 'primeng/textarea';
21
+ import { TextareaModule } from 'primeng/textarea';
22
+ import * as i2$1 from 'primeng/toggleswitch';
23
+ import { ToggleSwitchModule } from 'primeng/toggleswitch';
24
+
25
+ /**
26
+ * InjectionToken para prover mensagens de erro customizadas.
27
+ */
28
+ const DYNAMIC_FORM_ERROR_MESSAGES = new InjectionToken('DYNAMIC_FORM_ERROR_MESSAGES');
29
+
30
+ class DynamicFormErrorComponent {
31
+ control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
32
+ customMessages = inject(DYNAMIC_FORM_ERROR_MESSAGES, { optional: true });
33
+ // Mapeamento de erros para mensagens
34
+ defaultErrorMessages = {
35
+ required: () => this.customMessages?.required ?? 'Este campo é obrigatório.',
36
+ email: () => this.customMessages?.email ?? 'Por favor, insira um e-mail válido.',
37
+ minlength: (err) => this.customMessages?.minlength?.(err.requiredLength) ?? `Mínimo de ${err.requiredLength} caracteres.`,
38
+ maxlength: (err) => this.customMessages?.maxlength?.(err.requiredLength) ?? `Máximo de ${err.requiredLength} caracteres.`,
39
+ custom: (err) => (this.customMessages?.custom ? this.customMessages.custom(err) : err),
40
+ };
41
+ // Getter simples - Angular detecta mudanças automaticamente
42
+ get errorMessage() {
43
+ const ctrl = this.control();
44
+ if (!ctrl || !ctrl.errors || (!ctrl.touched && !ctrl.dirty)) {
45
+ return null;
46
+ }
47
+ const errorKey = Object.keys(ctrl.errors)[0];
48
+ return this.defaultErrorMessages[errorKey] ? this.defaultErrorMessages[errorKey](ctrl.errors[errorKey]) : 'Campo inválido.';
49
+ }
50
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: DynamicFormErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
51
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.7", type: DynamicFormErrorComponent, isStandalone: true, selector: "vp-form-field-error", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
52
+ @if (errorMessage) {
53
+ <small class="p-error">{{ errorMessage }}</small>
54
+ }
55
+ `, isInline: true, styles: [":host{display:block;margin-top:.5rem;min-height:1rem}.p-error{color:var(--p-red-500, #ef4444);font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
56
+ }
57
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: DynamicFormErrorComponent, decorators: [{
58
+ type: Component,
59
+ args: [{ selector: 'vp-form-field-error', standalone: true, imports: [CommonModule], template: `
60
+ @if (errorMessage) {
61
+ <small class="p-error">{{ errorMessage }}</small>
62
+ }
63
+ `, styles: [":host{display:block;margin-top:.5rem;min-height:1rem}.p-error{color:var(--p-red-500, #ef4444);font-size:.875rem}\n"] }]
64
+ }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }] } });
65
+
66
+ class DatePickerFieldComponent {
67
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
68
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
69
+ dateFormat = computed(() => {
70
+ const viewType = this.field().dateViewType || 'date';
71
+ const customFormat = this.field().dateFormat;
72
+ if (viewType === 'month') {
73
+ return 'mm/yy';
74
+ }
75
+ if (viewType === 'year') {
76
+ return 'yy';
77
+ }
78
+ return customFormat || 'dd/mm/yy';
79
+ }, ...(ngDevMode ? [{ debugName: "dateFormat" }] : []));
80
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: DatePickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
81
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: DatePickerFieldComponent, isStandalone: true, selector: "vp-datepicker-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
82
+ <div [formGroup]="form()">
83
+ <p-iftalabel>
84
+ <p-datepicker
85
+ [inputId]="field().key"
86
+ [formControlName]="field().key"
87
+ [showButtonBar]="true"
88
+ [iconDisplay]="'input'"
89
+ [placeholder]="field().placeholder || ''"
90
+ [dateFormat]="dateFormat()"
91
+ [view]="field().dateViewType || 'date'"
92
+ [disabled]="field().disabled ?? false"
93
+ />
94
+ <label [for]="field().key">{{ field().label }}</label>
95
+ </p-iftalabel>
96
+ </div>
97
+ `, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}p-datepicker{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i3.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
98
+ }
99
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: DatePickerFieldComponent, decorators: [{
100
+ type: Component,
101
+ args: [{ selector: 'vp-datepicker-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, DatePickerModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
102
+ <div [formGroup]="form()">
103
+ <p-iftalabel>
104
+ <p-datepicker
105
+ [inputId]="field().key"
106
+ [formControlName]="field().key"
107
+ [showButtonBar]="true"
108
+ [iconDisplay]="'input'"
109
+ [placeholder]="field().placeholder || ''"
110
+ [dateFormat]="dateFormat()"
111
+ [view]="field().dateViewType || 'date'"
112
+ [disabled]="field().disabled ?? false"
113
+ />
114
+ <label [for]="field().key">{{ field().label }}</label>
115
+ </p-iftalabel>
116
+ </div>
117
+ `, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}p-datepicker{width:100%}\n"] }]
118
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
119
+
120
+ class InputTextFieldComponent {
121
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
122
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
123
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: InputTextFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
124
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: InputTextFieldComponent, isStandalone: true, selector: "vp-input-text-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
125
+ <div [formGroup]="form()">
126
+ <p-iftalabel>
127
+ <input pInputText [id]="field().key" [type]="field().controlType" [formControlName]="field().key" [placeholder]="field().placeholder || ''" [disabled]="field().disabled ?? false" />
128
+ <label [for]="field().key">{{ field().label }}</label>
129
+ </p-iftalabel>
130
+ </div>
131
+ `, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}input{width:100%}\n"], 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.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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
132
+ }
133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: InputTextFieldComponent, decorators: [{
134
+ type: Component,
135
+ args: [{ selector: 'vp-input-text-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, InputTextModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
136
+ <div [formGroup]="form()">
137
+ <p-iftalabel>
138
+ <input pInputText [id]="field().key" [type]="field().controlType" [formControlName]="field().key" [placeholder]="field().placeholder || ''" [disabled]="field().disabled ?? false" />
139
+ <label [for]="field().key">{{ field().label }}</label>
140
+ </p-iftalabel>
141
+ </div>
142
+ `, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}input{width:100%}\n"] }]
143
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
144
+
145
+ class NumberInputFieldComponent {
146
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
147
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
148
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: NumberInputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
149
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: NumberInputFieldComponent, isStandalone: true, selector: "vp-number-input-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
150
+ <div [formGroup]="form()">
151
+ <p-iftalabel>
152
+ <p-inputNumber [id]="field().key" [formControlName]="field().key" [placeholder]="field().placeholder || ''" [disabled]="field().disabled ?? false" styleClass="w-full" class="w-full" />
153
+ <label [for]="field().key">{{ field().label }}</label>
154
+ </p-iftalabel>
155
+ </div>
156
+ `, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}:host ::ng-deep p-inputNumber,:host ::ng-deep .p-inputnumber,:host ::ng-deep .p-inputnumber input{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i3$2.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
157
+ }
158
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: NumberInputFieldComponent, decorators: [{
159
+ type: Component,
160
+ args: [{ selector: 'vp-number-input-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, InputNumberModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
161
+ <div [formGroup]="form()">
162
+ <p-iftalabel>
163
+ <p-inputNumber [id]="field().key" [formControlName]="field().key" [placeholder]="field().placeholder || ''" [disabled]="field().disabled ?? false" styleClass="w-full" class="w-full" />
164
+ <label [for]="field().key">{{ field().label }}</label>
165
+ </p-iftalabel>
166
+ </div>
167
+ `, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}:host ::ng-deep p-inputNumber,:host ::ng-deep .p-inputnumber,:host ::ng-deep .p-inputnumber input{width:100%}\n"] }]
168
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
169
+
170
+ class PasswordFieldComponent {
171
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
172
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
173
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: PasswordFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
174
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: PasswordFieldComponent, isStandalone: true, selector: "vp-password-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
175
+ <div [formGroup]="form()">
176
+ <p-iftalabel>
177
+ <p-password
178
+ [id]="field().key"
179
+ [formControlName]="field().key"
180
+ [feedback]="false"
181
+ [toggleMask]="true"
182
+ [placeholder]="field().placeholder || ''"
183
+ [disabled]="field().disabled ?? false"
184
+ styleClass="w-full"
185
+ class="w-full" />
186
+ <label [for]="field().key">{{ field().label }}</label>
187
+ </p-iftalabel>
188
+ </div>
189
+ `, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}:host ::ng-deep .p-password,:host ::ng-deep .p-password input{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: PasswordModule }, { kind: "component", type: i3$3.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
190
+ }
191
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: PasswordFieldComponent, decorators: [{
192
+ type: Component,
193
+ args: [{ selector: 'vp-password-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, PasswordModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
194
+ <div [formGroup]="form()">
195
+ <p-iftalabel>
196
+ <p-password
197
+ [id]="field().key"
198
+ [formControlName]="field().key"
199
+ [feedback]="false"
200
+ [toggleMask]="true"
201
+ [placeholder]="field().placeholder || ''"
202
+ [disabled]="field().disabled ?? false"
203
+ styleClass="w-full"
204
+ class="w-full" />
205
+ <label [for]="field().key">{{ field().label }}</label>
206
+ </p-iftalabel>
207
+ </div>
208
+ `, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}:host ::ng-deep .p-password,:host ::ng-deep .p-password input{width:100%}\n"] }]
209
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
210
+
211
+ class SelectFieldComponent {
212
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
213
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
214
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: SelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
215
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: SelectFieldComponent, isStandalone: true, selector: "vp-select-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
216
+ <div [formGroup]="form()">
217
+ <p-iftalabel>
218
+ <p-select
219
+ [inputId]="field().key"
220
+ [formControlName]="field().key"
221
+ [options]="field().options!"
222
+ [placeholder]="field().placeholder || 'Selecione'"
223
+ [disabled]="field().disabled ?? false"
224
+ optionLabel="label"
225
+ optionValue="value"
226
+ class="w-full" />
227
+ <label [for]="field().key">{{ field().label }}</label>
228
+ </p-iftalabel>
229
+ </div>
230
+ `, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}p-select{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i3$4.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
231
+ }
232
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: SelectFieldComponent, decorators: [{
233
+ type: Component,
234
+ args: [{ selector: 'vp-select-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, SelectModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
235
+ <div [formGroup]="form()">
236
+ <p-iftalabel>
237
+ <p-select
238
+ [inputId]="field().key"
239
+ [formControlName]="field().key"
240
+ [options]="field().options!"
241
+ [placeholder]="field().placeholder || 'Selecione'"
242
+ [disabled]="field().disabled ?? false"
243
+ optionLabel="label"
244
+ optionValue="value"
245
+ class="w-full" />
246
+ <label [for]="field().key">{{ field().label }}</label>
247
+ </p-iftalabel>
248
+ </div>
249
+ `, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}p-select{width:100%}\n"] }]
250
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
251
+
252
+ class TextareaFieldComponent {
253
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
254
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
255
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: TextareaFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
256
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: TextareaFieldComponent, isStandalone: true, selector: "vp-textarea-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
257
+ <div [formGroup]="form()">
258
+ <p-iftalabel>
259
+ <textarea
260
+ pTextarea
261
+ [id]="field().key"
262
+ [formControlName]="field().key"
263
+ [placeholder]="field().placeholder || ''"
264
+ [rows]="field().textareaRows ?? 1"
265
+ [cols]="field().textareaCols"
266
+ [autoResize]="field().textareaAutoResize ?? false"
267
+ [disabled]="field().disabled ?? false"
268
+ ></textarea>
269
+ <label [for]="field().key">{{ field().label }}</label>
270
+ </p-iftalabel>
271
+ </div>
272
+ `, isInline: true, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}textarea{width:100%}\n"], 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.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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: IftaLabelModule }, { kind: "component", type: i2.IftaLabel, selector: "p-iftalabel, p-iftaLabel, p-ifta-label" }, { kind: "ngmodule", type: TextareaModule }, { kind: "directive", type: i3$5.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
273
+ }
274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: TextareaFieldComponent, decorators: [{
275
+ type: Component,
276
+ args: [{ selector: 'vp-textarea-field', standalone: true, imports: [ReactiveFormsModule, IftaLabelModule, TextareaModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
277
+ <div [formGroup]="form()">
278
+ <p-iftalabel>
279
+ <textarea
280
+ pTextarea
281
+ [id]="field().key"
282
+ [formControlName]="field().key"
283
+ [placeholder]="field().placeholder || ''"
284
+ [rows]="field().textareaRows ?? 1"
285
+ [cols]="field().textareaCols"
286
+ [autoResize]="field().textareaAutoResize ?? false"
287
+ [disabled]="field().disabled ?? false"
288
+ ></textarea>
289
+ <label [for]="field().key">{{ field().label }}</label>
290
+ </p-iftalabel>
291
+ </div>
292
+ `, styles: [":host{display:block;width:100%}p-iftalabel{display:block;width:100%}textarea{width:100%}\n"] }]
293
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
294
+
295
+ class ToggleSwitchFieldComponent {
296
+ form = input.required(...(ngDevMode ? [{ debugName: "form" }] : []));
297
+ field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
298
+ isInvalid = computed(() => {
299
+ const control = this.form().get(this.field().key);
300
+ return control ? control.invalid && (control.touched || control.dirty) : false;
301
+ }, ...(ngDevMode ? [{ debugName: "isInvalid" }] : []));
302
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: ToggleSwitchFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
303
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.7", type: ToggleSwitchFieldComponent, isStandalone: true, selector: "vp-toggleswitch-field", inputs: { form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: true, transformFunction: null }, field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
304
+ <div [formGroup]="form()" class="toggleswitch-field">
305
+ <p-toggleswitch
306
+ [formControlName]="field().key"
307
+ [inputId]="field().key"
308
+ [invalid]="isInvalid()"
309
+ [disabled]="field().disabled ?? false"
310
+ [trueValue]="field().toggleTrueValue ?? true"
311
+ [falseValue]="field().toggleFalseValue ?? false" />
312
+ <label [for]="field().key" class="toggleswitch-label">{{ field().label }}</label>
313
+ </div>
314
+ `, isInline: true, styles: [":host{display:block;width:100%}.toggleswitch-field{display:flex;align-items:center;gap:.75rem;width:100%}.toggleswitch-label{cursor:pointer;-webkit-user-select:none;user-select:none;font-size:.875rem;color:var(--p-text-color, #333);margin:0}p-toggleswitch{flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$1.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
315
+ }
316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: ToggleSwitchFieldComponent, decorators: [{
317
+ type: Component,
318
+ args: [{ selector: 'vp-toggleswitch-field', standalone: true, imports: [ReactiveFormsModule, ToggleSwitchModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
319
+ <div [formGroup]="form()" class="toggleswitch-field">
320
+ <p-toggleswitch
321
+ [formControlName]="field().key"
322
+ [inputId]="field().key"
323
+ [invalid]="isInvalid()"
324
+ [disabled]="field().disabled ?? false"
325
+ [trueValue]="field().toggleTrueValue ?? true"
326
+ [falseValue]="field().toggleFalseValue ?? false" />
327
+ <label [for]="field().key" class="toggleswitch-label">{{ field().label }}</label>
328
+ </div>
329
+ `, styles: [":host{display:block;width:100%}.toggleswitch-field{display:flex;align-items:center;gap:.75rem;width:100%}.toggleswitch-label{cursor:pointer;-webkit-user-select:none;user-select:none;font-size:.875rem;color:var(--p-text-color, #333);margin:0}p-toggleswitch{flex-shrink:0}\n"] }]
330
+ }], propDecorators: { form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: true }] }], field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }] } });
331
+
332
+ /**
333
+ * Serviço para registro de campos customizados.
334
+ * Permite adicionar novos tipos de campos dinamicamente.
335
+ */
336
+ class FieldRegistryService {
337
+ registry = signal(new Map(), ...(ngDevMode ? [{ debugName: "registry" }] : []));
338
+ /**
339
+ * Registra um novo tipo de campo.
340
+ * @param type Tipo do campo (ex: 'custom', 'file', etc.)
341
+ * @param component Componente Angular que renderiza o campo
342
+ */
343
+ registerField(type, component) {
344
+ this.registry.update((map) => new Map(map).set(type, component));
345
+ }
346
+ /**
347
+ * Obtém o componente registrado para um tipo de campo.
348
+ * @param type Tipo do campo
349
+ * @returns Componente Angular ou undefined se não encontrado
350
+ */
351
+ getField(type) {
352
+ return this.registry().get(type);
353
+ }
354
+ /**
355
+ * Remove um tipo de campo do registro.
356
+ * @param type Tipo do campo a ser removido
357
+ */
358
+ unregisterField(type) {
359
+ this.registry.update((map) => {
360
+ const newMap = new Map(map);
361
+ newMap.delete(type);
362
+ return newMap;
363
+ });
364
+ }
365
+ /**
366
+ * Limpa todos os campos registrados.
367
+ */
368
+ clear() {
369
+ this.registry.set(new Map());
370
+ }
371
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: FieldRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
372
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: FieldRegistryService, providedIn: 'root' });
373
+ }
374
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: FieldRegistryService, decorators: [{
375
+ type: Injectable,
376
+ args: [{ providedIn: 'root' }]
377
+ }] });
378
+
379
+ class DynamicFormComponent {
380
+ destroyRef = inject(DestroyRef);
381
+ fieldRegistry = inject(FieldRegistryService);
382
+ config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
383
+ formReady = output();
384
+ form = new FormGroup({});
385
+ fieldComponents = {
386
+ text: InputTextFieldComponent,
387
+ email: InputTextFieldComponent,
388
+ password: PasswordFieldComponent,
389
+ number: NumberInputFieldComponent,
390
+ select: SelectFieldComponent,
391
+ datepicker: DatePickerFieldComponent,
392
+ textarea: TextareaFieldComponent,
393
+ toggleswitch: ToggleSwitchFieldComponent,
394
+ };
395
+ ngOnInit() {
396
+ const configValue = this.config();
397
+ if (configValue && configValue.length > 0) {
398
+ this.buildForm(configValue);
399
+ this.setupFieldDependencies(configValue);
400
+ this.formReady.emit(this.form);
401
+ }
402
+ }
403
+ buildForm(config) {
404
+ config.forEach((field) => {
405
+ // Para toggle switch, o valor padrão é false se não especificado
406
+ const defaultValue = field.controlType === 'toggleswitch' ? (field.value ?? false) : (field.value ?? '');
407
+ // Se o campo tem enabledWhen, ele deve começar desabilitado a menos que o toggle já esteja ativo
408
+ const shouldBeDisabled = field.disabled ?? (field.enabledWhen ? !this.getToggleValue(field.enabledWhen, config) : false);
409
+ const control = shouldBeDisabled
410
+ ? new FormControl({ value: defaultValue, disabled: true }, {
411
+ validators: field.validators ?? [],
412
+ })
413
+ : new FormControl(defaultValue, {
414
+ validators: field.validators ?? [],
415
+ });
416
+ this.form.addControl(field.key, control);
417
+ });
418
+ }
419
+ setupFieldDependencies(config) {
420
+ config.forEach((field) => {
421
+ if (!field.enabledWhen) {
422
+ return;
423
+ }
424
+ const toggleField = config.find((f) => f.key === field.enabledWhen);
425
+ if (!toggleField) {
426
+ console.warn(`DynamicFormComponent: Campo '${field.key}' referencia '${field.enabledWhen}' em enabledWhen, mas este campo não existe no formulário.`);
427
+ return;
428
+ }
429
+ if (toggleField.controlType !== 'toggleswitch') {
430
+ console.warn(`DynamicFormComponent: Campo '${field.key}' referencia '${field.enabledWhen}' em enabledWhen, mas este campo não é do tipo 'toggleswitch'.`);
431
+ return;
432
+ }
433
+ const toggleControl = this.form.get(field.enabledWhen);
434
+ const dependentControl = this.form.get(field.key);
435
+ if (!toggleControl || !dependentControl) {
436
+ console.warn(`DynamicFormComponent: Não foi possível encontrar os controles para configurar a dependência entre '${field.enabledWhen}' e '${field.key}'.`);
437
+ return;
438
+ }
439
+ // Configura a subscription para reagir às mudanças do toggle
440
+ toggleControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((toggleValue) => {
441
+ const isToggleActive = toggleValue === (toggleField.toggleTrueValue ?? true);
442
+ if (isToggleActive) {
443
+ dependentControl.enable();
444
+ }
445
+ else {
446
+ // Limpa o valor do campo antes de desabilitá-lo
447
+ const resetValue = this.getResetValueForFieldType(field.controlType);
448
+ dependentControl.setValue(resetValue, { emitEvent: false });
449
+ dependentControl.disable();
450
+ }
451
+ });
452
+ });
453
+ }
454
+ getToggleValue(toggleKey, config) {
455
+ const toggleField = config.find((f) => f.key === toggleKey);
456
+ if (!toggleField || toggleField.controlType !== 'toggleswitch') {
457
+ return false;
458
+ }
459
+ const toggleTrueValue = toggleField.toggleTrueValue ?? true;
460
+ const toggleValue = toggleField.value ?? false;
461
+ return toggleValue === toggleTrueValue;
462
+ }
463
+ /**
464
+ * Retorna o valor padrão de reset para cada tipo de campo.
465
+ * Usado quando um campo dependente é desabilitado e precisa ser limpo.
466
+ */
467
+ getResetValueForFieldType(controlType) {
468
+ switch (controlType) {
469
+ case 'text':
470
+ case 'email':
471
+ case 'password':
472
+ case 'textarea':
473
+ return '';
474
+ case 'number':
475
+ return null;
476
+ case 'select':
477
+ return null;
478
+ case 'datepicker':
479
+ return null;
480
+ default:
481
+ return '';
482
+ }
483
+ }
484
+ /**
485
+ * Obtém o componente a ser renderizado para um tipo de campo.
486
+ * Primeiro verifica no registro customizado, depois nos componentes padrão.
487
+ */
488
+ getFieldComponent(controlType) {
489
+ // Verifica primeiro no registro customizado
490
+ const customComponent = this.fieldRegistry.getField(controlType);
491
+ if (customComponent) {
492
+ return customComponent;
493
+ }
494
+ // Fallback para componentes padrão
495
+ return this.fieldComponents[controlType] || null;
496
+ }
497
+ getControl(key) {
498
+ const control = this.form.get(key);
499
+ if (!control) {
500
+ console.warn(`DynamicFormComponent: Controle não encontrado para a chave: ${key}`);
501
+ }
502
+ return control;
503
+ }
504
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
505
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.7", type: DynamicFormComponent, isStandalone: true, selector: "vp-dynamic-form", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { formReady: "formReady" }, ngImport: i0, template: "<form [formGroup]=\"form\" class=\"dynamic-form-container\">\n @for (field of config(); track field.key) {\n @if (getFieldComponent(field.controlType); as fieldComponent) {\n <div [class]=\"'form-field-wrapper ' + (field.styleClass || '')\">\n <!-- Dynamically render the correct field component -->\n <ng-container [ngComponentOutlet]=\"fieldComponent\" [ngComponentOutletInputs]=\"{ form: form, field: field }\" />\n\n @if (field.hint) {\n <small class=\"hint-text\">{{ field.hint }}</small>\n }\n\n <!-- Reusable error display component -->\n <vp-form-field-error [control]=\"getControl(field.key)\" />\n </div>\n } @else {\n <div class=\"form-field-wrapper\">\n <small class=\"p-error\">Tipo de campo '{{ field.controlType }}' n\u00E3o encontrado.</small>\n </div>\n }\n }\n</form>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.dynamic-form-container{display:flex;flex-direction:column;gap:1.75rem;padding:1rem;border:1px solid var(--p-surface-border);border-radius:var(--p-border-radius);background-color:var(--p-surface-section)}.form-field-wrapper{display:flex;flex-direction:column;position:relative}:is(p-inputNumber,p-password,p-select,p-iftalabel){width:100%}:host ::ng-deep .p-password,:host ::ng-deep .p-password input,:host ::ng-deep .p-inputnumber,:host ::ng-deep .p-inputnumber input,:host ::ng-deep .p-datepicker input,:host ::ng-deep .p-select{width:100%!important}input[pInputText]{width:100%}.hint-text{margin-top:.5rem;color:var(--p-text-muted-color)}.error-messages{margin-top:.5rem;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { 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: DynamicFormErrorComponent, selector: "vp-form-field-error", inputs: ["control"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
506
+ }
507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.7", ngImport: i0, type: DynamicFormComponent, decorators: [{
508
+ type: Component,
509
+ args: [{ selector: 'vp-dynamic-form', standalone: true, imports: [CommonModule, ReactiveFormsModule, NgComponentOutlet, DynamicFormErrorComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form [formGroup]=\"form\" class=\"dynamic-form-container\">\n @for (field of config(); track field.key) {\n @if (getFieldComponent(field.controlType); as fieldComponent) {\n <div [class]=\"'form-field-wrapper ' + (field.styleClass || '')\">\n <!-- Dynamically render the correct field component -->\n <ng-container [ngComponentOutlet]=\"fieldComponent\" [ngComponentOutletInputs]=\"{ form: form, field: field }\" />\n\n @if (field.hint) {\n <small class=\"hint-text\">{{ field.hint }}</small>\n }\n\n <!-- Reusable error display component -->\n <vp-form-field-error [control]=\"getControl(field.key)\" />\n </div>\n } @else {\n <div class=\"form-field-wrapper\">\n <small class=\"p-error\">Tipo de campo '{{ field.controlType }}' n\u00E3o encontrado.</small>\n </div>\n }\n }\n</form>\n", styles: ["@charset \"UTF-8\";:host{display:block;width:100%}.dynamic-form-container{display:flex;flex-direction:column;gap:1.75rem;padding:1rem;border:1px solid var(--p-surface-border);border-radius:var(--p-border-radius);background-color:var(--p-surface-section)}.form-field-wrapper{display:flex;flex-direction:column;position:relative}:is(p-inputNumber,p-password,p-select,p-iftalabel){width:100%}:host ::ng-deep .p-password,:host ::ng-deep .p-password input,:host ::ng-deep .p-inputnumber,:host ::ng-deep .p-inputnumber input,:host ::ng-deep .p-datepicker input,:host ::ng-deep .p-select{width:100%!important}input[pInputText]{width:100%}.hint-text{margin-top:.5rem;color:var(--p-text-muted-color)}.error-messages{margin-top:.5rem;display:flex;flex-direction:column}\n"] }]
510
+ }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], formReady: [{ type: i0.Output, args: ["formReady"] }] } });
511
+
512
+ const PRIMENG_PTBR = {
513
+ // Filtros
514
+ startsWith: 'Começa com',
515
+ contains: 'Contém',
516
+ notContains: 'Não contém',
517
+ endsWith: 'Termina com',
518
+ equals: 'Igual',
519
+ notEquals: 'Diferente',
520
+ noFilter: 'Sem filtro',
521
+ lt: 'Menor que',
522
+ lte: 'Menor ou igual a',
523
+ gt: 'Maior que',
524
+ gte: 'Maior ou igual a',
525
+ is: 'É',
526
+ isNot: 'Não é',
527
+ before: 'Antes',
528
+ after: 'Depois',
529
+ dateIs: 'Data é',
530
+ dateIsNot: 'Data não é',
531
+ dateBefore: 'Data antes',
532
+ dateAfter: 'Data depois',
533
+ // Regras
534
+ clear: 'Limpar',
535
+ apply: 'Aplicar',
536
+ matchAll: 'Corresponder a todos',
537
+ matchAny: 'Corresponder a qualquer',
538
+ addRule: 'Adicionar regra',
539
+ removeRule: 'Remover regra',
540
+ // Ações
541
+ accept: 'Sim',
542
+ reject: 'Não',
543
+ choose: 'Escolher',
544
+ upload: 'Enviar',
545
+ cancel: 'Cancelar',
546
+ completed: 'Concluído',
547
+ pending: 'Pendente',
548
+ // Arquivos
549
+ fileSizeTypes: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
550
+ emptyMessage: 'Nenhum registro encontrado',
551
+ emptyFilterMessage: 'Nenhum resultado encontrado',
552
+ fileChosenMessage: '{0} arquivo(s) selecionado(s)',
553
+ noFileChosenMessage: 'Nenhum arquivo selecionado',
554
+ // Datas
555
+ dayNames: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'],
556
+ dayNamesShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'],
557
+ dayNamesMin: ['D', 'S', 'T', 'Q', 'Q', 'S', 'S'],
558
+ monthNames: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
559
+ monthNamesShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'],
560
+ dateFormat: 'dd/mm/yy',
561
+ firstDayOfWeek: 0,
562
+ today: 'Hoje',
563
+ weekHeader: 'Sem',
564
+ // Password
565
+ weak: 'Fraca',
566
+ medium: 'Média',
567
+ strong: 'Forte',
568
+ passwordPrompt: 'Digite uma senha',
569
+ // Date navigation
570
+ chooseYear: 'Escolher ano',
571
+ chooseMonth: 'Escolher mês',
572
+ chooseDate: 'Escolher data',
573
+ prevDecade: 'Década anterior',
574
+ nextDecade: 'Próxima década',
575
+ prevYear: 'Ano anterior',
576
+ nextYear: 'Próximo ano',
577
+ prevMonth: 'Mês anterior',
578
+ nextMonth: 'Próximo mês',
579
+ prevHour: 'Hora anterior',
580
+ nextHour: 'Próxima hora',
581
+ prevMinute: 'Minuto anterior',
582
+ nextMinute: 'Próximo minuto',
583
+ prevSecond: 'Segundo anterior',
584
+ nextSecond: 'Próximo segundo',
585
+ am: 'AM',
586
+ pm: 'PM',
587
+ // Busca / seleção
588
+ searchMessage: 'Digite para pesquisar',
589
+ selectionMessage: '{0} item(ns) selecionado(s)',
590
+ emptySelectionMessage: 'Nenhum item selecionado',
591
+ emptySearchMessage: 'Nenhum resultado encontrado',
592
+ // ARIA (acessibilidade)
593
+ aria: {
594
+ trueLabel: 'Verdadeiro',
595
+ falseLabel: 'Falso',
596
+ nullLabel: 'Não selecionado',
597
+ star: '1 estrela',
598
+ stars: '{star} estrelas',
599
+ selectAll: 'Selecionar todos',
600
+ unselectAll: 'Desmarcar todos',
601
+ close: 'Fechar',
602
+ previous: 'Anterior',
603
+ next: 'Próximo',
604
+ navigation: 'Navegação',
605
+ scrollTop: 'Rolar para o topo',
606
+ moveTop: 'Mover para o topo',
607
+ moveUp: 'Mover para cima',
608
+ moveDown: 'Mover para baixo',
609
+ moveBottom: 'Mover para o final',
610
+ moveToTarget: 'Mover para o destino',
611
+ moveToSource: 'Mover para a origem',
612
+ moveAllToTarget: 'Mover todos para o destino',
613
+ moveAllToSource: 'Mover todos para a origem',
614
+ pageLabel: 'Página {page}',
615
+ firstPageLabel: 'Primeira página',
616
+ lastPageLabel: 'Última página',
617
+ nextPageLabel: 'Próxima página',
618
+ prevPageLabel: 'Página anterior',
619
+ rowsPerPageLabel: 'Itens por página',
620
+ previousPageLabel: 'Página anterior',
621
+ jumpToPageDropdownLabel: 'Pular para página',
622
+ jumpToPageInputLabel: 'Ir para página',
623
+ selectRow: 'Selecionar linha',
624
+ unselectRow: 'Desmarcar linha',
625
+ expandRow: 'Expandir linha',
626
+ collapseRow: 'Recolher linha',
627
+ showFilterMenu: 'Mostrar menu de filtro',
628
+ hideFilterMenu: 'Ocultar menu de filtro',
629
+ filterOperator: 'Operador de filtro',
630
+ filterConstraint: 'Restrição de filtro',
631
+ editRow: 'Editar linha',
632
+ saveEdit: 'Salvar edição',
633
+ cancelEdit: 'Cancelar edição',
634
+ listView: 'Visualização em lista',
635
+ gridView: 'Visualização em grade',
636
+ slide: 'Slide',
637
+ slideNumber: 'Slide {slideNumber}',
638
+ zoomImage: 'Ampliar imagem',
639
+ zoomIn: 'Aumentar zoom',
640
+ zoomOut: 'Reduzir zoom',
641
+ rotateRight: 'Girar à direita',
642
+ rotateLeft: 'Girar à esquerda',
643
+ listLabel: 'Lista',
644
+ selectColor: 'Selecionar cor',
645
+ removeLabel: 'Remover',
646
+ browseFiles: 'Procurar arquivos',
647
+ maximizeLabel: 'Maximizar',
648
+ minimizeLabel: 'Minimizar',
649
+ },
650
+ };
651
+
652
+ /**
653
+ * Provider para configurar mensagens de erro customizadas.
654
+ * @param messages Mensagens de erro customizadas
655
+ * @returns Provider configurado
656
+ */
657
+ function provideDynamicFormConfig(messages) {
658
+ const providers = [];
659
+ if (messages) {
660
+ providers.push({
661
+ provide: DYNAMIC_FORM_ERROR_MESSAGES,
662
+ useValue: messages,
663
+ });
664
+ }
665
+ return providers;
666
+ }
667
+
668
+ /*
669
+ * Public API Surface of @vipsolucoes/dynamic-form
670
+ */
671
+ // Componentes
672
+
673
+ /**
674
+ * Generated bundle index. Do not edit.
675
+ */
676
+
677
+ export { DYNAMIC_FORM_ERROR_MESSAGES, DatePickerFieldComponent, DynamicFormComponent, DynamicFormErrorComponent, FieldRegistryService, InputTextFieldComponent, NumberInputFieldComponent, PRIMENG_PTBR, PasswordFieldComponent, SelectFieldComponent, TextareaFieldComponent, ToggleSwitchFieldComponent, provideDynamicFormConfig };
678
+ //# sourceMappingURL=vipsolucoes-dynamic-form.mjs.map