@ng-forge/dynamic-forms 0.5.1 → 0.6.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 +10 -9
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs +416 -23
- package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
- package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-BWFdMPyw.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-Bf6Qnz0T.mjs} +12247 -7827
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-Bf6Qnz0T.mjs.map +1 -0
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-_mRHaw7x.mjs +109 -0
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-_mRHaw7x.mjs.map +1 -0
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-DIVyioMX.mjs → ng-forge-dynamic-forms-text-field.component-CmkBZk4p.mjs} +5 -5
- package/fesm2022/{ng-forge-dynamic-forms-text-field.component-DIVyioMX.mjs.map → ng-forge-dynamic-forms-text-field.component-CmkBZk4p.mjs.map} +1 -1
- package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
- package/package.json +1 -1
- package/types/ng-forge-dynamic-forms-integration.d.ts +234 -17
- package/types/ng-forge-dynamic-forms.d.ts +2296 -698
- package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-BWFdMPyw.mjs.map +0 -1
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-RN1hmG69.mjs +0 -120
- package/fesm2022/ng-forge-dynamic-forms-page-field.component-RN1hmG69.mjs.map +0 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, DestroyRef, Injector, input, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { NgComponentOutlet } from '@angular/common';
|
|
4
|
+
import { outputFromObservable } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { explicitEffect } from 'ngxtension/explicit-effect';
|
|
6
|
+
import { i as injectFieldRegistry, E as EventBus, D as DynamicFormLogger, c as computeContainerHostClasses, v as validatePageNesting, d as derivedFromDeferred, a as createFieldResolutionPipe, s as setupContainerInitEffect } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-Bf6Qnz0T.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Renders a single page in multi-page (wizard) forms.
|
|
10
|
+
*
|
|
11
|
+
* Visibility is controlled by the PageOrchestrator via the isVisible input.
|
|
12
|
+
* Pages cannot be nested within other pages - validation prevents this.
|
|
13
|
+
* Field values are flattened into the parent form (no nesting under page key).
|
|
14
|
+
*/
|
|
15
|
+
class PageFieldComponent {
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
// Dependencies
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
destroyRef = inject(DestroyRef);
|
|
20
|
+
fieldRegistry = injectFieldRegistry();
|
|
21
|
+
injector = inject(Injector);
|
|
22
|
+
eventBus = inject(EventBus);
|
|
23
|
+
logger = inject(DynamicFormLogger);
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
// Inputs
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
|
|
28
|
+
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
|
|
29
|
+
className = input(...(ngDevMode ? [undefined, { debugName: "className" }] : []));
|
|
30
|
+
pageIndex = input.required(...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
|
|
31
|
+
isVisible = input.required(...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
32
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
33
|
+
// Computed Signals
|
|
34
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
35
|
+
hostClasses = computed(() => computeContainerHostClasses('page-field', this.className()), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
36
|
+
disabled = computed(() => this.field().disabled || false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
37
|
+
isValid = computed(() => validatePageNesting(this.field()), ...(ngDevMode ? [{ debugName: "isValid" }] : []));
|
|
38
|
+
rawFieldRegistry = computed(() => this.fieldRegistry.raw, ...(ngDevMode ? [{ debugName: "rawFieldRegistry" }] : []));
|
|
39
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
40
|
+
// Outputs
|
|
41
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
42
|
+
nextPage = outputFromObservable(this.eventBus.on('next-page'));
|
|
43
|
+
previousPage = outputFromObservable(this.eventBus.on('previous-page'));
|
|
44
|
+
pageChange = outputFromObservable(this.eventBus.on('page-change'));
|
|
45
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
46
|
+
// Field Resolution
|
|
47
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
48
|
+
fieldsSource = computed(() => {
|
|
49
|
+
if (!this.isValid()) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
return this.field().fields || [];
|
|
53
|
+
}, ...(ngDevMode ? [{ debugName: "fieldsSource" }] : []));
|
|
54
|
+
resolvedFields = derivedFromDeferred(this.fieldsSource, createFieldResolutionPipe(() => ({
|
|
55
|
+
loadTypeComponent: (type) => this.fieldRegistry.loadTypeComponent(type),
|
|
56
|
+
registry: this.rawFieldRegistry(),
|
|
57
|
+
injector: this.injector,
|
|
58
|
+
destroyRef: this.destroyRef,
|
|
59
|
+
onError: (fieldDef, error) => {
|
|
60
|
+
const fieldKey = fieldDef.key || '<no key>';
|
|
61
|
+
this.logger.error(`Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +
|
|
62
|
+
`within page '${this.field().key}'. Ensure the field type is registered in your field registry.`, error);
|
|
63
|
+
},
|
|
64
|
+
})), { initialValue: [], injector: this.injector });
|
|
65
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
66
|
+
// Constructor
|
|
67
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
68
|
+
constructor() {
|
|
69
|
+
this.setupEffects();
|
|
70
|
+
}
|
|
71
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
// Private Methods
|
|
73
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
74
|
+
setupEffects() {
|
|
75
|
+
setupContainerInitEffect(this.resolvedFields, this.eventBus, 'page', () => this.field().key, this.injector);
|
|
76
|
+
explicitEffect([this.isValid, this.field], ([valid, pageField]) => {
|
|
77
|
+
if (!valid) {
|
|
78
|
+
this.logger.error(`Invalid configuration: Page '${pageField.key}' contains nested page fields. ` +
|
|
79
|
+
`Pages cannot contain other pages. Consider using groups or rows for nested structure.`, pageField);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PageFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
84
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: PageFieldComponent, isStandalone: true, selector: "section[page-field]", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, pageIndex: { classPropertyName: "pageIndex", publicName: "pageIndex", isSignal: true, isRequired: true, transformFunction: null }, isVisible: { classPropertyName: "isVisible", publicName: "isVisible", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { nextPage: "nextPage", previousPage: "previousPage", pageChange: "pageChange" }, host: { properties: { "class": "hostClasses()", "class.disabled": "disabled()", "class.df-page-visible": "isVisible()", "class.df-page-hidden": "!isVisible()", "attr.aria-hidden": "!isVisible()", "attr.data-page-index": "pageIndex()", "id": "`${key()}`", "attr.data-testid": "key()" } }, ngImport: i0, template: `
|
|
85
|
+
@for (field of resolvedFields(); track field.key) {
|
|
86
|
+
<ng-container *ngComponentOutlet="field.component; injector: field.injector; inputs: field.inputs()" />
|
|
87
|
+
}
|
|
88
|
+
`, isInline: true, styles: [":host,.df-form{--df-grid-columns: 12;--df-grid-gap: .5rem;--df-grid-row-gap: .5rem;--df-breakpoint-sm: 576px;--df-breakpoint-md: 768px;--df-breakpoint-lg: 992px;--df-breakpoint-xl: 1200px;--df-grid-gap-sm: .5rem;--df-grid-gap-md: .5rem;--df-grid-gap-lg: .5rem;--df-grid-gap-xl: .5rem;--df-grid-row-gap-sm: .5rem;--df-grid-row-gap-md: .5rem;--df-grid-row-gap-lg: .5rem;--df-grid-row-gap-xl: .5rem;--df-array-item-gap: var(--df-grid-row-gap);--df-group-gap: var(--df-grid-gap);--df-group-padding: var(--df-grid-gap)}.df-form{display:grid;grid-template-columns:1fr;gap:var(--df-grid-row-gap);width:100%}.df-form>*{grid-column:1/-1}.df-row{display:grid;grid-template-columns:repeat(var(--df-grid-columns, 12),1fr);gap:var(--df-grid-gap);align-items:start;width:100%}.df-row>*:not([class*=df-col-]){grid-column:1/-1}.df-col-1{grid-column:span 1}.df-col-2{grid-column:span 2}.df-col-3{grid-column:span 3}.df-col-4{grid-column:span 4}.df-col-5{grid-column:span 5}.df-col-6{grid-column:span 6}.df-col-7{grid-column:span 7}.df-col-8{grid-column:span 8}.df-col-9{grid-column:span 9}.df-col-10{grid-column:span 10}.df-col-11{grid-column:span 11}.df-col-12{grid-column:span 12}.df-col-auto{grid-column:span auto;width:auto}.df-col-full{grid-column:1/-1}.df-col-start-1{grid-column-start:1}.df-col-start-2{grid-column-start:2}.df-col-start-3{grid-column-start:3}.df-col-start-4{grid-column-start:4}.df-col-start-5{grid-column-start:5}.df-col-start-6{grid-column-start:6}.df-col-start-7{grid-column-start:7}.df-col-start-8{grid-column-start:8}.df-col-start-9{grid-column-start:9}.df-col-start-10{grid-column-start:10}.df-col-start-11{grid-column-start:11}.df-col-start-12{grid-column-start:12}.df-col-end-1{grid-column-end:1}.df-col-end-2{grid-column-end:2}.df-col-end-3{grid-column-end:3}.df-col-end-4{grid-column-end:4}.df-col-end-5{grid-column-end:5}.df-col-end-6{grid-column-end:6}.df-col-end-7{grid-column-end:7}.df-col-end-8{grid-column-end:8}.df-col-end-9{grid-column-end:9}.df-col-end-10{grid-column-end:10}.df-col-end-11{grid-column-end:11}.df-col-end-12{grid-column-end:12}.df-col-end-13{grid-column-end:13}@media(max-width:576px){.df-form{--df-grid-gap: var(--df-grid-gap-sm);--df-grid-row-gap: var(--df-grid-row-gap-sm)}.df-row{grid-template-columns:1fr}.df-row>*{grid-column:1/-1!important}.df-row.df-row-mobile-keep-cols{grid-template-columns:repeat(var(--df-grid-columns),1fr)}.df-row.df-row-mobile-keep-cols>*{grid-column:revert!important}}@media(min-width:577px)and (max-width:768px){.df-form{--df-grid-gap: var(--df-grid-gap-md);--df-grid-row-gap: var(--df-grid-row-gap-md)}.df-row{--df-grid-columns: 6}.df-col-sm-1{grid-column:span 1}.df-col-sm-2{grid-column:span 2}.df-col-sm-3{grid-column:span 3}.df-col-sm-4{grid-column:span 4}.df-col-sm-5{grid-column:span 5}.df-col-sm-6{grid-column:span 6}.df-col-sm-full{grid-column:1/-1}}@media(min-width:769px)and (max-width:992px){.df-form{--df-grid-gap: var(--df-grid-gap-lg);--df-grid-row-gap: var(--df-grid-row-gap-lg)}.df-col-md-1{grid-column:span 1}.df-col-md-2{grid-column:span 2}.df-col-md-3{grid-column:span 3}.df-col-md-4{grid-column:span 4}.df-col-md-5{grid-column:span 5}.df-col-md-6{grid-column:span 6}.df-col-md-7{grid-column:span 7}.df-col-md-8{grid-column:span 8}.df-col-md-9{grid-column:span 9}.df-col-md-10{grid-column:span 10}.df-col-md-11{grid-column:span 11}.df-col-md-12{grid-column:span 12}.df-col-md-full{grid-column:1/-1}}@media(min-width:993px){.df-form{--df-grid-gap: var(--df-grid-gap-xl);--df-grid-row-gap: var(--df-grid-row-gap-xl)}.df-col-lg-1{grid-column:span 1}.df-col-lg-2{grid-column:span 2}.df-col-lg-3{grid-column:span 3}.df-col-lg-4{grid-column:span 4}.df-col-lg-5{grid-column:span 5}.df-col-lg-6{grid-column:span 6}.df-col-lg-7{grid-column:span 7}.df-col-lg-8{grid-column:span 8}.df-col-lg-9{grid-column:span 9}.df-col-lg-10{grid-column:span 10}.df-col-lg-11{grid-column:span 11}.df-col-lg-12{grid-column:span 12}.df-col-lg-full{grid-column:1/-1}}.df-gap-none{--df-grid-gap: 0}.df-gap-xs{--df-grid-gap: .25rem}.df-gap-sm{--df-grid-gap: .5rem}.df-gap-md{--df-grid-gap: 1rem}.df-gap-lg{--df-grid-gap: 1.5rem}.df-gap-xl{--df-grid-gap: 2rem}.df-row-gap-none{--df-grid-row-gap: 0}.df-row-gap-xs{--df-grid-row-gap: .25rem}.df-row-gap-sm{--df-grid-row-gap: .5rem}.df-row-gap-md{--df-grid-row-gap: 1rem}.df-row-gap-lg{--df-grid-row-gap: 1.5rem}.df-row-gap-xl{--df-grid-row-gap: 2rem}.df-field{display:block;width:100%;min-width:0;overflow:hidden;margin:0}.df-group,.df-page{display:block;width:100%}.df-form.disabled,.df-row.disabled,.df-field.disabled{opacity:.6;pointer-events:none}.df-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-sr-only-focusable:focus,.df-sr-only-focusable:active{position:static;width:auto;height:auto;padding:inherit;margin:inherit;overflow:visible;clip:auto;white-space:normal}.df-live-region{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-form :focus-visible{outline:2px solid var(--df-focus-color, #005fcc);outline-offset:2px}.df-group:focus-within{outline:1px dashed var(--df-focus-color, #005fcc);outline-offset:4px}:host{display:grid;grid-template-columns:1fr;width:100%;gap:var(--df-grid-row-gap);transition:opacity .2s ease-in-out}:host.df-page-spacing-custom{--df-grid-row-gap: var(--page-custom-spacing, 1.5rem)}:host.df-page-visible{opacity:1}:host.df-page-hidden{display:none;opacity:0;pointer-events:none}:host[aria-hidden=true]{pointer-events:none;visibility:hidden}@media(prefers-reduced-motion:no-preference){:host{transition:opacity .3s ease-in-out,transform .3s ease-in-out}:host.df-page-visible{transform:translate(0)}:host.df-page-hidden{transform:translate(-10px)}}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
89
|
+
}
|
|
90
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PageFieldComponent, decorators: [{
|
|
91
|
+
type: Component,
|
|
92
|
+
args: [{ selector: 'section[page-field]', imports: [NgComponentOutlet], template: `
|
|
93
|
+
@for (field of resolvedFields(); track field.key) {
|
|
94
|
+
<ng-container *ngComponentOutlet="field.component; injector: field.injector; inputs: field.inputs()" />
|
|
95
|
+
}
|
|
96
|
+
`, host: {
|
|
97
|
+
'[class]': 'hostClasses()',
|
|
98
|
+
'[class.disabled]': 'disabled()',
|
|
99
|
+
'[class.df-page-visible]': 'isVisible()',
|
|
100
|
+
'[class.df-page-hidden]': '!isVisible()',
|
|
101
|
+
'[attr.aria-hidden]': '!isVisible()',
|
|
102
|
+
'[attr.data-page-index]': 'pageIndex()',
|
|
103
|
+
'[id]': '`${key()}`',
|
|
104
|
+
'[attr.data-testid]': 'key()',
|
|
105
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host,.df-form{--df-grid-columns: 12;--df-grid-gap: .5rem;--df-grid-row-gap: .5rem;--df-breakpoint-sm: 576px;--df-breakpoint-md: 768px;--df-breakpoint-lg: 992px;--df-breakpoint-xl: 1200px;--df-grid-gap-sm: .5rem;--df-grid-gap-md: .5rem;--df-grid-gap-lg: .5rem;--df-grid-gap-xl: .5rem;--df-grid-row-gap-sm: .5rem;--df-grid-row-gap-md: .5rem;--df-grid-row-gap-lg: .5rem;--df-grid-row-gap-xl: .5rem;--df-array-item-gap: var(--df-grid-row-gap);--df-group-gap: var(--df-grid-gap);--df-group-padding: var(--df-grid-gap)}.df-form{display:grid;grid-template-columns:1fr;gap:var(--df-grid-row-gap);width:100%}.df-form>*{grid-column:1/-1}.df-row{display:grid;grid-template-columns:repeat(var(--df-grid-columns, 12),1fr);gap:var(--df-grid-gap);align-items:start;width:100%}.df-row>*:not([class*=df-col-]){grid-column:1/-1}.df-col-1{grid-column:span 1}.df-col-2{grid-column:span 2}.df-col-3{grid-column:span 3}.df-col-4{grid-column:span 4}.df-col-5{grid-column:span 5}.df-col-6{grid-column:span 6}.df-col-7{grid-column:span 7}.df-col-8{grid-column:span 8}.df-col-9{grid-column:span 9}.df-col-10{grid-column:span 10}.df-col-11{grid-column:span 11}.df-col-12{grid-column:span 12}.df-col-auto{grid-column:span auto;width:auto}.df-col-full{grid-column:1/-1}.df-col-start-1{grid-column-start:1}.df-col-start-2{grid-column-start:2}.df-col-start-3{grid-column-start:3}.df-col-start-4{grid-column-start:4}.df-col-start-5{grid-column-start:5}.df-col-start-6{grid-column-start:6}.df-col-start-7{grid-column-start:7}.df-col-start-8{grid-column-start:8}.df-col-start-9{grid-column-start:9}.df-col-start-10{grid-column-start:10}.df-col-start-11{grid-column-start:11}.df-col-start-12{grid-column-start:12}.df-col-end-1{grid-column-end:1}.df-col-end-2{grid-column-end:2}.df-col-end-3{grid-column-end:3}.df-col-end-4{grid-column-end:4}.df-col-end-5{grid-column-end:5}.df-col-end-6{grid-column-end:6}.df-col-end-7{grid-column-end:7}.df-col-end-8{grid-column-end:8}.df-col-end-9{grid-column-end:9}.df-col-end-10{grid-column-end:10}.df-col-end-11{grid-column-end:11}.df-col-end-12{grid-column-end:12}.df-col-end-13{grid-column-end:13}@media(max-width:576px){.df-form{--df-grid-gap: var(--df-grid-gap-sm);--df-grid-row-gap: var(--df-grid-row-gap-sm)}.df-row{grid-template-columns:1fr}.df-row>*{grid-column:1/-1!important}.df-row.df-row-mobile-keep-cols{grid-template-columns:repeat(var(--df-grid-columns),1fr)}.df-row.df-row-mobile-keep-cols>*{grid-column:revert!important}}@media(min-width:577px)and (max-width:768px){.df-form{--df-grid-gap: var(--df-grid-gap-md);--df-grid-row-gap: var(--df-grid-row-gap-md)}.df-row{--df-grid-columns: 6}.df-col-sm-1{grid-column:span 1}.df-col-sm-2{grid-column:span 2}.df-col-sm-3{grid-column:span 3}.df-col-sm-4{grid-column:span 4}.df-col-sm-5{grid-column:span 5}.df-col-sm-6{grid-column:span 6}.df-col-sm-full{grid-column:1/-1}}@media(min-width:769px)and (max-width:992px){.df-form{--df-grid-gap: var(--df-grid-gap-lg);--df-grid-row-gap: var(--df-grid-row-gap-lg)}.df-col-md-1{grid-column:span 1}.df-col-md-2{grid-column:span 2}.df-col-md-3{grid-column:span 3}.df-col-md-4{grid-column:span 4}.df-col-md-5{grid-column:span 5}.df-col-md-6{grid-column:span 6}.df-col-md-7{grid-column:span 7}.df-col-md-8{grid-column:span 8}.df-col-md-9{grid-column:span 9}.df-col-md-10{grid-column:span 10}.df-col-md-11{grid-column:span 11}.df-col-md-12{grid-column:span 12}.df-col-md-full{grid-column:1/-1}}@media(min-width:993px){.df-form{--df-grid-gap: var(--df-grid-gap-xl);--df-grid-row-gap: var(--df-grid-row-gap-xl)}.df-col-lg-1{grid-column:span 1}.df-col-lg-2{grid-column:span 2}.df-col-lg-3{grid-column:span 3}.df-col-lg-4{grid-column:span 4}.df-col-lg-5{grid-column:span 5}.df-col-lg-6{grid-column:span 6}.df-col-lg-7{grid-column:span 7}.df-col-lg-8{grid-column:span 8}.df-col-lg-9{grid-column:span 9}.df-col-lg-10{grid-column:span 10}.df-col-lg-11{grid-column:span 11}.df-col-lg-12{grid-column:span 12}.df-col-lg-full{grid-column:1/-1}}.df-gap-none{--df-grid-gap: 0}.df-gap-xs{--df-grid-gap: .25rem}.df-gap-sm{--df-grid-gap: .5rem}.df-gap-md{--df-grid-gap: 1rem}.df-gap-lg{--df-grid-gap: 1.5rem}.df-gap-xl{--df-grid-gap: 2rem}.df-row-gap-none{--df-grid-row-gap: 0}.df-row-gap-xs{--df-grid-row-gap: .25rem}.df-row-gap-sm{--df-grid-row-gap: .5rem}.df-row-gap-md{--df-grid-row-gap: 1rem}.df-row-gap-lg{--df-grid-row-gap: 1.5rem}.df-row-gap-xl{--df-grid-row-gap: 2rem}.df-field{display:block;width:100%;min-width:0;overflow:hidden;margin:0}.df-group,.df-page{display:block;width:100%}.df-form.disabled,.df-row.disabled,.df-field.disabled{opacity:.6;pointer-events:none}.df-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-sr-only-focusable:focus,.df-sr-only-focusable:active{position:static;width:auto;height:auto;padding:inherit;margin:inherit;overflow:visible;clip:auto;white-space:normal}.df-live-region{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.df-form :focus-visible{outline:2px solid var(--df-focus-color, #005fcc);outline-offset:2px}.df-group:focus-within{outline:1px dashed var(--df-focus-color, #005fcc);outline-offset:4px}:host{display:grid;grid-template-columns:1fr;width:100%;gap:var(--df-grid-row-gap);transition:opacity .2s ease-in-out}:host.df-page-spacing-custom{--df-grid-row-gap: var(--page-custom-spacing, 1.5rem)}:host.df-page-visible{opacity:1}:host.df-page-hidden{display:none;opacity:0;pointer-events:none}:host[aria-hidden=true]{pointer-events:none;visibility:hidden}@media(prefers-reduced-motion:no-preference){:host{transition:opacity .3s ease-in-out,transform .3s ease-in-out}:host.df-page-visible{transform:translate(0)}:host.df-page-hidden{transform:translate(-10px)}}@media(prefers-reduced-motion:reduce){:host{transition:none}}\n"] }]
|
|
106
|
+
}], ctorParameters: () => [], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], pageIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageIndex", required: true }] }], isVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isVisible", required: true }] }], nextPage: [{ type: i0.Output, args: ["nextPage"] }], previousPage: [{ type: i0.Output, args: ["previousPage"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }] } });
|
|
107
|
+
|
|
108
|
+
export { PageFieldComponent as default };
|
|
109
|
+
//# sourceMappingURL=ng-forge-dynamic-forms-page-field.component-_mRHaw7x.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-forge-dynamic-forms-page-field.component-_mRHaw7x.mjs","sources":["../../../../packages/dynamic-forms/src/lib/fields/page/page-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, DestroyRef, inject, Injector, input } from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport { outputFromObservable } from '@angular/core/rxjs-interop';\nimport { explicitEffect } from 'ngxtension/explicit-effect';\nimport { derivedFromDeferred } from '../../utils/derived-from-deferred/derived-from-deferred';\nimport { createFieldResolutionPipe, ResolvedField } from '../../utils/resolve-field/resolve-field';\nimport { computeContainerHostClasses, setupContainerInitEffect } from '../../utils/container-utils/container-utils';\nimport { PageField, validatePageNesting } from '../../definitions/default/page-field';\nimport { injectFieldRegistry } from '../../utils/inject-field-registry/inject-field-registry';\nimport { EventBus } from '../../events/event.bus';\nimport { NextPageEvent, PageChangeEvent, PreviousPageEvent } from '../../events/constants';\nimport { FieldDef } from '../../definitions/base/field-def';\nimport { DynamicFormLogger } from '../../providers/features/logger/logger.token';\n\n/**\n * Renders a single page in multi-page (wizard) forms.\n *\n * Visibility is controlled by the PageOrchestrator via the isVisible input.\n * Pages cannot be nested within other pages - validation prevents this.\n * Field values are flattened into the parent form (no nesting under page key).\n */\n@Component({\n selector: 'section[page-field]',\n imports: [NgComponentOutlet],\n template: `\n @for (field of resolvedFields(); track field.key) {\n <ng-container *ngComponentOutlet=\"field.component; injector: field.injector; inputs: field.inputs()\" />\n }\n `,\n styleUrl: './page-field.component.scss',\n host: {\n '[class]': 'hostClasses()',\n '[class.disabled]': 'disabled()',\n '[class.df-page-visible]': 'isVisible()',\n '[class.df-page-hidden]': '!isVisible()',\n '[attr.aria-hidden]': '!isVisible()',\n '[attr.data-page-index]': 'pageIndex()',\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class PageFieldComponent {\n // ─────────────────────────────────────────────────────────────────────────────\n // Dependencies\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly fieldRegistry = injectFieldRegistry();\n private readonly injector = inject(Injector);\n private readonly eventBus = inject(EventBus);\n private readonly logger = inject(DynamicFormLogger);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Inputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n field = input.required<PageField>();\n key = input.required<string>();\n className = input<string>();\n pageIndex = input.required<number>();\n isVisible = input.required<boolean>();\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Computed Signals\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly hostClasses = computed(() => computeContainerHostClasses('page-field', this.className()));\n\n readonly disabled = computed(() => this.field().disabled || false);\n\n readonly isValid = computed(() => validatePageNesting(this.field()));\n\n private readonly rawFieldRegistry = computed(() => this.fieldRegistry.raw);\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Outputs\n // ─────────────────────────────────────────────────────────────────────────────\n\n readonly nextPage = outputFromObservable(this.eventBus.on<NextPageEvent>('next-page'));\n readonly previousPage = outputFromObservable(this.eventBus.on<PreviousPageEvent>('previous-page'));\n readonly pageChange = outputFromObservable(this.eventBus.on<PageChangeEvent>('page-change'));\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Field Resolution\n // ─────────────────────────────────────────────────────────────────────────────\n\n private readonly fieldsSource = computed(() => {\n if (!this.isValid()) {\n return [];\n }\n return this.field().fields || [];\n });\n\n protected readonly resolvedFields = derivedFromDeferred(\n this.fieldsSource,\n createFieldResolutionPipe(() => ({\n loadTypeComponent: (type: string) => this.fieldRegistry.loadTypeComponent(type),\n registry: this.rawFieldRegistry(),\n injector: this.injector,\n destroyRef: this.destroyRef,\n onError: (fieldDef: FieldDef<unknown>, error: unknown) => {\n const fieldKey = fieldDef.key || '<no key>';\n this.logger.error(\n `Failed to load component for field type '${fieldDef.type}' (key: ${fieldKey}) ` +\n `within page '${this.field().key}'. Ensure the field type is registered in your field registry.`,\n error,\n );\n },\n })),\n { initialValue: [] as ResolvedField[], injector: this.injector },\n );\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Constructor\n // ─────────────────────────────────────────────────────────────────────────────\n\n constructor() {\n this.setupEffects();\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n private setupEffects(): void {\n setupContainerInitEffect(this.resolvedFields, this.eventBus, 'page', () => this.field().key, this.injector);\n\n explicitEffect([this.isValid, this.field], ([valid, pageField]) => {\n if (!valid) {\n this.logger.error(\n `Invalid configuration: Page '${pageField.key}' contains nested page fields. ` +\n `Pages cannot contain other pages. Consider using groups or rows for nested structure.`,\n pageField,\n );\n }\n });\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { input, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import { AsyncPipe } from '@angular/common';
|
|
4
|
-
import {
|
|
4
|
+
import { b as DynamicTextPipe } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-Bf6Qnz0T.mjs';
|
|
5
5
|
|
|
6
6
|
class TextFieldComponent {
|
|
7
7
|
key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
|
|
@@ -11,8 +11,8 @@ class TextFieldComponent {
|
|
|
11
11
|
hidden = input(...(ngDevMode ? [undefined, { debugName: "hidden" }] : []));
|
|
12
12
|
props = input(...(ngDevMode ? [undefined, { debugName: "props" }] : []));
|
|
13
13
|
elementType = computed(() => this.props()?.elementType || 'p', ...(ngDevMode ? [{ debugName: "elementType" }] : []));
|
|
14
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
15
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
14
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TextFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: TextFieldComponent, isStandalone: true, selector: "df-text", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "id": "`${key()}`", "attr.data-testid": "key()", "attr.hidden": "hidden() || null" } }, ngImport: i0, template: `
|
|
16
16
|
@switch (elementType()) {
|
|
17
17
|
@case ('p') {
|
|
18
18
|
<p class="df-text df-text-p" [class]="className() || ''">
|
|
@@ -57,7 +57,7 @@ class TextFieldComponent {
|
|
|
57
57
|
}
|
|
58
58
|
`, isInline: true, styles: [":host([hidden]){display:none!important}.df-text{font-size:var(--df-text-font-size, 1rem);font-family:var(--df-text-font-family, inherit);font-weight:var(--df-text-font-weight, normal);color:var(--df-text-color, inherit);line-height:var(--df-text-line-height, 1.5);text-align:var(--df-text-text-align, inherit);letter-spacing:var(--df-text-letter-spacing, normal);text-decoration:var(--df-text-text-decoration, none);text-transform:var(--df-text-text-transform, none);margin:var(--df-text-margin, 0);padding:var(--df-text-padding, 0)}.df-text-h1{font-size:var(--df-text-h1-font-size, 2rem);font-weight:var(--df-text-h1-font-weight, bold);margin:var(--df-text-h1-margin, 0)}.df-text-h2{font-size:var(--df-text-h2-font-size, 1.75rem);font-weight:var(--df-text-h2-font-weight, bold);margin:var(--df-text-h2-margin, 0)}.df-text-h3{font-size:var(--df-text-h3-font-size, 1.5rem);font-weight:var(--df-text-h3-font-weight, bold);margin:var(--df-text-h3-margin, 0)}.df-text-h4{font-size:var(--df-text-h4-font-size, 1.25rem);font-weight:var(--df-text-h4-font-weight, bold);margin:var(--df-text-h4-margin, 0)}.df-text-h5{font-size:var(--df-text-h5-font-size, 1.125rem);font-weight:var(--df-text-h5-font-weight, bold);margin:var(--df-text-h5-margin, 0)}.df-text-h6{font-size:var(--df-text-h6-font-size, 1rem);font-weight:var(--df-text-h6-font-weight, bold);margin:var(--df-text-h6-margin, 0)}.df-text-p{font-size:var(--df-text-p-font-size, 1rem);margin:var(--df-text-p-margin, 0)}.df-text-span{display:var(--df-text-span-display, inline)}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DynamicTextPipe, name: "dynamicText" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
59
59
|
}
|
|
60
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TextFieldComponent, decorators: [{
|
|
61
61
|
type: Component,
|
|
62
62
|
args: [{ selector: 'df-text', template: `
|
|
63
63
|
@switch (elementType()) {
|
|
@@ -110,4 +110,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
110
110
|
}], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
|
|
111
111
|
|
|
112
112
|
export { TextFieldComponent as default };
|
|
113
|
-
//# sourceMappingURL=ng-forge-dynamic-forms-text-field.component-
|
|
113
|
+
//# sourceMappingURL=ng-forge-dynamic-forms-text-field.component-CmkBZk4p.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-forge-dynamic-forms-text-field.component-
|
|
1
|
+
{"version":3,"file":"ng-forge-dynamic-forms-text-field.component-CmkBZk4p.mjs","sources":["../../../../packages/dynamic-forms/src/lib/fields/text/text-field.component.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { AsyncPipe } from '@angular/common';\nimport { DynamicTextPipe } from '../../pipes/dynamic-text/dynamic-text.pipe';\nimport { TextProps } from '../../definitions/default/text-field';\nimport { DynamicText } from '../../models/types/dynamic-text';\n\n@Component({\n selector: 'df-text',\n template: `\n @switch (elementType()) {\n @case ('p') {\n <p class=\"df-text df-text-p\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </p>\n }\n @case ('h1') {\n <h1 class=\"df-text df-text-h1\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h1>\n }\n @case ('h2') {\n <h2 class=\"df-text df-text-h2\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h2>\n }\n @case ('h3') {\n <h3 class=\"df-text df-text-h3\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h3>\n }\n @case ('h4') {\n <h4 class=\"df-text df-text-h4\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h4>\n }\n @case ('h5') {\n <h5 class=\"df-text df-text-h5\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h5>\n }\n @case ('h6') {\n <h6 class=\"df-text df-text-h6\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </h6>\n }\n @case ('span') {\n <span class=\"df-text df-text-span\" [class]=\"className() || ''\">\n {{ label() | dynamicText | async }}\n </span>\n }\n }\n `,\n styleUrl: './text-field.component.scss',\n imports: [AsyncPipe, DynamicTextPipe],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[id]': '`${key()}`',\n '[attr.data-testid]': 'key()',\n '[attr.hidden]': 'hidden() || null',\n },\n})\nexport default class TextFieldComponent {\n readonly key = input.required<string>();\n readonly label = input.required<DynamicText>();\n readonly className = input<string>();\n readonly tabIndex = input<number>();\n readonly hidden = input<boolean>();\n readonly props = input<TextProps>();\n\n readonly elementType = computed(() => this.props()?.elementType || 'p');\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a7 as ARRAY_CONTEXT, J as AppendArrayItemEvent, ad as ArrayFieldComponent, ak as BUILT_IN_FIELDS, C as ConsoleLogger, a8 as DEFAULT_PROPS, a9 as DEFAULT_VALIDATION_MESSAGES, e as DynamicForm, _ as DynamicFormError, D as DynamicFormLogger, b as DynamicTextPipe, E as EventBus, a6 as FIELD_REGISTRY, aa as FIELD_SIGNAL_CONTEXT, ab as FORM_OPTIONS, K as FormClearEvent, L as FormResetEvent, ae as GroupFieldComponent, M as InsertArrayItemEvent, O as NextPageEvent, N as NoopLogger, P as PageChangeEvent, Q as PopArrayItemEvent, R as PrependArrayItemEvent, S as PreviousPageEvent, T as RemoveAtIndexEvent, ap as RootFormRegistryService, af as RowFieldComponent, U as ShiftArrayItemEvent, V as SubmitEvent, ao as applyMetaToElement, ag as applyValidator, ah as applyValidators, W as arrayEvent, a1 as arrayFieldMapper, $ as baseFieldMapper, a0 as buildBaseInputs, X as createField, ac as dynamicTextToObservable, o as evaluateNonFieldDisabled, n as evaluateNonFieldHidden, Y as field, Z as formConfig, ai as getArrayLength, a2 as groupFieldMapper, h as hasFormValue, an as interpolateParams, z as isArrayField, q as isCheckedField, A as isContainerField, B as isDisplayOnlyField, al as isEqual, j as isFormStateCondition, F as isGroupField, G as isLeafField, H as isPageField, y as isPropertyDerivationLogicConfig, u as isRowField, x as isSimplifiedArrayField, I as isValueBearingField, t as isValueField, am as omit, a3 as pageFieldMapper, p as provideDynamicForm, k as resolveNextButtonDisabled, m as resolveNonFieldDisabled, l as resolveNonFieldHidden, r as resolveSubmitButtonDisabled, aj as resolveTokens, a4 as rowFieldMapper, a5 as textFieldMapper, f as withEventFormValue, w as withLoggerConfig, g as withValueExclusionDefaults } from './ng-forge-dynamic-forms-ng-forge-dynamic-forms-Bf6Qnz0T.mjs';
|
|
2
2
|
//# sourceMappingURL=ng-forge-dynamic-forms.mjs.map
|
package/package.json
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import { FormEvent, FieldDef, FormEventConstructor, BaseCheckedField, BaseValueField, DynamicText, FieldMeta, FieldOption, ValidationMessages } from '@ng-forge/dynamic-forms';
|
|
2
|
-
export { isEqual } from '@ng-forge/dynamic-forms';
|
|
1
|
+
import { FormEvent, FieldDef, FormEventConstructor, StateLogicConfig, BaseCheckedField, BaseValueField, DynamicText, FieldMeta, FieldOption, ValidationMessages, ArrayAllowedChildren, NonFieldLogicConfig, NextPageEvent, PreviousPageEvent, FieldWithValidation } from '@ng-forge/dynamic-forms';
|
|
2
|
+
export { NonFieldLogicConfig, NonFieldLogicContext, NonFieldLogicType, isEqual, resolveNonFieldDisabled, resolveNonFieldHidden } from '@ng-forge/dynamic-forms';
|
|
3
3
|
import { Signal, Injector, ElementRef } from '@angular/core';
|
|
4
4
|
import { FieldTree } from '@angular/forms/signals';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Event arguments that can contain static values or tokens to be resolved at runtime
|
|
8
|
-
* Tokens supported: $key, $index, $arrayKey, formValue
|
|
7
|
+
* Event arguments that can contain static values or tokens to be resolved at runtime.
|
|
8
|
+
* Tokens supported: $key, $index, $arrayKey, $template, formValue
|
|
9
|
+
*
|
|
10
|
+
* Used by the generic button type when manually configuring events.
|
|
9
11
|
*/
|
|
10
12
|
type EventArgs = readonly (string | number | boolean | null | undefined)[];
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
14
|
+
* Base interface for button fields.
|
|
15
|
+
*
|
|
16
|
+
* This is used by the generic 'button' type which requires explicit event configuration.
|
|
17
|
+
* For specific button types (submit, next, previous, array buttons), use the
|
|
18
|
+
* pre-configured types from the UI library instead.
|
|
13
19
|
*/
|
|
14
20
|
interface ButtonField<TProps, TEvent extends FormEvent> extends FieldDef<TProps> {
|
|
15
21
|
type: 'button';
|
|
@@ -20,6 +26,7 @@ interface ButtonField<TProps, TEvent extends FormEvent> extends FieldDef<TProps>
|
|
|
20
26
|
* - $key: The current field key
|
|
21
27
|
* - $index: The array index (if inside an array field)
|
|
22
28
|
* - $arrayKey: The parent array field key (if inside an array field)
|
|
29
|
+
* - $template: The template for array item creation (for array add buttons)
|
|
23
30
|
* - formValue: Access to the current form value for indexing
|
|
24
31
|
*
|
|
25
32
|
* @example
|
|
@@ -27,6 +34,8 @@ interface ButtonField<TProps, TEvent extends FormEvent> extends FieldDef<TProps>
|
|
|
27
34
|
* eventArgs: ['contacts', 0]
|
|
28
35
|
*/
|
|
29
36
|
eventArgs?: EventArgs;
|
|
37
|
+
/** Logic rules for dynamic disabled state (overrides form-level defaults) */
|
|
38
|
+
logic?: StateLogicConfig[];
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
interface CheckboxField<TProps> extends BaseCheckedField<TProps> {
|
|
@@ -384,26 +393,43 @@ interface ToggleField<TProps> extends BaseCheckedField<TProps> {
|
|
|
384
393
|
}
|
|
385
394
|
|
|
386
395
|
/**
|
|
387
|
-
* Context for value field mapping, containing
|
|
388
|
-
* Used by specialized mappers to avoid duplicate
|
|
396
|
+
* Context for value field mapping, containing the injected context reference.
|
|
397
|
+
* Used by specialized mappers to avoid duplicate injection.
|
|
398
|
+
*
|
|
399
|
+
* Note: The field tree is resolved lazily via getFieldTree() to support
|
|
400
|
+
* reactive form access (e.g., for array items where the form structure
|
|
401
|
+
* may not exist at injection time but becomes available later).
|
|
389
402
|
*/
|
|
390
403
|
interface ValueFieldContext {
|
|
391
|
-
|
|
404
|
+
/**
|
|
405
|
+
* Gets the field tree for a given key from the form context.
|
|
406
|
+
* This is reactive for array items - the form getter is evaluated each time,
|
|
407
|
+
* allowing the computed to re-run when the root form structure updates.
|
|
408
|
+
*/
|
|
409
|
+
getFieldTree: (fieldKey: string) => FieldTree<unknown> | undefined;
|
|
392
410
|
}
|
|
393
411
|
/**
|
|
394
|
-
*
|
|
412
|
+
* Creates a value field context from the injected FIELD_SIGNAL_CONTEXT.
|
|
395
413
|
* Must be called within an injection context.
|
|
396
414
|
*
|
|
397
|
-
*
|
|
415
|
+
* With direct root form binding for array items, the FIELD_SIGNAL_CONTEXT.form
|
|
416
|
+
* uses a getter that evaluates reactively. This means:
|
|
417
|
+
* - For regular fields: direct access to the form's FieldTree
|
|
418
|
+
* - For array items: the getter resolves rootForm['arrayKey'][index] dynamically
|
|
419
|
+
*
|
|
420
|
+
* The returned context provides a getFieldTree function that should be called
|
|
421
|
+
* inside a computed to establish proper reactive dependencies.
|
|
398
422
|
*
|
|
399
|
-
* @
|
|
400
|
-
* @returns The resolved context with field tree
|
|
423
|
+
* @returns The value field context with reactive field tree accessor
|
|
401
424
|
*/
|
|
402
|
-
declare function resolveValueFieldContext(
|
|
425
|
+
declare function resolveValueFieldContext(): ValueFieldContext;
|
|
403
426
|
/**
|
|
404
427
|
* Builds the base inputs for a value field.
|
|
405
428
|
* This is a helper function used by valueFieldMapper and specialized mappers.
|
|
406
429
|
*
|
|
430
|
+
* Note: This function should be called inside a computed signal to ensure
|
|
431
|
+
* proper reactive dependency tracking for the field tree resolution.
|
|
432
|
+
*
|
|
407
433
|
* @param fieldDef The value field definition
|
|
408
434
|
* @param ctx The resolved value field context
|
|
409
435
|
* @param defaultProps Default props from the form configuration (may be undefined if not configured)
|
|
@@ -417,6 +443,12 @@ declare function buildValueFieldInputs<TProps, TValue = unknown>(fieldDef: BaseV
|
|
|
417
443
|
* Value fields are input fields that contribute to the form's value (text, number, etc.).
|
|
418
444
|
* This mapper injects FIELD_SIGNAL_CONTEXT to access the form structure and retrieve the field proxy.
|
|
419
445
|
*
|
|
446
|
+
* For array items, the FIELD_SIGNAL_CONTEXT.form uses a reactive getter that resolves
|
|
447
|
+
* rootForm['arrayKey'][index] dynamically. This means:
|
|
448
|
+
* - Zod/StandardSchema validation errors are automatically available
|
|
449
|
+
* - The field tree updates reactively when the root form structure changes
|
|
450
|
+
* - Newly added array items will get their field tree once the form value updates
|
|
451
|
+
*
|
|
420
452
|
* For fields with specific properties (select, datepicker, textarea, slider), use the specialized mappers:
|
|
421
453
|
* - selectFieldMapper: for fields with options (select, radio, multi-checkbox)
|
|
422
454
|
* - datepickerFieldMapper: for fields with minDate, maxDate, startAt
|
|
@@ -469,6 +501,191 @@ type FieldWithOptions<T = unknown, TProps = unknown> = SelectField<T, TProps> |
|
|
|
469
501
|
*/
|
|
470
502
|
declare function optionsFieldMapper<T, TProps>(fieldDef: FieldWithOptions<T, TProps>): Signal<Record<string, unknown>>;
|
|
471
503
|
|
|
504
|
+
/**
|
|
505
|
+
* Maps a button field to component inputs.
|
|
506
|
+
*
|
|
507
|
+
* Unlike value field mappers, button fields do not participate in form values
|
|
508
|
+
* and do not need field tree resolution or validation messages.
|
|
509
|
+
*
|
|
510
|
+
* Button-specific properties:
|
|
511
|
+
* - event: The FormEvent constructor to emit when clicked
|
|
512
|
+
* - eventArgs: Optional arguments to pass to the event constructor
|
|
513
|
+
*
|
|
514
|
+
* Hidden and disabled states are resolved using non-field logic resolvers which consider:
|
|
515
|
+
* 1. Explicit `hidden: true` / `disabled: true` on the field definition
|
|
516
|
+
* 2. Field-level `logic` array with `type: 'hidden'` or `type: 'disabled'` conditions
|
|
517
|
+
*
|
|
518
|
+
* @param fieldDef The button field definition
|
|
519
|
+
* @returns Signal containing Record of input names to values for ngComponentOutlet
|
|
520
|
+
*/
|
|
521
|
+
declare function buttonFieldMapper<TProps, TEvent extends FormEvent>(fieldDef: ButtonField<TProps, TEvent>): Signal<Record<string, unknown>>;
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Context for array button mapping, containing resolved array information.
|
|
525
|
+
* Used by array button mappers to build event context.
|
|
526
|
+
*/
|
|
527
|
+
interface ArrayButtonContext {
|
|
528
|
+
/** The target array key (from explicit arrayKey or ARRAY_CONTEXT) */
|
|
529
|
+
targetArrayKey: string | undefined;
|
|
530
|
+
/** Computed signal that returns the current array index (-1 if not inside array) */
|
|
531
|
+
indexSignal: Signal<number>;
|
|
532
|
+
/** The current form value for token resolution */
|
|
533
|
+
formValue: Record<string, unknown>;
|
|
534
|
+
/** Whether this button is inside an array context */
|
|
535
|
+
isInsideArray: boolean;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Event context passed to button components for array operations.
|
|
539
|
+
*/
|
|
540
|
+
interface ArrayButtonEventContext {
|
|
541
|
+
/** The button field key */
|
|
542
|
+
key: string;
|
|
543
|
+
/** The current array index (-1 if outside array) */
|
|
544
|
+
index: number;
|
|
545
|
+
/** The target array key */
|
|
546
|
+
arrayKey: string;
|
|
547
|
+
/** The form value for token resolution */
|
|
548
|
+
formValue: Record<string, unknown>;
|
|
549
|
+
/**
|
|
550
|
+
* Optional template for add operations.
|
|
551
|
+
* Can be a single field (primitive item) or array of fields (object item).
|
|
552
|
+
*/
|
|
553
|
+
template?: ArrayAllowedChildren | readonly ArrayAllowedChildren[];
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Resolves array button context for button mappers.
|
|
557
|
+
*
|
|
558
|
+
* Handles both inside-array (context from ARRAY_CONTEXT) and
|
|
559
|
+
* outside-array (explicit arrayKey) placements.
|
|
560
|
+
*
|
|
561
|
+
* Must be called in injection context.
|
|
562
|
+
*
|
|
563
|
+
* @param fieldKey The button field key (for logging)
|
|
564
|
+
* @param buttonType The button type name (for logging)
|
|
565
|
+
* @param explicitArrayKey Optional explicit arrayKey from field definition
|
|
566
|
+
* @returns The array button context with reactive index signal
|
|
567
|
+
*/
|
|
568
|
+
declare function resolveArrayButtonContext(fieldKey: string, buttonType: string, explicitArrayKey?: string): ArrayButtonContext;
|
|
569
|
+
/**
|
|
570
|
+
* Builds the event context passed to the button component.
|
|
571
|
+
*
|
|
572
|
+
* Should be called inside a computed to track index signal changes.
|
|
573
|
+
*
|
|
574
|
+
* @param fieldKey The button field key
|
|
575
|
+
* @param ctx The resolved array button context
|
|
576
|
+
* @param template Optional template for add operations (single field or array of fields)
|
|
577
|
+
* @returns The event context for the button component
|
|
578
|
+
*/
|
|
579
|
+
declare function buildArrayButtonEventContext(fieldKey: string, ctx: ArrayButtonContext, template?: ArrayAllowedChildren | readonly ArrayAllowedChildren[]): ArrayButtonEventContext;
|
|
580
|
+
/**
|
|
581
|
+
* Event argument type - supports static values and tokens.
|
|
582
|
+
* Tokens: $key, $index, $arrayKey, $template, formValue
|
|
583
|
+
*/
|
|
584
|
+
type EventArg = string | number | boolean | null | undefined;
|
|
585
|
+
/**
|
|
586
|
+
* Resolves eventArgs with defaults for array buttons.
|
|
587
|
+
*
|
|
588
|
+
* @param fieldEventArgs The eventArgs from field definition (may be undefined)
|
|
589
|
+
* @param defaultEventArgs The default eventArgs to use if not specified
|
|
590
|
+
* @returns The resolved eventArgs array
|
|
591
|
+
*/
|
|
592
|
+
declare function resolveArrayButtonEventArgs(fieldEventArgs: readonly EventArg[] | undefined, defaultEventArgs?: readonly EventArg[]): readonly EventArg[];
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Base interface for array add button fields (append, prepend, insert).
|
|
596
|
+
* Template is required to define the structure for new items.
|
|
597
|
+
*/
|
|
598
|
+
interface BaseArrayAddButtonField<TProps = unknown> {
|
|
599
|
+
key: string;
|
|
600
|
+
type: string;
|
|
601
|
+
label?: string;
|
|
602
|
+
disabled?: boolean;
|
|
603
|
+
hidden?: boolean;
|
|
604
|
+
className?: string;
|
|
605
|
+
props?: TProps;
|
|
606
|
+
/** Target array key (required when outside array, optional inside) */
|
|
607
|
+
arrayKey?: string;
|
|
608
|
+
/**
|
|
609
|
+
* Template defining the field structure for new items. REQUIRED.
|
|
610
|
+
* - Single field (ArrayAllowedChildren): Creates a primitive item (field's value is extracted directly)
|
|
611
|
+
* - Array of fields (ArrayAllowedChildren[]): Creates an object item (fields merged into object)
|
|
612
|
+
*/
|
|
613
|
+
template: ArrayAllowedChildren | readonly ArrayAllowedChildren[];
|
|
614
|
+
/** Optional custom eventArgs */
|
|
615
|
+
eventArgs?: readonly EventArg[];
|
|
616
|
+
/** Logic rules for dynamic hidden/disabled state (only hidden and disabled are supported) */
|
|
617
|
+
logic?: NonFieldLogicConfig[];
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Base interface for array remove button fields (remove, pop, shift).
|
|
621
|
+
* No template needed - removes existing items.
|
|
622
|
+
*/
|
|
623
|
+
interface BaseArrayRemoveButtonField<TProps = unknown> {
|
|
624
|
+
key: string;
|
|
625
|
+
type: string;
|
|
626
|
+
label?: string;
|
|
627
|
+
disabled?: boolean;
|
|
628
|
+
hidden?: boolean;
|
|
629
|
+
className?: string;
|
|
630
|
+
props?: TProps;
|
|
631
|
+
/** Target array key (required when outside array, optional inside) */
|
|
632
|
+
arrayKey?: string;
|
|
633
|
+
/** Optional custom eventArgs */
|
|
634
|
+
eventArgs?: readonly EventArg[];
|
|
635
|
+
/** Logic rules for dynamic hidden/disabled state (only hidden and disabled are supported) */
|
|
636
|
+
logic?: NonFieldLogicConfig[];
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Interface for insert array item button fields.
|
|
640
|
+
* Extends add button with required index.
|
|
641
|
+
*/
|
|
642
|
+
interface BaseInsertArrayItemButtonField<TProps = unknown> extends BaseArrayAddButtonField<TProps> {
|
|
643
|
+
/** The index at which to insert the new item */
|
|
644
|
+
index: number;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Mapper for add array item button — appends new item to end of array.
|
|
648
|
+
* Template is REQUIRED to define the field structure for new items.
|
|
649
|
+
*/
|
|
650
|
+
declare function addArrayItemButtonMapper<TProps>(fieldDef: BaseArrayAddButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
651
|
+
/**
|
|
652
|
+
* Mapper for prepend array item button — inserts new item at beginning of array.
|
|
653
|
+
* Template is REQUIRED to define the field structure for new items.
|
|
654
|
+
*/
|
|
655
|
+
declare function prependArrayItemButtonMapper<TProps>(fieldDef: BaseArrayAddButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
656
|
+
/**
|
|
657
|
+
* Mapper for insert array item button — inserts new item at specific index.
|
|
658
|
+
* Template and index are REQUIRED.
|
|
659
|
+
*/
|
|
660
|
+
declare function insertArrayItemButtonMapper<TProps>(fieldDef: BaseInsertArrayItemButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
661
|
+
/**
|
|
662
|
+
* Mapper for remove array item button.
|
|
663
|
+
* Inside array: RemoveAtIndexEvent. Outside array: PopArrayItemEvent.
|
|
664
|
+
*/
|
|
665
|
+
declare function removeArrayItemButtonMapper<TProps>(fieldDef: BaseArrayRemoveButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
666
|
+
/** Mapper for pop array item button — removes the last item from array. */
|
|
667
|
+
declare function popArrayItemButtonMapper<TProps>(fieldDef: BaseArrayRemoveButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
668
|
+
/** Mapper for shift array item button — removes the first item from array. */
|
|
669
|
+
declare function shiftArrayItemButtonMapper<TProps>(fieldDef: BaseArrayRemoveButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Base interface for navigation button fields (submit, next, previous).
|
|
673
|
+
*/
|
|
674
|
+
type BaseNavigationButtonField<TProps = unknown> = ButtonField<TProps, SubmitEvent | NextPageEvent | PreviousPageEvent> & {
|
|
675
|
+
type: string;
|
|
676
|
+
/** Logic rules for dynamic disabled state */
|
|
677
|
+
logic?: FieldWithValidation['logic'];
|
|
678
|
+
};
|
|
679
|
+
/**
|
|
680
|
+
* Mapper for submit button — configures native form submission via type="submit".
|
|
681
|
+
* Triggers native form submission rather than dispatching events directly.
|
|
682
|
+
*/
|
|
683
|
+
declare function submitButtonFieldMapper<TProps>(fieldDef: BaseNavigationButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
684
|
+
/** Mapper for next page button — preconfigures NextPageEvent. */
|
|
685
|
+
declare function nextButtonFieldMapper<TProps>(fieldDef: BaseNavigationButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
686
|
+
/** Mapper for previous page button — preconfigures PreviousPageEvent. */
|
|
687
|
+
declare function previousButtonFieldMapper<TProps>(fieldDef: BaseNavigationButtonField<TProps>): Signal<Record<string, unknown>>;
|
|
688
|
+
|
|
472
689
|
/**
|
|
473
690
|
* Resolved validation error with interpolated message
|
|
474
691
|
*/
|
|
@@ -498,8 +715,8 @@ interface ResolvedError {
|
|
|
498
715
|
declare function createResolvedErrorsSignal<T>(field: Signal<FieldTree<T>>, validationMessages: Signal<ValidationMessages | undefined>, defaultValidationMessages?: Signal<ValidationMessages | undefined>, injector?: Injector): Signal<ResolvedError[]>;
|
|
499
716
|
|
|
500
717
|
/**
|
|
501
|
-
* Computed signal that determines if errors should be displayed
|
|
502
|
-
* Based on field's invalid, touched, and error count
|
|
718
|
+
* Computed signal that determines if errors should be displayed.
|
|
719
|
+
* Based on field's invalid, touched, and error count.
|
|
503
720
|
*
|
|
504
721
|
* @param field - Signal containing FieldTree
|
|
505
722
|
* @returns Signal<boolean> - True if errors should be displayed
|
|
@@ -571,5 +788,5 @@ interface MetaTrackingOptions {
|
|
|
571
788
|
*/
|
|
572
789
|
declare function setupMetaTracking(elementRef: ElementRef<HTMLElement>, meta: Signal<FieldMeta | undefined>, options?: MetaTrackingOptions): void;
|
|
573
790
|
|
|
574
|
-
export { buildValueFieldInputs, checkboxFieldMapper, createResolvedErrorsSignal, datepickerFieldMapper, optionsFieldMapper, resolveValueFieldContext, setupMetaTracking, shouldShowErrors, valueFieldMapper };
|
|
575
|
-
export type { Autocapitalize, AutocompleteValue, ButtonField, CheckboxField, DatepickerField, DatepickerProps, EnterKeyHint, EventArgs, FieldWithOptions, HtmlInputType, InferInputValue, InputField, InputMeta, InputMode, InputProps, InputType, InputTypeToValueType, MetaTrackingOptions, MultiCheckboxField, NumericInputType, RadioField, ResolvedError, SelectField, SelectProps, SliderField, StringInputType, TextareaField, TextareaMeta, TextareaProps, TextareaWrap, ToggleField, ValueFieldContext };
|
|
791
|
+
export { addArrayItemButtonMapper, buildArrayButtonEventContext, buildValueFieldInputs, buttonFieldMapper, checkboxFieldMapper, createResolvedErrorsSignal, datepickerFieldMapper, insertArrayItemButtonMapper, nextButtonFieldMapper, optionsFieldMapper, popArrayItemButtonMapper, prependArrayItemButtonMapper, previousButtonFieldMapper, removeArrayItemButtonMapper, resolveArrayButtonContext, resolveArrayButtonEventArgs, resolveValueFieldContext, setupMetaTracking, shiftArrayItemButtonMapper, shouldShowErrors, submitButtonFieldMapper, valueFieldMapper };
|
|
792
|
+
export type { ArrayButtonContext, ArrayButtonEventContext, Autocapitalize, AutocompleteValue, BaseArrayAddButtonField, BaseArrayRemoveButtonField, BaseInsertArrayItemButtonField, BaseNavigationButtonField, ButtonField, CheckboxField, DatepickerField, DatepickerProps, EnterKeyHint, EventArg, EventArgs, FieldWithOptions, HtmlInputType, InferInputValue, InputField, InputMeta, InputMode, InputProps, InputType, InputTypeToValueType, MetaTrackingOptions, MultiCheckboxField, NumericInputType, RadioField, ResolvedError, SelectField, SelectProps, SliderField, StringInputType, TextareaField, TextareaMeta, TextareaProps, TextareaWrap, ToggleField, ValueFieldContext };
|