@suntelecoms/ngx-dynamic-form 1.1.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 @@
1
+ {"version":3,"file":"suntelecoms-ngx-dynamic-form.mjs","sources":["../../../projects/ngx-dynamic-form/src/lib/services/dynamic-form-builder.service.ts","../../../projects/ngx-dynamic-form/src/lib/components/dynamic-field/dynamic-field.component.ts","../../../projects/ngx-dynamic-form/src/lib/services/condition-evaluator.service.ts","../../../projects/ngx-dynamic-form/src/lib/components/dynamic-form/dynamic-form.component.ts","../../../projects/ngx-dynamic-form/src/lib/storage/form-storage.adapter.ts","../../../projects/ngx-dynamic-form/src/lib/services/form-config.service.ts","../../../projects/ngx-dynamic-form/src/lib/components/form-builder/form-builder.component.ts","../../../projects/ngx-dynamic-form/src/lib/components/form-builder/form-builder.component.html","../../../projects/ngx-dynamic-form/src/lib/components/mes-formulaires/mes-formulaires.component.ts","../../../projects/ngx-dynamic-form/src/lib/components/mes-formulaires/mes-formulaires.component.html","../../../projects/ngx-dynamic-form/src/lib/components/form-loader/form-loader.component.ts","../../../projects/ngx-dynamic-form/src/lib/components/form-loader/form-loader.component.html","../../../projects/ngx-dynamic-form/src/lib/storage/local-storage.adapter.ts","../../../projects/ngx-dynamic-form/src/lib/storage/http-storage.adapter.ts","../../../projects/ngx-dynamic-form/src/lib/providers.ts","../../../projects/ngx-dynamic-form/src/public-api.ts","../../../projects/ngx-dynamic-form/src/suntelecoms-ngx-dynamic-form.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport {\n AbstractControl,\n FormControl,\n FormGroup,\n ValidatorFn,\n Validators,\n} from '@angular/forms';\nimport { DynamicFormField, FieldValidation } from '../models/form-field.model';\n\n@Injectable({ providedIn: 'root' })\nexport class DynamicFormBuilderService {\n /**\n * Build a FormGroup from an array of DynamicFormField definitions.\n */\n buildFormGroup(fields: DynamicFormField[]): FormGroup {\n const group: Record<string, AbstractControl> = {};\n\n for (const field of fields) {\n if (field.type === 'divider' || field.type === 'heading') continue;\n\n const validators = this.buildValidators(field.validation);\n const control = new FormControl(\n {\n value: field.defaultValue ?? null,\n disabled: field.disabled ?? false,\n },\n validators\n );\n group[field.key] = control;\n }\n\n return new FormGroup(group);\n }\n\n /**\n * Convert FieldValidation config into Angular ValidatorFn[].\n */\n buildValidators(validation?: FieldValidation): ValidatorFn[] {\n if (!validation) return [];\n\n const validators: ValidatorFn[] = [];\n\n if (validation.required) validators.push(Validators.required);\n if (validation.email) validators.push(Validators.email);\n if (validation.minLength != null)\n validators.push(Validators.minLength(validation.minLength));\n if (validation.maxLength != null)\n validators.push(Validators.maxLength(validation.maxLength));\n if (validation.min != null) validators.push(Validators.min(validation.min));\n if (validation.max != null) validators.push(Validators.max(validation.max));\n if (validation.pattern)\n validators.push(Validators.pattern(validation.pattern));\n\n if (validation.custom) {\n const customFn = validation.custom;\n validators.push((control: AbstractControl) => {\n const msg = customFn(control.value);\n return msg ? { custom: msg } : null;\n });\n }\n\n return validators;\n }\n\n /**\n * Get the human-readable error message for a form control.\n */\n getErrorMessage(\n control: AbstractControl,\n validation?: FieldValidation\n ): string | null {\n if (!control.errors || !control.touched) return null;\n\n const msgs = validation?.messages ?? {};\n\n if (control.errors['required'])\n return msgs['required'] ?? 'Ce champ est requis.';\n if (control.errors['email'])\n return msgs['email'] ?? 'Adresse e-mail invalide.';\n if (control.errors['minlength'])\n return (\n msgs['minLength'] ??\n `Minimum ${control.errors['minlength'].requiredLength} caractères.`\n );\n if (control.errors['maxlength'])\n return (\n msgs['maxLength'] ??\n `Maximum ${control.errors['maxlength'].requiredLength} caractères.`\n );\n if (control.errors['min'])\n return msgs['min'] ?? `Valeur minimum : ${control.errors['min'].min}.`;\n if (control.errors['max'])\n return msgs['max'] ?? `Valeur maximum : ${control.errors['max'].max}.`;\n if (control.errors['pattern'])\n return msgs['pattern'] ?? 'Format invalide.';\n if (control.errors['custom']) return control.errors['custom'];\n\n return 'Valeur invalide.';\n }\n}\n","import {\n Component,\n Input,\n OnInit,\n} from '@angular/core';\nimport { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { MatFormField, MatLabel, MatError, MatHint, MatPrefix, MatSuffix } from '@angular/material/form-field';\nimport { MatInput } from '@angular/material/input';\nimport { MatSelect } from '@angular/material/select';\nimport { MatOption } from '@angular/material/core';\nimport { MatRadioGroup, MatRadioButton } from '@angular/material/radio';\nimport { MatCheckbox } from '@angular/material/checkbox';\nimport { MatIcon } from '@angular/material/icon';\nimport { DynamicFormField, SelectOption } from '../../models/form-field.model';\nimport { DynamicFormBuilderService } from '../../services/dynamic-form-builder.service';\n\n@Component({\n selector: 'ngx-dynamic-field',\n standalone: true,\n imports: [\n ReactiveFormsModule,\n MatFormField, MatLabel, MatError, MatHint, MatPrefix, MatSuffix,\n MatInput,\n MatSelect, MatOption,\n MatRadioGroup, MatRadioButton,\n MatCheckbox,\n MatIcon,\n ],\n template: `\n @if (field.type === 'divider') {\n <hr class=\"ngx-divider\" />\n }\n\n @if (field.type === 'heading') {\n @switch (field.level || 2) {\n @case (1) { <h1 class=\"ngx-heading\">{{ field.text || field.label }}</h1> }\n @case (2) { <h2 class=\"ngx-heading\">{{ field.text || field.label }}</h2> }\n @case (3) { <h3 class=\"ngx-heading\">{{ field.text || field.label }}</h3> }\n @case (4) { <h4 class=\"ngx-heading\">{{ field.text || field.label }}</h4> }\n @case (5) { <h5 class=\"ngx-heading\">{{ field.text || field.label }}</h5> }\n @case (6) { <h6 class=\"ngx-heading\">{{ field.text || field.label }}</h6> }\n @default { <h2 class=\"ngx-heading\">{{ field.text || field.label }}</h2> }\n }\n }\n\n @if (isInputField) {\n @if (field.type === 'checkbox') {\n <div class=\"ngx-checkbox-wrapper\">\n <mat-checkbox color=\"primary\" [formControl]=\"formControl\">\n {{ field.placeholder || field.label }}\n </mat-checkbox>\n @if (hasError) {\n <small class=\"ngx-mat-standalone-error\">{{ errorMessage }}</small>\n }\n </div>\n\n } @else if (field.type === 'radio') {\n <div class=\"ngx-radio-wrapper\">\n @if (field.label) {\n <label class=\"ngx-radio-label\">{{ field.label }}</label>\n }\n <mat-radio-group [formControl]=\"formControl\" class=\"ngx-radio-group\">\n @for (opt of resolvedOptions; track opt.value) {\n <mat-radio-button [value]=\"opt.value\" color=\"primary\">\n {{ opt.label }}\n </mat-radio-button>\n }\n </mat-radio-group>\n @if (hasError) {\n <small class=\"ngx-mat-standalone-error\">{{ errorMessage }}</small>\n }\n </div>\n\n } @else if (field.type === 'textarea') {\n <mat-form-field appearance=\"outline\" class=\"ngx-mat-field\">\n @if (field.label) { <mat-label>{{ field.label }}</mat-label> }\n @if (field.icon) { <mat-icon matPrefix>{{ field.icon }}</mat-icon> }\n <textarea\n matInput\n [id]=\"field.key\"\n [formControl]=\"formControl\"\n [placeholder]=\"field.placeholder || ''\"\n [rows]=\"field.rows || 3\"\n [readonly]=\"field.readonly || false\"\n ></textarea>\n @if (field.iconSuffix) { <mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon> }\n @if (field.hint) { <mat-hint>{{ field.hint }}</mat-hint> }\n <mat-error>{{ errorMessage }}</mat-error>\n </mat-form-field>\n\n } @else if (field.type === 'select' || field.type === 'multiselect') {\n <mat-form-field appearance=\"outline\" class=\"ngx-mat-field\">\n @if (field.label) { <mat-label>{{ field.label }}</mat-label> }\n @if (field.icon) { <mat-icon matPrefix>{{ field.icon }}</mat-icon> }\n <mat-select [formControl]=\"formControl\" [multiple]=\"field.type === 'multiselect'\">\n @if (field.placeholder) {\n <mat-option value=\"\">{{ field.placeholder }}</mat-option>\n }\n @for (opt of resolvedOptions; track opt.value) {\n <mat-option [value]=\"opt.value\" [disabled]=\"opt.disabled || false\">\n {{ opt.label }}\n </mat-option>\n }\n </mat-select>\n @if (field.iconSuffix) { <mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon> }\n @if (field.hint) { <mat-hint>{{ field.hint }}</mat-hint> }\n <mat-error>{{ errorMessage }}</mat-error>\n </mat-form-field>\n\n } @else if (field.type === 'file') {\n <div class=\"ngx-file-wrapper\">\n @if (field.label) {\n <label class=\"ngx-file-label\">\n {{ field.label }}\n @if (field.validation?.required) {\n <span class=\"ngx-required\" aria-hidden=\"true\"> *</span>\n }\n </label>\n }\n <input\n type=\"file\"\n [id]=\"field.key\"\n [accept]=\"field.accept || '*'\"\n [multiple]=\"field.multiple || false\"\n class=\"ngx-file-input\"\n />\n @if (field.hint) { <small class=\"ngx-hint\">{{ field.hint }}</small> }\n </div>\n\n } @else if (field.type === 'hidden') {\n <input type=\"hidden\" [formControl]=\"formControl\" />\n\n } @else {\n <mat-form-field appearance=\"outline\" class=\"ngx-mat-field\">\n @if (field.label) { <mat-label>{{ field.label }}</mat-label> }\n @if (field.icon) { <mat-icon matPrefix>{{ field.icon }}</mat-icon> }\n <input\n matInput\n [id]=\"field.key\"\n [type]=\"field.type\"\n [formControl]=\"formControl\"\n [placeholder]=\"field.placeholder || ''\"\n [readonly]=\"field.readonly || false\"\n [attr.min]=\"field.validation?.min\"\n [attr.max]=\"field.validation?.max\"\n [attr.minlength]=\"field.validation?.minLength\"\n [attr.maxlength]=\"field.validation?.maxLength\"\n />\n @if (field.iconSuffix) { <mat-icon matSuffix>{{ field.iconSuffix }}</mat-icon> }\n @if (field.hint) { <mat-hint>{{ field.hint }}</mat-hint> }\n <mat-error>{{ errorMessage }}</mat-error>\n </mat-form-field>\n }\n }\n `,\n styles: [`\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n }\n\n .ngx-mat-field {\n width: 100%;\n }\n\n .ngx-radio-wrapper {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n padding: 0.25rem 0 0.75rem;\n }\n\n .ngx-radio-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: rgba(0, 0, 0, 0.6);\n }\n\n .ngx-radio-group {\n display: flex;\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .ngx-checkbox-wrapper {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n padding: 0.25rem 0;\n }\n\n .ngx-file-wrapper {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n padding-bottom: 0.75rem;\n }\n\n .ngx-file-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: rgba(0, 0, 0, 0.87);\n }\n\n .ngx-file-input {\n border: 1px solid rgba(0, 0, 0, 0.23);\n border-radius: 4px;\n padding: 0.625rem 0.75rem;\n font-size: 0.875rem;\n cursor: pointer;\n background: transparent;\n transition: border-color 0.15s;\n }\n\n .ngx-file-input:hover {\n border-color: rgba(0, 0, 0, 0.87);\n }\n\n .ngx-mat-standalone-error {\n font-size: 0.75rem;\n color: var(--mat-sys-error, #b00020);\n }\n `],\n})\nexport class DynamicFieldComponent implements OnInit {\n @Input({ required: true }) field!: DynamicFormField;\n @Input({ required: true }) form!: FormGroup;\n\n constructor(private builder: DynamicFormBuilderService) {}\n\n resolvedOptions: SelectOption[] = [];\n\n ngOnInit(): void {\n if (this.hasOptions) {\n this.resolveOptions();\n }\n }\n\n private resolveOptions(): void {\n const opts = this.field.options;\n if (!opts) return;\n if (Array.isArray(opts)) {\n this.resolvedOptions = opts.map((o) =>\n typeof o === 'string' ? { label: o, value: o } : o\n );\n }\n }\n\n get formControl(): FormControl {\n return this.form.get(this.field.key) as FormControl;\n }\n\n get isInputField(): boolean {\n return this.field.type !== 'divider' && this.field.type !== 'heading';\n }\n\n get hasOptions(): boolean {\n return ['select', 'multiselect', 'radio'].includes(this.field.type);\n }\n\n get hasError(): boolean {\n const ctrl = this.formControl;\n return !!(ctrl && ctrl.invalid && ctrl.touched);\n }\n\n get errorMessage(): string | null {\n const ctrl = this.formControl;\n if (!ctrl) return null;\n return this.builder.getErrorMessage(ctrl, this.field.validation);\n }\n}\n","import { Injectable } from '@angular/core';\nimport { FormGroup } from '@angular/forms';\nimport { FieldCondition, DynamicFormField } from '../models/form-field.model';\n\n@Injectable({ providedIn: 'root' })\nexport class ConditionEvaluatorService {\n /**\n * Evaluate whether a field should be visible based on its showWhen condition(s).\n */\n isVisible(field: DynamicFormField, form: FormGroup): boolean {\n if (field.hidden) return false;\n if (!field.showWhen) return true;\n\n const conditions = Array.isArray(field.showWhen)\n ? field.showWhen\n : [field.showWhen];\n\n // ALL conditions must be true (AND logic)\n return conditions.every((condition) => this.evaluate(condition, form));\n }\n\n private evaluate(condition: FieldCondition, form: FormGroup): boolean {\n const control = form.get(condition.field);\n const value = control?.value;\n\n switch (condition.operator) {\n case 'equals':\n return value === condition.value;\n case 'notEquals':\n return value !== condition.value;\n case 'contains':\n return Array.isArray(value)\n ? value.includes(condition.value)\n : String(value ?? '').includes(String(condition.value));\n case 'greaterThan':\n return Number(value) > Number(condition.value);\n case 'lessThan':\n return Number(value) < Number(condition.value);\n case 'exists':\n return value !== null && value !== undefined && value !== '';\n case 'notExists':\n return value === null || value === undefined || value === '';\n default:\n return true;\n }\n }\n}\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnChanges,\n SimpleChanges,\n ChangeDetectorRef,\n} from '@angular/core';\nimport { JsonPipe } from '@angular/common';\nimport { ReactiveFormsModule, FormGroup } from '@angular/forms';\nimport { MatButton } from '@angular/material/button';\nimport {\n DynamicFormConfig,\n DynamicFormField,\n DynamicFormSubmitEvent,\n} from '../../models/form-field.model';\nimport { DynamicFormBuilderService } from '../../services/dynamic-form-builder.service';\nimport { ConditionEvaluatorService } from '../../services/condition-evaluator.service';\nimport { DynamicFieldComponent } from '../dynamic-field/dynamic-field.component';\n\n@Component({\n selector: 'ngx-dynamic-form',\n standalone: true,\n imports: [JsonPipe, ReactiveFormsModule, DynamicFieldComponent, MatButton],\n template: `\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n [class]=\"'ngx-form ngx-form--' + (config.layout || 'vertical') + ' ' + (config.cssClass || '')\"\n novalidate\n >\n <div class=\"ngx-form-grid\">\n @for (field of config.fields; track field.key) {\n @if (isVisible(field)) {\n <div [style.grid-column]=\"'span ' + (field.col ?? 12)\">\n <ngx-dynamic-field [field]=\"field\" [form]=\"form\" />\n </div>\n }\n }\n </div>\n\n @if (config.debug) {\n <pre class=\"ngx-debug\">{{ form.value | json }}</pre>\n }\n\n <div class=\"ngx-form-actions\">\n @if (config.showReset) {\n <button type=\"button\" mat-stroked-button (click)=\"onReset()\">\n {{ config.resetLabel || 'Réinitialiser' }}\n </button>\n }\n <button\n type=\"submit\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"form.invalid && form.touched\"\n >\n {{ config.submitLabel || 'Envoyer' }}\n </button>\n </div>\n </form>\n `,\n styles: [],\n})\nexport class DynamicFormComponent implements OnInit, OnChanges {\n @Input({ required: true }) config!: DynamicFormConfig;\n\n /** Pre-fill the form with values (e.g. in edit mode) */\n @Input() initialValues?: Record<string, any>;\n\n /** Emitted on valid form submit */\n @Output() formSubmit = new EventEmitter<DynamicFormSubmitEvent>();\n\n /** Emitted on every value change */\n @Output() formChange = new EventEmitter<Record<string, any>>();\n\n /** Emitted when form is reset */\n @Output() formReset = new EventEmitter<void>();\n\n form!: FormGroup;\n\n constructor(\n private builder: DynamicFormBuilderService,\n private conditionEvaluator: ConditionEvaluatorService,\n private cdr: ChangeDetectorRef,\n ) {}\n\n ngOnInit(): void {\n this.buildForm();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n // Rebuild form if config changes (e.g. dynamic schema loading)\n if (changes['config'] && !changes['config'].firstChange) {\n this.buildForm();\n }\n // Patch values if initialValues is updated\n if (changes['initialValues'] && this.form) {\n this.form.patchValue(this.initialValues ?? {});\n }\n }\n\n private buildForm(): void {\n this.form = this.builder.buildFormGroup(this.config.fields);\n\n if (this.initialValues) {\n this.form.patchValue(this.initialValues);\n }\n\n this.form.valueChanges.subscribe((val) => {\n this.formChange.emit(val);\n this.cdr.markForCheck();\n });\n }\n\n isVisible(field: DynamicFormField): boolean {\n return this.conditionEvaluator.isVisible(field, this.form);\n }\n\n onSubmit(): void {\n this.form.markAllAsTouched();\n\n if (this.form.invalid) {\n this.cdr.markForCheck();\n return;\n }\n\n this.formSubmit.emit({\n value: this.form.value,\n rawValue: this.form.getRawValue(), // includes disabled fields\n });\n }\n\n onReset(): void {\n this.form.reset();\n this.formReset.emit();\n }\n\n /** Public API: access the FormGroup from the parent */\n getForm(): FormGroup {\n return this.form;\n }\n\n /** Public API: patch values from outside */\n patchValues(values: Record<string, any>): void {\n this.form.patchValue(values);\n }\n}\n","import { Observable } from 'rxjs';\nimport type { SavedFormSchema } from '../models/saved-form.model';\n\nexport abstract class FormStorageAdapter {\n abstract list(): Observable<SavedFormSchema[]>;\n abstract get(id: string): Observable<SavedFormSchema | null>;\n abstract save(schema: SavedFormSchema): Observable<SavedFormSchema>;\n abstract delete(id: string): Observable<void>;\n\n generateId(): string {\n return Date.now().toString(36) + Math.random().toString(36).slice(2, 7);\n }\n}\n","import { inject, Injectable, signal } from '@angular/core';\nimport { Observable, tap } from 'rxjs';\nimport { FormStorageAdapter } from '../storage/form-storage.adapter';\nimport type { SavedFormSchema } from '../models/saved-form.model';\nimport type { DynamicFormConfig } from '../models/form-field.model';\n\n@Injectable()\nexport class FormConfigService {\n private adapter = inject(FormStorageAdapter);\n private _schemas = signal<SavedFormSchema[]>([]);\n\n readonly schemas = this._schemas.asReadonly();\n\n constructor() {\n this.adapter.list().subscribe(list => this._schemas.set(list));\n }\n\n get(id: string): SavedFormSchema | null {\n return this._schemas().find(s => s.id === id) ?? null;\n }\n\n save(id: string, title: string, config: DynamicFormConfig): Observable<SavedFormSchema> {\n const schema: SavedFormSchema = {\n id,\n title: title.trim() || 'Sans titre',\n config,\n updatedAt: new Date().toISOString(),\n };\n return this.adapter.save(schema).pipe(\n tap(saved => this._schemas.update(list => [...list.filter(s => s.id !== saved.id), saved])),\n );\n }\n\n delete(id: string): Observable<void> {\n return this.adapter.delete(id).pipe(\n tap(() => this._schemas.update(list => list.filter(s => s.id !== id))),\n );\n }\n\n generateId(): string {\n return this.adapter.generateId();\n }\n}\n","import { Component, computed, inject, Input, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { RouterLink } from '@angular/router';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { MatTooltip } from '@angular/material/tooltip';\n\nimport { DynamicFormComponent } from '../dynamic-form/dynamic-form.component';\nimport { FormConfigService } from '../../services/form-config.service';\nimport type {\n DynamicFormConfig,\n DynamicFormField,\n FieldType,\n FieldValidation,\n SelectOption,\n} from '../../models/form-field.model';\n\ninterface FieldTypeDef {\n type: FieldType;\n label: string;\n icon: string;\n group: 'Saisie' | 'Choix' | 'Mise en page';\n}\n\nconst FIELD_TYPES: FieldTypeDef[] = [\n { type: 'text', label: 'Texte', icon: 'text_fields', group: 'Saisie' },\n { type: 'email', label: 'E-mail', icon: 'email', group: 'Saisie' },\n { type: 'password', label: 'Mot de passe', icon: 'lock', group: 'Saisie' },\n { type: 'number', label: 'Nombre', icon: 'pin', group: 'Saisie' },\n { type: 'tel', label: 'Téléphone', icon: 'phone', group: 'Saisie' },\n { type: 'url', label: 'URL', icon: 'link', group: 'Saisie' },\n { type: 'date', label: 'Date', icon: 'calendar_today', group: 'Saisie' },\n { type: 'textarea', label: 'Zone de texte', icon: 'notes', group: 'Saisie' },\n { type: 'file', label: 'Fichier', icon: 'attach_file', group: 'Saisie' },\n { type: 'select', label: 'Liste déroulante', icon: 'arrow_drop_down_circle', group: 'Choix' },\n { type: 'multiselect', label: 'Multi-sélection', icon: 'checklist', group: 'Choix' },\n { type: 'radio', label: 'Boutons radio', icon: 'radio_button_checked', group: 'Choix' },\n { type: 'checkbox', label: 'Case à cocher', icon: 'check_box', group: 'Choix' },\n { type: 'heading', label: 'Titre de section', icon: 'title', group: 'Mise en page' },\n { type: 'divider', label: 'Séparateur', icon: 'horizontal_rule', group: 'Mise en page' },\n];\n\nconst FIELD_ICONS: Record<string, string> = Object.fromEntries(\n FIELD_TYPES.map(f => [f.type, f.icon]),\n);\n\nconst GROUPS = ['Saisie', 'Choix', 'Mise en page'] as const;\nconst COL_OPTIONS = [1, 2, 3, 4, 6, 8, 9, 12] as const;\n\n@Component({\n selector: 'ngx-form-builder',\n standalone: true,\n imports: [FormsModule, MatIcon, MatTooltip, RouterLink, DynamicFormComponent],\n templateUrl: './form-builder.component.html',\n styleUrl: './form-builder.component.scss',\n})\nexport class FormBuilderComponent {\n /** Route du lien \"Retour\" dans la topbar */\n @Input() backRoute = '/';\n\n private formService = inject(FormConfigService);\n private snack = inject(MatSnackBar);\n\n fields = signal<DynamicFormField[]>([]);\n selectedIdx = signal<number | null>(null);\n activeTab = signal<'schema' | 'preview'>('schema');\n formTitle = signal('Mon formulaire');\n submitLabel = signal('Envoyer');\n resetLabel = signal('Réinitialiser');\n showReset = signal(false);\n currentId = signal<string | null>(null);\n showExport = signal(false);\n exportContent = signal('');\n\n savedSchemas = this.formService.schemas;\n\n readonly groups = GROUPS;\n readonly fieldTypes = FIELD_TYPES;\n readonly colOptions = COL_OPTIONS;\n\n selectedField = computed(() => {\n const i = this.selectedIdx();\n return i !== null ? this.fields()[i] : null;\n });\n\n previewConfig = computed<DynamicFormConfig>(() => ({\n submitLabel: this.submitLabel(),\n resetLabel: this.resetLabel(),\n showReset: this.showReset(),\n fields: this.fields(),\n }));\n\n groupedTypes = computed(() =>\n GROUPS.map(g => ({ label: g, types: FIELD_TYPES.filter(f => f.group === g) })),\n );\n\n getIcon(type: string): string { return FIELD_ICONS[type] ?? 'input'; }\n\n getFieldDisplay(field: DynamicFormField): string {\n return field.label || field.text || field.placeholder || field.key;\n }\n\n isInputField(type: FieldType): boolean { return type !== 'divider' && type !== 'heading'; }\n hasOptions(type: FieldType): boolean { return ['select', 'multiselect', 'radio'].includes(type); }\n needsRows(type: FieldType): boolean { return type === 'textarea'; }\n isHeading(type: FieldType): boolean { return type === 'heading'; }\n isDivider(type: FieldType): boolean { return type === 'divider'; }\n\n addField(type: FieldType): void {\n const existing = this.fields().filter(f => f.type === type).length;\n const suffix = existing > 0 ? existing + 1 : '';\n const key = `${type.replace('-', '_')}${suffix}`;\n const base: DynamicFormField = { key, type, col: 12 };\n if (this.isInputField(type)) base.label = this._defaultLabel(type);\n if (this.hasOptions(type)) base.options = [{ label: 'Option 1', value: 'option1' }];\n if (type === 'heading') Object.assign(base, { text: 'Nouvelle section', level: 3 });\n if (type === 'radio') base.defaultValue = null;\n this.fields.update(f => [...f, base]);\n this.selectedIdx.set(this.fields().length - 1);\n this.activeTab.set('schema');\n }\n\n removeField(i: number, e: Event): void {\n e.stopPropagation();\n this.fields.update(f => f.filter((_, idx) => idx !== i));\n if (this.selectedIdx() === i) this.selectedIdx.set(null);\n else if ((this.selectedIdx() ?? 0) > i) this.selectedIdx.update(v => (v ?? 1) - 1);\n }\n\n moveUp(i: number, e: Event): void {\n e.stopPropagation();\n if (i === 0) return;\n this.fields.update(f => { const a = [...f]; [a[i - 1], a[i]] = [a[i], a[i - 1]]; return a; });\n if (this.selectedIdx() === i) this.selectedIdx.set(i - 1);\n }\n\n moveDown(i: number, e: Event): void {\n e.stopPropagation();\n if (i >= this.fields().length - 1) return;\n this.fields.update(f => { const a = [...f]; [a[i], a[i + 1]] = [a[i + 1], a[i]]; return a; });\n if (this.selectedIdx() === i) this.selectedIdx.set(i + 1);\n }\n\n selectField(i: number): void { this.selectedIdx.set(this.selectedIdx() === i ? null : i); }\n\n duplicateField(i: number, e: Event): void {\n e.stopPropagation();\n const clone: DynamicFormField = {\n ...this.fields()[i],\n key: `${this.fields()[i].key}_copy${Date.now().toString(36).slice(-3)}`,\n };\n this.fields.update(f => [...f.slice(0, i + 1), clone, ...f.slice(i + 1)]);\n this.selectedIdx.set(i + 1);\n }\n\n updateProp(prop: keyof DynamicFormField, value: any): void {\n const i = this.selectedIdx();\n if (i === null) return;\n this.fields.update(list => { const c = [...list]; c[i] = { ...c[i], [prop]: value }; return c; });\n }\n\n updateValidation(prop: keyof FieldValidation, value: any): void {\n const i = this.selectedIdx();\n if (i === null) return;\n this.fields.update(list => {\n const c = [...list];\n const field = { ...c[i] };\n const valid = { ...field.validation };\n if (value === '' || value === null || value === undefined || value === false) {\n delete (valid as any)[prop];\n } else {\n (valid as any)[prop] = value;\n }\n field.validation = Object.keys(valid).length ? valid : undefined;\n c[i] = field;\n return c;\n });\n }\n\n getOptions(): SelectOption[] { return (this.selectedField()?.options as SelectOption[]) ?? []; }\n\n addOption(): void {\n const n = this.getOptions().length + 1;\n this.updateProp('options', [...this.getOptions(), { label: `Option ${n}`, value: `option${n}` }]);\n }\n\n updateOption(idx: number, prop: 'label' | 'value', value: string): void {\n const opts = [...this.getOptions()];\n opts[idx] = { ...opts[idx], [prop]: value };\n this.updateProp('options', opts);\n }\n\n removeOption(idx: number): void {\n this.updateProp('options', this.getOptions().filter((_, i) => i !== idx));\n }\n\n save(): void {\n const id = this.currentId() ?? this.formService.generateId();\n const title = this.formTitle();\n this.formService.save(id, title, this.previewConfig()).subscribe(() => {\n this.currentId.set(id);\n this.snack.open(`✓ \"${title}\" sauvegardé`, '', { duration: 2500 });\n });\n }\n\n loadSchema(id: string): void {\n const schema = this.formService.get(id);\n if (!schema) return;\n this.fields.set(schema.config.fields ?? []);\n this.formTitle.set(schema.title);\n this.submitLabel.set(schema.config.submitLabel ?? 'Envoyer');\n this.resetLabel.set(schema.config.resetLabel ?? 'Réinitialiser');\n this.showReset.set(schema.config.showReset ?? false);\n this.currentId.set(id);\n this.selectedIdx.set(null);\n this.snack.open(`✓ \"${schema.title}\" chargé`, '', { duration: 2000 });\n }\n\n deleteSchema(id: string, e: Event): void {\n e.stopPropagation();\n this.formService.delete(id).subscribe(() => {\n if (this.currentId() === id) this.newForm();\n });\n }\n\n newForm(): void {\n this.fields.set([]);\n this.formTitle.set('Mon formulaire');\n this.submitLabel.set('Envoyer');\n this.resetLabel.set('Réinitialiser');\n this.showReset.set(false);\n this.currentId.set(null);\n this.selectedIdx.set(null);\n }\n\n exportJSON(): void {\n this.exportContent.set(JSON.stringify(this.previewConfig(), null, 2));\n this.showExport.set(true);\n }\n\n exportTypeScript(): void {\n const ts = `const config: DynamicFormConfig = ${\n JSON.stringify(this.previewConfig(), null, 2)\n .replace(/\"([a-zA-Z_][a-zA-Z0-9_]*)\"\\s*:/g, '$1:')\n .replace(/\"/g, \"'\")\n };\\n`;\n this.exportContent.set(ts);\n this.showExport.set(true);\n }\n\n async copyExport(): Promise<void> {\n await navigator.clipboard.writeText(this.exportContent());\n this.snack.open('✓ Copié dans le presse-papiers', '', { duration: 2000 });\n }\n\n copyFormUrl(): void {\n const id = this.currentId();\n if (!id) {\n this.snack.open('Sauvegardez d\\'abord le formulaire', '', { duration: 2000 });\n return;\n }\n navigator.clipboard.writeText(`${location.origin}/form/${id}`);\n this.snack.open(`✓ Lien copié : /form/${id}`, '', { duration: 3000 });\n }\n\n validationOf(key: keyof FieldValidation): any {\n return this.selectedField()?.validation?.[key] ?? null;\n }\n\n labelOf(type: FieldType): string {\n return FIELD_TYPES.find(f => f.type === type)?.label ?? type;\n }\n\n trackByKey(_i: number, field: DynamicFormField): string { return field.key; }\n trackByIdx(i: number): number { return i; }\n\n private _defaultLabel(type: FieldType): string {\n const map: Partial<Record<FieldType, string>> = {\n text: 'Texte', email: 'E-mail', password: 'Mot de passe', number: 'Nombre',\n tel: 'Téléphone', url: 'URL', date: 'Date', textarea: 'Message',\n select: 'Sélection', multiselect: 'Sélection multiple', radio: 'Choix',\n checkbox: 'Option', file: 'Fichier',\n };\n return map[type] ?? type;\n }\n}\n","<div class=\"builder-root\">\n\n <!-- ── Top Bar ───────────────────────────────────────────── -->\n <header class=\"topbar\">\n <a [routerLink]=\"backRoute\" class=\"topbar-back\">\n <mat-icon>arrow_back</mat-icon>\n <span>Retour</span>\n </a>\n\n <div class=\"topbar-center\">\n <mat-icon class=\"topbar-logo\">dashboard_customize</mat-icon>\n <input\n class=\"title-input\"\n [ngModel]=\"formTitle()\"\n (ngModelChange)=\"formTitle.set($event)\"\n placeholder=\"Titre du formulaire\"\n aria-label=\"Titre du formulaire\"\n />\n </div>\n\n <div class=\"topbar-actions\">\n <button class=\"btn-icon\" matTooltip=\"Nouveau formulaire\" (click)=\"newForm()\">\n <mat-icon>add_circle_outline</mat-icon>\n </button>\n <button class=\"btn-icon\" matTooltip=\"Copier le lien du formulaire\" (click)=\"copyFormUrl()\">\n <mat-icon>share</mat-icon>\n </button>\n <button class=\"btn-outline\" (click)=\"exportJSON()\">\n <mat-icon>data_object</mat-icon> JSON\n </button>\n <button class=\"btn-outline\" (click)=\"exportTypeScript()\">\n <mat-icon>code</mat-icon> TypeScript\n </button>\n <button class=\"btn-primary\" (click)=\"save()\">\n <mat-icon>save</mat-icon> Sauvegarder\n </button>\n </div>\n </header>\n\n <!-- ── Main Layout ───────────────────────────────────────── -->\n <div class=\"builder-body\">\n\n <!-- ── Left: Palette ──────────────────────────────────── -->\n <aside class=\"palette\">\n\n <div class=\"palette-section\">\n <p class=\"palette-section-title\">Types de champs</p>\n @for (group of groupedTypes(); track group.label) {\n <p class=\"palette-group-label\">{{ group.label }}</p>\n @for (ft of group.types; track ft.type) {\n <button class=\"palette-btn\" (click)=\"addField(ft.type)\" matTooltip=\"Ajouter {{ ft.label }}\">\n <mat-icon>{{ ft.icon }}</mat-icon>\n <span>{{ ft.label }}</span>\n </button>\n }\n }\n </div>\n\n <!-- Saved schemas -->\n <div class=\"palette-section\">\n <p class=\"palette-section-title\">\n <mat-icon style=\"font-size:1rem;width:1rem;height:1rem;vertical-align:middle\">folder_open</mat-icon>\n Formulaires sauvegardés\n </p>\n @if (savedSchemas().length === 0) {\n <p class=\"palette-empty\">Aucun formulaire sauvegardé</p>\n }\n @for (schema of savedSchemas(); track schema.id) {\n <div class=\"saved-item\" [class.active]=\"currentId() === schema.id\">\n <button class=\"saved-item-name\" (click)=\"loadSchema(schema.id)\" matTooltip=\"Charger\">\n <mat-icon>description</mat-icon>\n <span>{{ schema.title }}</span>\n </button>\n <button class=\"saved-item-delete\" (click)=\"deleteSchema(schema.id, $event)\" matTooltip=\"Supprimer\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n }\n </div>\n\n </aside>\n\n <!-- ── Center: Canvas ──────────────────────────────────── -->\n <main class=\"canvas\">\n\n <!-- Tab bar -->\n <div class=\"canvas-tabs\">\n <button\n class=\"canvas-tab\"\n [class.active]=\"activeTab() === 'schema'\"\n (click)=\"activeTab.set('schema')\"\n >\n <mat-icon>list_alt</mat-icon> Schéma\n </button>\n <button\n class=\"canvas-tab\"\n [class.active]=\"activeTab() === 'preview'\"\n (click)=\"activeTab.set('preview')\"\n >\n <mat-icon>visibility</mat-icon> Aperçu\n </button>\n <span class=\"canvas-tabs-info\">\n {{ fields().length }} champ{{ fields().length !== 1 ? 's' : '' }}\n </span>\n </div>\n\n <!-- ── Schema Tab ───────────────────────────────────── -->\n @if (activeTab() === 'schema') {\n <div class=\"schema-view\">\n\n @if (fields().length === 0) {\n <div class=\"empty-canvas\">\n <mat-icon>add_box</mat-icon>\n <p>Cliquez sur un type de champ à gauche pour commencer</p>\n </div>\n }\n\n <div class=\"field-list\">\n @for (field of fields(); track trackByKey($index, field); let i = $index) {\n <div\n class=\"field-card\"\n [class.selected]=\"selectedIdx() === i\"\n (click)=\"selectField(i)\"\n >\n <mat-icon class=\"field-card-icon\">{{ getIcon(field.type) }}</mat-icon>\n\n <div class=\"field-card-body\">\n <span class=\"field-card-label\">{{ getFieldDisplay(field) }}</span>\n <span class=\"field-card-meta\">{{ labelOf(field.type) }} · col-{{ field.col ?? 12 }}</span>\n </div>\n\n @if (field.key) {\n <code class=\"field-card-key\">{{ field.key }}</code>\n }\n\n <div class=\"field-card-actions\">\n <button class=\"action-btn\" (click)=\"moveUp(i, $event)\" [disabled]=\"i === 0\" matTooltip=\"Monter\">\n <mat-icon>arrow_upward</mat-icon>\n </button>\n <button class=\"action-btn\" (click)=\"moveDown(i, $event)\" [disabled]=\"i === fields().length - 1\" matTooltip=\"Descendre\">\n <mat-icon>arrow_downward</mat-icon>\n </button>\n <button class=\"action-btn\" (click)=\"duplicateField(i, $event)\" matTooltip=\"Dupliquer\">\n <mat-icon>content_copy</mat-icon>\n </button>\n <button class=\"action-btn danger\" (click)=\"removeField(i, $event)\" matTooltip=\"Supprimer\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Form settings -->\n <div class=\"form-settings\">\n <p class=\"settings-title\">\n <mat-icon>settings</mat-icon> Paramètres du formulaire\n </p>\n <div class=\"settings-row\">\n <label>Bouton Envoyer</label>\n <input [ngModel]=\"submitLabel()\" (ngModelChange)=\"submitLabel.set($event)\" placeholder=\"Envoyer\" />\n </div>\n <div class=\"settings-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"showReset()\" (ngModelChange)=\"showReset.set($event)\" />\n Afficher Réinitialiser\n </label>\n </div>\n @if (showReset()) {\n <div class=\"settings-row\">\n <label>Bouton Reset</label>\n <input [ngModel]=\"resetLabel()\" (ngModelChange)=\"resetLabel.set($event)\" placeholder=\"Réinitialiser\" />\n </div>\n }\n </div>\n\n </div>\n }\n\n <!-- ── Preview Tab ──────────────────────────────────── -->\n @if (activeTab() === 'preview') {\n <div class=\"preview-view\">\n @if (fields().length === 0) {\n <div class=\"empty-canvas\">\n <mat-icon>preview</mat-icon>\n <p>Ajoutez des champs pour voir l'aperçu du formulaire</p>\n </div>\n } @else {\n <div class=\"preview-wrapper\">\n <p class=\"preview-hint\">\n <mat-icon>info_outline</mat-icon>\n Aperçu en temps réel — les données ne sont pas envoyées\n </p>\n <ngx-dynamic-form [config]=\"previewConfig()\" />\n </div>\n }\n </div>\n }\n\n </main>\n\n <!-- ── Right: Properties ───────────────────────────────── -->\n <aside class=\"properties\">\n\n @if (selectedField(); as field) {\n <div class=\"props-header\">\n <mat-icon>{{ getIcon(field.type) }}</mat-icon>\n <span>{{ labelOf(field.type) }}</span>\n <button class=\"props-close\" (click)=\"selectedIdx.set(null)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <div class=\"props-body\">\n\n <!-- ── GÉNÉRAL ─────────────────────────────────── -->\n <section class=\"prop-section\">\n <p class=\"prop-section-title\">Général</p>\n\n <div class=\"prop-row\">\n <label>Clé (key)</label>\n <input [ngModel]=\"field.key\" (ngModelChange)=\"updateProp('key', $event)\" placeholder=\"mon_champ\" />\n </div>\n\n <div class=\"prop-row\">\n <label>Largeur (col)</label>\n <select [ngModel]=\"field.col ?? 12\" (ngModelChange)=\"updateProp('col', +$event)\">\n @for (c of colOptions; track c) {\n <option [value]=\"c\">{{ c }} / 12</option>\n }\n </select>\n </div>\n\n @if (!isDivider(field.type) && !isHeading(field.type)) {\n <div class=\"prop-row\">\n <label>Label</label>\n <input [ngModel]=\"field.label\" (ngModelChange)=\"updateProp('label', $event)\" placeholder=\"Libellé du champ\" />\n </div>\n }\n\n @if (isHeading(field.type)) {\n <div class=\"prop-row\">\n <label>Texte</label>\n <input [ngModel]=\"field.text\" (ngModelChange)=\"updateProp('text', $event)\" placeholder=\"Titre de section\" />\n </div>\n <div class=\"prop-row\">\n <label>Niveau (h1–h6)</label>\n <select [ngModel]=\"field.level ?? 3\" (ngModelChange)=\"updateProp('level', +$event)\">\n @for (n of [1,2,3,4,5,6]; track n) {\n <option [value]=\"n\">h{{ n }}</option>\n }\n </select>\n </div>\n }\n </section>\n\n <!-- ── SAISIE ──────────────────────────────────── -->\n @if (isInputField(field.type)) {\n <section class=\"prop-section\">\n <p class=\"prop-section-title\">Saisie</p>\n\n <div class=\"prop-row\">\n <label>Placeholder</label>\n <input [ngModel]=\"field.placeholder\" (ngModelChange)=\"updateProp('placeholder', $event)\" placeholder=\"Texte indicatif\" />\n </div>\n\n <div class=\"prop-row\">\n <label>Texte d'aide (hint)</label>\n <input [ngModel]=\"field.hint\" (ngModelChange)=\"updateProp('hint', $event)\" placeholder=\"Aide visible sous le champ\" />\n </div>\n\n @if (needsRows(field.type)) {\n <div class=\"prop-row\">\n <label>Lignes (rows)</label>\n <input type=\"number\" min=\"2\" max=\"20\" [ngModel]=\"field.rows ?? 4\" (ngModelChange)=\"updateProp('rows', +$event)\" />\n </div>\n }\n\n <div class=\"prop-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"field.readonly ?? false\" (ngModelChange)=\"updateProp('readonly', $event)\" />\n Lecture seule (readonly)\n </label>\n </div>\n </section>\n\n <!-- ── ICÔNES ──────────────────────────────── -->\n <section class=\"prop-section\">\n <p class=\"prop-section-title\">Icônes <span class=\"prop-hint\">Material Icons</span></p>\n <div class=\"prop-row\">\n <label>Préfixe (gauche)</label>\n <input [ngModel]=\"field.icon\" (ngModelChange)=\"updateProp('icon', $event || undefined)\" placeholder=\"person, email, lock…\" />\n </div>\n <div class=\"prop-row\">\n <label>Suffixe (droite)</label>\n <input [ngModel]=\"field.iconSuffix\" (ngModelChange)=\"updateProp('iconSuffix', $event || undefined)\" placeholder=\"visibility, search…\" />\n </div>\n </section>\n\n <!-- ── VALIDATION ─────────────────────────── -->\n <section class=\"prop-section\">\n <p class=\"prop-section-title\">Validation</p>\n\n <div class=\"prop-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"!!field.validation?.required\" (ngModelChange)=\"updateValidation('required', $event)\" />\n Champ obligatoire (required)\n </label>\n </div>\n\n @if (['text','email','password','textarea','url'].includes(field.type)) {\n <div class=\"prop-row\">\n <label>Longueur min</label>\n <input type=\"number\" min=\"0\"\n [ngModel]=\"field.validation?.minLength ?? ''\"\n (ngModelChange)=\"updateValidation('minLength', $event ? +$event : null)\"\n placeholder=\"–\" />\n </div>\n <div class=\"prop-row\">\n <label>Longueur max</label>\n <input type=\"number\" min=\"0\"\n [ngModel]=\"field.validation?.maxLength ?? ''\"\n (ngModelChange)=\"updateValidation('maxLength', $event ? +$event : null)\"\n placeholder=\"–\" />\n </div>\n }\n\n @if (field.type === 'number') {\n <div class=\"prop-row\">\n <label>Valeur min</label>\n <input type=\"number\"\n [ngModel]=\"field.validation?.min ?? ''\"\n (ngModelChange)=\"updateValidation('min', $event !== '' ? +$event : null)\"\n placeholder=\"–\" />\n </div>\n <div class=\"prop-row\">\n <label>Valeur max</label>\n <input type=\"number\"\n [ngModel]=\"field.validation?.max ?? ''\"\n (ngModelChange)=\"updateValidation('max', $event !== '' ? +$event : null)\"\n placeholder=\"–\" />\n </div>\n }\n\n @if (field.type === 'email') {\n <div class=\"prop-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"!!field.validation?.email\" (ngModelChange)=\"updateValidation('email', $event)\" />\n Valider le format e-mail\n </label>\n </div>\n }\n\n @if (field.type === 'file') {\n <div class=\"prop-row\">\n <label>Types acceptés</label>\n <input [ngModel]=\"field.accept\" (ngModelChange)=\"updateProp('accept', $event)\" placeholder=\".pdf,.docx,image/*\" />\n </div>\n <div class=\"prop-row\">\n <label>\n <input type=\"checkbox\" [ngModel]=\"field.multiple ?? false\" (ngModelChange)=\"updateProp('multiple', $event)\" />\n Fichiers multiples\n </label>\n </div>\n }\n </section>\n }\n\n <!-- ── OPTIONS (select / radio) ───────────────── -->\n @if (hasOptions(field.type)) {\n <section class=\"prop-section\">\n <p class=\"prop-section-title\">Options</p>\n <div class=\"options-list\">\n @for (opt of getOptions(); track trackByIdx($index); let oi = $index) {\n <div class=\"option-row\">\n <input placeholder=\"Label\" [ngModel]=\"opt.label\" (ngModelChange)=\"updateOption(oi, 'label', $event)\" />\n <input placeholder=\"Valeur\" [ngModel]=\"opt.value\" (ngModelChange)=\"updateOption(oi, 'value', $event)\" />\n <button class=\"action-btn danger\" (click)=\"removeOption(oi)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n }\n </div>\n <button class=\"btn-add-option\" (click)=\"addOption()\">\n <mat-icon>add</mat-icon> Ajouter une option\n </button>\n </section>\n }\n\n </div>\n\n } @else {\n <div class=\"props-empty\">\n <mat-icon>tune</mat-icon>\n <p>Sélectionnez un champ pour modifier ses propriétés</p>\n </div>\n }\n\n </aside>\n\n </div><!-- /.builder-body -->\n\n</div><!-- /.builder-root -->\n\n<!-- ── Export Modal ─────────────────────────────────────────── -->\n@if (showExport()) {\n <div class=\"modal-overlay\" (click)=\"showExport.set(false)\">\n <div class=\"modal\" (click)=\"$event.stopPropagation()\">\n <div class=\"modal-header\">\n <span>Code exporté</span>\n <button (click)=\"showExport.set(false)\"><mat-icon>close</mat-icon></button>\n </div>\n <textarea class=\"modal-code\" readonly [value]=\"exportContent()\"></textarea>\n <div class=\"modal-footer\">\n <button class=\"btn-primary\" (click)=\"copyExport()\">\n <mat-icon>content_copy</mat-icon> Copier\n </button>\n <button class=\"btn-outline\" (click)=\"showExport.set(false)\">Fermer</button>\n </div>\n </div>\n </div>\n}\n","import { Component, computed, inject, Input, signal } from '@angular/core';\nimport { JsonPipe } from '@angular/common';\nimport { RouterLink } from '@angular/router';\nimport { MatIcon } from '@angular/material/icon';\n\nimport { DynamicFormComponent } from '../dynamic-form/dynamic-form.component';\nimport { FormConfigService } from '../../services/form-config.service';\nimport type { DynamicFormConfig, DynamicFormSubmitEvent } from '../../models/form-field.model';\nimport type { SavedFormSchema } from '../../models/saved-form.model';\n\n@Component({\n selector: 'ngx-mes-formulaires',\n standalone: true,\n imports: [RouterLink, MatIcon, DynamicFormComponent, JsonPipe],\n templateUrl: './mes-formulaires.component.html',\n styleUrl: './mes-formulaires.component.scss',\n})\nexport class MesFormulairesComponent {\n /** Route vers le builder (lien \"Nouveau formulaire\" et actions d'édition) */\n @Input() builderRoute = '/builder';\n /** Préfixe de route pour l'ouverture d'un formulaire par ID */\n @Input() formRoute = '/form';\n /** Route du lien \"Retour\" */\n @Input() backRoute = '/';\n\n private formService = inject(FormConfigService);\n\n readonly savedForms = this.formService.schemas;\n\n selectedId = signal<string | null>(null);\n submitted = signal(false);\n submitData = signal<Record<string, unknown>>({});\n\n activeConfig = computed<DynamicFormConfig | null>(() => {\n const id = this.selectedId();\n return id ? (this.formService.get(id)?.config ?? null) : null;\n });\n\n activeSchema = computed<SavedFormSchema | null>(() => {\n const id = this.selectedId();\n return id ? (this.formService.get(id) ?? null) : null;\n });\n\n selectForm(id: string): void {\n if (this.selectedId() === id) {\n this.selectedId.set(null);\n } else {\n this.selectedId.set(id);\n this.submitted.set(false);\n this.submitData.set({});\n }\n }\n\n onSubmit(event: DynamicFormSubmitEvent): void {\n this.submitData.set(event.value as Record<string, unknown>);\n this.submitted.set(true);\n }\n\n resetForm(): void {\n this.submitted.set(false);\n this.submitData.set({});\n }\n\n deleteForm(id: string, e: Event): void {\n e.stopPropagation();\n this.formService.delete(id).subscribe(() => {\n if (this.selectedId() === id) this.selectedId.set(null);\n });\n }\n\n formatDate(iso: string): string {\n return new Date(iso).toLocaleDateString('fr-FR', {\n day: '2-digit', month: 'short', year: 'numeric',\n hour: '2-digit', minute: '2-digit',\n });\n }\n\n fieldCount(config: DynamicFormConfig): number {\n return config.fields?.filter(f => f.type !== 'divider' && f.type !== 'heading').length ?? 0;\n }\n}\n","<div class=\"page\">\n\n <header class=\"page-header\">\n <a [routerLink]=\"backRoute\" class=\"back-link\">\n <mat-icon>arrow_back</mat-icon>\n </a>\n <div class=\"header-text\">\n <h1>Mes Formulaires</h1>\n <p>Sélectionnez un formulaire pour le charger via <code>FormConfigService</code></p>\n </div>\n <a [routerLink]=\"builderRoute\" class=\"btn-primary\">\n <mat-icon>add</mat-icon> Nouveau formulaire\n </a>\n </header>\n\n <div class=\"page-body\">\n\n <!-- ════ COLONNE GAUCHE : liste des formulaires ════ -->\n <aside class=\"sidebar\">\n\n <p class=\"sidebar-title\">\n <mat-icon>folder_open</mat-icon>\n {{ savedForms().length }} formulaire{{ savedForms().length !== 1 ? 's' : '' }} sauvegardé{{ savedForms().length !== 1 ? 's' : '' }}\n </p>\n\n @if (savedForms().length === 0) {\n <div class=\"empty-state\">\n <mat-icon>inbox</mat-icon>\n <p>Aucun formulaire sauvegardé</p>\n <a [routerLink]=\"builderRoute\" class=\"btn-outline-sm\">\n <mat-icon>add</mat-icon> Créer un formulaire\n </a>\n </div>\n }\n\n <div class=\"form-list\">\n @for (schema of savedForms(); track schema.id) {\n <div\n class=\"form-item\"\n [class.active]=\"selectedId() === schema.id\"\n (click)=\"selectForm(schema.id)\"\n role=\"button\"\n tabindex=\"0\"\n >\n <div class=\"form-item-icon\">\n <mat-icon>description</mat-icon>\n </div>\n\n <div class=\"form-item-body\">\n <span class=\"form-item-title\">{{ schema.title }}</span>\n <span class=\"form-item-meta\">\n {{ fieldCount(schema.config) }} champ{{ fieldCount(schema.config) !== 1 ? 's' : '' }}\n &nbsp;·&nbsp; {{ formatDate(schema.updatedAt) }}\n </span>\n <code class=\"form-item-id\">ID : {{ schema.id }}</code>\n </div>\n\n <div class=\"form-item-actions\">\n <a\n [routerLink]=\"[formRoute, schema.id]\"\n class=\"action-icon\"\n title=\"Ouvrir dans la page dédiée\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-icon>open_in_new</mat-icon>\n </a>\n <a\n [routerLink]=\"builderRoute\"\n class=\"action-icon\"\n title=\"Éditer dans le Builder\"\n (click)=\"$event.stopPropagation()\"\n >\n <mat-icon>edit</mat-icon>\n </a>\n <button\n class=\"action-icon danger\"\n title=\"Supprimer\"\n (click)=\"deleteForm(schema.id, $event)\"\n >\n <mat-icon>delete_outline</mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n\n <div class=\"code-hint\">\n <p class=\"code-hint-title\">\n <mat-icon>integration_instructions</mat-icon> Chargement par ID\n </p>\n <pre class=\"code-block\">private formService = inject(FormConfigService);\n\nconst schema = this.formService.get('{{ selectedId() ?? \"votre-id\" }}');\nthis.config.set(schema?.config ?? null);</pre>\n </div>\n\n </aside>\n\n <!-- ════ COLONNE DROITE : rendu du formulaire ════ -->\n <main class=\"content\">\n\n @if (!selectedId()) {\n <div class=\"select-hint\">\n <mat-icon>arrow_back</mat-icon>\n <p>Sélectionnez un formulaire à gauche pour le charger</p>\n </div>\n }\n\n @if (selectedId() && activeConfig(); as config) {\n\n @if (!submitted()) {\n <div class=\"form-card\">\n\n <div class=\"form-card-header\">\n <mat-icon>dynamic_form</mat-icon>\n <div>\n <h2>{{ activeSchema()?.title }}</h2>\n <span class=\"loaded-badge\">\n <mat-icon>check_circle</mat-icon>\n Chargé via <code>FormConfigService.get('{{ selectedId() }}')</code>\n </span>\n </div>\n </div>\n\n <ngx-dynamic-form\n [config]=\"config\"\n (formSubmit)=\"onSubmit($event)\"\n />\n\n </div>\n }\n\n @if (submitted()) {\n <div class=\"result-card\">\n <mat-icon class=\"result-icon\">check_circle</mat-icon>\n <h2>Données soumises avec succès</h2>\n <p class=\"result-sub\">\n Les données ci-dessous ont été reçues par <code>onSubmit(event)</code>\n </p>\n\n <div class=\"result-data\">\n <p class=\"result-data-title\">event.value :</p>\n <pre>{{ submitData() | json }}</pre>\n </div>\n\n <div class=\"result-actions\">\n <button class=\"btn-outline\" (click)=\"resetForm()\">\n <mat-icon>refresh</mat-icon> Recommencer\n </button>\n <a class=\"btn-primary\" [routerLink]=\"builderRoute\">\n <mat-icon>dashboard_customize</mat-icon> Builder\n </a>\n </div>\n </div>\n }\n\n }\n\n @if (selectedId() && !activeConfig()) {\n <div class=\"select-hint error\">\n <mat-icon>error_outline</mat-icon>\n <p>Formulaire introuvable pour l'ID <code>{{ selectedId() }}</code></p>\n </div>\n }\n\n </main>\n\n </div>\n</div>\n","import { Component, inject, Input, OnInit, Optional, signal } from '@angular/core';\nimport { JsonPipe } from '@angular/common';\nimport { ActivatedRoute, RouterLink } from '@angular/router';\nimport { MatIcon } from '@angular/material/icon';\n\nimport { DynamicFormComponent } from '../dynamic-form/dynamic-form.component';\nimport { FormConfigService } from '../../services/form-config.service';\nimport type { DynamicFormConfig, DynamicFormSubmitEvent } from '../../models/form-field.model';\n\n@Component({\n selector: 'ngx-form-loader',\n standalone: true,\n imports: [DynamicFormComponent, MatIcon, RouterLink, JsonPipe],\n templateUrl: './form-loader.component.html',\n styleUrl: './form-loader.component.scss',\n})\nexport class FormLoaderComponent implements OnInit {\n /** Passé directement si le composant est utilisé sans ActivatedRoute */\n @Input() formId?: string;\n /** Route du lien \"Retour\" */\n @Input() backRoute = '/';\n /** Route vers le builder */\n @Input() builderRoute = '/builder';\n\n private route = inject(ActivatedRoute, { optional: true } as any);\n private formService = inject(FormConfigService);\n\n config = signal<DynamicFormConfig | null>(null);\n formTitle = signal('');\n schemaId = signal('');\n submitted = signal(false);\n submitData = signal<Record<string, unknown>>({});\n notFound = signal(false);\n\n ngOnInit(): void {\n const id = this.formId\n ?? (this.route as ActivatedRoute | null)?.snapshot?.paramMap?.get('id')\n ?? '';\n\n this.schemaId.set(id);\n\n const schema = this.formService.get(id);\n if (schema) {\n this.config.set(schema.config);\n this.formTitle.set(schema.title);\n } else {\n this.notFound.set(true);\n }\n }\n\n onSubmit(event: DynamicFormSubmitEvent): void {\n this.submitData.set(event.value as Record<string, unknown>);\n this.submitted.set(true);\n }\n\n reset(): void {\n this.submitted.set(false);\n this.submitData.set({});\n }\n}\n","<div class=\"loader-page\">\n\n <header class=\"loader-header\">\n <a [routerLink]=\"backRoute\" class=\"back-link\">\n <mat-icon>arrow_back</mat-icon>\n </a>\n @if (formTitle()) {\n <h1 class=\"loader-title\">{{ formTitle() }}</h1>\n }\n <a [routerLink]=\"builderRoute\" class=\"edit-link\" title=\"Éditer dans le Builder\">\n <mat-icon>edit</mat-icon>\n <span>Éditer</span>\n </a>\n </header>\n\n <div class=\"loader-body\">\n\n @if (config(); as cfg) {\n\n @if (!submitted()) {\n <div class=\"form-wrapper\">\n <p class=\"api-badge\">\n <mat-icon>api</mat-icon>\n Chargé via FormConfigService · ID :\n <code>{{ schemaId() }}</code>\n </p>\n <ngx-dynamic-form [config]=\"cfg\" (formSubmit)=\"onSubmit($event)\" />\n </div>\n }\n\n @if (submitted()) {\n <div class=\"success-card\">\n <mat-icon class=\"success-icon\">check_circle</mat-icon>\n <h2>Formulaire soumis avec succès</h2>\n <p>Les données ont été reçues (simulation — aucun envoi réseau).</p>\n\n <div class=\"data-preview\">\n <p class=\"data-title\">Données reçues :</p>\n <pre>{{ submitData() | json }}</pre>\n </div>\n\n <div class=\"success-actions\">\n <button class=\"btn-outline\" (click)=\"reset()\">\n <mat-icon>refresh</mat-icon> Recommencer\n </button>\n <a class=\"btn-primary\" [routerLink]=\"builderRoute\">\n <mat-icon>dashboard_customize</mat-icon> Retour au builder\n </a>\n </div>\n </div>\n }\n\n }\n\n @if (notFound()) {\n <div class=\"not-found\">\n <mat-icon>search_off</mat-icon>\n <h2>Formulaire introuvable</h2>\n <p>\n Aucun formulaire avec l'identifiant <code>{{ schemaId() }}</code> n'a été trouvé\n dans le stockage.\n </p>\n <p class=\"not-found-hint\">\n Créez un formulaire dans le <a [routerLink]=\"builderRoute\">Form Builder</a>,\n sauvegardez-le, puis copiez son lien.\n </p>\n </div>\n }\n\n </div>\n</div>\n","import { Injectable } from '@angular/core';\nimport { Observable, of } from 'rxjs';\nimport { FormStorageAdapter } from './form-storage.adapter';\nimport type { SavedFormSchema } from '../models/saved-form.model';\n\nconst KEY = 'ngx-dynamic-form__schemas';\n\n@Injectable()\nexport class LocalStorageAdapter extends FormStorageAdapter {\n\n list(): Observable<SavedFormSchema[]> {\n return of(this._read());\n }\n\n get(id: string): Observable<SavedFormSchema | null> {\n return of(this._read().find(s => s.id === id) ?? null);\n }\n\n save(schema: SavedFormSchema): Observable<SavedFormSchema> {\n const list = this._read().filter(s => s.id !== schema.id);\n this._write([...list, schema]);\n return of(schema);\n }\n\n delete(id: string): Observable<void> {\n this._write(this._read().filter(s => s.id !== id));\n return of(undefined);\n }\n\n private _read(): SavedFormSchema[] {\n try {\n const raw = localStorage.getItem(KEY);\n return raw ? JSON.parse(raw) : [];\n } catch {\n return [];\n }\n }\n\n private _write(schemas: SavedFormSchema[]): void {\n try {\n localStorage.setItem(KEY, JSON.stringify(schemas));\n } catch {\n console.warn('[LocalStorageAdapter] Cannot write to localStorage');\n }\n }\n}\n","import { inject, Injectable, InjectionToken } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { map, Observable } from 'rxjs';\nimport { FormStorageAdapter } from './form-storage.adapter';\nimport type { SavedFormSchema } from '../models/saved-form.model';\n\nexport const FORM_API_URL = new InjectionToken<string>('FORM_API_URL');\n\n@Injectable()\nexport class HttpStorageAdapter extends FormStorageAdapter {\n private http = inject(HttpClient);\n private apiUrl = inject(FORM_API_URL);\n\n list(): Observable<SavedFormSchema[]> {\n return this.http.get<SavedFormSchema[]>(this.apiUrl);\n }\n\n get(id: string): Observable<SavedFormSchema | null> {\n return this.http.get<SavedFormSchema>(`${this.apiUrl}/${id}`).pipe(\n map(s => s ?? null),\n );\n }\n\n save(schema: SavedFormSchema): Observable<SavedFormSchema> {\n return this.http.put<SavedFormSchema>(`${this.apiUrl}/${schema.id}`, schema);\n }\n\n delete(id: string): Observable<void> {\n return this.http.delete<void>(`${this.apiUrl}/${id}`);\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { FormStorageAdapter } from './storage/form-storage.adapter';\nimport { LocalStorageAdapter } from './storage/local-storage.adapter';\nimport { HttpStorageAdapter, FORM_API_URL } from './storage/http-storage.adapter';\nimport { FormConfigService } from './services/form-config.service';\n\nexport interface NgxFormsLocalOptions {\n storage: 'local';\n}\n\nexport interface NgxFormsHttpOptions {\n storage: 'http';\n /** URL de base de l'API Spring, ex: 'https://api.example.com/forms' */\n apiUrl: string;\n}\n\nexport type NgxFormsOptions = NgxFormsLocalOptions | NgxFormsHttpOptions;\n\nexport function provideNgxForms(options: NgxFormsOptions): EnvironmentProviders {\n if (options.storage === 'http') {\n return makeEnvironmentProviders([\n { provide: FORM_API_URL, useValue: options.apiUrl },\n { provide: FormStorageAdapter, useClass: HttpStorageAdapter },\n FormConfigService,\n ]);\n }\n return makeEnvironmentProviders([\n { provide: FormStorageAdapter, useClass: LocalStorageAdapter },\n FormConfigService,\n ]);\n}\n","// Components\nexport { DynamicFormComponent } from './lib/components/dynamic-form/dynamic-form.component';\nexport { DynamicFieldComponent } from './lib/components/dynamic-field/dynamic-field.component';\nexport { FormBuilderComponent } from './lib/components/form-builder/form-builder.component';\nexport { MesFormulairesComponent } from './lib/components/mes-formulaires/mes-formulaires.component';\nexport { FormLoaderComponent } from './lib/components/form-loader/form-loader.component';\n\n// Services\nexport { DynamicFormBuilderService } from './lib/services/dynamic-form-builder.service';\nexport { ConditionEvaluatorService } from './lib/services/condition-evaluator.service';\nexport { FormConfigService } from './lib/services/form-config.service';\n\n// Storage\nexport { FormStorageAdapter } from './lib/storage/form-storage.adapter';\nexport { LocalStorageAdapter } from './lib/storage/local-storage.adapter';\nexport { HttpStorageAdapter, FORM_API_URL } from './lib/storage/http-storage.adapter';\n\n// Providers\nexport { provideNgxForms } from './lib/providers';\nexport type { NgxFormsOptions, NgxFormsLocalOptions, NgxFormsHttpOptions } from './lib/providers';\n\n// Models & types\nexport type {\n DynamicFormField,\n DynamicFormConfig,\n DynamicFormSubmitEvent,\n FieldType,\n FieldValidation,\n FieldCondition,\n SelectOption,\n} from './lib/models/form-field.model';\n\nexport type { SavedFormSchema } from './lib/models/saved-form.model';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.DynamicFormBuilderService","i2","i2.ConditionEvaluatorService","i3"],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="@suntelecoms/ngx-dynamic-form" />
5
+ export * from './public-api';
@@ -0,0 +1,21 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { FormControl, FormGroup } from '@angular/forms';
3
+ import { DynamicFormField, SelectOption } from '../../models/form-field.model';
4
+ import { DynamicFormBuilderService } from '../../services/dynamic-form-builder.service';
5
+ import * as i0 from "@angular/core";
6
+ export declare class DynamicFieldComponent implements OnInit {
7
+ private builder;
8
+ field: DynamicFormField;
9
+ form: FormGroup;
10
+ constructor(builder: DynamicFormBuilderService);
11
+ resolvedOptions: SelectOption[];
12
+ ngOnInit(): void;
13
+ private resolveOptions;
14
+ get formControl(): FormControl;
15
+ get isInputField(): boolean;
16
+ get hasOptions(): boolean;
17
+ get hasError(): boolean;
18
+ get errorMessage(): string | null;
19
+ static ɵfac: i0.ɵɵFactoryDeclaration<DynamicFieldComponent, never>;
20
+ static ɵcmp: i0.ɵɵComponentDeclaration<DynamicFieldComponent, "ngx-dynamic-field", never, { "field": { "alias": "field"; "required": true; }; "form": { "alias": "form"; "required": true; }; }, {}, never, never, true, never>;
21
+ }
@@ -0,0 +1,34 @@
1
+ import { EventEmitter, OnInit, OnChanges, SimpleChanges, ChangeDetectorRef } from '@angular/core';
2
+ import { FormGroup } from '@angular/forms';
3
+ import { DynamicFormConfig, DynamicFormField, DynamicFormSubmitEvent } from '../../models/form-field.model';
4
+ import { DynamicFormBuilderService } from '../../services/dynamic-form-builder.service';
5
+ import { ConditionEvaluatorService } from '../../services/condition-evaluator.service';
6
+ import * as i0 from "@angular/core";
7
+ export declare class DynamicFormComponent implements OnInit, OnChanges {
8
+ private builder;
9
+ private conditionEvaluator;
10
+ private cdr;
11
+ config: DynamicFormConfig;
12
+ /** Pre-fill the form with values (e.g. in edit mode) */
13
+ initialValues?: Record<string, any>;
14
+ /** Emitted on valid form submit */
15
+ formSubmit: EventEmitter<DynamicFormSubmitEvent>;
16
+ /** Emitted on every value change */
17
+ formChange: EventEmitter<Record<string, any>>;
18
+ /** Emitted when form is reset */
19
+ formReset: EventEmitter<void>;
20
+ form: FormGroup;
21
+ constructor(builder: DynamicFormBuilderService, conditionEvaluator: ConditionEvaluatorService, cdr: ChangeDetectorRef);
22
+ ngOnInit(): void;
23
+ ngOnChanges(changes: SimpleChanges): void;
24
+ private buildForm;
25
+ isVisible(field: DynamicFormField): boolean;
26
+ onSubmit(): void;
27
+ onReset(): void;
28
+ /** Public API: access the FormGroup from the parent */
29
+ getForm(): FormGroup;
30
+ /** Public API: patch values from outside */
31
+ patchValues(values: Record<string, any>): void;
32
+ static ɵfac: i0.ɵɵFactoryDeclaration<DynamicFormComponent, never>;
33
+ static ɵcmp: i0.ɵɵComponentDeclaration<DynamicFormComponent, "ngx-dynamic-form", never, { "config": { "alias": "config"; "required": true; }; "initialValues": { "alias": "initialValues"; "required": false; }; }, { "formSubmit": "formSubmit"; "formChange": "formChange"; "formReset": "formReset"; }, never, never, true, never>;
34
+ }
@@ -0,0 +1,69 @@
1
+ import type { DynamicFormConfig, DynamicFormField, FieldType, FieldValidation, SelectOption } from '../../models/form-field.model';
2
+ import * as i0 from "@angular/core";
3
+ interface FieldTypeDef {
4
+ type: FieldType;
5
+ label: string;
6
+ icon: string;
7
+ group: 'Saisie' | 'Choix' | 'Mise en page';
8
+ }
9
+ export declare class FormBuilderComponent {
10
+ /** Route du lien "Retour" dans la topbar */
11
+ backRoute: string;
12
+ private formService;
13
+ private snack;
14
+ fields: import("@angular/core").WritableSignal<DynamicFormField[]>;
15
+ selectedIdx: import("@angular/core").WritableSignal<number | null>;
16
+ activeTab: import("@angular/core").WritableSignal<"schema" | "preview">;
17
+ formTitle: import("@angular/core").WritableSignal<string>;
18
+ submitLabel: import("@angular/core").WritableSignal<string>;
19
+ resetLabel: import("@angular/core").WritableSignal<string>;
20
+ showReset: import("@angular/core").WritableSignal<boolean>;
21
+ currentId: import("@angular/core").WritableSignal<string | null>;
22
+ showExport: import("@angular/core").WritableSignal<boolean>;
23
+ exportContent: import("@angular/core").WritableSignal<string>;
24
+ savedSchemas: import("@angular/core").Signal<import("@suntelecoms/ngx-dynamic-form").SavedFormSchema[]>;
25
+ readonly groups: readonly ["Saisie", "Choix", "Mise en page"];
26
+ readonly fieldTypes: FieldTypeDef[];
27
+ readonly colOptions: readonly [1, 2, 3, 4, 6, 8, 9, 12];
28
+ selectedField: import("@angular/core").Signal<DynamicFormField | null>;
29
+ previewConfig: import("@angular/core").Signal<DynamicFormConfig>;
30
+ groupedTypes: import("@angular/core").Signal<{
31
+ label: "Saisie" | "Choix" | "Mise en page";
32
+ types: FieldTypeDef[];
33
+ }[]>;
34
+ getIcon(type: string): string;
35
+ getFieldDisplay(field: DynamicFormField): string;
36
+ isInputField(type: FieldType): boolean;
37
+ hasOptions(type: FieldType): boolean;
38
+ needsRows(type: FieldType): boolean;
39
+ isHeading(type: FieldType): boolean;
40
+ isDivider(type: FieldType): boolean;
41
+ addField(type: FieldType): void;
42
+ removeField(i: number, e: Event): void;
43
+ moveUp(i: number, e: Event): void;
44
+ moveDown(i: number, e: Event): void;
45
+ selectField(i: number): void;
46
+ duplicateField(i: number, e: Event): void;
47
+ updateProp(prop: keyof DynamicFormField, value: any): void;
48
+ updateValidation(prop: keyof FieldValidation, value: any): void;
49
+ getOptions(): SelectOption[];
50
+ addOption(): void;
51
+ updateOption(idx: number, prop: 'label' | 'value', value: string): void;
52
+ removeOption(idx: number): void;
53
+ save(): void;
54
+ loadSchema(id: string): void;
55
+ deleteSchema(id: string, e: Event): void;
56
+ newForm(): void;
57
+ exportJSON(): void;
58
+ exportTypeScript(): void;
59
+ copyExport(): Promise<void>;
60
+ copyFormUrl(): void;
61
+ validationOf(key: keyof FieldValidation): any;
62
+ labelOf(type: FieldType): string;
63
+ trackByKey(_i: number, field: DynamicFormField): string;
64
+ trackByIdx(i: number): number;
65
+ private _defaultLabel;
66
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormBuilderComponent, never>;
67
+ static ɵcmp: i0.ɵɵComponentDeclaration<FormBuilderComponent, "ngx-form-builder", never, { "backRoute": { "alias": "backRoute"; "required": false; }; }, {}, never, never, true, never>;
68
+ }
69
+ export {};
@@ -0,0 +1,24 @@
1
+ import { OnInit } from '@angular/core';
2
+ import type { DynamicFormConfig, DynamicFormSubmitEvent } from '../../models/form-field.model';
3
+ import * as i0 from "@angular/core";
4
+ export declare class FormLoaderComponent implements OnInit {
5
+ /** Passé directement si le composant est utilisé sans ActivatedRoute */
6
+ formId?: string;
7
+ /** Route du lien "Retour" */
8
+ backRoute: string;
9
+ /** Route vers le builder */
10
+ builderRoute: string;
11
+ private route;
12
+ private formService;
13
+ config: import("@angular/core").WritableSignal<DynamicFormConfig | null>;
14
+ formTitle: import("@angular/core").WritableSignal<string>;
15
+ schemaId: import("@angular/core").WritableSignal<string>;
16
+ submitted: import("@angular/core").WritableSignal<boolean>;
17
+ submitData: import("@angular/core").WritableSignal<Record<string, unknown>>;
18
+ notFound: import("@angular/core").WritableSignal<boolean>;
19
+ ngOnInit(): void;
20
+ onSubmit(event: DynamicFormSubmitEvent): void;
21
+ reset(): void;
22
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormLoaderComponent, never>;
23
+ static ɵcmp: i0.ɵɵComponentDeclaration<FormLoaderComponent, "ngx-form-loader", never, { "formId": { "alias": "formId"; "required": false; }; "backRoute": { "alias": "backRoute"; "required": false; }; "builderRoute": { "alias": "builderRoute"; "required": false; }; }, {}, never, never, true, never>;
24
+ }
@@ -0,0 +1,26 @@
1
+ import type { DynamicFormConfig, DynamicFormSubmitEvent } from '../../models/form-field.model';
2
+ import type { SavedFormSchema } from '../../models/saved-form.model';
3
+ import * as i0 from "@angular/core";
4
+ export declare class MesFormulairesComponent {
5
+ /** Route vers le builder (lien "Nouveau formulaire" et actions d'édition) */
6
+ builderRoute: string;
7
+ /** Préfixe de route pour l'ouverture d'un formulaire par ID */
8
+ formRoute: string;
9
+ /** Route du lien "Retour" */
10
+ backRoute: string;
11
+ private formService;
12
+ readonly savedForms: import("@angular/core").Signal<SavedFormSchema[]>;
13
+ selectedId: import("@angular/core").WritableSignal<string | null>;
14
+ submitted: import("@angular/core").WritableSignal<boolean>;
15
+ submitData: import("@angular/core").WritableSignal<Record<string, unknown>>;
16
+ activeConfig: import("@angular/core").Signal<DynamicFormConfig | null>;
17
+ activeSchema: import("@angular/core").Signal<SavedFormSchema | null>;
18
+ selectForm(id: string): void;
19
+ onSubmit(event: DynamicFormSubmitEvent): void;
20
+ resetForm(): void;
21
+ deleteForm(id: string, e: Event): void;
22
+ formatDate(iso: string): string;
23
+ fieldCount(config: DynamicFormConfig): number;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<MesFormulairesComponent, never>;
25
+ static ɵcmp: i0.ɵɵComponentDeclaration<MesFormulairesComponent, "ngx-mes-formulaires", never, { "builderRoute": { "alias": "builderRoute"; "required": false; }; "formRoute": { "alias": "formRoute"; "required": false; }; "backRoute": { "alias": "backRoute"; "required": false; }; }, {}, never, never, true, never>;
26
+ }
@@ -0,0 +1,68 @@
1
+ export type FieldType = 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'textarea' | 'select' | 'multiselect' | 'checkbox' | 'radio' | 'date' | 'datetime-local' | 'file' | 'hidden' | 'divider' | 'heading';
2
+ export interface SelectOption {
3
+ label: string;
4
+ value: any;
5
+ disabled?: boolean;
6
+ group?: string;
7
+ }
8
+ export interface FieldValidation {
9
+ required?: boolean;
10
+ minLength?: number;
11
+ maxLength?: number;
12
+ min?: number;
13
+ max?: number;
14
+ pattern?: string | RegExp;
15
+ email?: boolean;
16
+ custom?: (value: any) => string | null;
17
+ messages?: {
18
+ required?: string;
19
+ minLength?: string;
20
+ maxLength?: string;
21
+ min?: string;
22
+ max?: string;
23
+ pattern?: string;
24
+ email?: string;
25
+ };
26
+ }
27
+ export interface FieldCondition {
28
+ field: string;
29
+ operator: 'equals' | 'notEquals' | 'contains' | 'greaterThan' | 'lessThan' | 'exists' | 'notExists';
30
+ value?: any;
31
+ }
32
+ export interface DynamicFormField {
33
+ key: string;
34
+ type: FieldType;
35
+ label?: string;
36
+ placeholder?: string;
37
+ hint?: string;
38
+ defaultValue?: any;
39
+ disabled?: boolean;
40
+ readonly?: boolean;
41
+ hidden?: boolean;
42
+ options?: SelectOption[] | string;
43
+ validation?: FieldValidation;
44
+ col?: 1 | 2 | 3 | 4 | 6 | 8 | 9 | 12;
45
+ cssClass?: string;
46
+ showWhen?: FieldCondition | FieldCondition[];
47
+ accept?: string;
48
+ multiple?: boolean;
49
+ rows?: number;
50
+ text?: string;
51
+ level?: 1 | 2 | 3 | 4 | 5 | 6;
52
+ icon?: string;
53
+ iconSuffix?: string;
54
+ attrs?: Record<string, any>;
55
+ }
56
+ export interface DynamicFormConfig {
57
+ fields: DynamicFormField[];
58
+ submitLabel?: string;
59
+ resetLabel?: string;
60
+ showReset?: boolean;
61
+ layout?: 'vertical' | 'horizontal' | 'inline';
62
+ cssClass?: string;
63
+ debug?: boolean;
64
+ }
65
+ export interface DynamicFormSubmitEvent {
66
+ value: Record<string, any>;
67
+ rawValue: Record<string, any>;
68
+ }
@@ -0,0 +1,7 @@
1
+ import type { DynamicFormConfig } from './form-field.model';
2
+ export interface SavedFormSchema {
3
+ id: string;
4
+ title: string;
5
+ config: DynamicFormConfig;
6
+ updatedAt: string;
7
+ }
@@ -0,0 +1,11 @@
1
+ import { EnvironmentProviders } from '@angular/core';
2
+ export interface NgxFormsLocalOptions {
3
+ storage: 'local';
4
+ }
5
+ export interface NgxFormsHttpOptions {
6
+ storage: 'http';
7
+ /** URL de base de l'API Spring, ex: 'https://api.example.com/forms' */
8
+ apiUrl: string;
9
+ }
10
+ export type NgxFormsOptions = NgxFormsLocalOptions | NgxFormsHttpOptions;
11
+ export declare function provideNgxForms(options: NgxFormsOptions): EnvironmentProviders;
@@ -0,0 +1,12 @@
1
+ import { FormGroup } from '@angular/forms';
2
+ import { DynamicFormField } from '../models/form-field.model';
3
+ import * as i0 from "@angular/core";
4
+ export declare class ConditionEvaluatorService {
5
+ /**
6
+ * Evaluate whether a field should be visible based on its showWhen condition(s).
7
+ */
8
+ isVisible(field: DynamicFormField, form: FormGroup): boolean;
9
+ private evaluate;
10
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConditionEvaluatorService, never>;
11
+ static ɵprov: i0.ɵɵInjectableDeclaration<ConditionEvaluatorService>;
12
+ }
@@ -0,0 +1,19 @@
1
+ import { AbstractControl, FormGroup, ValidatorFn } from '@angular/forms';
2
+ import { DynamicFormField, FieldValidation } from '../models/form-field.model';
3
+ import * as i0 from "@angular/core";
4
+ export declare class DynamicFormBuilderService {
5
+ /**
6
+ * Build a FormGroup from an array of DynamicFormField definitions.
7
+ */
8
+ buildFormGroup(fields: DynamicFormField[]): FormGroup;
9
+ /**
10
+ * Convert FieldValidation config into Angular ValidatorFn[].
11
+ */
12
+ buildValidators(validation?: FieldValidation): ValidatorFn[];
13
+ /**
14
+ * Get the human-readable error message for a form control.
15
+ */
16
+ getErrorMessage(control: AbstractControl, validation?: FieldValidation): string | null;
17
+ static ɵfac: i0.ɵɵFactoryDeclaration<DynamicFormBuilderService, never>;
18
+ static ɵprov: i0.ɵɵInjectableDeclaration<DynamicFormBuilderService>;
19
+ }
@@ -0,0 +1,16 @@
1
+ import { Observable } from 'rxjs';
2
+ import type { SavedFormSchema } from '../models/saved-form.model';
3
+ import type { DynamicFormConfig } from '../models/form-field.model';
4
+ import * as i0 from "@angular/core";
5
+ export declare class FormConfigService {
6
+ private adapter;
7
+ private _schemas;
8
+ readonly schemas: import("@angular/core").Signal<SavedFormSchema[]>;
9
+ constructor();
10
+ get(id: string): SavedFormSchema | null;
11
+ save(id: string, title: string, config: DynamicFormConfig): Observable<SavedFormSchema>;
12
+ delete(id: string): Observable<void>;
13
+ generateId(): string;
14
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormConfigService, never>;
15
+ static ɵprov: i0.ɵɵInjectableDeclaration<FormConfigService>;
16
+ }