@ng-modular-forms/core 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,26 +23,16 @@ Coordinates form structure and lifecycle.
23
23
  ```ts
24
24
  @Component({...})
25
25
  export class ExampleComponent extends FormOrchestratorBase {
26
- form = new FormGroup({});
27
26
 
28
27
  ngOnInit() {
29
28
  // Handlers are not required if there is no reactive logic or value change subscriptions.
30
29
  const mainHandler = inject(ExampleFormHandler);
31
30
  const sectionAHandler = inject(SectionAHandler);
32
31
 
33
- const formOptions = {
34
- mainHandler: mainHandler,
35
- subHandlers: {
36
- sectionA: sectionAHandler
37
- }
38
- };
39
-
40
- this.initialize(this.form, formOptions);
41
- }
32
+ form = new FormGroup({});
33
+ handlers = [mainHandler, sectionAHandler]
42
34
 
43
- // Only required if forms are split across multiple components
44
- onSubformReady(form: FormGroup, key: string) {
45
- super.onSubformReady(form, key);
35
+ this.initialize(form, handlers);
46
36
  }
47
37
  }
48
38
  ```
@@ -60,8 +50,8 @@ type ControlNames = (typeof CONTROL_NAMES)[number];
60
50
 
61
51
  @Injectable()
62
52
  export class SectionAHandler extends FormHandlerBase<ControlNames> {
63
- override getReactiveLogic(): Subscription {
64
- this.registerControls(this.form, [...CONTROL_NAMES]);
53
+ override getReactiveLogic(form?: FormGroup): Subscription {
54
+ this.registerControls(form, [...CONTROL_NAMES]);
65
55
 
66
56
  return this.valueChangesOf("fieldA").subscribe((value) => {
67
57
  if (value) {
@@ -1,85 +1,101 @@
1
- import { NgControl, Validators, FormGroup } from '@angular/forms';
1
+ import { NgControl, FormControl, Validators, TouchedChangeEvent, FormGroup } from '@angular/forms';
2
2
  import * as i0 from '@angular/core';
3
- import { inject, ChangeDetectorRef, DestroyRef, input, booleanAttribute, signal, computed, HostBinding, Directive } from '@angular/core';
3
+ import { inject, ChangeDetectorRef, DestroyRef, input, booleanAttribute, signal, computed, effect, Directive, Injectable } from '@angular/core';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
- import { Subscription } from 'rxjs';
5
+ import { Subscription, startWith } from 'rxjs';
6
6
 
7
7
  class FormControlBase {
8
- static nextId = 0;
9
- id = `nmf-form-control-${FormControlBase.nextId++}`;
10
8
  cdr = inject(ChangeDetectorRef);
11
9
  destroyRef = inject(DestroyRef);
12
- ngControl = inject(NgControl, {
13
- optional: true,
14
- self: true,
15
- });
10
+ static nextId = 0;
11
+ id = input(`nmf-form-control-${FormControlBase.nextId++}`);
12
+ _id = input(null, { alias: 'id' });
16
13
  label = input('');
17
14
  classList = input([]);
18
15
  loading = input(false);
19
- _name = input('', { alias: 'name' });
20
- _placeholder = input('', { alias: 'placeholder' });
21
- _required = input(false, {
22
- alias: 'required',
23
- transform: booleanAttribute,
24
- });
16
+ name = input('');
17
+ placeholder = input('');
25
18
  _disabledByInput = input(false, {
26
- alias: 'disabled',
27
19
  transform: booleanAttribute,
28
20
  });
29
- _readonly = input(false, { alias: 'readonly' });
30
21
  _disabledByCva = signal(false);
31
- _disabled = computed(() => this._disabledByInput() || this._disabledByCva() || this.loading());
32
- focused = false;
33
- lastErrorState = false;
34
- _value = null;
35
- get value() {
36
- return this._value;
37
- }
38
- set value(value) {
39
- this._value = value;
40
- this.cdr.markForCheck();
41
- }
42
- get name() {
43
- return this._name();
44
- }
45
- get placeholder() {
46
- return this._placeholder();
47
- }
48
- get required() {
49
- const formControl = this.ngControl?.control;
50
- const required = !!formControl && formControl.hasValidator(Validators.required);
51
- return this._required() || required;
52
- }
53
- get disabled() {
54
- return this._disabled();
55
- }
56
- get readonly() {
57
- return this._readonly();
22
+ ngControl = inject(NgControl, {
23
+ self: true,
24
+ optional: true,
25
+ });
26
+ control = new FormControl(null);
27
+ disabled = computed(() => this._disabledByInput() || this._disabledByCva());
28
+ isRequired = signal(this.ngControl?.control?.hasValidator(Validators.required) ?? false);
29
+ hasErrors = signal(false);
30
+ changeSub = new Subscription();
31
+ onChange = () => { };
32
+ onTouched = () => { };
33
+ constructor() {
34
+ if (this.ngControl) {
35
+ this.ngControl.valueAccessor = this;
36
+ }
37
+ effect(() => {
38
+ const inputDisabled = this._disabledByInput();
39
+ const cvaDisabled = this._disabledByCva();
40
+ if (inputDisabled || cvaDisabled) {
41
+ this.control.disable({ emitEvent: false });
42
+ }
43
+ else {
44
+ this.control.enable({ emitEvent: true });
45
+ }
46
+ });
58
47
  }
59
- get errorState() {
60
- const control = this.ngControl?.control;
61
- return !!control && control.invalid && control.touched;
48
+ ngOnInit() {
49
+ const parent = this.ngControl?.control;
50
+ if (!parent)
51
+ return;
52
+ parent.statusChanges
53
+ .pipe(startWith(null), takeUntilDestroyed(this.destroyRef))
54
+ .subscribe(() => {
55
+ this.control.setValidators(parent.validator ?? null);
56
+ this.control.setAsyncValidators(parent.asyncValidator ?? null);
57
+ this.control.updateValueAndValidity({ emitEvent: false });
58
+ this.hasErrors.set(parent.invalid && parent.touched);
59
+ this.isRequired.set(parent.hasValidator(Validators.required) ?? false);
60
+ this.cdr.markForCheck();
61
+ });
62
+ parent.events
63
+ .pipe(takeUntilDestroyed(this.destroyRef))
64
+ .subscribe((event) => {
65
+ if (event instanceof TouchedChangeEvent) {
66
+ if (parent.touched) {
67
+ this.control.markAsTouched();
68
+ }
69
+ else {
70
+ this.control.markAsUntouched();
71
+ }
72
+ this.hasErrors.set(parent.invalid && parent.touched);
73
+ this.cdr.markForCheck();
74
+ }
75
+ });
76
+ parent.valueChanges
77
+ .pipe(startWith(null), takeUntilDestroyed(this.destroyRef))
78
+ .subscribe(() => this.cdr.markForCheck());
62
79
  }
63
- get empty() {
64
- return (this._value === null || this._value === '' || this._value === undefined);
80
+ writeValue(value) {
81
+ this.control.setValue(value, { emitEvent: false });
65
82
  }
66
- ngOnInit() {
67
- const control = this.ngControl?.control;
68
- if (!control) {
69
- throw new Error(`FormControl ${this.id} not found`);
70
- }
71
- control.statusChanges
83
+ registerOnChange(fn) {
84
+ this.onChange = fn;
85
+ this.changeSub.unsubscribe();
86
+ this.changeSub = this.control.valueChanges
72
87
  .pipe(takeUntilDestroyed(this.destroyRef))
73
- .subscribe((val) => this.cdr.markForCheck());
88
+ .subscribe((v) => {
89
+ fn(v);
90
+ });
74
91
  }
75
- ngDoCheck() {
76
- const newState = this.errorState;
77
- if (newState !== this.lastErrorState) {
78
- this.lastErrorState = newState;
79
- this.cdr.markForCheck();
80
- }
92
+ registerOnTouched(fn) {
93
+ this.onTouched = fn;
94
+ }
95
+ setDisabledState(isDisabled) {
96
+ this._disabledByCva.set(isDisabled);
81
97
  }
82
- getErrorMessage() {
98
+ errorMessage() {
83
99
  const control = this.ngControl?.control;
84
100
  if (control == null || !control.errors || !control.touched)
85
101
  return null;
@@ -110,13 +126,11 @@ class FormControlBase {
110
126
  }
111
127
  }
112
128
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormControlBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
113
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: FormControlBase, isStandalone: true, inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, classList: { classPropertyName: "classList", publicName: "classList", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, _name: { classPropertyName: "_name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, _placeholder: { classPropertyName: "_placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, _required: { classPropertyName: "_required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, _disabledByInput: { classPropertyName: "_disabledByInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, _readonly: { classPropertyName: "_readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "this.id" } }, ngImport: i0 });
129
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.21", type: FormControlBase, isStandalone: true, inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, _id: { classPropertyName: "_id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, classList: { classPropertyName: "classList", publicName: "classList", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, _disabledByInput: { classPropertyName: "_disabledByInput", publicName: "_disabledByInput", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
114
130
  }
115
131
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormControlBase, decorators: [{
116
132
  type: Directive
117
- }], propDecorators: { id: [{
118
- type: HostBinding
119
- }] } });
133
+ }], ctorParameters: () => [] });
120
134
 
121
135
  function getControl(controlName, form) {
122
136
  if (!form) {
@@ -177,19 +191,6 @@ function formatNumber(value, locale = 'en-US', options = { maximumFractionDigits
177
191
  const formatted = numericValue.toLocaleString(locale, options);
178
192
  return isNegative ? `-${formatted}` : formatted;
179
193
  }
180
- function formatCurrency(value, locale = 'en-US', options = { maximumFractionDigits: 2 }) {
181
- if (value == null || value === '') {
182
- return null;
183
- }
184
- if (typeof value !== 'string') {
185
- value = String(value);
186
- }
187
- value = value.replace(/[^\d\-,.]/g, '');
188
- const isNegative = value.startsWith('-');
189
- const numericValue = Number(value.replace(/[,$-]/g, ''));
190
- const formatted = numericValue.toLocaleString(locale, options);
191
- return isNegative ? `-${formatted}` : formatted;
192
- }
193
194
 
194
195
  class FormHandlerBase {
195
196
  registeredControls = {};
@@ -215,57 +216,107 @@ class FormHandlerBase {
215
216
  }
216
217
 
217
218
  class FormMapperBase {
218
- patchForm(form, data, _context, emitEvent = false) {
219
- form.patchValue({
220
- ...data,
221
- }, { emitEvent });
219
+ fromModel(model) {
220
+ return structuredClone(model);
221
+ }
222
+ toRequest(formValue) {
223
+ return formValue;
224
+ }
225
+ }
226
+
227
+ class FormHydrator {
228
+ hydrate(form, model, registry = {}) {
229
+ Object.entries(form.controls).forEach(([key, control]) => {
230
+ if (!(key in model))
231
+ return;
232
+ const mapper = registry[key];
233
+ const value = model?.[key];
234
+ if (control instanceof FormGroup) {
235
+ if (mapper) {
236
+ control.patchValue(mapper.fromModel(value), { emitEvent: false });
237
+ }
238
+ else {
239
+ this.hydrate(control, value, registry);
240
+ }
241
+ return;
242
+ }
243
+ control.patchValue(value, { emitEvent: false });
244
+ });
222
245
  }
223
- patchFromModel(form, model, store) {
224
- const formModel = this.transformFromModel(model);
225
- this.patchForm(form, formModel, store);
246
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormHydrator, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
247
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormHydrator, providedIn: 'root' });
248
+ }
249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormHydrator, decorators: [{
250
+ type: Injectable,
251
+ args: [{ providedIn: 'root' }]
252
+ }] });
253
+
254
+ class FormSerializer {
255
+ toRequest(form, registry = {}) {
256
+ const result = {};
257
+ Object.entries(form.controls).forEach(([key, control]) => {
258
+ const mapper = registry[key];
259
+ if (control instanceof FormGroup) {
260
+ if (mapper) {
261
+ result[key] = mapper.toRequest(control.value);
262
+ }
263
+ else {
264
+ result[key] = this.toRequest(control, registry);
265
+ }
266
+ return;
267
+ }
268
+ result[key] = control.value;
269
+ });
270
+ return result;
226
271
  }
272
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormSerializer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
273
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormSerializer, providedIn: 'root' });
227
274
  }
275
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormSerializer, decorators: [{
276
+ type: Injectable,
277
+ args: [{ providedIn: 'root' }]
278
+ }] });
228
279
 
229
- class FormOrchestratorBase {
280
+ class FormOrchestrator extends FormMapperBase {
281
+ hydrator;
282
+ serializer;
230
283
  _form = signal(new FormGroup({}));
231
- _mainHandler = signal(null);
232
- _subHandlers = signal({});
284
+ _handlers = signal([]);
285
+ _mapperRegistry = signal({});
233
286
  _status = signal('idle');
234
287
  _errorMessage = signal(null);
235
- _loadedHandlers = signal(0);
236
- _allHandlersLoaded = signal(false);
237
- _logicSubscription = new Subscription();
238
288
  form = this._form.asReadonly();
239
- mainHandler = this._mainHandler.asReadonly();
240
- subHandlers = this._subHandlers.asReadonly();
289
+ handlers = this._handlers.asReadonly();
290
+ mapperRegistry = this._mapperRegistry.asReadonly();
241
291
  status = this._status.asReadonly();
242
292
  errorMessage = this._errorMessage.asReadonly();
293
+ _logicSubscription = new Subscription();
294
+ constructor(hydrator, serializer) {
295
+ super();
296
+ this.hydrator = hydrator;
297
+ this.serializer = serializer;
298
+ }
243
299
  /**
244
300
  * Initializes orchestration state.
245
301
  * Must be called before any subform registration or handler execution.
246
302
  */
247
- initialize(form, formOrchestratorOptions) {
248
- const { mainHandler, subHandlers = {} } = formOrchestratorOptions ?? {};
303
+ orchestrate(options) {
304
+ const { form, handlers, mapperRegistry } = options;
249
305
  this._form.set(form);
250
- this._mainHandler.set(mainHandler ?? null);
251
- this._subHandlers.set(subHandlers);
252
- this._loadedHandlers.set(0);
253
- const subHandlerCount = Object.keys(this.subHandlers());
254
- if (subHandlerCount.length === 0) {
255
- this.loadMainHandler();
256
- }
306
+ this._handlers.set(handlers);
307
+ this._mapperRegistry.set(mapperRegistry);
308
+ Object.values(this.handlers()).forEach((handler) => {
309
+ this.addReactiveLogic(handler.getReactiveLogic(form));
310
+ });
257
311
  }
258
312
  setForm(form) {
259
313
  this._form.set(form);
260
314
  }
261
- getHandler(key) {
262
- return this.subHandlers()[key];
315
+ getSubForm(key) {
316
+ return this.form().get(key);
263
317
  }
264
- setHandler(key, handler) {
265
- this._subHandlers.set({
266
- ...this._subHandlers(),
267
- [key]: handler,
268
- });
318
+ addHandler(handler) {
319
+ this._handlers.set([...this._handlers(), handler]);
269
320
  }
270
321
  addReactiveLogic(subscription) {
271
322
  this._logicSubscription.add(subscription);
@@ -276,53 +327,31 @@ class FormOrchestratorBase {
276
327
  setErrorMessage(message) {
277
328
  this._errorMessage.set(message);
278
329
  }
279
- ngOnDestroy() {
280
- this._logicSubscription.unsubscribe();
330
+ hydrateFromModel(model) {
331
+ const form = this.form();
332
+ const registry = this.mapperRegistry();
333
+ Object.entries(form.controls).forEach(([key, control]) => {
334
+ if (!(key in model))
335
+ return;
336
+ const mapper = registry[key];
337
+ const value = model?.[key];
338
+ if (control instanceof FormGroup) {
339
+ this.hydrator.hydrate(control, mapper ? mapper.fromModel(value) : value);
340
+ }
341
+ });
281
342
  }
282
- /**
283
- * Registers a subform into the main form tree and coordinates handler execution.
284
- *
285
- * IMPORTANT:
286
- * - Handler execution is gated until all registered subhandlers are ready.
287
- * - Calling order matters; this is lifecycle-sensitive orchestration logic.
288
- */
289
- onSubformReady(subform, groupName, nestGroups = false) {
290
- if (nestGroups) {
291
- this.form().setControl(groupName, subform);
292
- }
293
- else {
294
- const keys = Object.keys(subform.controls);
295
- keys.forEach((key) => {
296
- this.form().setControl(key, subform.get(key));
297
- });
298
- }
299
- // Prevent duplicate main handler execution when all subhandlers already resolved
300
- if (this._allHandlersLoaded()) {
301
- return;
302
- }
303
- const subformHandler = this.subHandlers()[groupName];
304
- if (subformHandler) {
305
- this._loadedHandlers.set(this._loadedHandlers() + 1);
306
- this.addReactiveLogic(subformHandler.getReactiveLogic());
307
- }
308
- const totalSubHandlers = Object.keys(this.subHandlers()).length;
309
- const allSubHandlersLoaded = this._loadedHandlers() === totalSubHandlers;
310
- if (allSubHandlersLoaded && this.mainHandler()) {
311
- this.loadMainHandler();
312
- }
343
+ buildRequest() {
344
+ return this.serializer.toRequest(this.form(), this.mapperRegistry());
313
345
  }
314
- loadMainHandler() {
315
- if (!this.mainHandler())
316
- return;
317
- this.addReactiveLogic(this.mainHandler().getReactiveLogic(this.form()));
318
- this._allHandlersLoaded.set(true);
346
+ ngOnDestroy() {
347
+ this._logicSubscription.unsubscribe();
319
348
  }
320
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormOrchestratorBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
321
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.21", type: FormOrchestratorBase, isStandalone: true, ngImport: i0 });
349
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormOrchestrator, deps: [{ token: FormHydrator }, { token: FormSerializer }], target: i0.ɵɵFactoryTarget.Directive });
350
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.21", type: FormOrchestrator, isStandalone: true, usesInheritance: true, ngImport: i0 });
322
351
  }
323
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormOrchestratorBase, decorators: [{
352
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: FormOrchestrator, decorators: [{
324
353
  type: Directive
325
- }] });
354
+ }], ctorParameters: () => [{ type: FormHydrator }, { type: FormSerializer }] });
326
355
 
327
356
  /*
328
357
  * Public API Surface of core
@@ -332,5 +361,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
332
361
  * Generated bundle index. Do not edit.
333
362
  */
334
363
 
335
- export { FormControlBase, FormHandlerBase, FormMapperBase, FormOrchestratorBase, formatCurrency, formatNumber, getControl, getControlValue, parseNumber };
364
+ export { FormControlBase, FormHandlerBase, FormHydrator, FormMapperBase, FormOrchestrator, FormSerializer, formatNumber, getControl, getControlValue, parseNumber };
336
365
  //# sourceMappingURL=ng-modular-forms-core.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-modular-forms-core.mjs","sources":["../../../projects/core/src/lib/form-control-base.ts","../../../projects/core/src/lib/form.util.ts","../../../projects/core/src/lib/form-handler-base.ts","../../../projects/core/src/lib/form-mapper-base.ts","../../../projects/core/src/lib/form-orchestrator-base.ts","../../../projects/core/src/public-api.ts","../../../projects/core/src/ng-modular-forms-core.ts"],"sourcesContent":["import { NgControl, Validators } from '@angular/forms';\nimport {\n booleanAttribute,\n ChangeDetectorRef,\n computed,\n DestroyRef,\n Directive,\n DoCheck,\n HostBinding,\n inject,\n input,\n OnInit,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\n@Directive()\nexport abstract class FormControlBase<T> implements OnInit, DoCheck {\n static nextId = 0;\n\n @HostBinding()\n id = `nmf-form-control-${FormControlBase.nextId++}`;\n\n protected readonly cdr = inject(ChangeDetectorRef);\n protected readonly destroyRef = inject(DestroyRef);\n\n readonly ngControl = inject(NgControl, {\n optional: true,\n self: true,\n });\n\n readonly label = input<string>('');\n readonly classList = input<string[]>([]);\n readonly loading = input<boolean>(false);\n\n readonly _name = input<string>('', { alias: 'name' });\n readonly _placeholder = input<string>('', { alias: 'placeholder' });\n readonly _required = input<boolean, unknown>(false, {\n alias: 'required',\n transform: booleanAttribute,\n });\n readonly _disabledByInput = input<boolean, unknown>(false, {\n alias: 'disabled',\n transform: booleanAttribute,\n });\n readonly _readonly = input<boolean>(false, { alias: 'readonly' });\n\n protected readonly _disabledByCva = signal(false);\n readonly _disabled = computed(\n () => this._disabledByInput() || this._disabledByCva() || this.loading(),\n );\n\n focused = false;\n\n private lastErrorState = false;\n\n private _value: T | null = null;\n\n get value(): T | null {\n return this._value;\n }\n\n set value(value: T | null) {\n this._value = value;\n this.cdr.markForCheck();\n }\n\n get name(): string {\n return this._name();\n }\n\n get placeholder(): string {\n return this._placeholder();\n }\n\n get required(): boolean {\n const formControl = this.ngControl?.control;\n const required =\n !!formControl && formControl.hasValidator(Validators.required);\n return this._required() || required;\n }\n\n get disabled(): boolean {\n return this._disabled();\n }\n\n get readonly(): boolean {\n return this._readonly();\n }\n\n get errorState(): boolean {\n const control = this.ngControl?.control;\n return !!control && control.invalid && control.touched;\n }\n\n get empty(): boolean {\n return (\n this._value === null || this._value === '' || this._value === undefined\n );\n }\n\n ngOnInit() {\n const control = this.ngControl?.control;\n if (!control) {\n throw new Error(`FormControl ${this.id} not found`);\n }\n\n control.statusChanges\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((val) => this.cdr.markForCheck());\n }\n\n ngDoCheck() {\n const newState = this.errorState;\n\n if (newState !== this.lastErrorState) {\n this.lastErrorState = newState;\n this.cdr.markForCheck();\n }\n }\n\n protected getErrorMessage(): string | null {\n const control = this.ngControl?.control;\n\n if (control == null || !control.errors || !control.touched) return null;\n\n const firstKey = Object.keys(control.errors)[0];\n const error = control.errors[firstKey];\n\n switch (firstKey) {\n case 'required':\n return 'This field is required';\n case 'minlength':\n return `Minimum length is ${error.requiredLength}`;\n case 'maxlength':\n return `Maximum length is ${error.requiredLength}`;\n case 'min':\n return `Minimum value is ${error.min}`;\n case 'max':\n return `Maximum value is ${error.max}`;\n case 'email':\n return 'Invalid email address';\n case 'pattern':\n return 'Invalid format';\n case 'custom':\n if (typeof error === 'string') {\n return error;\n }\n return 'Invalid value';\n default:\n return 'Invalid value';\n }\n }\n}\n","import { FormControl, FormGroup } from '@angular/forms';\n\nexport function getControl<T = unknown>(controlName: string, form: FormGroup) {\n if (!form) {\n throw new Error(\n `Missing form instance while getting the control of \"${controlName}\"`,\n );\n }\n\n const control = form.get(controlName) as FormControl<T>;\n if (!control) {\n throw new Error(`Missing control \"${controlName}\" in form \"${form}\"`);\n }\n\n return control;\n}\n\nexport function getControlValue<T = unknown>(\n controlName: string,\n form: FormGroup,\n): T | null;\n\nexport function getControlValue(\n controlName: string,\n form: FormGroup,\n): number | null;\n\nexport function getControlValue<T = unknown>(\n controlName: string,\n form: FormGroup,\n): T | null {\n const control = getControl<T>(controlName, form);\n if (!control) {\n throw new Error(`Missing control \"${controlName}\" in form \"${form}\"`);\n }\n\n const value = control.getRawValue();\n if (value === '') {\n return null;\n }\n\n if (typeof value === 'string') {\n const cleaned = value.replace(/,/g, '');\n\n if (!Number.isNaN(Number(cleaned))) {\n return parseNumber(value) as T;\n }\n }\n\n return value;\n}\n\nexport function parseNumber(\n input: string | number | null | undefined,\n): number | null {\n if (input == null || input === '') return null;\n\n if (typeof input === 'number') {\n return Number.isFinite(input) ? input : null;\n }\n\n const normalized = input\n .trim()\n .replace(/,/g, '') // remove thousands\n .replace(/(?!^)-/g, ''); // only allow leading '-'\n\n if (normalized === '-' || normalized === '.' || normalized === '-.') {\n return null;\n }\n\n const num = Number(normalized);\n\n return Number.isFinite(num) ? num : null;\n}\n\nexport function formatNumber(\n value: string | number | null,\n locale: string = 'en-US',\n options: Intl.NumberFormatOptions = { maximumFractionDigits: 2 },\n): string | null {\n if (value == null || value === '') {\n return null;\n }\n if (typeof value !== 'string') {\n value = String(value);\n }\n\n value = value.replace(/[^\\d\\-,.]/g, '');\n\n if (value === '') {\n return null;\n }\n\n const isNegative = value.startsWith('-');\n const numericValue = Number(value.replace(/[,$-]/g, ''));\n const formatted = numericValue.toLocaleString(locale, options);\n\n return isNegative ? `-${formatted}` : formatted;\n}\n\nexport function formatCurrency(\n value: string | number | null,\n locale: string = 'en-US',\n options: Intl.NumberFormatOptions = { maximumFractionDigits: 2 },\n): string | null {\n if (value == null || value === '') {\n return null;\n }\n if (typeof value !== 'string') {\n value = String(value);\n }\n\n value = value.replace(/[^\\d\\-,.]/g, '');\n\n const isNegative = value.startsWith('-');\n const numericValue = Number(value.replace(/[,$-]/g, ''));\n const formatted = numericValue.toLocaleString(locale, options);\n\n return isNegative ? `-${formatted}` : formatted;\n}\n","import { FormControl, FormGroup } from '@angular/forms';\nimport { Observable, Subscription } from 'rxjs';\nimport { getControl } from './form.util';\n\nexport abstract class FormHandlerBase<ControlNames extends string = string> {\n abstract getReactiveLogic(form?: FormGroup): Subscription;\n\n protected registeredControls: Record<string, FormControl> = {};\n\n /**\n * Registers form controls for later reactive access.\n */\n registerControls(form: FormGroup, controlNames: ControlNames[]): void {\n controlNames.forEach((cn) => {\n const control = getControl(cn.replace(/_/g, '.'), form);\n\n if (!control) {\n throw new Error(\n `Failed to register control with name: \"${cn}\" in form group: \"${form}\"`,\n );\n }\n\n const key = cn as ControlNames;\n this.registeredControls[key] = control;\n });\n }\n\n valueChangesOf<T>(key: ControlNames): Observable<T> {\n if (!this.registeredControls[key]) {\n throw new Error(\n `Control with name: \"${key}\" not found. Ensure it is registered in registerControls(...)`,\n );\n }\n\n return this.registeredControls[key].valueChanges as Observable<T>;\n }\n}\n","import { FormGroup } from '@angular/forms';\n\nexport abstract class FormMapperBase<\n TModelIn = unknown,\n TModelOut = unknown,\n TFormModel = unknown,\n TStore = Record<string, unknown>,\n> {\n /**\n * Maps form state + external store into an API request payload.\n */\n abstract buildRequest(form: FormGroup, store: TStore): Partial<TModelOut>;\n\n /**\n * Transforms a domain/API model into a form-compatible structure.\n */\n abstract transformFromModel(model: TModelIn): TFormModel;\n\n patchForm(\n form: FormGroup,\n data: TFormModel,\n _context: TStore,\n emitEvent: boolean = false,\n ): void {\n form.patchValue(\n {\n ...(data as Record<string, unknown>),\n },\n { emitEvent },\n );\n }\n\n patchFromModel(form: FormGroup, model: TModelIn, store: TStore): void {\n const formModel = this.transformFromModel(model);\n this.patchForm(form, formModel, store);\n }\n}\n","import { FormGroup } from '@angular/forms';\nimport { Directive, OnDestroy, signal } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { FormHandlerBase } from './form-handler-base';\n\nexport type FormStatus = 'idle' | 'submitting' | 'error' | 'success';\n\ntype FormHandlerRegistry = Record<string, FormHandlerBase<string>>;\n\ninterface FormOrchestratorOptions {\n mainHandler?: FormHandlerBase<string> | null;\n subHandlers?: FormHandlerRegistry;\n}\n\n@Directive()\nexport abstract class FormOrchestratorBase implements OnDestroy {\n private _form = signal<FormGroup>(new FormGroup({}));\n\n private _mainHandler = signal<FormHandlerBase<string> | null>(null);\n private _subHandlers = signal<FormHandlerRegistry>({});\n\n private _status = signal<FormStatus>('idle');\n private _errorMessage = signal<string | null>(null);\n\n private _loadedHandlers = signal<number>(0);\n private _allHandlersLoaded = signal<boolean>(false);\n\n private _logicSubscription = new Subscription();\n\n public readonly form = this._form.asReadonly();\n public readonly mainHandler = this._mainHandler.asReadonly();\n public readonly subHandlers = this._subHandlers.asReadonly();\n public readonly status = this._status.asReadonly();\n public readonly errorMessage = this._errorMessage.asReadonly();\n\n /**\n * Initializes orchestration state.\n * Must be called before any subform registration or handler execution.\n */\n public initialize(\n form: FormGroup,\n formOrchestratorOptions?: FormOrchestratorOptions,\n ) {\n const { mainHandler, subHandlers = {} } = formOrchestratorOptions ?? {};\n\n this._form.set(form);\n this._mainHandler.set(mainHandler ?? null);\n this._subHandlers.set(subHandlers);\n this._loadedHandlers.set(0);\n\n const subHandlerCount = Object.keys(this.subHandlers());\n if (subHandlerCount.length === 0) {\n this.loadMainHandler();\n }\n }\n\n public setForm(form: FormGroup) {\n this._form.set(form);\n }\n\n public getHandler(key: string): FormHandlerBase<string> | undefined {\n return this.subHandlers()[key];\n }\n\n public setHandler(key: string, handler: FormHandlerBase<string>) {\n this._subHandlers.set({\n ...this._subHandlers(),\n [key]: handler,\n });\n }\n\n public addReactiveLogic(subscription: Subscription) {\n this._logicSubscription.add(subscription);\n }\n\n public setStatus(status: FormStatus) {\n this._status.set(status);\n }\n\n public setErrorMessage(message: string | null) {\n this._errorMessage.set(message);\n }\n\n ngOnDestroy(): void {\n this._logicSubscription.unsubscribe();\n }\n\n /**\n * Registers a subform into the main form tree and coordinates handler execution.\n *\n * IMPORTANT:\n * - Handler execution is gated until all registered subhandlers are ready.\n * - Calling order matters; this is lifecycle-sensitive orchestration logic.\n */\n onSubformReady(\n subform: FormGroup,\n groupName: string,\n nestGroups: boolean = false,\n ): void {\n if (nestGroups) {\n this.form().setControl(groupName, subform);\n } else {\n const keys = Object.keys(subform.controls);\n keys.forEach((key) => {\n this.form().setControl(key, subform.get(key));\n });\n }\n\n // Prevent duplicate main handler execution when all subhandlers already resolved\n if (this._allHandlersLoaded()) {\n return;\n }\n\n const subformHandler = this.subHandlers()[groupName];\n\n if (subformHandler) {\n this._loadedHandlers.set(this._loadedHandlers() + 1);\n this.addReactiveLogic(subformHandler.getReactiveLogic());\n }\n\n const totalSubHandlers = Object.keys(this.subHandlers()).length;\n const allSubHandlersLoaded = this._loadedHandlers() === totalSubHandlers;\n\n if (allSubHandlersLoaded && this.mainHandler()) {\n this.loadMainHandler();\n }\n }\n\n private loadMainHandler() {\n if (!this.mainHandler()) return;\n\n this.addReactiveLogic(this.mainHandler()!.getReactiveLogic(this.form()));\n this._allHandlersLoaded.set(true);\n }\n}\n","/*\n * Public API Surface of core\n */\n\nexport * from './lib/form-control-base';\nexport * from './lib/form-handler-base';\nexport * from './lib/form-mapper-base';\nexport * from './lib/form-orchestrator-base';\nexport * from './lib/form.util';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ng-modular-forms-core.mjs","sources":["../../../projects/core/src/lib/base/form-control-base.ts","../../../projects/core/src/lib/form-util.ts","../../../projects/core/src/lib/base/form-handler-base.ts","../../../projects/core/src/lib/base/form-mapper-base.ts","../../../projects/core/src/lib/form-hydrator.ts","../../../projects/core/src/lib/form-serializer.ts","../../../projects/core/src/lib/form-orchestrator.ts","../../../projects/core/src/public-api.ts","../../../projects/core/src/ng-modular-forms-core.ts"],"sourcesContent":["import {\n ControlValueAccessor,\n FormControl,\n NgControl,\n TouchedChangeEvent,\n Validators,\n} from '@angular/forms';\nimport {\n booleanAttribute,\n ChangeDetectorRef,\n computed,\n DestroyRef,\n Directive,\n effect,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { startWith, Subscription } from 'rxjs';\n\n@Directive()\nexport abstract class FormControlBase<T> implements ControlValueAccessor {\n protected readonly cdr = inject(ChangeDetectorRef);\n protected readonly destroyRef = inject(DestroyRef);\n\n static nextId = 0;\n\n readonly id = input<string | null>(\n `nmf-form-control-${FormControlBase.nextId++}`,\n );\n\n readonly _id = input<string | null>(null, { alias: 'id' });\n readonly label = input<string>('');\n readonly classList = input<string[]>([]);\n readonly loading = input<boolean>(false);\n\n readonly name = input<string>('');\n readonly placeholder = input<string>('');\n readonly _disabledByInput = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n readonly _disabledByCva = signal(false);\n\n readonly ngControl = inject(NgControl, {\n self: true,\n optional: true,\n });\n\n protected readonly control = new FormControl<T | null>(null);\n\n protected readonly disabled = computed(\n () => this._disabledByInput() || this._disabledByCva(),\n );\n\n protected readonly isRequired = signal(\n this.ngControl?.control?.hasValidator(Validators.required) ?? false,\n );\n\n protected readonly hasErrors = signal(false);\n\n private changeSub = new Subscription();\n\n protected onChange: (value: T | null) => void = () => {};\n protected onTouched: () => void = () => {};\n\n constructor() {\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n\n effect(() => {\n const inputDisabled = this._disabledByInput();\n const cvaDisabled = this._disabledByCva();\n\n if (inputDisabled || cvaDisabled) {\n this.control.disable({ emitEvent: false });\n } else {\n this.control.enable({ emitEvent: true });\n }\n });\n }\n\n ngOnInit() {\n const parent = this.ngControl?.control;\n if (!parent) return;\n\n parent.statusChanges\n .pipe(startWith(null), takeUntilDestroyed(this.destroyRef))\n .subscribe(() => {\n this.control.setValidators(parent.validator ?? null);\n this.control.setAsyncValidators(parent.asyncValidator ?? null);\n this.control.updateValueAndValidity({ emitEvent: false });\n\n this.hasErrors.set(parent.invalid && parent.touched);\n this.isRequired.set(parent.hasValidator(Validators.required) ?? false);\n\n this.cdr.markForCheck();\n });\n\n parent.events\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((event) => {\n if (event instanceof TouchedChangeEvent) {\n if (parent.touched) {\n this.control.markAsTouched();\n } else {\n this.control.markAsUntouched();\n }\n this.hasErrors.set(parent.invalid && parent.touched);\n this.cdr.markForCheck();\n }\n });\n\n parent.valueChanges\n .pipe(startWith(null), takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this.cdr.markForCheck());\n }\n\n writeValue(value: T): void {\n this.control.setValue(value, { emitEvent: false });\n }\n\n registerOnChange(fn: (value: T | null) => void): void {\n this.onChange = fn;\n\n this.changeSub.unsubscribe();\n this.changeSub = this.control.valueChanges\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((v) => {\n fn(v);\n });\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._disabledByCva.set(isDisabled);\n }\n\n protected errorMessage(): string | null {\n const control = this.ngControl?.control;\n if (control == null || !control.errors || !control.touched) return null;\n\n const firstKey = Object.keys(control.errors)[0];\n const error = control.errors[firstKey];\n\n switch (firstKey) {\n case 'required':\n return 'This field is required';\n case 'minlength':\n return `Minimum length is ${error.requiredLength}`;\n case 'maxlength':\n return `Maximum length is ${error.requiredLength}`;\n case 'min':\n return `Minimum value is ${error.min}`;\n case 'max':\n return `Maximum value is ${error.max}`;\n case 'email':\n return 'Invalid email address';\n case 'pattern':\n return 'Invalid format';\n case 'custom':\n if (typeof error === 'string') {\n return error;\n }\n return 'Invalid value';\n default:\n return 'Invalid value';\n }\n }\n}\n","import { FormControl, FormGroup } from '@angular/forms';\n\nexport function getControl<T = unknown>(controlName: string, form: FormGroup) {\n if (!form) {\n throw new Error(\n `Missing form instance while getting the control of \"${controlName}\"`,\n );\n }\n\n const control = form.get(controlName) as FormControl<T>;\n if (!control) {\n throw new Error(`Missing control \"${controlName}\" in form \"${form}\"`);\n }\n\n return control;\n}\n\nexport function getControlValue<T = unknown>(\n controlName: string,\n form: FormGroup,\n): T | null;\n\nexport function getControlValue(\n controlName: string,\n form: FormGroup,\n): number | null;\n\nexport function getControlValue<T = unknown>(\n controlName: string,\n form: FormGroup,\n): T | null {\n const control = getControl<T>(controlName, form);\n if (!control) {\n throw new Error(`Missing control \"${controlName}\" in form \"${form}\"`);\n }\n\n const value = control.getRawValue();\n if (value === '') {\n return null;\n }\n\n if (typeof value === 'string') {\n const cleaned = value.replace(/,/g, '');\n\n if (!Number.isNaN(Number(cleaned))) {\n return parseNumber(value) as T;\n }\n }\n\n return value;\n}\n\nexport function parseNumber(\n input: string | number | null | undefined,\n): number | null {\n if (input == null || input === '') return null;\n\n if (typeof input === 'number') {\n return Number.isFinite(input) ? input : null;\n }\n\n const normalized = input\n .trim()\n .replace(/,/g, '') // remove thousands\n .replace(/(?!^)-/g, ''); // only allow leading '-'\n\n if (normalized === '-' || normalized === '.' || normalized === '-.') {\n return null;\n }\n\n const num = Number(normalized);\n\n return Number.isFinite(num) ? num : null;\n}\n\nexport function formatNumber(\n value: string | number | null,\n locale: string = 'en-US',\n options: Intl.NumberFormatOptions = { maximumFractionDigits: 2 },\n): string | null {\n if (value == null || value === '') {\n return null;\n }\n if (typeof value !== 'string') {\n value = String(value);\n }\n\n value = value.replace(/[^\\d\\-,.]/g, '');\n\n if (value === '') {\n return null;\n }\n\n const isNegative = value.startsWith('-');\n const numericValue = Number(value.replace(/[,$-]/g, ''));\n const formatted = numericValue.toLocaleString(locale, options);\n\n return isNegative ? `-${formatted}` : formatted;\n}\n","import { FormControl, FormGroup } from '@angular/forms';\nimport { Observable, Subscription } from 'rxjs';\nimport { getControl } from '../form-util';\n\nexport abstract class FormHandlerBase<ControlNames extends string = string> {\n abstract getReactiveLogic(form: FormGroup): Subscription;\n\n private registeredControls: Record<string, FormControl> = {};\n\n /**\n * Registers form controls for later reactive access.\n */\n registerControls(form: FormGroup, controlNames: ControlNames[]): void {\n controlNames.forEach((cn) => {\n const control = getControl(cn.replace(/_/g, '.'), form);\n\n if (!control) {\n throw new Error(\n `Failed to register control with name: \"${cn}\" in form group: \"${form}\"`,\n );\n }\n\n const key = cn as ControlNames;\n this.registeredControls[key] = control;\n });\n }\n\n valueChangesOf<T>(key: ControlNames): Observable<T> {\n if (!this.registeredControls[key]) {\n throw new Error(\n `Control with name: \"${key}\" not found. Ensure it is registered in registerControls(...)`,\n );\n }\n\n return this.registeredControls[key].valueChanges as Observable<T>;\n }\n}\n","export abstract class FormMapperBase<TIn = unknown, TOut = TIn, TForm = TIn> {\n public fromModel(model: TIn): TForm {\n return structuredClone(model) as unknown as TForm;\n }\n\n public toRequest(formValue: TForm): TOut {\n return formValue as unknown as TOut;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { FormGroup } from '@angular/forms';\nimport { MapperRegistry } from './types';\n\n@Injectable({ providedIn: 'root' })\nexport class FormHydrator {\n hydrate(form: FormGroup, model: any, registry: MapperRegistry = {}) {\n Object.entries(form.controls).forEach(([key, control]) => {\n if (!(key in model)) return;\n\n const mapper = registry[key];\n const value = model?.[key];\n\n if (control instanceof FormGroup) {\n if (mapper) {\n control.patchValue(mapper.fromModel(value), { emitEvent: false });\n } else {\n this.hydrate(control, value, registry);\n }\n return;\n }\n\n control.patchValue(value, { emitEvent: false });\n });\n }\n}\n","import { Injectable } from '@angular/core';\nimport { FormGroup } from '@angular/forms';\nimport { MapperRegistry } from './types';\n\n@Injectable({ providedIn: 'root' })\nexport class FormSerializer {\n toRequest(form: FormGroup, registry: MapperRegistry = {}) {\n const result: any = {};\n\n Object.entries(form.controls).forEach(([key, control]) => {\n const mapper = registry[key];\n\n if (control instanceof FormGroup) {\n if (mapper) {\n result[key] = mapper.toRequest(control.value);\n } else {\n result[key] = this.toRequest(control, registry);\n }\n return;\n }\n\n result[key] = control.value;\n });\n\n return result;\n }\n}\n","import { FormGroup } from '@angular/forms';\nimport { Directive, OnDestroy, signal } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { FormHandlerBase } from './base/form-handler-base';\nimport { FormMapperBase } from './base/form-mapper-base';\nimport { FormHydrator } from './form-hydrator';\nimport { FormSerializer } from './form-serializer';\nimport {\n FormHandlerRegistry,\n FormOrchestratorOptions,\n FormStatus,\n MapperRegistry,\n} from './types';\n\n@Directive()\nexport abstract class FormOrchestrator\n extends FormMapperBase\n implements OnDestroy\n{\n private readonly _form = signal<FormGroup>(new FormGroup({}));\n private readonly _handlers = signal<FormHandlerRegistry>([]);\n private readonly _mapperRegistry = signal<MapperRegistry>({});\n private readonly _status = signal<FormStatus>('idle');\n private readonly _errorMessage = signal<string | null>(null);\n\n public readonly form = this._form.asReadonly();\n public readonly handlers = this._handlers.asReadonly();\n public readonly mapperRegistry = this._mapperRegistry.asReadonly();\n public readonly status = this._status.asReadonly();\n public readonly errorMessage = this._errorMessage.asReadonly();\n\n private _logicSubscription = new Subscription();\n\n constructor(\n protected readonly hydrator: FormHydrator,\n protected readonly serializer: FormSerializer,\n ) {\n super();\n }\n\n /**\n * Initializes orchestration state.\n * Must be called before any subform registration or handler execution.\n */\n public orchestrate(options: FormOrchestratorOptions) {\n const { form, handlers, mapperRegistry } = options;\n this._form.set(form);\n this._handlers.set(handlers);\n this._mapperRegistry.set(mapperRegistry);\n\n Object.values(this.handlers()).forEach((handler) => {\n this.addReactiveLogic(handler.getReactiveLogic(form));\n });\n }\n\n public setForm(form: FormGroup) {\n this._form.set(form);\n }\n\n public getSubForm(key: string): FormGroup {\n return this.form().get(key) as FormGroup;\n }\n\n public addHandler(handler: FormHandlerBase) {\n this._handlers.set([...this._handlers(), handler]);\n }\n\n public addReactiveLogic(subscription: Subscription) {\n this._logicSubscription.add(subscription);\n }\n\n public setStatus(status: FormStatus) {\n this._status.set(status);\n }\n\n public setErrorMessage(message: string | null) {\n this._errorMessage.set(message);\n }\n\n public hydrateFromModel(model: any) {\n const form = this.form();\n const registry = this.mapperRegistry();\n\n Object.entries(form.controls).forEach(([key, control]) => {\n if (!(key in model)) return;\n\n const mapper = registry[key];\n const value = model?.[key];\n\n if (control instanceof FormGroup) {\n this.hydrator.hydrate(\n control,\n mapper ? mapper.fromModel(value) : value,\n );\n }\n });\n }\n\n public buildRequest(): any {\n return this.serializer.toRequest(this.form(), this.mapperRegistry());\n }\n\n ngOnDestroy(): void {\n this._logicSubscription.unsubscribe();\n }\n}\n","/*\n * Public API Surface of core\n */\n\nexport * from './lib/base/form-control-base';\nexport * from './lib/base/form-handler-base';\nexport * from './lib/base/form-mapper-base';\nexport * from './lib/form-hydrator';\nexport * from './lib/form-orchestrator';\nexport * from './lib/form-serializer';\nexport * from './lib/form-util';\nexport * from './lib/types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.FormHydrator","i2.FormSerializer"],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { ControlValueAccessor, FormControl, NgControl } from '@angular/forms';
2
+ import { ChangeDetectorRef, DestroyRef } from '@angular/core';
3
+ import * as i0 from "@angular/core";
4
+ export declare abstract class FormControlBase<T> implements ControlValueAccessor {
5
+ protected readonly cdr: ChangeDetectorRef;
6
+ protected readonly destroyRef: DestroyRef;
7
+ static nextId: number;
8
+ readonly id: import("@angular/core").InputSignal<string | null>;
9
+ readonly _id: import("@angular/core").InputSignal<string | null>;
10
+ readonly label: import("@angular/core").InputSignal<string>;
11
+ readonly classList: import("@angular/core").InputSignal<string[]>;
12
+ readonly loading: import("@angular/core").InputSignal<boolean>;
13
+ readonly name: import("@angular/core").InputSignal<string>;
14
+ readonly placeholder: import("@angular/core").InputSignal<string>;
15
+ readonly _disabledByInput: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16
+ readonly _disabledByCva: import("@angular/core").WritableSignal<boolean>;
17
+ readonly ngControl: NgControl | null;
18
+ protected readonly control: FormControl<T | null>;
19
+ protected readonly disabled: import("@angular/core").Signal<boolean>;
20
+ protected readonly isRequired: import("@angular/core").WritableSignal<boolean>;
21
+ protected readonly hasErrors: import("@angular/core").WritableSignal<boolean>;
22
+ private changeSub;
23
+ protected onChange: (value: T | null) => void;
24
+ protected onTouched: () => void;
25
+ constructor();
26
+ ngOnInit(): void;
27
+ writeValue(value: T): void;
28
+ registerOnChange(fn: (value: T | null) => void): void;
29
+ registerOnTouched(fn: () => void): void;
30
+ setDisabledState(isDisabled: boolean): void;
31
+ protected errorMessage(): string | null;
32
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormControlBase<any>, never>;
33
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FormControlBase<any>, never, never, { "id": { "alias": "id"; "required": false; "isSignal": true; }; "_id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "classList": { "alias": "classList"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "_disabledByInput": { "alias": "_disabledByInput"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
34
+ }
@@ -1,8 +1,8 @@
1
- import { FormControl, FormGroup } from '@angular/forms';
1
+ import { FormGroup } from '@angular/forms';
2
2
  import { Observable, Subscription } from 'rxjs';
3
3
  export declare abstract class FormHandlerBase<ControlNames extends string = string> {
4
- abstract getReactiveLogic(form?: FormGroup): Subscription;
5
- protected registeredControls: Record<string, FormControl>;
4
+ abstract getReactiveLogic(form: FormGroup): Subscription;
5
+ private registeredControls;
6
6
  /**
7
7
  * Registers form controls for later reactive access.
8
8
  */
@@ -0,0 +1,4 @@
1
+ export declare abstract class FormMapperBase<TIn = unknown, TOut = TIn, TForm = TIn> {
2
+ fromModel(model: TIn): TForm;
3
+ toRequest(formValue: TForm): TOut;
4
+ }
@@ -0,0 +1,8 @@
1
+ import { FormGroup } from '@angular/forms';
2
+ import { MapperRegistry } from './types';
3
+ import * as i0 from "@angular/core";
4
+ export declare class FormHydrator {
5
+ hydrate(form: FormGroup, model: any, registry?: MapperRegistry): void;
6
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormHydrator, never>;
7
+ static ɵprov: i0.ɵɵInjectableDeclaration<FormHydrator>;
8
+ }
@@ -0,0 +1,41 @@
1
+ import { FormGroup } from '@angular/forms';
2
+ import { OnDestroy } from '@angular/core';
3
+ import { Subscription } from 'rxjs';
4
+ import { FormHandlerBase } from './base/form-handler-base';
5
+ import { FormMapperBase } from './base/form-mapper-base';
6
+ import { FormHydrator } from './form-hydrator';
7
+ import { FormSerializer } from './form-serializer';
8
+ import { FormHandlerRegistry, FormOrchestratorOptions, FormStatus, MapperRegistry } from './types';
9
+ import * as i0 from "@angular/core";
10
+ export declare abstract class FormOrchestrator extends FormMapperBase implements OnDestroy {
11
+ protected readonly hydrator: FormHydrator;
12
+ protected readonly serializer: FormSerializer;
13
+ private readonly _form;
14
+ private readonly _handlers;
15
+ private readonly _mapperRegistry;
16
+ private readonly _status;
17
+ private readonly _errorMessage;
18
+ readonly form: import("@angular/core").Signal<FormGroup<any>>;
19
+ readonly handlers: import("@angular/core").Signal<FormHandlerRegistry>;
20
+ readonly mapperRegistry: import("@angular/core").Signal<MapperRegistry>;
21
+ readonly status: import("@angular/core").Signal<FormStatus>;
22
+ readonly errorMessage: import("@angular/core").Signal<string | null>;
23
+ private _logicSubscription;
24
+ constructor(hydrator: FormHydrator, serializer: FormSerializer);
25
+ /**
26
+ * Initializes orchestration state.
27
+ * Must be called before any subform registration or handler execution.
28
+ */
29
+ orchestrate(options: FormOrchestratorOptions): void;
30
+ setForm(form: FormGroup): void;
31
+ getSubForm(key: string): FormGroup;
32
+ addHandler(handler: FormHandlerBase): void;
33
+ addReactiveLogic(subscription: Subscription): void;
34
+ setStatus(status: FormStatus): void;
35
+ setErrorMessage(message: string | null): void;
36
+ hydrateFromModel(model: any): void;
37
+ buildRequest(): any;
38
+ ngOnDestroy(): void;
39
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormOrchestrator, never>;
40
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FormOrchestrator, never, never, {}, {}, never, never, true, never>;
41
+ }
@@ -0,0 +1,8 @@
1
+ import { FormGroup } from '@angular/forms';
2
+ import { MapperRegistry } from './types';
3
+ import * as i0 from "@angular/core";
4
+ export declare class FormSerializer {
5
+ toRequest(form: FormGroup, registry?: MapperRegistry): any;
6
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormSerializer, never>;
7
+ static ɵprov: i0.ɵɵInjectableDeclaration<FormSerializer>;
8
+ }
@@ -4,4 +4,3 @@ export declare function getControlValue<T = unknown>(controlName: string, form:
4
4
  export declare function getControlValue(controlName: string, form: FormGroup): number | null;
5
5
  export declare function parseNumber(input: string | number | null | undefined): number | null;
6
6
  export declare function formatNumber(value: string | number | null, locale?: string, options?: Intl.NumberFormatOptions): string | null;
7
- export declare function formatCurrency(value: string | number | null, locale?: string, options?: Intl.NumberFormatOptions): string | null;
package/lib/types.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { FormGroup } from '@angular/forms';
2
+ import { FormMapperBase } from './base/form-mapper-base';
3
+ import { FormHandlerBase } from './base/form-handler-base';
4
+ export type FormStatus = 'idle' | 'submitting' | 'error' | 'success';
5
+ export type MapperRegistry = Record<string, FormMapperBase<any, any, any>>;
6
+ export type FormHandlerRegistry = FormHandlerBase[];
7
+ export interface FormOrchestratorOptions {
8
+ form: FormGroup;
9
+ handlers: FormHandlerRegistry;
10
+ mapperRegistry: MapperRegistry;
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-modular-forms/core",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "peerDependencies": {
5
5
  "@angular/core": ">=19.0.0 <22.0.0",
6
6
  "@angular/common": ">=19.0.0 <22.0.0",
package/public-api.d.ts CHANGED
@@ -1,5 +1,8 @@
1
- export * from './lib/form-control-base';
2
- export * from './lib/form-handler-base';
3
- export * from './lib/form-mapper-base';
4
- export * from './lib/form-orchestrator-base';
5
- export * from './lib/form.util';
1
+ export * from './lib/base/form-control-base';
2
+ export * from './lib/base/form-handler-base';
3
+ export * from './lib/base/form-mapper-base';
4
+ export * from './lib/form-hydrator';
5
+ export * from './lib/form-orchestrator';
6
+ export * from './lib/form-serializer';
7
+ export * from './lib/form-util';
8
+ export * from './lib/types';
@@ -1,37 +0,0 @@
1
- import { NgControl } from '@angular/forms';
2
- import { ChangeDetectorRef, DestroyRef, DoCheck, OnInit } from '@angular/core';
3
- import * as i0 from "@angular/core";
4
- export declare abstract class FormControlBase<T> implements OnInit, DoCheck {
5
- static nextId: number;
6
- id: string;
7
- protected readonly cdr: ChangeDetectorRef;
8
- protected readonly destroyRef: DestroyRef;
9
- readonly ngControl: NgControl | null;
10
- readonly label: import("@angular/core").InputSignal<string>;
11
- readonly classList: import("@angular/core").InputSignal<string[]>;
12
- readonly loading: import("@angular/core").InputSignal<boolean>;
13
- readonly _name: import("@angular/core").InputSignal<string>;
14
- readonly _placeholder: import("@angular/core").InputSignal<string>;
15
- readonly _required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
16
- readonly _disabledByInput: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
17
- readonly _readonly: import("@angular/core").InputSignal<boolean>;
18
- protected readonly _disabledByCva: import("@angular/core").WritableSignal<boolean>;
19
- readonly _disabled: import("@angular/core").Signal<boolean>;
20
- focused: boolean;
21
- private lastErrorState;
22
- private _value;
23
- get value(): T | null;
24
- set value(value: T | null);
25
- get name(): string;
26
- get placeholder(): string;
27
- get required(): boolean;
28
- get disabled(): boolean;
29
- get readonly(): boolean;
30
- get errorState(): boolean;
31
- get empty(): boolean;
32
- ngOnInit(): void;
33
- ngDoCheck(): void;
34
- protected getErrorMessage(): string | null;
35
- static ɵfac: i0.ɵɵFactoryDeclaration<FormControlBase<any>, never>;
36
- static ɵdir: i0.ɵɵDirectiveDeclaration<FormControlBase<any>, never, never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "classList": { "alias": "classList"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "_name": { "alias": "name"; "required": false; "isSignal": true; }; "_placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "_required": { "alias": "required"; "required": false; "isSignal": true; }; "_disabledByInput": { "alias": "disabled"; "required": false; "isSignal": true; }; "_readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
37
- }
@@ -1,13 +0,0 @@
1
- import { FormGroup } from '@angular/forms';
2
- export declare abstract class FormMapperBase<TModelIn = unknown, TModelOut = unknown, TFormModel = unknown, TStore = Record<string, unknown>> {
3
- /**
4
- * Maps form state + external store into an API request payload.
5
- */
6
- abstract buildRequest(form: FormGroup, store: TStore): Partial<TModelOut>;
7
- /**
8
- * Transforms a domain/API model into a form-compatible structure.
9
- */
10
- abstract transformFromModel(model: TModelIn): TFormModel;
11
- patchForm(form: FormGroup, data: TFormModel, _context: TStore, emitEvent?: boolean): void;
12
- patchFromModel(form: FormGroup, model: TModelIn, store: TStore): void;
13
- }
@@ -1,50 +0,0 @@
1
- import { FormGroup } from '@angular/forms';
2
- import { OnDestroy } from '@angular/core';
3
- import { Subscription } from 'rxjs';
4
- import { FormHandlerBase } from './form-handler-base';
5
- import * as i0 from "@angular/core";
6
- export type FormStatus = 'idle' | 'submitting' | 'error' | 'success';
7
- type FormHandlerRegistry = Record<string, FormHandlerBase<string>>;
8
- interface FormOrchestratorOptions {
9
- mainHandler?: FormHandlerBase<string> | null;
10
- subHandlers?: FormHandlerRegistry;
11
- }
12
- export declare abstract class FormOrchestratorBase implements OnDestroy {
13
- private _form;
14
- private _mainHandler;
15
- private _subHandlers;
16
- private _status;
17
- private _errorMessage;
18
- private _loadedHandlers;
19
- private _allHandlersLoaded;
20
- private _logicSubscription;
21
- readonly form: import("@angular/core").Signal<FormGroup<any>>;
22
- readonly mainHandler: import("@angular/core").Signal<FormHandlerBase<string> | null>;
23
- readonly subHandlers: import("@angular/core").Signal<FormHandlerRegistry>;
24
- readonly status: import("@angular/core").Signal<FormStatus>;
25
- readonly errorMessage: import("@angular/core").Signal<string | null>;
26
- /**
27
- * Initializes orchestration state.
28
- * Must be called before any subform registration or handler execution.
29
- */
30
- initialize(form: FormGroup, formOrchestratorOptions?: FormOrchestratorOptions): void;
31
- setForm(form: FormGroup): void;
32
- getHandler(key: string): FormHandlerBase<string> | undefined;
33
- setHandler(key: string, handler: FormHandlerBase<string>): void;
34
- addReactiveLogic(subscription: Subscription): void;
35
- setStatus(status: FormStatus): void;
36
- setErrorMessage(message: string | null): void;
37
- ngOnDestroy(): void;
38
- /**
39
- * Registers a subform into the main form tree and coordinates handler execution.
40
- *
41
- * IMPORTANT:
42
- * - Handler execution is gated until all registered subhandlers are ready.
43
- * - Calling order matters; this is lifecycle-sensitive orchestration logic.
44
- */
45
- onSubformReady(subform: FormGroup, groupName: string, nestGroups?: boolean): void;
46
- private loadMainHandler;
47
- static ɵfac: i0.ɵɵFactoryDeclaration<FormOrchestratorBase, never>;
48
- static ɵdir: i0.ɵɵDirectiveDeclaration<FormOrchestratorBase, never, never, {}, {}, never, never, true, never>;
49
- }
50
- export {};