@mosaicoo/form-angular 0.4.0 → 0.5.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.
- package/README.md +15 -0
- package/fesm2022/mosaicoo-form-angular-material.mjs +393 -0
- package/fesm2022/mosaicoo-form-angular-material.mjs.map +1 -0
- package/fesm2022/mosaicoo-form-angular.mjs +11 -3
- package/fesm2022/mosaicoo-form-angular.mjs.map +1 -1
- package/package.json +17 -3
- package/types/mosaicoo-form-angular-material.d.ts +77 -0
- package/types/mosaicoo-form-angular.d.ts +7 -1
package/README.md
CHANGED
|
@@ -57,6 +57,21 @@ undo/redo (Ctrl+Z/Y), duplicate/delete/move, live schema diagnostics,
|
|
|
57
57
|
import/export and a Preview mode with test data. The host owns persistence:
|
|
58
58
|
`schemaChanged` hands you the versioned schema document.
|
|
59
59
|
|
|
60
|
+
## Material Design 3 adapter
|
|
61
|
+
|
|
62
|
+
Optional entry point (requires `@angular/material`, an optional peer):
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { provideMaterialForms } from '@mosaicoo/form-angular/material';
|
|
66
|
+
|
|
67
|
+
bootstrapApplication(App, { providers: [provideMaterialForms()] });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Swaps text/number/select/checkbox/radio (and friends) for Material
|
|
71
|
+
components styled by YOUR M3 theme; unmapped types keep the accessible
|
|
72
|
+
built-in renderers. Individual types can still be overridden by later
|
|
73
|
+
`provideMosaicooForm({components})` calls.
|
|
74
|
+
|
|
60
75
|
## Extending
|
|
61
76
|
|
|
62
77
|
```ts
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { provideMosaicooForm } from '@mosaicoo/form-angular';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { input, Directive, ChangeDetectionStrategy, Component, computed } from '@angular/core';
|
|
4
|
+
import * as i1 from '@angular/forms';
|
|
5
|
+
import { FormsModule } from '@angular/forms';
|
|
6
|
+
import { MatOption } from '@angular/material/core';
|
|
7
|
+
import * as i2 from '@angular/material/form-field';
|
|
8
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
9
|
+
import * as i3 from '@angular/material/input';
|
|
10
|
+
import { MatInputModule } from '@angular/material/input';
|
|
11
|
+
import * as i4 from '@angular/material/select';
|
|
12
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
13
|
+
import * as i5 from '@angular/material/checkbox';
|
|
14
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
15
|
+
import * as i6 from '@angular/material/radio';
|
|
16
|
+
import { MatRadioModule } from '@angular/material/radio';
|
|
17
|
+
import { maskValue } from '@mosaicoo/form-core';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Material Design 3 field components.
|
|
21
|
+
*
|
|
22
|
+
* Every component implements the renderer's `MformFieldComponent` contract
|
|
23
|
+
* (signal inputs `field`/`engine`/`path`/`tick`/`mode`) and talks to the form
|
|
24
|
+
* exclusively through the engine — validation, conditionals, calculations and
|
|
25
|
+
* events keep working unchanged. The HOST's Material theme (M3 tokens) styles
|
|
26
|
+
* everything; this entry adds no theming of its own.
|
|
27
|
+
*/
|
|
28
|
+
class MaterialFieldBase {
|
|
29
|
+
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
|
|
30
|
+
engine = input.required(...(ngDevMode ? [{ debugName: "engine" }] : /* istanbul ignore next */ []));
|
|
31
|
+
path = input.required(...(ngDevMode ? [{ debugName: "path" }] : /* istanbul ignore next */ []));
|
|
32
|
+
tick = input(0, ...(ngDevMode ? [{ debugName: "tick" }] : /* istanbul ignore next */ []));
|
|
33
|
+
mode = input('edit', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
34
|
+
/** Error state driven by the ENGINE, not by template validators. */
|
|
35
|
+
errorMatcher = {
|
|
36
|
+
isErrorState: () => this.errors().length > 0,
|
|
37
|
+
};
|
|
38
|
+
value() {
|
|
39
|
+
this.tick();
|
|
40
|
+
return this.engine().getValue(this.path());
|
|
41
|
+
}
|
|
42
|
+
errors() {
|
|
43
|
+
this.tick();
|
|
44
|
+
return this.engine().getFieldErrors(this.path());
|
|
45
|
+
}
|
|
46
|
+
firstError() {
|
|
47
|
+
return this.errors()[0]?.message ?? null;
|
|
48
|
+
}
|
|
49
|
+
required() {
|
|
50
|
+
return this.field().validators?.some((v) => v.type === 'required') ?? false;
|
|
51
|
+
}
|
|
52
|
+
disabled() {
|
|
53
|
+
return (this.mode() !== 'edit' ||
|
|
54
|
+
this.field().disabled === true ||
|
|
55
|
+
this.field().calculate !== undefined);
|
|
56
|
+
}
|
|
57
|
+
label() {
|
|
58
|
+
return this.field().label ?? this.field().key;
|
|
59
|
+
}
|
|
60
|
+
setValue(value) {
|
|
61
|
+
this.engine().setValue(this.path(), value);
|
|
62
|
+
}
|
|
63
|
+
touch() {
|
|
64
|
+
this.engine().markTouched(this.path());
|
|
65
|
+
void this.engine().validateFieldAsync(this.path());
|
|
66
|
+
}
|
|
67
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MaterialFieldBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
68
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.19", type: MaterialFieldBase, isStandalone: true, inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, engine: { classPropertyName: "engine", publicName: "engine", isSignal: true, isRequired: true, transformFunction: null }, path: { classPropertyName: "path", publicName: "path", isSignal: true, isRequired: true, transformFunction: null }, tick: { classPropertyName: "tick", publicName: "tick", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
|
|
69
|
+
}
|
|
70
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MaterialFieldBase, decorators: [{
|
|
71
|
+
type: Directive
|
|
72
|
+
}], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], engine: [{ type: i0.Input, args: [{ isSignal: true, alias: "engine", required: true }] }], path: [{ type: i0.Input, args: [{ isSignal: true, alias: "path", required: true }] }], tick: [{ type: i0.Input, args: [{ isSignal: true, alias: "tick", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }] } });
|
|
73
|
+
class MatTextFieldComponent extends MaterialFieldBase {
|
|
74
|
+
isTextarea() {
|
|
75
|
+
return this.field().type === 'textarea';
|
|
76
|
+
}
|
|
77
|
+
stringValue() {
|
|
78
|
+
const value = this.value();
|
|
79
|
+
if (value === undefined || value === null)
|
|
80
|
+
return '';
|
|
81
|
+
const mask = this.field().format?.mask;
|
|
82
|
+
if (mask && typeof value === 'string')
|
|
83
|
+
return maskValue(value, mask).masked;
|
|
84
|
+
return String(value);
|
|
85
|
+
}
|
|
86
|
+
inputType() {
|
|
87
|
+
switch (this.field().type) {
|
|
88
|
+
case 'number':
|
|
89
|
+
case 'currency':
|
|
90
|
+
return 'number';
|
|
91
|
+
case 'email': return 'email';
|
|
92
|
+
case 'password': return 'password';
|
|
93
|
+
case 'phone': return 'tel';
|
|
94
|
+
case 'url': return 'url';
|
|
95
|
+
case 'time': return 'time';
|
|
96
|
+
case 'datetime': return 'datetime-local';
|
|
97
|
+
case 'day': return 'date';
|
|
98
|
+
default: return 'text';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
prefixText() {
|
|
102
|
+
const value = this.field().props?.['prefix'];
|
|
103
|
+
return typeof value === 'string' && value ? value : null;
|
|
104
|
+
}
|
|
105
|
+
suffixText() {
|
|
106
|
+
const value = this.field().props?.['suffix'];
|
|
107
|
+
return typeof value === 'string' && value ? value : null;
|
|
108
|
+
}
|
|
109
|
+
write(raw) {
|
|
110
|
+
const mask = this.field().format?.mask;
|
|
111
|
+
if (mask) {
|
|
112
|
+
const { masked, raw: stripped } = maskValue(raw, mask);
|
|
113
|
+
this.setValue(this.field().format?.keepMask ? masked : stripped);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (this.field().dataType === 'number') {
|
|
117
|
+
const parsed = raw === '' ? undefined : Number(raw);
|
|
118
|
+
this.setValue(parsed !== undefined && Number.isFinite(parsed) ? parsed : undefined);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.setValue(raw);
|
|
122
|
+
}
|
|
123
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatTextFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
124
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: MatTextFieldComponent, isStandalone: true, selector: "mform-mat-text", usesInheritance: true, ngImport: i0, template: `
|
|
125
|
+
<mat-form-field appearance="outline" class="mform-mat-field">
|
|
126
|
+
<mat-label>{{ label() }}</mat-label>
|
|
127
|
+
@if (isTextarea()) {
|
|
128
|
+
<textarea
|
|
129
|
+
matInput
|
|
130
|
+
[rows]="3"
|
|
131
|
+
[ngModel]="stringValue()"
|
|
132
|
+
[errorStateMatcher]="errorMatcher"
|
|
133
|
+
[placeholder]="field().placeholder ?? ''"
|
|
134
|
+
[required]="required()"
|
|
135
|
+
[disabled]="disabled()"
|
|
136
|
+
(ngModelChange)="write($event)"
|
|
137
|
+
(blur)="touch()"
|
|
138
|
+
></textarea>
|
|
139
|
+
} @else {
|
|
140
|
+
<input
|
|
141
|
+
matInput
|
|
142
|
+
[type]="inputType()"
|
|
143
|
+
[ngModel]="stringValue()"
|
|
144
|
+
[errorStateMatcher]="errorMatcher"
|
|
145
|
+
[placeholder]="field().placeholder ?? ''"
|
|
146
|
+
[required]="required()"
|
|
147
|
+
[disabled]="disabled()"
|
|
148
|
+
(ngModelChange)="write($event)"
|
|
149
|
+
(blur)="touch()"
|
|
150
|
+
/>
|
|
151
|
+
}
|
|
152
|
+
@if (prefixText(); as p) {
|
|
153
|
+
<span matTextPrefix>{{ p }} </span>
|
|
154
|
+
}
|
|
155
|
+
@if (suffixText(); as s) {
|
|
156
|
+
<span matTextSuffix>{{ s }}</span>
|
|
157
|
+
}
|
|
158
|
+
@if (field().description; as hint) {
|
|
159
|
+
<mat-hint>{{ hint }}</mat-hint>
|
|
160
|
+
}
|
|
161
|
+
@if (firstError(); as error) {
|
|
162
|
+
<mat-error>{{ error }}</mat-error>
|
|
163
|
+
}
|
|
164
|
+
</mat-form-field>
|
|
165
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
166
|
+
}
|
|
167
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatTextFieldComponent, decorators: [{
|
|
168
|
+
type: Component,
|
|
169
|
+
args: [{
|
|
170
|
+
selector: 'mform-mat-text',
|
|
171
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
172
|
+
imports: [FormsModule, MatFormFieldModule, MatInputModule],
|
|
173
|
+
template: `
|
|
174
|
+
<mat-form-field appearance="outline" class="mform-mat-field">
|
|
175
|
+
<mat-label>{{ label() }}</mat-label>
|
|
176
|
+
@if (isTextarea()) {
|
|
177
|
+
<textarea
|
|
178
|
+
matInput
|
|
179
|
+
[rows]="3"
|
|
180
|
+
[ngModel]="stringValue()"
|
|
181
|
+
[errorStateMatcher]="errorMatcher"
|
|
182
|
+
[placeholder]="field().placeholder ?? ''"
|
|
183
|
+
[required]="required()"
|
|
184
|
+
[disabled]="disabled()"
|
|
185
|
+
(ngModelChange)="write($event)"
|
|
186
|
+
(blur)="touch()"
|
|
187
|
+
></textarea>
|
|
188
|
+
} @else {
|
|
189
|
+
<input
|
|
190
|
+
matInput
|
|
191
|
+
[type]="inputType()"
|
|
192
|
+
[ngModel]="stringValue()"
|
|
193
|
+
[errorStateMatcher]="errorMatcher"
|
|
194
|
+
[placeholder]="field().placeholder ?? ''"
|
|
195
|
+
[required]="required()"
|
|
196
|
+
[disabled]="disabled()"
|
|
197
|
+
(ngModelChange)="write($event)"
|
|
198
|
+
(blur)="touch()"
|
|
199
|
+
/>
|
|
200
|
+
}
|
|
201
|
+
@if (prefixText(); as p) {
|
|
202
|
+
<span matTextPrefix>{{ p }} </span>
|
|
203
|
+
}
|
|
204
|
+
@if (suffixText(); as s) {
|
|
205
|
+
<span matTextSuffix>{{ s }}</span>
|
|
206
|
+
}
|
|
207
|
+
@if (field().description; as hint) {
|
|
208
|
+
<mat-hint>{{ hint }}</mat-hint>
|
|
209
|
+
}
|
|
210
|
+
@if (firstError(); as error) {
|
|
211
|
+
<mat-error>{{ error }}</mat-error>
|
|
212
|
+
}
|
|
213
|
+
</mat-form-field>
|
|
214
|
+
`,
|
|
215
|
+
}]
|
|
216
|
+
}] });
|
|
217
|
+
class MatSelectFieldComponent extends MaterialFieldBase {
|
|
218
|
+
options = computed(() => this.field().options ?? [], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
219
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatSelectFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
220
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: MatSelectFieldComponent, isStandalone: true, selector: "mform-mat-select", usesInheritance: true, ngImport: i0, template: `
|
|
221
|
+
<mat-form-field appearance="outline" class="mform-mat-field">
|
|
222
|
+
<mat-label>{{ label() }}</mat-label>
|
|
223
|
+
<mat-select
|
|
224
|
+
[ngModel]="value()"
|
|
225
|
+
[errorStateMatcher]="errorMatcher"
|
|
226
|
+
[required]="required()"
|
|
227
|
+
[disabled]="disabled()"
|
|
228
|
+
(ngModelChange)="setValue($event)"
|
|
229
|
+
(closed)="touch()"
|
|
230
|
+
>
|
|
231
|
+
@for (option of options(); track option.value) {
|
|
232
|
+
<mat-option [value]="option.value">{{ option.label }}</mat-option>
|
|
233
|
+
}
|
|
234
|
+
</mat-select>
|
|
235
|
+
@if (field().description; as hint) {
|
|
236
|
+
<mat-hint>{{ hint }}</mat-hint>
|
|
237
|
+
}
|
|
238
|
+
@if (firstError(); as error) {
|
|
239
|
+
<mat-error>{{ error }}</mat-error>
|
|
240
|
+
}
|
|
241
|
+
</mat-form-field>
|
|
242
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
243
|
+
}
|
|
244
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatSelectFieldComponent, decorators: [{
|
|
245
|
+
type: Component,
|
|
246
|
+
args: [{
|
|
247
|
+
selector: 'mform-mat-select',
|
|
248
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
249
|
+
imports: [FormsModule, MatFormFieldModule, MatSelectModule, MatOption],
|
|
250
|
+
template: `
|
|
251
|
+
<mat-form-field appearance="outline" class="mform-mat-field">
|
|
252
|
+
<mat-label>{{ label() }}</mat-label>
|
|
253
|
+
<mat-select
|
|
254
|
+
[ngModel]="value()"
|
|
255
|
+
[errorStateMatcher]="errorMatcher"
|
|
256
|
+
[required]="required()"
|
|
257
|
+
[disabled]="disabled()"
|
|
258
|
+
(ngModelChange)="setValue($event)"
|
|
259
|
+
(closed)="touch()"
|
|
260
|
+
>
|
|
261
|
+
@for (option of options(); track option.value) {
|
|
262
|
+
<mat-option [value]="option.value">{{ option.label }}</mat-option>
|
|
263
|
+
}
|
|
264
|
+
</mat-select>
|
|
265
|
+
@if (field().description; as hint) {
|
|
266
|
+
<mat-hint>{{ hint }}</mat-hint>
|
|
267
|
+
}
|
|
268
|
+
@if (firstError(); as error) {
|
|
269
|
+
<mat-error>{{ error }}</mat-error>
|
|
270
|
+
}
|
|
271
|
+
</mat-form-field>
|
|
272
|
+
`,
|
|
273
|
+
}]
|
|
274
|
+
}] });
|
|
275
|
+
class MatCheckboxFieldComponent extends MaterialFieldBase {
|
|
276
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatCheckboxFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
277
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: MatCheckboxFieldComponent, isStandalone: true, selector: "mform-mat-checkbox", usesInheritance: true, ngImport: i0, template: `
|
|
278
|
+
<div class="mform-mat-checkbox">
|
|
279
|
+
<mat-checkbox
|
|
280
|
+
[ngModel]="value() === true"
|
|
281
|
+
[required]="required()"
|
|
282
|
+
[disabled]="disabled()"
|
|
283
|
+
(ngModelChange)="setValue($event)"
|
|
284
|
+
(blur)="touch()"
|
|
285
|
+
>
|
|
286
|
+
{{ label() }}
|
|
287
|
+
</mat-checkbox>
|
|
288
|
+
@if (firstError(); as error) {
|
|
289
|
+
<div class="mform-mat-error">{{ error }}</div>
|
|
290
|
+
}
|
|
291
|
+
</div>
|
|
292
|
+
`, isInline: true, styles: [".mform-mat-error{color:var(--mat-sys-error, #ba1a1a);font-size:12px;padding-left:12px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
293
|
+
}
|
|
294
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatCheckboxFieldComponent, decorators: [{
|
|
295
|
+
type: Component,
|
|
296
|
+
args: [{ selector: 'mform-mat-checkbox', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, MatCheckboxModule], template: `
|
|
297
|
+
<div class="mform-mat-checkbox">
|
|
298
|
+
<mat-checkbox
|
|
299
|
+
[ngModel]="value() === true"
|
|
300
|
+
[required]="required()"
|
|
301
|
+
[disabled]="disabled()"
|
|
302
|
+
(ngModelChange)="setValue($event)"
|
|
303
|
+
(blur)="touch()"
|
|
304
|
+
>
|
|
305
|
+
{{ label() }}
|
|
306
|
+
</mat-checkbox>
|
|
307
|
+
@if (firstError(); as error) {
|
|
308
|
+
<div class="mform-mat-error">{{ error }}</div>
|
|
309
|
+
}
|
|
310
|
+
</div>
|
|
311
|
+
`, styles: [".mform-mat-error{color:var(--mat-sys-error, #ba1a1a);font-size:12px;padding-left:12px}\n"] }]
|
|
312
|
+
}] });
|
|
313
|
+
class MatRadioFieldComponent extends MaterialFieldBase {
|
|
314
|
+
options = computed(() => this.field().options ?? [], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
315
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatRadioFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
316
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: MatRadioFieldComponent, isStandalone: true, selector: "mform-mat-radio", usesInheritance: true, ngImport: i0, template: `
|
|
317
|
+
<div class="mform-mat-radio">
|
|
318
|
+
<span class="mform-mat-radio-label">{{ label() }}</span>
|
|
319
|
+
<mat-radio-group
|
|
320
|
+
[ngModel]="value()"
|
|
321
|
+
[disabled]="disabled()"
|
|
322
|
+
(ngModelChange)="setValue($event)"
|
|
323
|
+
>
|
|
324
|
+
@for (option of options(); track option.value) {
|
|
325
|
+
<mat-radio-button [value]="option.value">{{ option.label }}</mat-radio-button>
|
|
326
|
+
}
|
|
327
|
+
</mat-radio-group>
|
|
328
|
+
@if (firstError(); as error) {
|
|
329
|
+
<div class="mform-mat-error">{{ error }}</div>
|
|
330
|
+
}
|
|
331
|
+
</div>
|
|
332
|
+
`, isInline: true, styles: [".mform-mat-radio{display:flex;flex-direction:column;gap:4px}.mform-mat-radio-label{font-size:13px;font-weight:500}.mform-mat-radio mat-radio-group{display:flex;flex-direction:column}.mform-mat-error{color:var(--mat-sys-error, #ba1a1a);font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i6.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i6.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
333
|
+
}
|
|
334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MatRadioFieldComponent, decorators: [{
|
|
335
|
+
type: Component,
|
|
336
|
+
args: [{ selector: 'mform-mat-radio', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, MatRadioModule], template: `
|
|
337
|
+
<div class="mform-mat-radio">
|
|
338
|
+
<span class="mform-mat-radio-label">{{ label() }}</span>
|
|
339
|
+
<mat-radio-group
|
|
340
|
+
[ngModel]="value()"
|
|
341
|
+
[disabled]="disabled()"
|
|
342
|
+
(ngModelChange)="setValue($event)"
|
|
343
|
+
>
|
|
344
|
+
@for (option of options(); track option.value) {
|
|
345
|
+
<mat-radio-button [value]="option.value">{{ option.label }}</mat-radio-button>
|
|
346
|
+
}
|
|
347
|
+
</mat-radio-group>
|
|
348
|
+
@if (firstError(); as error) {
|
|
349
|
+
<div class="mform-mat-error">{{ error }}</div>
|
|
350
|
+
}
|
|
351
|
+
</div>
|
|
352
|
+
`, styles: [".mform-mat-radio{display:flex;flex-direction:column;gap:4px}.mform-mat-radio-label{font-size:13px;font-weight:500}.mform-mat-radio mat-radio-group{display:flex;flex-direction:column}.mform-mat-error{color:var(--mat-sys-error, #ba1a1a);font-size:12px}\n"] }]
|
|
353
|
+
}] });
|
|
354
|
+
|
|
355
|
+
/** Field types rendered with Material components (others stay built-in). */
|
|
356
|
+
const MATERIAL_FIELD_COMPONENTS = {
|
|
357
|
+
text: MatTextFieldComponent,
|
|
358
|
+
textarea: MatTextFieldComponent,
|
|
359
|
+
number: MatTextFieldComponent,
|
|
360
|
+
currency: MatTextFieldComponent,
|
|
361
|
+
email: MatTextFieldComponent,
|
|
362
|
+
password: MatTextFieldComponent,
|
|
363
|
+
phone: MatTextFieldComponent,
|
|
364
|
+
url: MatTextFieldComponent,
|
|
365
|
+
time: MatTextFieldComponent,
|
|
366
|
+
datetime: MatTextFieldComponent,
|
|
367
|
+
day: MatTextFieldComponent,
|
|
368
|
+
select: MatSelectFieldComponent,
|
|
369
|
+
checkbox: MatCheckboxFieldComponent,
|
|
370
|
+
radio: MatRadioFieldComponent,
|
|
371
|
+
};
|
|
372
|
+
/**
|
|
373
|
+
* Registers the Material field set:
|
|
374
|
+
*
|
|
375
|
+
* ```ts
|
|
376
|
+
* bootstrapApplication(App, {
|
|
377
|
+
* providers: [provideMaterialForms()],
|
|
378
|
+
* });
|
|
379
|
+
* ```
|
|
380
|
+
*
|
|
381
|
+
* Composable: later `provideMosaicooForm({components})` calls can override
|
|
382
|
+
* individual types (host-specific fields win).
|
|
383
|
+
*/
|
|
384
|
+
function provideMaterialForms() {
|
|
385
|
+
return provideMosaicooForm({ components: MATERIAL_FIELD_COMPONENTS });
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Generated bundle index. Do not edit.
|
|
390
|
+
*/
|
|
391
|
+
|
|
392
|
+
export { MATERIAL_FIELD_COMPONENTS, MatCheckboxFieldComponent, MatRadioFieldComponent, MatSelectFieldComponent, MatTextFieldComponent, provideMaterialForms };
|
|
393
|
+
//# sourceMappingURL=mosaicoo-form-angular-material.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mosaicoo-form-angular-material.mjs","sources":["../../../packages/angular/material/src/material-fields.ts","../../../packages/angular/material/src/public-api.ts","../../../packages/angular/material/src/mosaicoo-form-angular-material.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, Directive, computed, input } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { ErrorStateMatcher, MatOption } from '@angular/material/core';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatRadioModule } from '@angular/material/radio';\nimport { maskValue } from '@mosaicoo/form-core';\nimport type { FieldOption, FormEngine, InputField } from '@mosaicoo/form-core';\n\n/**\n * Material Design 3 field components.\n *\n * Every component implements the renderer's `MformFieldComponent` contract\n * (signal inputs `field`/`engine`/`path`/`tick`/`mode`) and talks to the form\n * exclusively through the engine — validation, conditionals, calculations and\n * events keep working unchanged. The HOST's Material theme (M3 tokens) styles\n * everything; this entry adds no theming of its own.\n */\n\n@Directive()\nabstract class MaterialFieldBase {\n readonly field = input.required<InputField>();\n readonly engine = input.required<FormEngine>();\n readonly path = input.required<string>();\n readonly tick = input<number>(0);\n readonly mode = input<'edit' | 'readonly' | 'disabled'>('edit');\n\n /** Error state driven by the ENGINE, not by template validators. */\n readonly errorMatcher: ErrorStateMatcher = {\n isErrorState: () => this.errors().length > 0,\n };\n\n value(): unknown {\n this.tick();\n return this.engine().getValue(this.path());\n }\n\n errors() {\n this.tick();\n return this.engine().getFieldErrors(this.path());\n }\n\n firstError(): string | null {\n return this.errors()[0]?.message ?? null;\n }\n\n required(): boolean {\n return this.field().validators?.some((v) => v.type === 'required') ?? false;\n }\n\n disabled(): boolean {\n return (\n this.mode() !== 'edit' ||\n this.field().disabled === true ||\n this.field().calculate !== undefined\n );\n }\n\n label(): string {\n return this.field().label ?? this.field().key;\n }\n\n setValue(value: unknown): void {\n this.engine().setValue(this.path(), value);\n }\n\n touch(): void {\n this.engine().markTouched(this.path());\n void this.engine().validateFieldAsync(this.path());\n }\n}\n\n@Component({\n selector: 'mform-mat-text',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatFormFieldModule, MatInputModule],\n template: `\n <mat-form-field appearance=\"outline\" class=\"mform-mat-field\">\n <mat-label>{{ label() }}</mat-label>\n @if (isTextarea()) {\n <textarea\n matInput\n [rows]=\"3\"\n [ngModel]=\"stringValue()\"\n [errorStateMatcher]=\"errorMatcher\"\n [placeholder]=\"field().placeholder ?? ''\"\n [required]=\"required()\"\n [disabled]=\"disabled()\"\n (ngModelChange)=\"write($event)\"\n (blur)=\"touch()\"\n ></textarea>\n } @else {\n <input\n matInput\n [type]=\"inputType()\"\n [ngModel]=\"stringValue()\"\n [errorStateMatcher]=\"errorMatcher\"\n [placeholder]=\"field().placeholder ?? ''\"\n [required]=\"required()\"\n [disabled]=\"disabled()\"\n (ngModelChange)=\"write($event)\"\n (blur)=\"touch()\"\n />\n }\n @if (prefixText(); as p) {\n <span matTextPrefix>{{ p }} </span>\n }\n @if (suffixText(); as s) {\n <span matTextSuffix>{{ s }}</span>\n }\n @if (field().description; as hint) {\n <mat-hint>{{ hint }}</mat-hint>\n }\n @if (firstError(); as error) {\n <mat-error>{{ error }}</mat-error>\n }\n </mat-form-field>\n `,\n})\nexport class MatTextFieldComponent extends MaterialFieldBase {\n isTextarea(): boolean {\n return this.field().type === 'textarea';\n }\n\n stringValue(): string {\n const value = this.value();\n if (value === undefined || value === null) return '';\n const mask = this.field().format?.mask;\n if (mask && typeof value === 'string') return maskValue(value, mask).masked;\n return String(value);\n }\n\n inputType(): string {\n switch (this.field().type) {\n case 'number':\n case 'currency':\n return 'number';\n case 'email': return 'email';\n case 'password': return 'password';\n case 'phone': return 'tel';\n case 'url': return 'url';\n case 'time': return 'time';\n case 'datetime': return 'datetime-local';\n case 'day': return 'date';\n default: return 'text';\n }\n }\n\n prefixText(): string | null {\n const value = this.field().props?.['prefix'];\n return typeof value === 'string' && value ? value : null;\n }\n\n suffixText(): string | null {\n const value = this.field().props?.['suffix'];\n return typeof value === 'string' && value ? value : null;\n }\n\n write(raw: string): void {\n const mask = this.field().format?.mask;\n if (mask) {\n const { masked, raw: stripped } = maskValue(raw, mask);\n this.setValue(this.field().format?.keepMask ? masked : stripped);\n return;\n }\n if (this.field().dataType === 'number') {\n const parsed = raw === '' ? undefined : Number(raw);\n this.setValue(parsed !== undefined && Number.isFinite(parsed) ? parsed : undefined);\n return;\n }\n this.setValue(raw);\n }\n}\n\n@Component({\n selector: 'mform-mat-select',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatFormFieldModule, MatSelectModule, MatOption],\n template: `\n <mat-form-field appearance=\"outline\" class=\"mform-mat-field\">\n <mat-label>{{ label() }}</mat-label>\n <mat-select\n [ngModel]=\"value()\"\n [errorStateMatcher]=\"errorMatcher\"\n [required]=\"required()\"\n [disabled]=\"disabled()\"\n (ngModelChange)=\"setValue($event)\"\n (closed)=\"touch()\"\n >\n @for (option of options(); track option.value) {\n <mat-option [value]=\"option.value\">{{ option.label }}</mat-option>\n }\n </mat-select>\n @if (field().description; as hint) {\n <mat-hint>{{ hint }}</mat-hint>\n }\n @if (firstError(); as error) {\n <mat-error>{{ error }}</mat-error>\n }\n </mat-form-field>\n `,\n})\nexport class MatSelectFieldComponent extends MaterialFieldBase {\n readonly options = computed<FieldOption[]>(() => this.field().options ?? []);\n}\n\n@Component({\n selector: 'mform-mat-checkbox',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatCheckboxModule],\n template: `\n <div class=\"mform-mat-checkbox\">\n <mat-checkbox\n [ngModel]=\"value() === true\"\n [required]=\"required()\"\n [disabled]=\"disabled()\"\n (ngModelChange)=\"setValue($event)\"\n (blur)=\"touch()\"\n >\n {{ label() }}\n </mat-checkbox>\n @if (firstError(); as error) {\n <div class=\"mform-mat-error\">{{ error }}</div>\n }\n </div>\n `,\n styles: `\n .mform-mat-error { color: var(--mat-sys-error, #ba1a1a); font-size: 12px; padding-left: 12px; }\n `,\n})\nexport class MatCheckboxFieldComponent extends MaterialFieldBase {}\n\n@Component({\n selector: 'mform-mat-radio',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [FormsModule, MatRadioModule],\n template: `\n <div class=\"mform-mat-radio\">\n <span class=\"mform-mat-radio-label\">{{ label() }}</span>\n <mat-radio-group\n [ngModel]=\"value()\"\n [disabled]=\"disabled()\"\n (ngModelChange)=\"setValue($event)\"\n >\n @for (option of options(); track option.value) {\n <mat-radio-button [value]=\"option.value\">{{ option.label }}</mat-radio-button>\n }\n </mat-radio-group>\n @if (firstError(); as error) {\n <div class=\"mform-mat-error\">{{ error }}</div>\n }\n </div>\n `,\n styles: `\n .mform-mat-radio { display: flex; flex-direction: column; gap: 4px; }\n .mform-mat-radio-label { font-size: 13px; font-weight: 500; }\n .mform-mat-radio mat-radio-group { display: flex; flex-direction: column; }\n .mform-mat-error { color: var(--mat-sys-error, #ba1a1a); font-size: 12px; }\n `,\n})\nexport class MatRadioFieldComponent extends MaterialFieldBase {\n readonly options = computed<FieldOption[]>(() => this.field().options ?? []);\n}\n","/*\n * Material adapter entry point (`@mosaicoo/form-angular/material`).\n *\n * Optional: requires the host to install @angular/material (optional peer).\n * Registers Material Design 3 field components over the runtime's registry —\n * unmapped types keep the built-in accessible renderers. The host's Material\n * theme (M3 tokens) drives all styling.\n */\nimport { type EnvironmentProviders } from '@angular/core';\nimport { provideMosaicooForm, type FieldComponentMap } from '@mosaicoo/form-angular';\nimport {\n MatCheckboxFieldComponent,\n MatRadioFieldComponent,\n MatSelectFieldComponent,\n MatTextFieldComponent,\n} from './material-fields.js';\n\nexport {\n MatCheckboxFieldComponent,\n MatRadioFieldComponent,\n MatSelectFieldComponent,\n MatTextFieldComponent,\n};\n\n/** Field types rendered with Material components (others stay built-in). */\nexport const MATERIAL_FIELD_COMPONENTS: FieldComponentMap = {\n text: MatTextFieldComponent,\n textarea: MatTextFieldComponent,\n number: MatTextFieldComponent,\n currency: MatTextFieldComponent,\n email: MatTextFieldComponent,\n password: MatTextFieldComponent,\n phone: MatTextFieldComponent,\n url: MatTextFieldComponent,\n time: MatTextFieldComponent,\n datetime: MatTextFieldComponent,\n day: MatTextFieldComponent,\n select: MatSelectFieldComponent,\n checkbox: MatCheckboxFieldComponent,\n radio: MatRadioFieldComponent,\n};\n\n/**\n * Registers the Material field set:\n *\n * ```ts\n * bootstrapApplication(App, {\n * providers: [provideMaterialForms()],\n * });\n * ```\n *\n * Composable: later `provideMosaicooForm({components})` calls can override\n * individual types (host-specific fields win).\n */\nexport function provideMaterialForms(): EnvironmentProviders {\n return provideMosaicooForm({ components: MATERIAL_FIELD_COMPONENTS });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NgComponentOutlet, DOCUMENT } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { InjectionToken, makeEnvironmentProviders, input, signal, inject, ChangeDetectorRef, effect, untracked, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, output } from '@angular/core';
|
|
3
|
+
import { InjectionToken, makeEnvironmentProviders, input, signal, inject, ChangeDetectorRef, reflectComponentType, effect, untracked, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, output } from '@angular/core';
|
|
4
4
|
import { maskValue, importForm, createLegacyImporter, createFormEngine, collectInputs } from '@mosaicoo/form-core';
|
|
5
5
|
|
|
6
6
|
/** Multi-provider token: maps merge, later providers win on conflicts. */
|
|
@@ -99,14 +99,22 @@ class FormNodeComponent {
|
|
|
99
99
|
}
|
|
100
100
|
return null;
|
|
101
101
|
}
|
|
102
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* Inputs handed to a custom component (MformFieldComponent contract).
|
|
104
|
+
* Only inputs the component actually declares are passed, so optional
|
|
105
|
+
* contract members (`mode`) never break third-party components.
|
|
106
|
+
*/
|
|
103
107
|
customInputs() {
|
|
104
|
-
|
|
108
|
+
const component = this.customComponent();
|
|
109
|
+
const declared = new Set(component ? (reflectComponentType(component)?.inputs ?? []).map((i) => i.propName) : []);
|
|
110
|
+
const all = {
|
|
105
111
|
field: this.field(),
|
|
106
112
|
engine: this.engine(),
|
|
107
113
|
path: this.path(),
|
|
108
114
|
tick: this.tick(),
|
|
115
|
+
mode: this.mode(),
|
|
109
116
|
};
|
|
117
|
+
return Object.fromEntries(Object.entries(all).filter(([key]) => declared.has(key)));
|
|
110
118
|
}
|
|
111
119
|
/** Options resolved from a dynamic source (provider or remote URL). */
|
|
112
120
|
resolvedOptions = signal(null, ...(ngDevMode ? [{ debugName: "resolvedOptions" }] : /* istanbul ignore next */ []));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mosaicoo-form-angular.mjs","sources":["../../../packages/angular/src/lib/providers.ts","../../../packages/angular/src/lib/form-node.component.ts","../../../packages/angular/src/lib/form-renderer.component.ts","../../../packages/angular/src/public-api.ts","../../../packages/angular/src/mosaicoo-form-angular.ts"],"sourcesContent":["import {\n InjectionToken,\n makeEnvironmentProviders,\n type EnvironmentProviders,\n type Provider,\n type Type,\n} from '@angular/core';\nimport type { FormEngine, InputField, RemoteOptionsFetcher } from '@mosaicoo/form-core';\n\n/**\n * Extension surface of the renderer.\n *\n * Hosts extend or replace field rendering by registering components per field\n * `type` — new types (signature, rating, references…) plug in, and built-in\n * types can be overridden (e.g. a design-system adapter swapping the native\n * select for its own). The registry is DI-scoped: different areas of an app\n * can provide different catalogs.\n */\n\n/**\n * Contract of a registered field component. Implementations receive these\n * values as signal inputs with the SAME names (`field`, `engine`, `path`,\n * `tick`) and interact with the form exclusively through the engine —\n * `engine.getValue(path)` / `engine.setValue(path, value)` /\n * `engine.markTouched(path)` — so validation, conditionals and events keep\n * working with no extra wiring.\n */\nexport interface MformFieldComponent {\n field: () => InputField;\n engine: () => FormEngine;\n path: () => string;\n /** Bumped on every engine event; read it to stay in sync. */\n tick: () => number;\n}\n\n/** Map of field `type` → component implementing {@link MformFieldComponent}. */\nexport type FieldComponentMap = Record<string, Type<unknown>>;\n\n/** Multi-provider token: maps merge, later providers win on conflicts. */\nexport const MFORM_FIELD_COMPONENTS = new InjectionToken<FieldComponentMap[]>(\n 'MFORM_FIELD_COMPONENTS',\n);\n\n/**\n * Transport used for `optionsSource: { type: 'remote' }` fields. Register it\n * to route those requests through the host's HTTP stack (authentication,\n * base URLs, caching). Without it, a plain `fetch` is used.\n */\nexport const MFORM_REMOTE_FETCHER = new InjectionToken<RemoteOptionsFetcher>(\n 'MFORM_REMOTE_FETCHER',\n);\n\n/** Reference the host returns after uploading one file. */\nexport interface UploadedFileRef {\n name: string;\n id?: string;\n url?: string;\n size?: number;\n [extra: string]: unknown;\n}\n\n/**\n * Host-owned file upload: receives each selected file, delivers it wherever\n * the host decides (API, bucket, queue) and returns the reference stored in\n * the form data. Without it, `file` fields keep only file names.\n */\nexport type FileUploadFn = (\n file: File,\n context: { field: InputField; path: string },\n) => Promise<UploadedFileRef>;\n\nexport const MFORM_UPLOAD = new InjectionToken<FileUploadFn>('MFORM_UPLOAD');\n\nexport interface MosaicooFormConfig {\n /** Custom/override field components, keyed by field `type`. */\n components?: FieldComponentMap;\n /** Host transport for remote options sources. */\n remoteFetcher?: RemoteOptionsFetcher;\n /** Host-owned file upload for `file` fields. */\n uploadFiles?: FileUploadFn;\n}\n\n/**\n * Registers renderer extensions at any injector level:\n *\n * ```ts\n * bootstrapApplication(App, {\n * providers: [\n * provideMosaicooForm({\n * components: { signature: SignatureFieldComponent },\n * remoteFetcher: (url) => authenticatedGet(url),\n * }),\n * ],\n * });\n * ```\n */\nexport function provideMosaicooForm(config: MosaicooFormConfig): EnvironmentProviders {\n const providers: Provider[] = [];\n if (config.components) {\n providers.push({ provide: MFORM_FIELD_COMPONENTS, useValue: config.components, multi: true });\n }\n if (config.remoteFetcher) {\n providers.push({ provide: MFORM_REMOTE_FETCHER, useValue: config.remoteFetcher });\n }\n if (config.uploadFiles) {\n providers.push({ provide: MFORM_UPLOAD, useValue: config.uploadFiles });\n }\n return makeEnvironmentProviders(providers);\n}\n","import { NgComponentOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n type Type,\n} from '@angular/core';\nimport { maskValue } from '@mosaicoo/form-core';\nimport type {\n ContainerField,\n FieldNode,\n FieldOption,\n FormEngine,\n InputField,\n OptionsProviderRegistry,\n StaticField,\n} from '@mosaicoo/form-core';\nimport { MFORM_FIELD_COMPONENTS, MFORM_REMOTE_FETCHER, MFORM_UPLOAD } from './providers.js';\n\n/** Rendering mode: `readonly` hides actions, `disabled` grays everything. */\nexport type FormMode = 'edit' | 'readonly' | 'disabled';\n\n/**\n * Renders one schema node (input, container or static) and recurses into\n * children. State lives in the headless engine — this component only projects\n * it and forwards user interaction. `tick` changes whenever the engine emits,\n * invalidating the OnPush view.\n */\n@Component({\n selector: 'mform-node',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mform-node' },\n imports: [NgComponentOutlet],\n template: `\n @let n = node();\n @if (visible()) {\n @switch (n.kind) {\n @case ('static') {\n @if (n.type === 'button') {\n @if (interactive()) {\n <button\n class=\"mform-btn\"\n [type]=\"buttonAction() === 'submit' ? 'submit' : 'button'\"\n >\n {{ n.label || 'Submit' }}\n </button>\n }\n } @else if (n.type === 'content') {\n <div class=\"mform-content\" [innerHTML]=\"content()\"></div>\n } @else {\n <div class=\"mform-unsupported\" role=\"note\">\n {{ n.label || n.key }} — unsupported content\n </div>\n }\n }\n @case ('container') {\n @switch (containerLayout()) {\n @case ('columns') {\n <div class=\"mform-columns\" [style.grid-template-columns]=\"columnsTemplate()\">\n @for (column of columns(); track $index) {\n <div class=\"mform-column\">\n @for (child of column; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" />\n }\n </div>\n }\n </div>\n }\n @case ('tabs') {\n <div class=\"mform-tabs\">\n <div class=\"mform-tabbar\" role=\"tablist\">\n @for (tab of container().children; track tab.key; let i = $index) {\n <button\n type=\"button\"\n class=\"mform-tab\"\n role=\"tab\"\n [class.is-active]=\"activeTab() === i\"\n [attr.aria-selected]=\"activeTab() === i\"\n (click)=\"activeTab.set(i)\"\n >\n {{ tab.label || 'Tab ' + (i + 1) }}\n </button>\n }\n </div>\n @for (tab of container().children; track tab.key; let i = $index) {\n @if (activeTab() === i) {\n <div class=\"mform-tabpanel\" role=\"tabpanel\">\n <mform-node [node]=\"tab\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" [bare]=\"true\" />\n </div>\n }\n }\n </div>\n }\n @case ('array') {\n <section class=\"mform-panel mform-grid\">\n @if (container().label) {\n <header class=\"mform-panel-head\">{{ container().label }}</header>\n }\n <div class=\"mform-panel-body\">\n @for (row of rows(); track $index; let i = $index) {\n <div class=\"mform-grid-row\" role=\"group\" [attr.aria-label]=\"(container().label || container().key) + ' ' + (i + 1)\">\n <div class=\"mform-grid-fields\">\n @for (child of container().children; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"rowScope(i)\" />\n }\n </div>\n @if (interactive()) {\n <button\n type=\"button\"\n class=\"mform-row-remove\"\n (click)=\"removeRow(i)\"\n [attr.aria-label]=\"'Remove row ' + (i + 1)\"\n >\n ✕\n </button>\n }\n </div>\n }\n @if (interactive()) {\n <button type=\"button\" class=\"mform-row-add\" (click)=\"addRow()\">+ Add</button>\n }\n </div>\n </section>\n }\n @default {\n @if (container().label && !bare()) {\n <section class=\"mform-panel\">\n <header class=\"mform-panel-head\">{{ container().label }}</header>\n <div class=\"mform-panel-body\">\n @for (child of container().children; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" />\n }\n </div>\n </section>\n } @else {\n <div class=\"mform-group\">\n @for (child of container().children; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" />\n }\n </div>\n }\n }\n }\n }\n @case ('input') {\n @if (customComponent(); as custom) {\n <ng-container\n [ngComponentOutlet]=\"custom\"\n [ngComponentOutletInputs]=\"customInputs()\"\n />\n } @else if (field().type !== 'hidden') {\n <div class=\"mform-field\" [class.has-error]=\"errors().length > 0\" [class.is-pending]=\"pending()\">\n @if (field().type !== 'checkbox') {\n <label class=\"mform-label\" [attr.for]=\"controlId()\">\n {{ field().label || field().key }}\n @if (required()) {\n <span class=\"mform-req\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n @switch (field().type) {\n @case ('textarea') {\n <textarea\n class=\"mform-control\"\n [id]=\"controlId()\"\n [value]=\"stringValue()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.rows]=\"rowsProp()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (input)=\"setString($event)\"\n (blur)=\"touch()\"\n ></textarea>\n }\n @case ('select') {\n <select\n class=\"mform-control\"\n [id]=\"controlId()\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"setSelect($event)\"\n (blur)=\"touch()\"\n >\n <option value=\"\" [selected]=\"stringValue() === ''\"></option>\n @for (option of options(); track option.value) {\n <option\n [value]=\"option.value\"\n [selected]=\"stringValue() === '' + option.value\"\n >\n {{ option.label }}\n </option>\n }\n </select>\n }\n @case ('radio') {\n <div class=\"mform-choices\" role=\"radiogroup\" [attr.aria-label]=\"field().label || field().key\">\n @for (option of options(); track option.value) {\n <label class=\"mform-check\">\n <input\n type=\"radio\"\n [name]=\"controlId()\"\n [checked]=\"stringValue() === '' + option.value\"\n [disabled]=\"controlDisabled()\"\n (change)=\"setValue(option.value)\"\n (blur)=\"touch()\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n }\n @case ('checkbox') {\n <label class=\"mform-check\">\n <input\n type=\"checkbox\"\n [id]=\"controlId()\"\n [checked]=\"value() === true\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"setChecked($event)\"\n (blur)=\"touch()\"\n />\n <span>\n {{ field().label || field().key }}\n @if (required()) {\n <span class=\"mform-req\" aria-hidden=\"true\">*</span>\n }\n </span>\n </label>\n }\n @case ('checkbox-group') {\n <div class=\"mform-choices\" role=\"group\" [attr.aria-label]=\"field().label || field().key\">\n @for (option of options(); track option.value) {\n <label class=\"mform-check\">\n <input\n type=\"checkbox\"\n [checked]=\"mapValue()['' + option.value] === true\"\n [disabled]=\"controlDisabled()\"\n (change)=\"toggleMap('' + option.value, $event)\"\n (blur)=\"touch()\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n }\n @case ('tags') {\n <div class=\"mform-tags\">\n @for (tag of tagValues(); track $index; let i = $index) {\n <span class=\"mform-tag\">\n {{ tag }}\n <button\n type=\"button\"\n (click)=\"removeTag(i)\"\n [attr.aria-label]=\"'Remove ' + tag\"\n >✕</button>\n </span>\n }\n <input\n class=\"mform-control mform-tag-input\"\n type=\"text\"\n [id]=\"controlId()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-describedby]=\"describedBy()\"\n (keydown.enter)=\"addTag($event)\"\n (blur)=\"touch()\"\n />\n </div>\n }\n @case ('file') {\n <input\n class=\"mform-control\"\n type=\"file\"\n multiple\n [id]=\"controlId()\"\n [disabled]=\"controlDisabled() || uploading()\"\n [attr.aria-busy]=\"uploading() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"setFiles($event)\"\n (blur)=\"touch()\"\n />\n @if (uploading()) {\n <div class=\"mform-desc\" role=\"status\">Uploading…</div>\n }\n @for (name of fileNames(); track $index) {\n <div class=\"mform-file-name\">📎 {{ name }}</div>\n }\n }\n @case ('reference') {\n <div class=\"mform-reference\">\n <input\n class=\"mform-control\"\n type=\"text\"\n role=\"combobox\"\n [id]=\"controlId()\"\n [value]=\"refDisplay()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-expanded]=\"refOpen()\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (input)=\"refSearch($event)\"\n (blur)=\"refBlur()\"\n />\n @if (refOpen() && refOptions().length > 0) {\n <ul class=\"mform-ref-list\" role=\"listbox\">\n @for (option of refOptions(); track option.value) {\n <li role=\"option\">\n <button type=\"button\" (click)=\"refPick(option)\">{{ option.label }}</button>\n </li>\n }\n </ul>\n }\n </div>\n }\n @case ('unsupported') {\n <input\n class=\"mform-control\"\n type=\"text\"\n disabled\n [id]=\"controlId()\"\n [value]=\"'Unsupported field (' + (sourceType() || 'unknown') + ')'\"\n />\n }\n @default {\n <div class=\"mform-affix\" [class.has-affix]=\"prefix() || suffix()\">\n @if (prefix(); as p) {\n <span class=\"mform-prefix\" aria-hidden=\"true\">{{ p }}</span>\n }\n <input\n class=\"mform-control\"\n [type]=\"inputType()\"\n [id]=\"controlId()\"\n [value]=\"stringValue()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.step]=\"field().type === 'currency' ? '0.01' : null\"\n [attr.inputmode]=\"field().type === 'currency' ? 'decimal' : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (input)=\"setString($event)\"\n (blur)=\"touch()\"\n />\n @if (suffix(); as s) {\n <span class=\"mform-suffix\" aria-hidden=\"true\">{{ s }}</span>\n }\n </div>\n }\n }\n @if (field().description) {\n <div class=\"mform-desc\" [id]=\"controlId() + '-desc'\">{{ field().description }}</div>\n }\n @for (error of errors(); track error.rule) {\n <div class=\"mform-error\" [id]=\"controlId() + '-err'\" role=\"alert\">{{ error.message }}</div>\n }\n </div>\n }\n }\n }\n }\n `,\n})\nexport class FormNodeComponent {\n readonly node = input.required<FieldNode>();\n readonly engine = input.required<FormEngine>();\n /** Monotonic counter bumped on every engine event — invalidates the view. */\n readonly tick = input.required<number>();\n /** Data-path prefix (set by array rows and nested groups above this node). */\n readonly scope = input<string>('');\n /** Suppresses the panel chrome (used when a tab already framed the child). */\n readonly bare = input<boolean>(false);\n /** Host-registered providers for `optionsSource: provider` fields. */\n readonly providers = input<OptionsProviderRegistry>({});\n /** Rendering mode inherited from the renderer. */\n readonly mode = input<FormMode>('edit');\n /** Renderer-supplied refresh hook for async completions (zoneless-safe). */\n readonly notify = input<() => void>(() => {});\n\n readonly activeTab = signal(0);\n\n /** DI-registered custom field components (maps merge; later wins). */\n private readonly componentMaps = inject(MFORM_FIELD_COMPONENTS, { optional: true });\n /** Host transport for remote options; plain fetch when absent. */\n private readonly remoteFetcher = inject(MFORM_REMOTE_FETCHER, { optional: true });\n /** Host-owned upload for `file` fields. */\n private readonly uploader = inject(MFORM_UPLOAD, { optional: true });\n /**\n * Async resolutions (debounce timers, provider promises) finish outside\n * any template event — explicitly schedule the refresh for zoneless apps.\n */\n private readonly changeDetector = inject(ChangeDetectorRef);\n\n readonly uploading = signal(false);\n\n /** Effective disabled state: mode, schema flag or calculated field. */\n controlDisabled(): boolean {\n return (\n this.mode() !== 'edit' ||\n this.field().disabled === true ||\n this.field().calculate !== undefined\n );\n }\n\n interactive(): boolean {\n return this.mode() === 'edit';\n }\n\n pending(): boolean {\n this.tick();\n return this.engine().isPending(this.path());\n }\n\n /** Custom component registered for this field type, if any. */\n customComponent(): Type<unknown> | null {\n const node = this.node();\n if (node.kind !== 'input' || !this.componentMaps) return null;\n for (let i = this.componentMaps.length - 1; i >= 0; i--) {\n const match = this.componentMaps[i]?.[node.type];\n if (match) return match;\n }\n return null;\n }\n\n /** Inputs handed to a custom component (MformFieldComponent contract). */\n customInputs(): Record<string, unknown> {\n return {\n field: this.field(),\n engine: this.engine(),\n path: this.path(),\n tick: this.tick(),\n };\n }\n\n /** Options resolved from a dynamic source (provider or remote URL). */\n private readonly resolvedOptions = signal<FieldOption[] | null>(null);\n /** Snapshot of the observed refresh source at the last resolution. */\n private lastRefreshKey: string | null = null;\n /** Discards resolutions that arrive after a newer request started. */\n private optionsRequestSeq = 0;\n\n constructor() {\n effect(() => {\n const node = this.node();\n const registry = this.providers();\n if (node.kind !== 'input' || !node.optionsSource) {\n this.resolvedOptions.set(null);\n return;\n }\n const source = node.optionsSource;\n // With refreshOn, engine events re-run this effect; the refresh key\n // then decides whether the observed data actually changed.\n if (source.refreshOn) this.tick();\n const engine = untracked(() => this.engine());\n const path = untracked(() => this.path());\n const refreshKey = !source.refreshOn\n ? 'static'\n : source.refreshOn === 'data'\n ? JSON.stringify(engine.getData())\n : JSON.stringify(engine.getValue(source.refreshOn) ?? null);\n if (refreshKey === this.lastRefreshKey) return;\n this.lastRefreshKey = refreshKey;\n // Stale-response guard: only the latest request may write options.\n const requestId = ++this.optionsRequestSeq;\n const apply = (options: FieldOption[]) => {\n if (requestId === this.optionsRequestSeq) this.resolvedOptions.set(options);\n };\n if (source.type === 'provider') {\n const provider = registry[source.name];\n if (!provider) return; // no provider: static options/fallback stand\n Promise.resolve(\n provider({ field: node, path, data: engine.getData(), args: source.args }),\n )\n .then((options) => { apply(options); this.changeDetector.markForCheck();\n this.notify()(); })\n .catch(() => {}); // provider failure keeps the static fallback\n } else {\n // The host's transport (auth, base URL, caching) when registered via\n // provideMosaicooForm; plain fetch as the zero-config default.\n const request = this.remoteFetcher\n ? this.remoteFetcher(source.url)\n : fetch(source.url).then((response) => (response.ok ? response.json() : []));\n request\n .then((list) =>\n apply(\n (Array.isArray(list) ? (list as Array<Record<string, unknown>>) : []).map((item) => ({\n label: String(item[source.labelKey ?? 'label'] ?? item[source.valueKey ?? 'value'] ?? ''),\n value: (item[source.valueKey ?? 'value'] ?? '') as FieldOption['value'],\n })),\n ),\n )\n .then(() => this.changeDetector.markForCheck())\n .catch(() => {});\n }\n });\n }\n\n /** Effective options: dynamically resolved first, static as fallback. */\n options(): FieldOption[] {\n return this.resolvedOptions() ?? this.field().options ?? [];\n }\n\n // -- typed views of the node ---------------------------------------------\n\n field(): InputField {\n return this.node() as InputField;\n }\n\n container(): ContainerField {\n return this.node() as ContainerField;\n }\n\n content(): string {\n return (this.node() as StaticField).content ?? '';\n }\n\n buttonAction(): string {\n return String(this.node().props?.['action'] ?? 'submit');\n }\n\n sourceType(): string {\n return String(this.node().props?.['sourceType'] ?? '');\n }\n\n rowsProp(): number | null {\n const rows = this.node().props?.['rows'];\n return typeof rows === 'number' ? rows : null;\n }\n\n // -- paths and visibility -------------------------------------------------\n\n /** Data path of this node (inputs) or of its scope (containers). */\n readonly path = computed(() => {\n const scope = this.scope();\n const node = this.node();\n if (node.kind === 'input') return scope ? `${scope}.${node.key}` : node.key;\n if (node.kind === 'container' && node.dataScope !== 'inherit') {\n return scope ? `${scope}.${node.key}` : node.key;\n }\n return scope;\n });\n\n /** Scope handed to children (nested/array containers extend it). */\n readonly childScope = computed(() => {\n const node = this.node();\n if (node.kind === 'container' && node.dataScope === 'nested') return this.path();\n return this.scope();\n });\n\n rowScope(index: number): string {\n return `${this.path()}.${index}`;\n }\n\n visible(): boolean {\n this.tick();\n const node = this.node();\n const key = node.kind === 'input' ? this.path() : node.key;\n return this.engine().isVisible(key);\n }\n\n containerLayout(): 'columns' | 'tabs' | 'array' | 'block' {\n const node = this.container();\n if (node.dataScope === 'array') return 'array';\n if (node.type === 'tabs') return 'tabs';\n if (node.type === 'columns' && node.columns?.length) return 'columns';\n return 'block';\n }\n\n columns(): FieldNode[][] {\n const node = this.container();\n return (node.columns ?? []).map((column) =>\n column.children\n .map((index) => node.children[index])\n .filter((child): child is FieldNode => child !== undefined),\n );\n }\n\n columnsTemplate(): string {\n const cols = this.container().columns ?? [];\n const total = cols.reduce((sum, c) => sum + c.width, 0) || 12;\n return cols.map((c) => `${((c.width / total) * 100).toFixed(3)}fr`).join(' ');\n }\n\n // -- values ---------------------------------------------------------------\n\n value(): unknown {\n this.tick();\n return this.engine().getValue(this.path());\n }\n\n stringValue(): string {\n const value = this.value();\n if (value === undefined || value === null) return '';\n const mask = this.field().format?.mask;\n if (mask && typeof value === 'string') return maskValue(value, mask).masked;\n return String(value);\n }\n\n mapValue(): Record<string, unknown> {\n const value = this.value();\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n }\n\n rows(): unknown[] {\n const value = this.value();\n return Array.isArray(value) ? value : [];\n }\n\n required(): boolean {\n return this.field().validators?.some((v) => v.type === 'required') ?? false;\n }\n\n errors() {\n this.tick();\n return this.engine().getFieldErrors(this.path());\n }\n\n controlId(): string {\n return `mform-${this.path().replace(/\\./g, '-')}`;\n }\n\n describedBy(): string | null {\n const parts: string[] = [];\n if (this.field().description) parts.push(`${this.controlId()}-desc`);\n if (this.errors().length > 0) parts.push(`${this.controlId()}-err`);\n return parts.length ? parts.join(' ') : null;\n }\n\n inputType(): string {\n switch (this.field().type) {\n case 'number':\n case 'currency':\n return 'number';\n case 'email':\n return 'email';\n case 'password':\n return 'password';\n case 'phone':\n return 'tel';\n case 'url':\n return 'url';\n case 'time':\n return 'time';\n case 'datetime':\n return 'datetime-local';\n case 'day':\n return 'date';\n default:\n return 'text';\n }\n }\n\n // -- interaction ----------------------------------------------------------\n\n setValue(value: unknown): void {\n this.engine().setValue(this.path(), value);\n }\n\n setString(event: Event): void {\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n const raw = target.value;\n const mask = this.field().format?.mask;\n if (mask) {\n const { masked, raw: stripped } = maskValue(raw, mask);\n target.value = masked; // the control always shows the masked shape\n this.setValue(this.field().format?.keepMask ? masked : stripped);\n return;\n }\n if (this.field().dataType === 'number') {\n const parsed = raw === '' ? undefined : Number(raw);\n this.setValue(parsed !== undefined && Number.isFinite(parsed) ? parsed : undefined);\n } else {\n this.setValue(raw);\n }\n }\n\n setSelect(event: Event): void {\n this.setValue((event.target as HTMLSelectElement).value);\n }\n\n setChecked(event: Event): void {\n this.setValue((event.target as HTMLInputElement).checked);\n }\n\n toggleMap(option: string, event: Event): void {\n const checked = (event.target as HTMLInputElement).checked;\n this.setValue({ ...this.mapValue(), [option]: checked });\n }\n\n setFiles(event: Event): void {\n const files = (event.target as HTMLInputElement).files;\n const list = files ? Array.from(files) : [];\n if (!this.uploader || list.length === 0) {\n // no host uploader: only file names are stored\n this.setValue(list.map((f) => f.name));\n return;\n }\n const field = this.field();\n const path = this.path();\n this.uploading.set(true);\n Promise.all(list.map((file) => this.uploader!(file, { field, path })))\n .then((refs) => this.setValue(refs))\n .catch(() => {}) // host upload failure keeps the previous value\n .finally(() => { this.uploading.set(false); this.changeDetector.markForCheck();\n this.notify()(); });\n }\n\n /** Names shown under a `file` control (refs or plain names). */\n fileNames(): string[] {\n const value = this.value();\n if (!Array.isArray(value)) return [];\n return value.map((item) =>\n typeof item === 'object' && item !== null\n ? String((item as { name?: unknown }).name ?? '')\n : String(item),\n );\n }\n\n prefix(): string | null {\n const value = this.node().props?.['prefix'];\n return typeof value === 'string' && value ? value : null;\n }\n\n suffix(): string | null {\n const value = this.node().props?.['suffix'];\n return typeof value === 'string' && value ? value : null;\n }\n\n tagValues(): string[] {\n const value = this.value();\n return Array.isArray(value) ? value.map(String) : [];\n }\n\n addTag(event: Event): void {\n event.preventDefault();\n const input = event.target as HTMLInputElement;\n const tag = input.value.trim();\n if (!tag) return;\n this.setValue([...this.tagValues(), tag]);\n input.value = '';\n }\n\n removeTag(index: number): void {\n const next = [...this.tagValues()];\n next.splice(index, 1);\n this.setValue(next);\n }\n\n touch(): void {\n this.engine().markTouched(this.path());\n // Async-aware: resolves immediately for sync-only fields; pending events\n // drive the busy indicator otherwise.\n void this.engine().validateFieldAsync(this.path());\n }\n\n // -- reference (autocomplete) ---------------------------------------------\n\n readonly refOptions = signal<FieldOption[]>([]);\n readonly refOpen = signal(false);\n private refTimer: ReturnType<typeof setTimeout> | null = null;\n /** Label of the chosen option (falls back to the raw value). */\n readonly refLabel = signal<string | null>(null);\n\n refDisplay(): string {\n return this.refLabel() ?? this.stringValue();\n }\n\n refSearch(event: Event): void {\n const query = (event.target as HTMLInputElement).value;\n this.refLabel.set(null);\n if (this.refTimer) clearTimeout(this.refTimer);\n this.refTimer = setTimeout(() => this.refResolve(query), 250);\n }\n\n private refResolve(query: string): void {\n const source = this.field().optionsSource;\n if (!source || source.type !== 'provider') {\n // static options filter locally\n const filter = query.toLowerCase();\n this.refOptions.set(\n (this.field().options ?? []).filter((o) => o.label.toLowerCase().includes(filter)),\n );\n this.refOpen.set(true);\n this.changeDetector.markForCheck();\n this.notify()();\n return;\n }\n const provider = this.providers()[source.name];\n if (!provider) return;\n Promise.resolve(\n provider({\n field: this.field(),\n path: this.path(),\n data: this.engine().getData(),\n args: source.args,\n query,\n }),\n )\n .then((options) => {\n this.refOptions.set(options);\n this.refOpen.set(true);\n this.changeDetector.markForCheck();\n this.notify()();\n })\n .catch(() => {});\n }\n\n refPick(option: FieldOption): void {\n this.setValue(option.value);\n this.refLabel.set(option.label);\n this.refOpen.set(false);\n this.touch();\n }\n\n refBlur(): void {\n // let a click on an option land before closing\n setTimeout(() => { this.refOpen.set(false); this.changeDetector.markForCheck();\n this.notify()(); }, 150);\n this.touch();\n }\n\n addRow(): void {\n this.engine().addRow(this.path());\n }\n\n removeRow(index: number): void {\n this.engine().removeRow(this.path(), index);\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport {\n collectInputs,\n createFormEngine,\n createLegacyImporter,\n importForm,\n type ContainerField,\n type FieldError,\n type FormEngine,\n type FormSchema,\n type ImportWarning,\n type MessageResolver,\n type OptionsProviderRegistry,\n type SubmitResult,\n type ValidatorRegistry,\n} from '@mosaicoo/form-core';\nimport { FormNodeComponent, type FormMode } from './form-node.component.js';\n\n/**\n * `<mform-renderer>` — renders a form at runtime from a `FormSchema` (or any\n * definition a registered importer understands) and manages its lifecycle:\n * values, validation, conditional visibility and submission. Wizard schemas\n * (`settings.display: 'wizard'`) render as steps with per-step validation.\n *\n * Theming: every visual primitive reads a `--mform-*` CSS custom property\n * with a self-contained fallback, so the component looks finished on its own\n * and adopts the host design system when the host overrides the tokens.\n */\n@Component({\n selector: 'mform-renderer',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [FormNodeComponent],\n styleUrls: ['./form-theme.css'],\n template: `\n @if (engine(); as engine) {\n <form class=\"mform-root\" novalidate (submit)=\"onSubmit($event)\">\n @if (errorSummary().length > 0) {\n <div class=\"mform-summary\" role=\"alert\" tabindex=\"-1\">\n <strong>{{ summaryTitle() }}</strong>\n <ul>\n @for (error of errorSummary(); track error.path + error.rule) {\n <li>{{ error.message }}</li>\n }\n </ul>\n </div>\n }\n @if (isWizard()) {\n <ol class=\"mform-steps\">\n @for (step of steps(); track step.key; let i = $index) {\n <li\n class=\"mform-step\"\n [class.is-active]=\"currentStep() === i\"\n [class.is-done]=\"i < currentStep()\"\n [attr.aria-current]=\"currentStep() === i ? 'step' : null\"\n >\n <span class=\"mform-step-index\">{{ i + 1 }}</span>\n <span class=\"mform-step-label\">{{ step.label || 'Step ' + (i + 1) }}</span>\n </li>\n }\n </ol>\n @if (steps()[currentStep()]; as step) {\n <mform-node\n [node]=\"step\"\n [engine]=\"engine\"\n [tick]=\"tick()\"\n [providers]=\"optionsProviders()\"\n [mode]=\"mode()\" [notify]=\"bumpTick\"\n [bare]=\"true\"\n />\n }\n <div class=\"mform-wizard-nav\">\n @if (currentStep() > 0) {\n <button type=\"button\" class=\"mform-btn mform-btn-secondary\" (click)=\"previousStep()\">\n {{ labels().previous }}\n </button>\n }\n @if (currentStep() < steps().length - 1) {\n <button type=\"button\" class=\"mform-btn\" (click)=\"nextStep()\">\n {{ labels().next }}\n </button>\n } @else if (mode() === 'edit') {\n <button type=\"submit\" class=\"mform-btn\" [disabled]=\"submitting()\">\n {{ submitting() ? '…' : labels().submit }}\n </button>\n }\n </div>\n } @else {\n @for (node of engine.schema.fields; track node.key) {\n <mform-node [node]=\"node\" [engine]=\"engine\" [tick]=\"tick()\" [providers]=\"optionsProviders()\" [mode]=\"mode()\" [notify]=\"bumpTick\" />\n }\n }\n @if (submitError(); as error) {\n <div class=\"mform-summary\" role=\"alert\">{{ error }}</div>\n }\n </form>\n }\n `,\n})\nexport class FormRendererComponent {\n /** Native schema input. Takes precedence over `source`. */\n readonly schema = input<FormSchema | null>(null);\n /** Foreign definition (object or JSON string) resolved via importers. */\n readonly source = input<unknown>(null);\n /** Initial data merged over schema defaults. */\n readonly initialData = input<Record<string, unknown> | null>(null);\n /** Named providers resolving `optionsSource: provider` fields. */\n readonly optionsProviders = input<OptionsProviderRegistry>({});\n /** Host-supplied message resolver (localization of validation messages). */\n readonly messages = input<MessageResolver | null>(null);\n /** Named custom validators (sync or async — Promises get pending states). */\n readonly validators = input<ValidatorRegistry | null>(null);\n /** `edit` (default), `readonly` (no actions) or `disabled`. */\n readonly mode = input<FormMode>('edit');\n /**\n * Optional host submission: called after a VALID submit with the result;\n * rejections surface as the submission error state. Persistence transport\n * stays entirely on the host side.\n */\n readonly submitHandler = input<((result: SubmitResult) => Promise<void>) | null>(null);\n\n /** True while async validation or the submit handler is running. */\n readonly submitting = signal(false);\n /** Message when the host submission rejected. */\n readonly submitError = signal<string | null>(null);\n /** Fixed renderer texts (override to localize). `{{count}}` in `summary`. */\n readonly labels = input(\n {\n previous: 'Previous',\n next: 'Next',\n submit: 'Submit',\n summary: '{{count}} field(s) need attention:',\n },\n {\n transform: (value: Partial<{ previous: string; next: string; submit: string; summary: string }>) => ({\n previous: 'Previous',\n next: 'Next',\n submit: 'Submit',\n summary: '{{count}} field(s) need attention:',\n ...value,\n }),\n },\n );\n\n summaryTitle(): string {\n return this.labels().summary.replace(/\\{\\{\\s*count\\s*\\}\\}/g, String(this.errorSummary().length));\n }\n\n /** Fired on submit; `ok` is false when validation failed. */\n readonly submitted = output<SubmitResult>();\n /** Fired on every value change with the full data snapshot. */\n readonly valueChanged = output<Record<string, unknown>>();\n\n /** Bumped on every engine event; nodes read it to refresh. */\n readonly tick = signal(0);\n\n /** Handed to nodes so async completions re-render (zoneless-safe). */\n readonly bumpTick = (): void => this.tick.update((v) => v + 1);\n /** Active wizard step index. */\n readonly currentStep = signal(0);\n\n private readonly resolved = computed<{\n schema: FormSchema | null;\n warnings: ImportWarning[];\n }>(() => {\n const native = this.schema();\n if (native) return { schema: native, warnings: [] };\n const source = this.source();\n if (source === null || source === undefined) return { schema: null, warnings: [] };\n try {\n const result = importForm(source, [createLegacyImporter()]);\n return { schema: result.schema, warnings: result.warnings };\n } catch {\n return {\n schema: null,\n warnings: [\n { code: 'unreadable-source', message: 'The form definition could not be read.' },\n ],\n };\n }\n });\n\n /** Import degradations for the current `source`, if any. */\n readonly importWarnings = computed(() => this.resolved().warnings);\n\n readonly engine = computed<FormEngine | null>(() => {\n const schema = this.resolved().schema;\n return schema\n ? createFormEngine(schema, {\n initialData: this.initialData() ?? undefined,\n messages: this.messages() ?? undefined,\n validators: this.validators() ?? undefined,\n })\n : null;\n });\n\n readonly isWizard = computed(\n () => this.resolved().schema?.settings?.display === 'wizard' && this.steps().length > 0,\n );\n\n /** Wizard pages: the top-level containers of the schema. */\n readonly steps = computed<ContainerField[]>(() =>\n (this.resolved().schema?.fields ?? []).filter(\n (node): node is ContainerField => node.kind === 'container',\n ),\n );\n\n readonly errorSummary = signal<FieldError[]>([]);\n\n constructor() {\n effect((onCleanup) => {\n const engine = this.engine();\n this.errorSummary.set([]);\n this.tick.set(0);\n this.currentStep.set(0);\n if (!engine) return;\n const unsubscribe = engine.subscribe((event) => {\n this.tick.update((v) => v + 1);\n if (event.type === 'value-change') {\n this.valueChanged.emit(engine.getData());\n }\n if (event.type === 'validation') {\n // Keep the banner in sync as the user fixes fields after a submit.\n if (this.errorSummary().length > 0) {\n this.errorSummary.set(event.errors);\n }\n }\n });\n onCleanup(unsubscribe);\n });\n }\n\n // -- wizard navigation ----------------------------------------------------\n\n previousStep(): void {\n this.errorSummary.set([]);\n this.currentStep.update((step) => Math.max(0, step - 1));\n }\n\n nextStep(): void {\n const engine = this.engine();\n const step = this.steps()[this.currentStep()];\n if (!engine || !step) return;\n const errors = engine.validateContainer(step.key);\n if (errors.length > 0) {\n this.errorSummary.set(errors);\n this.focusFirstError(errors);\n return;\n }\n this.errorSummary.set([]);\n this.currentStep.update((index) => Math.min(this.steps().length - 1, index + 1));\n }\n\n // -- submission -----------------------------------------------------------\n\n async onSubmit(event: Event): Promise<void> {\n event.preventDefault();\n const engine = this.engine();\n if (!engine || this.submitting() || this.mode() !== 'edit') return;\n this.submitting.set(true);\n this.submitError.set(null);\n try {\n const result = await engine.submitAsync();\n this.errorSummary.set(result.errors);\n if (!result.ok) {\n if (this.isWizard()) {\n const stepIndex = this.stepIndexForPath(result.errors[0]?.path ?? '');\n if (stepIndex >= 0) this.currentStep.set(stepIndex);\n }\n this.focusFirstError(result.errors);\n } else if (this.submitHandler()) {\n try {\n await this.submitHandler()!(result);\n } catch (error) {\n this.submitError.set(String(error instanceof Error ? error.message : error));\n }\n }\n this.submitted.emit(result);\n } finally {\n this.submitting.set(false);\n }\n }\n\n /** Finds the wizard step that owns a (possibly row-indexed) data path. */\n private stepIndexForPath(path: string): number {\n const pattern = path\n .split('.')\n .map((part) => (/^\\d+$/.test(part) ? '*' : part))\n .join('.');\n return this.steps().findIndex((step) =>\n collectInputs({ version: 1, fields: step.children }).some(\n (entry) => entry.path === pattern,\n ),\n );\n }\n\n private readonly documentRef = inject(DOCUMENT);\n\n private focusFirstError(errors: FieldError[]): void {\n const first = errors[0];\n if (!first) return;\n const id = `mform-${first.path.replace(/\\./g, '-')}`;\n // Focus after the view updated with the error states.\n queueMicrotask(() => this.documentRef.getElementById(id)?.focus());\n }\n}\n","/*\n * Runtime entry point of @mosaicoo/form-angular.\n *\n * Architectural note: this primary entry stays runtime-only. Authoring\n * tooling (the visual designer) will ship as a SECONDARY entry point\n * (`@mosaicoo/form-angular/designer`) so applications that only render\n * forms never load authoring code — a requirement for federated hosts.\n */\nexport { FormRendererComponent } from './lib/form-renderer.component.js';\nexport { FormNodeComponent, type FormMode } from './lib/form-node.component.js';\nexport {\n MFORM_FIELD_COMPONENTS,\n MFORM_REMOTE_FETCHER,\n MFORM_UPLOAD,\n provideMosaicooForm,\n type FieldComponentMap,\n type FileUploadFn,\n type MformFieldComponent,\n type MosaicooFormConfig,\n type UploadedFileRef,\n} from './lib/providers.js';\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":"mosaicoo-form-angular.mjs","sources":["../../../packages/angular/src/lib/providers.ts","../../../packages/angular/src/lib/form-node.component.ts","../../../packages/angular/src/lib/form-renderer.component.ts","../../../packages/angular/src/public-api.ts","../../../packages/angular/src/mosaicoo-form-angular.ts"],"sourcesContent":["import {\n InjectionToken,\n makeEnvironmentProviders,\n type EnvironmentProviders,\n type Provider,\n type Type,\n} from '@angular/core';\nimport type { FormEngine, InputField, RemoteOptionsFetcher } from '@mosaicoo/form-core';\n\n/**\n * Extension surface of the renderer.\n *\n * Hosts extend or replace field rendering by registering components per field\n * `type` — new types (signature, rating, references…) plug in, and built-in\n * types can be overridden (e.g. a design-system adapter swapping the native\n * select for its own). The registry is DI-scoped: different areas of an app\n * can provide different catalogs.\n */\n\n/**\n * Contract of a registered field component. Implementations receive these\n * values as signal inputs with the SAME names (`field`, `engine`, `path`,\n * `tick`) and interact with the form exclusively through the engine —\n * `engine.getValue(path)` / `engine.setValue(path, value)` /\n * `engine.markTouched(path)` — so validation, conditionals and events keep\n * working with no extra wiring.\n */\nexport interface MformFieldComponent {\n field: () => InputField;\n engine: () => FormEngine;\n path: () => string;\n /** Bumped on every engine event; read it to stay in sync. */\n tick: () => number;\n /** Rendering mode of the surrounding form (optional input). */\n mode?: () => 'edit' | 'readonly' | 'disabled';\n}\n\n/** Map of field `type` → component implementing {@link MformFieldComponent}. */\nexport type FieldComponentMap = Record<string, Type<unknown>>;\n\n/** Multi-provider token: maps merge, later providers win on conflicts. */\nexport const MFORM_FIELD_COMPONENTS = new InjectionToken<FieldComponentMap[]>(\n 'MFORM_FIELD_COMPONENTS',\n);\n\n/**\n * Transport used for `optionsSource: { type: 'remote' }` fields. Register it\n * to route those requests through the host's HTTP stack (authentication,\n * base URLs, caching). Without it, a plain `fetch` is used.\n */\nexport const MFORM_REMOTE_FETCHER = new InjectionToken<RemoteOptionsFetcher>(\n 'MFORM_REMOTE_FETCHER',\n);\n\n/** Reference the host returns after uploading one file. */\nexport interface UploadedFileRef {\n name: string;\n id?: string;\n url?: string;\n size?: number;\n [extra: string]: unknown;\n}\n\n/**\n * Host-owned file upload: receives each selected file, delivers it wherever\n * the host decides (API, bucket, queue) and returns the reference stored in\n * the form data. Without it, `file` fields keep only file names.\n */\nexport type FileUploadFn = (\n file: File,\n context: { field: InputField; path: string },\n) => Promise<UploadedFileRef>;\n\nexport const MFORM_UPLOAD = new InjectionToken<FileUploadFn>('MFORM_UPLOAD');\n\nexport interface MosaicooFormConfig {\n /** Custom/override field components, keyed by field `type`. */\n components?: FieldComponentMap;\n /** Host transport for remote options sources. */\n remoteFetcher?: RemoteOptionsFetcher;\n /** Host-owned file upload for `file` fields. */\n uploadFiles?: FileUploadFn;\n}\n\n/**\n * Registers renderer extensions at any injector level:\n *\n * ```ts\n * bootstrapApplication(App, {\n * providers: [\n * provideMosaicooForm({\n * components: { signature: SignatureFieldComponent },\n * remoteFetcher: (url) => authenticatedGet(url),\n * }),\n * ],\n * });\n * ```\n */\nexport function provideMosaicooForm(config: MosaicooFormConfig): EnvironmentProviders {\n const providers: Provider[] = [];\n if (config.components) {\n providers.push({ provide: MFORM_FIELD_COMPONENTS, useValue: config.components, multi: true });\n }\n if (config.remoteFetcher) {\n providers.push({ provide: MFORM_REMOTE_FETCHER, useValue: config.remoteFetcher });\n }\n if (config.uploadFiles) {\n providers.push({ provide: MFORM_UPLOAD, useValue: config.uploadFiles });\n }\n return makeEnvironmentProviders(providers);\n}\n","import { NgComponentOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n reflectComponentType,\n signal,\n untracked,\n type Type,\n} from '@angular/core';\nimport { maskValue } from '@mosaicoo/form-core';\nimport type {\n ContainerField,\n FieldNode,\n FieldOption,\n FormEngine,\n InputField,\n OptionsProviderRegistry,\n StaticField,\n} from '@mosaicoo/form-core';\nimport { MFORM_FIELD_COMPONENTS, MFORM_REMOTE_FETCHER, MFORM_UPLOAD } from './providers.js';\n\n/** Rendering mode: `readonly` hides actions, `disabled` grays everything. */\nexport type FormMode = 'edit' | 'readonly' | 'disabled';\n\n/**\n * Renders one schema node (input, container or static) and recurses into\n * children. State lives in the headless engine — this component only projects\n * it and forwards user interaction. `tick` changes whenever the engine emits,\n * invalidating the OnPush view.\n */\n@Component({\n selector: 'mform-node',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mform-node' },\n imports: [NgComponentOutlet],\n template: `\n @let n = node();\n @if (visible()) {\n @switch (n.kind) {\n @case ('static') {\n @if (n.type === 'button') {\n @if (interactive()) {\n <button\n class=\"mform-btn\"\n [type]=\"buttonAction() === 'submit' ? 'submit' : 'button'\"\n >\n {{ n.label || 'Submit' }}\n </button>\n }\n } @else if (n.type === 'content') {\n <div class=\"mform-content\" [innerHTML]=\"content()\"></div>\n } @else {\n <div class=\"mform-unsupported\" role=\"note\">\n {{ n.label || n.key }} — unsupported content\n </div>\n }\n }\n @case ('container') {\n @switch (containerLayout()) {\n @case ('columns') {\n <div class=\"mform-columns\" [style.grid-template-columns]=\"columnsTemplate()\">\n @for (column of columns(); track $index) {\n <div class=\"mform-column\">\n @for (child of column; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" />\n }\n </div>\n }\n </div>\n }\n @case ('tabs') {\n <div class=\"mform-tabs\">\n <div class=\"mform-tabbar\" role=\"tablist\">\n @for (tab of container().children; track tab.key; let i = $index) {\n <button\n type=\"button\"\n class=\"mform-tab\"\n role=\"tab\"\n [class.is-active]=\"activeTab() === i\"\n [attr.aria-selected]=\"activeTab() === i\"\n (click)=\"activeTab.set(i)\"\n >\n {{ tab.label || 'Tab ' + (i + 1) }}\n </button>\n }\n </div>\n @for (tab of container().children; track tab.key; let i = $index) {\n @if (activeTab() === i) {\n <div class=\"mform-tabpanel\" role=\"tabpanel\">\n <mform-node [node]=\"tab\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" [bare]=\"true\" />\n </div>\n }\n }\n </div>\n }\n @case ('array') {\n <section class=\"mform-panel mform-grid\">\n @if (container().label) {\n <header class=\"mform-panel-head\">{{ container().label }}</header>\n }\n <div class=\"mform-panel-body\">\n @for (row of rows(); track $index; let i = $index) {\n <div class=\"mform-grid-row\" role=\"group\" [attr.aria-label]=\"(container().label || container().key) + ' ' + (i + 1)\">\n <div class=\"mform-grid-fields\">\n @for (child of container().children; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"rowScope(i)\" />\n }\n </div>\n @if (interactive()) {\n <button\n type=\"button\"\n class=\"mform-row-remove\"\n (click)=\"removeRow(i)\"\n [attr.aria-label]=\"'Remove row ' + (i + 1)\"\n >\n ✕\n </button>\n }\n </div>\n }\n @if (interactive()) {\n <button type=\"button\" class=\"mform-row-add\" (click)=\"addRow()\">+ Add</button>\n }\n </div>\n </section>\n }\n @default {\n @if (container().label && !bare()) {\n <section class=\"mform-panel\">\n <header class=\"mform-panel-head\">{{ container().label }}</header>\n <div class=\"mform-panel-body\">\n @for (child of container().children; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" />\n }\n </div>\n </section>\n } @else {\n <div class=\"mform-group\">\n @for (child of container().children; track child.key) {\n <mform-node [node]=\"child\" [engine]=\"engine()\" [tick]=\"tick()\" [providers]=\"providers()\" [mode]=\"mode()\" [notify]=\"notify()\" [scope]=\"childScope()\" />\n }\n </div>\n }\n }\n }\n }\n @case ('input') {\n @if (customComponent(); as custom) {\n <ng-container\n [ngComponentOutlet]=\"custom\"\n [ngComponentOutletInputs]=\"customInputs()\"\n />\n } @else if (field().type !== 'hidden') {\n <div class=\"mform-field\" [class.has-error]=\"errors().length > 0\" [class.is-pending]=\"pending()\">\n @if (field().type !== 'checkbox') {\n <label class=\"mform-label\" [attr.for]=\"controlId()\">\n {{ field().label || field().key }}\n @if (required()) {\n <span class=\"mform-req\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n @switch (field().type) {\n @case ('textarea') {\n <textarea\n class=\"mform-control\"\n [id]=\"controlId()\"\n [value]=\"stringValue()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.rows]=\"rowsProp()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (input)=\"setString($event)\"\n (blur)=\"touch()\"\n ></textarea>\n }\n @case ('select') {\n <select\n class=\"mform-control\"\n [id]=\"controlId()\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"setSelect($event)\"\n (blur)=\"touch()\"\n >\n <option value=\"\" [selected]=\"stringValue() === ''\"></option>\n @for (option of options(); track option.value) {\n <option\n [value]=\"option.value\"\n [selected]=\"stringValue() === '' + option.value\"\n >\n {{ option.label }}\n </option>\n }\n </select>\n }\n @case ('radio') {\n <div class=\"mform-choices\" role=\"radiogroup\" [attr.aria-label]=\"field().label || field().key\">\n @for (option of options(); track option.value) {\n <label class=\"mform-check\">\n <input\n type=\"radio\"\n [name]=\"controlId()\"\n [checked]=\"stringValue() === '' + option.value\"\n [disabled]=\"controlDisabled()\"\n (change)=\"setValue(option.value)\"\n (blur)=\"touch()\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n }\n @case ('checkbox') {\n <label class=\"mform-check\">\n <input\n type=\"checkbox\"\n [id]=\"controlId()\"\n [checked]=\"value() === true\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"setChecked($event)\"\n (blur)=\"touch()\"\n />\n <span>\n {{ field().label || field().key }}\n @if (required()) {\n <span class=\"mform-req\" aria-hidden=\"true\">*</span>\n }\n </span>\n </label>\n }\n @case ('checkbox-group') {\n <div class=\"mform-choices\" role=\"group\" [attr.aria-label]=\"field().label || field().key\">\n @for (option of options(); track option.value) {\n <label class=\"mform-check\">\n <input\n type=\"checkbox\"\n [checked]=\"mapValue()['' + option.value] === true\"\n [disabled]=\"controlDisabled()\"\n (change)=\"toggleMap('' + option.value, $event)\"\n (blur)=\"touch()\"\n />\n <span>{{ option.label }}</span>\n </label>\n }\n </div>\n }\n @case ('tags') {\n <div class=\"mform-tags\">\n @for (tag of tagValues(); track $index; let i = $index) {\n <span class=\"mform-tag\">\n {{ tag }}\n <button\n type=\"button\"\n (click)=\"removeTag(i)\"\n [attr.aria-label]=\"'Remove ' + tag\"\n >✕</button>\n </span>\n }\n <input\n class=\"mform-control mform-tag-input\"\n type=\"text\"\n [id]=\"controlId()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-describedby]=\"describedBy()\"\n (keydown.enter)=\"addTag($event)\"\n (blur)=\"touch()\"\n />\n </div>\n }\n @case ('file') {\n <input\n class=\"mform-control\"\n type=\"file\"\n multiple\n [id]=\"controlId()\"\n [disabled]=\"controlDisabled() || uploading()\"\n [attr.aria-busy]=\"uploading() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (change)=\"setFiles($event)\"\n (blur)=\"touch()\"\n />\n @if (uploading()) {\n <div class=\"mform-desc\" role=\"status\">Uploading…</div>\n }\n @for (name of fileNames(); track $index) {\n <div class=\"mform-file-name\">📎 {{ name }}</div>\n }\n }\n @case ('reference') {\n <div class=\"mform-reference\">\n <input\n class=\"mform-control\"\n type=\"text\"\n role=\"combobox\"\n [id]=\"controlId()\"\n [value]=\"refDisplay()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.aria-expanded]=\"refOpen()\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (input)=\"refSearch($event)\"\n (blur)=\"refBlur()\"\n />\n @if (refOpen() && refOptions().length > 0) {\n <ul class=\"mform-ref-list\" role=\"listbox\">\n @for (option of refOptions(); track option.value) {\n <li role=\"option\">\n <button type=\"button\" (click)=\"refPick(option)\">{{ option.label }}</button>\n </li>\n }\n </ul>\n }\n </div>\n }\n @case ('unsupported') {\n <input\n class=\"mform-control\"\n type=\"text\"\n disabled\n [id]=\"controlId()\"\n [value]=\"'Unsupported field (' + (sourceType() || 'unknown') + ')'\"\n />\n }\n @default {\n <div class=\"mform-affix\" [class.has-affix]=\"prefix() || suffix()\">\n @if (prefix(); as p) {\n <span class=\"mform-prefix\" aria-hidden=\"true\">{{ p }}</span>\n }\n <input\n class=\"mform-control\"\n [type]=\"inputType()\"\n [id]=\"controlId()\"\n [value]=\"stringValue()\"\n [placeholder]=\"field().placeholder || ''\"\n [disabled]=\"controlDisabled()\"\n [attr.step]=\"field().type === 'currency' ? '0.01' : null\"\n [attr.inputmode]=\"field().type === 'currency' ? 'decimal' : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"errors().length > 0 || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (input)=\"setString($event)\"\n (blur)=\"touch()\"\n />\n @if (suffix(); as s) {\n <span class=\"mform-suffix\" aria-hidden=\"true\">{{ s }}</span>\n }\n </div>\n }\n }\n @if (field().description) {\n <div class=\"mform-desc\" [id]=\"controlId() + '-desc'\">{{ field().description }}</div>\n }\n @for (error of errors(); track error.rule) {\n <div class=\"mform-error\" [id]=\"controlId() + '-err'\" role=\"alert\">{{ error.message }}</div>\n }\n </div>\n }\n }\n }\n }\n `,\n})\nexport class FormNodeComponent {\n readonly node = input.required<FieldNode>();\n readonly engine = input.required<FormEngine>();\n /** Monotonic counter bumped on every engine event — invalidates the view. */\n readonly tick = input.required<number>();\n /** Data-path prefix (set by array rows and nested groups above this node). */\n readonly scope = input<string>('');\n /** Suppresses the panel chrome (used when a tab already framed the child). */\n readonly bare = input<boolean>(false);\n /** Host-registered providers for `optionsSource: provider` fields. */\n readonly providers = input<OptionsProviderRegistry>({});\n /** Rendering mode inherited from the renderer. */\n readonly mode = input<FormMode>('edit');\n /** Renderer-supplied refresh hook for async completions (zoneless-safe). */\n readonly notify = input<() => void>(() => {});\n\n readonly activeTab = signal(0);\n\n /** DI-registered custom field components (maps merge; later wins). */\n private readonly componentMaps = inject(MFORM_FIELD_COMPONENTS, { optional: true });\n /** Host transport for remote options; plain fetch when absent. */\n private readonly remoteFetcher = inject(MFORM_REMOTE_FETCHER, { optional: true });\n /** Host-owned upload for `file` fields. */\n private readonly uploader = inject(MFORM_UPLOAD, { optional: true });\n /**\n * Async resolutions (debounce timers, provider promises) finish outside\n * any template event — explicitly schedule the refresh for zoneless apps.\n */\n private readonly changeDetector = inject(ChangeDetectorRef);\n\n readonly uploading = signal(false);\n\n /** Effective disabled state: mode, schema flag or calculated field. */\n controlDisabled(): boolean {\n return (\n this.mode() !== 'edit' ||\n this.field().disabled === true ||\n this.field().calculate !== undefined\n );\n }\n\n interactive(): boolean {\n return this.mode() === 'edit';\n }\n\n pending(): boolean {\n this.tick();\n return this.engine().isPending(this.path());\n }\n\n /** Custom component registered for this field type, if any. */\n customComponent(): Type<unknown> | null {\n const node = this.node();\n if (node.kind !== 'input' || !this.componentMaps) return null;\n for (let i = this.componentMaps.length - 1; i >= 0; i--) {\n const match = this.componentMaps[i]?.[node.type];\n if (match) return match;\n }\n return null;\n }\n\n /**\n * Inputs handed to a custom component (MformFieldComponent contract).\n * Only inputs the component actually declares are passed, so optional\n * contract members (`mode`) never break third-party components.\n */\n customInputs(): Record<string, unknown> {\n const component = this.customComponent();\n const declared = new Set(\n component ? (reflectComponentType(component)?.inputs ?? []).map((i) => i.propName) : [],\n );\n const all: Record<string, unknown> = {\n field: this.field(),\n engine: this.engine(),\n path: this.path(),\n tick: this.tick(),\n mode: this.mode(),\n };\n return Object.fromEntries(Object.entries(all).filter(([key]) => declared.has(key)));\n }\n\n /** Options resolved from a dynamic source (provider or remote URL). */\n private readonly resolvedOptions = signal<FieldOption[] | null>(null);\n /** Snapshot of the observed refresh source at the last resolution. */\n private lastRefreshKey: string | null = null;\n /** Discards resolutions that arrive after a newer request started. */\n private optionsRequestSeq = 0;\n\n constructor() {\n effect(() => {\n const node = this.node();\n const registry = this.providers();\n if (node.kind !== 'input' || !node.optionsSource) {\n this.resolvedOptions.set(null);\n return;\n }\n const source = node.optionsSource;\n // With refreshOn, engine events re-run this effect; the refresh key\n // then decides whether the observed data actually changed.\n if (source.refreshOn) this.tick();\n const engine = untracked(() => this.engine());\n const path = untracked(() => this.path());\n const refreshKey = !source.refreshOn\n ? 'static'\n : source.refreshOn === 'data'\n ? JSON.stringify(engine.getData())\n : JSON.stringify(engine.getValue(source.refreshOn) ?? null);\n if (refreshKey === this.lastRefreshKey) return;\n this.lastRefreshKey = refreshKey;\n // Stale-response guard: only the latest request may write options.\n const requestId = ++this.optionsRequestSeq;\n const apply = (options: FieldOption[]) => {\n if (requestId === this.optionsRequestSeq) this.resolvedOptions.set(options);\n };\n if (source.type === 'provider') {\n const provider = registry[source.name];\n if (!provider) return; // no provider: static options/fallback stand\n Promise.resolve(\n provider({ field: node, path, data: engine.getData(), args: source.args }),\n )\n .then((options) => { apply(options); this.changeDetector.markForCheck();\n this.notify()(); })\n .catch(() => {}); // provider failure keeps the static fallback\n } else {\n // The host's transport (auth, base URL, caching) when registered via\n // provideMosaicooForm; plain fetch as the zero-config default.\n const request = this.remoteFetcher\n ? this.remoteFetcher(source.url)\n : fetch(source.url).then((response) => (response.ok ? response.json() : []));\n request\n .then((list) =>\n apply(\n (Array.isArray(list) ? (list as Array<Record<string, unknown>>) : []).map((item) => ({\n label: String(item[source.labelKey ?? 'label'] ?? item[source.valueKey ?? 'value'] ?? ''),\n value: (item[source.valueKey ?? 'value'] ?? '') as FieldOption['value'],\n })),\n ),\n )\n .then(() => this.changeDetector.markForCheck())\n .catch(() => {});\n }\n });\n }\n\n /** Effective options: dynamically resolved first, static as fallback. */\n options(): FieldOption[] {\n return this.resolvedOptions() ?? this.field().options ?? [];\n }\n\n // -- typed views of the node ---------------------------------------------\n\n field(): InputField {\n return this.node() as InputField;\n }\n\n container(): ContainerField {\n return this.node() as ContainerField;\n }\n\n content(): string {\n return (this.node() as StaticField).content ?? '';\n }\n\n buttonAction(): string {\n return String(this.node().props?.['action'] ?? 'submit');\n }\n\n sourceType(): string {\n return String(this.node().props?.['sourceType'] ?? '');\n }\n\n rowsProp(): number | null {\n const rows = this.node().props?.['rows'];\n return typeof rows === 'number' ? rows : null;\n }\n\n // -- paths and visibility -------------------------------------------------\n\n /** Data path of this node (inputs) or of its scope (containers). */\n readonly path = computed(() => {\n const scope = this.scope();\n const node = this.node();\n if (node.kind === 'input') return scope ? `${scope}.${node.key}` : node.key;\n if (node.kind === 'container' && node.dataScope !== 'inherit') {\n return scope ? `${scope}.${node.key}` : node.key;\n }\n return scope;\n });\n\n /** Scope handed to children (nested/array containers extend it). */\n readonly childScope = computed(() => {\n const node = this.node();\n if (node.kind === 'container' && node.dataScope === 'nested') return this.path();\n return this.scope();\n });\n\n rowScope(index: number): string {\n return `${this.path()}.${index}`;\n }\n\n visible(): boolean {\n this.tick();\n const node = this.node();\n const key = node.kind === 'input' ? this.path() : node.key;\n return this.engine().isVisible(key);\n }\n\n containerLayout(): 'columns' | 'tabs' | 'array' | 'block' {\n const node = this.container();\n if (node.dataScope === 'array') return 'array';\n if (node.type === 'tabs') return 'tabs';\n if (node.type === 'columns' && node.columns?.length) return 'columns';\n return 'block';\n }\n\n columns(): FieldNode[][] {\n const node = this.container();\n return (node.columns ?? []).map((column) =>\n column.children\n .map((index) => node.children[index])\n .filter((child): child is FieldNode => child !== undefined),\n );\n }\n\n columnsTemplate(): string {\n const cols = this.container().columns ?? [];\n const total = cols.reduce((sum, c) => sum + c.width, 0) || 12;\n return cols.map((c) => `${((c.width / total) * 100).toFixed(3)}fr`).join(' ');\n }\n\n // -- values ---------------------------------------------------------------\n\n value(): unknown {\n this.tick();\n return this.engine().getValue(this.path());\n }\n\n stringValue(): string {\n const value = this.value();\n if (value === undefined || value === null) return '';\n const mask = this.field().format?.mask;\n if (mask && typeof value === 'string') return maskValue(value, mask).masked;\n return String(value);\n }\n\n mapValue(): Record<string, unknown> {\n const value = this.value();\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n }\n\n rows(): unknown[] {\n const value = this.value();\n return Array.isArray(value) ? value : [];\n }\n\n required(): boolean {\n return this.field().validators?.some((v) => v.type === 'required') ?? false;\n }\n\n errors() {\n this.tick();\n return this.engine().getFieldErrors(this.path());\n }\n\n controlId(): string {\n return `mform-${this.path().replace(/\\./g, '-')}`;\n }\n\n describedBy(): string | null {\n const parts: string[] = [];\n if (this.field().description) parts.push(`${this.controlId()}-desc`);\n if (this.errors().length > 0) parts.push(`${this.controlId()}-err`);\n return parts.length ? parts.join(' ') : null;\n }\n\n inputType(): string {\n switch (this.field().type) {\n case 'number':\n case 'currency':\n return 'number';\n case 'email':\n return 'email';\n case 'password':\n return 'password';\n case 'phone':\n return 'tel';\n case 'url':\n return 'url';\n case 'time':\n return 'time';\n case 'datetime':\n return 'datetime-local';\n case 'day':\n return 'date';\n default:\n return 'text';\n }\n }\n\n // -- interaction ----------------------------------------------------------\n\n setValue(value: unknown): void {\n this.engine().setValue(this.path(), value);\n }\n\n setString(event: Event): void {\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\n const raw = target.value;\n const mask = this.field().format?.mask;\n if (mask) {\n const { masked, raw: stripped } = maskValue(raw, mask);\n target.value = masked; // the control always shows the masked shape\n this.setValue(this.field().format?.keepMask ? masked : stripped);\n return;\n }\n if (this.field().dataType === 'number') {\n const parsed = raw === '' ? undefined : Number(raw);\n this.setValue(parsed !== undefined && Number.isFinite(parsed) ? parsed : undefined);\n } else {\n this.setValue(raw);\n }\n }\n\n setSelect(event: Event): void {\n this.setValue((event.target as HTMLSelectElement).value);\n }\n\n setChecked(event: Event): void {\n this.setValue((event.target as HTMLInputElement).checked);\n }\n\n toggleMap(option: string, event: Event): void {\n const checked = (event.target as HTMLInputElement).checked;\n this.setValue({ ...this.mapValue(), [option]: checked });\n }\n\n setFiles(event: Event): void {\n const files = (event.target as HTMLInputElement).files;\n const list = files ? Array.from(files) : [];\n if (!this.uploader || list.length === 0) {\n // no host uploader: only file names are stored\n this.setValue(list.map((f) => f.name));\n return;\n }\n const field = this.field();\n const path = this.path();\n this.uploading.set(true);\n Promise.all(list.map((file) => this.uploader!(file, { field, path })))\n .then((refs) => this.setValue(refs))\n .catch(() => {}) // host upload failure keeps the previous value\n .finally(() => { this.uploading.set(false); this.changeDetector.markForCheck();\n this.notify()(); });\n }\n\n /** Names shown under a `file` control (refs or plain names). */\n fileNames(): string[] {\n const value = this.value();\n if (!Array.isArray(value)) return [];\n return value.map((item) =>\n typeof item === 'object' && item !== null\n ? String((item as { name?: unknown }).name ?? '')\n : String(item),\n );\n }\n\n prefix(): string | null {\n const value = this.node().props?.['prefix'];\n return typeof value === 'string' && value ? value : null;\n }\n\n suffix(): string | null {\n const value = this.node().props?.['suffix'];\n return typeof value === 'string' && value ? value : null;\n }\n\n tagValues(): string[] {\n const value = this.value();\n return Array.isArray(value) ? value.map(String) : [];\n }\n\n addTag(event: Event): void {\n event.preventDefault();\n const input = event.target as HTMLInputElement;\n const tag = input.value.trim();\n if (!tag) return;\n this.setValue([...this.tagValues(), tag]);\n input.value = '';\n }\n\n removeTag(index: number): void {\n const next = [...this.tagValues()];\n next.splice(index, 1);\n this.setValue(next);\n }\n\n touch(): void {\n this.engine().markTouched(this.path());\n // Async-aware: resolves immediately for sync-only fields; pending events\n // drive the busy indicator otherwise.\n void this.engine().validateFieldAsync(this.path());\n }\n\n // -- reference (autocomplete) ---------------------------------------------\n\n readonly refOptions = signal<FieldOption[]>([]);\n readonly refOpen = signal(false);\n private refTimer: ReturnType<typeof setTimeout> | null = null;\n /** Label of the chosen option (falls back to the raw value). */\n readonly refLabel = signal<string | null>(null);\n\n refDisplay(): string {\n return this.refLabel() ?? this.stringValue();\n }\n\n refSearch(event: Event): void {\n const query = (event.target as HTMLInputElement).value;\n this.refLabel.set(null);\n if (this.refTimer) clearTimeout(this.refTimer);\n this.refTimer = setTimeout(() => this.refResolve(query), 250);\n }\n\n private refResolve(query: string): void {\n const source = this.field().optionsSource;\n if (!source || source.type !== 'provider') {\n // static options filter locally\n const filter = query.toLowerCase();\n this.refOptions.set(\n (this.field().options ?? []).filter((o) => o.label.toLowerCase().includes(filter)),\n );\n this.refOpen.set(true);\n this.changeDetector.markForCheck();\n this.notify()();\n return;\n }\n const provider = this.providers()[source.name];\n if (!provider) return;\n Promise.resolve(\n provider({\n field: this.field(),\n path: this.path(),\n data: this.engine().getData(),\n args: source.args,\n query,\n }),\n )\n .then((options) => {\n this.refOptions.set(options);\n this.refOpen.set(true);\n this.changeDetector.markForCheck();\n this.notify()();\n })\n .catch(() => {});\n }\n\n refPick(option: FieldOption): void {\n this.setValue(option.value);\n this.refLabel.set(option.label);\n this.refOpen.set(false);\n this.touch();\n }\n\n refBlur(): void {\n // let a click on an option land before closing\n setTimeout(() => { this.refOpen.set(false); this.changeDetector.markForCheck();\n this.notify()(); }, 150);\n this.touch();\n }\n\n addRow(): void {\n this.engine().addRow(this.path());\n }\n\n removeRow(index: number): void {\n this.engine().removeRow(this.path(), index);\n }\n}\n","import { DOCUMENT } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport {\n collectInputs,\n createFormEngine,\n createLegacyImporter,\n importForm,\n type ContainerField,\n type FieldError,\n type FormEngine,\n type FormSchema,\n type ImportWarning,\n type MessageResolver,\n type OptionsProviderRegistry,\n type SubmitResult,\n type ValidatorRegistry,\n} from '@mosaicoo/form-core';\nimport { FormNodeComponent, type FormMode } from './form-node.component.js';\n\n/**\n * `<mform-renderer>` — renders a form at runtime from a `FormSchema` (or any\n * definition a registered importer understands) and manages its lifecycle:\n * values, validation, conditional visibility and submission. Wizard schemas\n * (`settings.display: 'wizard'`) render as steps with per-step validation.\n *\n * Theming: every visual primitive reads a `--mform-*` CSS custom property\n * with a self-contained fallback, so the component looks finished on its own\n * and adopts the host design system when the host overrides the tokens.\n */\n@Component({\n selector: 'mform-renderer',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [FormNodeComponent],\n styleUrls: ['./form-theme.css'],\n template: `\n @if (engine(); as engine) {\n <form class=\"mform-root\" novalidate (submit)=\"onSubmit($event)\">\n @if (errorSummary().length > 0) {\n <div class=\"mform-summary\" role=\"alert\" tabindex=\"-1\">\n <strong>{{ summaryTitle() }}</strong>\n <ul>\n @for (error of errorSummary(); track error.path + error.rule) {\n <li>{{ error.message }}</li>\n }\n </ul>\n </div>\n }\n @if (isWizard()) {\n <ol class=\"mform-steps\">\n @for (step of steps(); track step.key; let i = $index) {\n <li\n class=\"mform-step\"\n [class.is-active]=\"currentStep() === i\"\n [class.is-done]=\"i < currentStep()\"\n [attr.aria-current]=\"currentStep() === i ? 'step' : null\"\n >\n <span class=\"mform-step-index\">{{ i + 1 }}</span>\n <span class=\"mform-step-label\">{{ step.label || 'Step ' + (i + 1) }}</span>\n </li>\n }\n </ol>\n @if (steps()[currentStep()]; as step) {\n <mform-node\n [node]=\"step\"\n [engine]=\"engine\"\n [tick]=\"tick()\"\n [providers]=\"optionsProviders()\"\n [mode]=\"mode()\" [notify]=\"bumpTick\"\n [bare]=\"true\"\n />\n }\n <div class=\"mform-wizard-nav\">\n @if (currentStep() > 0) {\n <button type=\"button\" class=\"mform-btn mform-btn-secondary\" (click)=\"previousStep()\">\n {{ labels().previous }}\n </button>\n }\n @if (currentStep() < steps().length - 1) {\n <button type=\"button\" class=\"mform-btn\" (click)=\"nextStep()\">\n {{ labels().next }}\n </button>\n } @else if (mode() === 'edit') {\n <button type=\"submit\" class=\"mform-btn\" [disabled]=\"submitting()\">\n {{ submitting() ? '…' : labels().submit }}\n </button>\n }\n </div>\n } @else {\n @for (node of engine.schema.fields; track node.key) {\n <mform-node [node]=\"node\" [engine]=\"engine\" [tick]=\"tick()\" [providers]=\"optionsProviders()\" [mode]=\"mode()\" [notify]=\"bumpTick\" />\n }\n }\n @if (submitError(); as error) {\n <div class=\"mform-summary\" role=\"alert\">{{ error }}</div>\n }\n </form>\n }\n `,\n})\nexport class FormRendererComponent {\n /** Native schema input. Takes precedence over `source`. */\n readonly schema = input<FormSchema | null>(null);\n /** Foreign definition (object or JSON string) resolved via importers. */\n readonly source = input<unknown>(null);\n /** Initial data merged over schema defaults. */\n readonly initialData = input<Record<string, unknown> | null>(null);\n /** Named providers resolving `optionsSource: provider` fields. */\n readonly optionsProviders = input<OptionsProviderRegistry>({});\n /** Host-supplied message resolver (localization of validation messages). */\n readonly messages = input<MessageResolver | null>(null);\n /** Named custom validators (sync or async — Promises get pending states). */\n readonly validators = input<ValidatorRegistry | null>(null);\n /** `edit` (default), `readonly` (no actions) or `disabled`. */\n readonly mode = input<FormMode>('edit');\n /**\n * Optional host submission: called after a VALID submit with the result;\n * rejections surface as the submission error state. Persistence transport\n * stays entirely on the host side.\n */\n readonly submitHandler = input<((result: SubmitResult) => Promise<void>) | null>(null);\n\n /** True while async validation or the submit handler is running. */\n readonly submitting = signal(false);\n /** Message when the host submission rejected. */\n readonly submitError = signal<string | null>(null);\n /** Fixed renderer texts (override to localize). `{{count}}` in `summary`. */\n readonly labels = input(\n {\n previous: 'Previous',\n next: 'Next',\n submit: 'Submit',\n summary: '{{count}} field(s) need attention:',\n },\n {\n transform: (value: Partial<{ previous: string; next: string; submit: string; summary: string }>) => ({\n previous: 'Previous',\n next: 'Next',\n submit: 'Submit',\n summary: '{{count}} field(s) need attention:',\n ...value,\n }),\n },\n );\n\n summaryTitle(): string {\n return this.labels().summary.replace(/\\{\\{\\s*count\\s*\\}\\}/g, String(this.errorSummary().length));\n }\n\n /** Fired on submit; `ok` is false when validation failed. */\n readonly submitted = output<SubmitResult>();\n /** Fired on every value change with the full data snapshot. */\n readonly valueChanged = output<Record<string, unknown>>();\n\n /** Bumped on every engine event; nodes read it to refresh. */\n readonly tick = signal(0);\n\n /** Handed to nodes so async completions re-render (zoneless-safe). */\n readonly bumpTick = (): void => this.tick.update((v) => v + 1);\n /** Active wizard step index. */\n readonly currentStep = signal(0);\n\n private readonly resolved = computed<{\n schema: FormSchema | null;\n warnings: ImportWarning[];\n }>(() => {\n const native = this.schema();\n if (native) return { schema: native, warnings: [] };\n const source = this.source();\n if (source === null || source === undefined) return { schema: null, warnings: [] };\n try {\n const result = importForm(source, [createLegacyImporter()]);\n return { schema: result.schema, warnings: result.warnings };\n } catch {\n return {\n schema: null,\n warnings: [\n { code: 'unreadable-source', message: 'The form definition could not be read.' },\n ],\n };\n }\n });\n\n /** Import degradations for the current `source`, if any. */\n readonly importWarnings = computed(() => this.resolved().warnings);\n\n readonly engine = computed<FormEngine | null>(() => {\n const schema = this.resolved().schema;\n return schema\n ? createFormEngine(schema, {\n initialData: this.initialData() ?? undefined,\n messages: this.messages() ?? undefined,\n validators: this.validators() ?? undefined,\n })\n : null;\n });\n\n readonly isWizard = computed(\n () => this.resolved().schema?.settings?.display === 'wizard' && this.steps().length > 0,\n );\n\n /** Wizard pages: the top-level containers of the schema. */\n readonly steps = computed<ContainerField[]>(() =>\n (this.resolved().schema?.fields ?? []).filter(\n (node): node is ContainerField => node.kind === 'container',\n ),\n );\n\n readonly errorSummary = signal<FieldError[]>([]);\n\n constructor() {\n effect((onCleanup) => {\n const engine = this.engine();\n this.errorSummary.set([]);\n this.tick.set(0);\n this.currentStep.set(0);\n if (!engine) return;\n const unsubscribe = engine.subscribe((event) => {\n this.tick.update((v) => v + 1);\n if (event.type === 'value-change') {\n this.valueChanged.emit(engine.getData());\n }\n if (event.type === 'validation') {\n // Keep the banner in sync as the user fixes fields after a submit.\n if (this.errorSummary().length > 0) {\n this.errorSummary.set(event.errors);\n }\n }\n });\n onCleanup(unsubscribe);\n });\n }\n\n // -- wizard navigation ----------------------------------------------------\n\n previousStep(): void {\n this.errorSummary.set([]);\n this.currentStep.update((step) => Math.max(0, step - 1));\n }\n\n nextStep(): void {\n const engine = this.engine();\n const step = this.steps()[this.currentStep()];\n if (!engine || !step) return;\n const errors = engine.validateContainer(step.key);\n if (errors.length > 0) {\n this.errorSummary.set(errors);\n this.focusFirstError(errors);\n return;\n }\n this.errorSummary.set([]);\n this.currentStep.update((index) => Math.min(this.steps().length - 1, index + 1));\n }\n\n // -- submission -----------------------------------------------------------\n\n async onSubmit(event: Event): Promise<void> {\n event.preventDefault();\n const engine = this.engine();\n if (!engine || this.submitting() || this.mode() !== 'edit') return;\n this.submitting.set(true);\n this.submitError.set(null);\n try {\n const result = await engine.submitAsync();\n this.errorSummary.set(result.errors);\n if (!result.ok) {\n if (this.isWizard()) {\n const stepIndex = this.stepIndexForPath(result.errors[0]?.path ?? '');\n if (stepIndex >= 0) this.currentStep.set(stepIndex);\n }\n this.focusFirstError(result.errors);\n } else if (this.submitHandler()) {\n try {\n await this.submitHandler()!(result);\n } catch (error) {\n this.submitError.set(String(error instanceof Error ? error.message : error));\n }\n }\n this.submitted.emit(result);\n } finally {\n this.submitting.set(false);\n }\n }\n\n /** Finds the wizard step that owns a (possibly row-indexed) data path. */\n private stepIndexForPath(path: string): number {\n const pattern = path\n .split('.')\n .map((part) => (/^\\d+$/.test(part) ? '*' : part))\n .join('.');\n return this.steps().findIndex((step) =>\n collectInputs({ version: 1, fields: step.children }).some(\n (entry) => entry.path === pattern,\n ),\n );\n }\n\n private readonly documentRef = inject(DOCUMENT);\n\n private focusFirstError(errors: FieldError[]): void {\n const first = errors[0];\n if (!first) return;\n const id = `mform-${first.path.replace(/\\./g, '-')}`;\n // Focus after the view updated with the error states.\n queueMicrotask(() => this.documentRef.getElementById(id)?.focus());\n }\n}\n","/*\n * Runtime entry point of @mosaicoo/form-angular.\n *\n * Architectural note: this primary entry stays runtime-only. Authoring\n * tooling (the visual designer) will ship as a SECONDARY entry point\n * (`@mosaicoo/form-angular/designer`) so applications that only render\n * forms never load authoring code — a requirement for federated hosts.\n */\nexport { FormRendererComponent } from './lib/form-renderer.component.js';\nexport { FormNodeComponent, type FormMode } from './lib/form-node.component.js';\nexport {\n MFORM_FIELD_COMPONENTS,\n MFORM_REMOTE_FETCHER,\n MFORM_UPLOAD,\n provideMosaicooForm,\n type FieldComponentMap,\n type FileUploadFn,\n type MformFieldComponent,\n type MosaicooFormConfig,\n type UploadedFileRef,\n} from './lib/providers.js';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mosaicoo/form-angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Angular renderer for Mosaicoo Form: accessible, token-themable dynamic forms with wizard mode and host-provided dynamic options",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Mosaicoo",
|
|
@@ -26,10 +26,20 @@
|
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@angular/common": "^21.0.0",
|
|
29
|
-
"@angular/core": "^21.0.0"
|
|
29
|
+
"@angular/core": "^21.0.0",
|
|
30
|
+
"@angular/forms": "^21.0.0",
|
|
31
|
+
"@angular/material": "^21.0.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"@angular/forms": {
|
|
35
|
+
"optional": true
|
|
36
|
+
},
|
|
37
|
+
"@angular/material": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
30
40
|
},
|
|
31
41
|
"dependencies": {
|
|
32
|
-
"@mosaicoo/form-core": "^0.
|
|
42
|
+
"@mosaicoo/form-core": "^0.5.0",
|
|
33
43
|
"tslib": "^2.3.0"
|
|
34
44
|
},
|
|
35
45
|
"sideEffects": false,
|
|
@@ -46,6 +56,10 @@
|
|
|
46
56
|
"./designer": {
|
|
47
57
|
"types": "./types/mosaicoo-form-angular-designer.d.ts",
|
|
48
58
|
"default": "./fesm2022/mosaicoo-form-angular-designer.mjs"
|
|
59
|
+
},
|
|
60
|
+
"./material": {
|
|
61
|
+
"types": "./types/mosaicoo-form-angular-material.d.ts",
|
|
62
|
+
"default": "./fesm2022/mosaicoo-form-angular-material.mjs"
|
|
49
63
|
}
|
|
50
64
|
},
|
|
51
65
|
"type": "module"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { EnvironmentProviders } from '@angular/core';
|
|
3
|
+
import { FieldComponentMap } from '@mosaicoo/form-angular';
|
|
4
|
+
import * as _mosaicoo_form_core from '@mosaicoo/form-core';
|
|
5
|
+
import { InputField, FormEngine, FieldOption } from '@mosaicoo/form-core';
|
|
6
|
+
import { ErrorStateMatcher } from '@angular/material/core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Material Design 3 field components.
|
|
10
|
+
*
|
|
11
|
+
* Every component implements the renderer's `MformFieldComponent` contract
|
|
12
|
+
* (signal inputs `field`/`engine`/`path`/`tick`/`mode`) and talks to the form
|
|
13
|
+
* exclusively through the engine — validation, conditionals, calculations and
|
|
14
|
+
* events keep working unchanged. The HOST's Material theme (M3 tokens) styles
|
|
15
|
+
* everything; this entry adds no theming of its own.
|
|
16
|
+
*/
|
|
17
|
+
declare abstract class MaterialFieldBase {
|
|
18
|
+
readonly field: i0.InputSignal<InputField>;
|
|
19
|
+
readonly engine: i0.InputSignal<FormEngine>;
|
|
20
|
+
readonly path: i0.InputSignal<string>;
|
|
21
|
+
readonly tick: i0.InputSignal<number>;
|
|
22
|
+
readonly mode: i0.InputSignal<"edit" | "readonly" | "disabled">;
|
|
23
|
+
/** Error state driven by the ENGINE, not by template validators. */
|
|
24
|
+
readonly errorMatcher: ErrorStateMatcher;
|
|
25
|
+
value(): unknown;
|
|
26
|
+
errors(): _mosaicoo_form_core.FieldError[];
|
|
27
|
+
firstError(): string | null;
|
|
28
|
+
required(): boolean;
|
|
29
|
+
disabled(): boolean;
|
|
30
|
+
label(): string;
|
|
31
|
+
setValue(value: unknown): void;
|
|
32
|
+
touch(): void;
|
|
33
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MaterialFieldBase, never>;
|
|
34
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<MaterialFieldBase, never, never, { "field": { "alias": "field"; "required": true; "isSignal": true; }; "engine": { "alias": "engine"; "required": true; "isSignal": true; }; "path": { "alias": "path"; "required": true; "isSignal": true; }; "tick": { "alias": "tick"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
35
|
+
}
|
|
36
|
+
declare class MatTextFieldComponent extends MaterialFieldBase {
|
|
37
|
+
isTextarea(): boolean;
|
|
38
|
+
stringValue(): string;
|
|
39
|
+
inputType(): string;
|
|
40
|
+
prefixText(): string | null;
|
|
41
|
+
suffixText(): string | null;
|
|
42
|
+
write(raw: string): void;
|
|
43
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MatTextFieldComponent, never>;
|
|
44
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MatTextFieldComponent, "mform-mat-text", never, {}, {}, never, never, true, never>;
|
|
45
|
+
}
|
|
46
|
+
declare class MatSelectFieldComponent extends MaterialFieldBase {
|
|
47
|
+
readonly options: i0.Signal<FieldOption[]>;
|
|
48
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MatSelectFieldComponent, never>;
|
|
49
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MatSelectFieldComponent, "mform-mat-select", never, {}, {}, never, never, true, never>;
|
|
50
|
+
}
|
|
51
|
+
declare class MatCheckboxFieldComponent extends MaterialFieldBase {
|
|
52
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MatCheckboxFieldComponent, never>;
|
|
53
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MatCheckboxFieldComponent, "mform-mat-checkbox", never, {}, {}, never, never, true, never>;
|
|
54
|
+
}
|
|
55
|
+
declare class MatRadioFieldComponent extends MaterialFieldBase {
|
|
56
|
+
readonly options: i0.Signal<FieldOption[]>;
|
|
57
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MatRadioFieldComponent, never>;
|
|
58
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MatRadioFieldComponent, "mform-mat-radio", never, {}, {}, never, never, true, never>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Field types rendered with Material components (others stay built-in). */
|
|
62
|
+
declare const MATERIAL_FIELD_COMPONENTS: FieldComponentMap;
|
|
63
|
+
/**
|
|
64
|
+
* Registers the Material field set:
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* bootstrapApplication(App, {
|
|
68
|
+
* providers: [provideMaterialForms()],
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* Composable: later `provideMosaicooForm({components})` calls can override
|
|
73
|
+
* individual types (host-specific fields win).
|
|
74
|
+
*/
|
|
75
|
+
declare function provideMaterialForms(): EnvironmentProviders;
|
|
76
|
+
|
|
77
|
+
export { MATERIAL_FIELD_COMPONENTS, MatCheckboxFieldComponent, MatRadioFieldComponent, MatSelectFieldComponent, MatTextFieldComponent, provideMaterialForms };
|
|
@@ -45,7 +45,11 @@ declare class FormNodeComponent {
|
|
|
45
45
|
pending(): boolean;
|
|
46
46
|
/** Custom component registered for this field type, if any. */
|
|
47
47
|
customComponent(): Type<unknown> | null;
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* Inputs handed to a custom component (MformFieldComponent contract).
|
|
50
|
+
* Only inputs the component actually declares are passed, so optional
|
|
51
|
+
* contract members (`mode`) never break third-party components.
|
|
52
|
+
*/
|
|
49
53
|
customInputs(): Record<string, unknown>;
|
|
50
54
|
/** Options resolved from a dynamic source (provider or remote URL). */
|
|
51
55
|
private readonly resolvedOptions;
|
|
@@ -211,6 +215,8 @@ interface MformFieldComponent {
|
|
|
211
215
|
path: () => string;
|
|
212
216
|
/** Bumped on every engine event; read it to stay in sync. */
|
|
213
217
|
tick: () => number;
|
|
218
|
+
/** Rendering mode of the surrounding form (optional input). */
|
|
219
|
+
mode?: () => 'edit' | 'readonly' | 'disabled';
|
|
214
220
|
}
|
|
215
221
|
/** Map of field `type` → component implementing {@link MformFieldComponent}. */
|
|
216
222
|
type FieldComponentMap = Record<string, Type<unknown>>;
|