@dynamic-field-kit/angular 1.2.10 → 1.3.3
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 +63 -1
- package/angular.json +27 -0
- package/dist/README.md +63 -1
- package/dist/components/BaseInput.d.ts +23 -5
- package/dist/components/DynamicInput.d.ts +13 -6
- package/dist/components/FieldInput.d.ts +10 -6
- package/dist/components/MultiFieldInput.d.ts +20 -3
- package/dist/esm2022/components/BaseInput.mjs +11 -3
- package/dist/esm2022/components/DynamicInput.mjs +112 -83
- package/dist/esm2022/components/FieldInput.mjs +25 -16
- package/dist/esm2022/components/MultiFieldInput.mjs +207 -28
- package/dist/esm2022/layout/defaultLayouts.mjs +70 -23
- package/dist/esm2022/layout/index.mjs +2 -1
- package/dist/esm2022/layout/layoutRegistry.mjs +14 -0
- package/dist/esm2022/public-api.mjs +1 -1
- package/dist/esm2022/types/layout.mjs +1 -1
- package/dist/fesm2022/dynamic-field-kit-angular.mjs +430 -146
- package/dist/fesm2022/dynamic-field-kit-angular.mjs.map +1 -1
- package/dist/layout/defaultLayouts.d.ts +21 -3
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/layoutRegistry.d.ts +12 -0
- package/dist/public-api.d.ts +1 -1
- package/dist/types/layout.d.ts +25 -1
- package/karma.conf.js +37 -0
- package/package.json +18 -5
- package/src/components/BaseInput.ts +34 -5
- package/src/components/DynamicInput.ts +142 -106
- package/src/components/FieldInput.ts +30 -12
- package/src/components/MultiFieldInput.ts +181 -18
- package/src/layout/defaultLayouts.ts +42 -10
- package/src/layout/index.ts +1 -0
- package/src/layout/layoutRegistry.ts +25 -0
- package/src/public-api.ts +1 -1
- package/src/types/layout.ts +36 -1
- package/test/DynamicInput.spec.ts +30 -0
- package/test/FieldInput.spec.ts +44 -0
- package/test/angular.spec.ts +102 -0
- package/test/integration.spec.ts +57 -0
- package/test/layouts.spec.ts +26 -0
- package/test.ts +12 -0
- package/tsconfig.spec.json +21 -0
- package/src/adapters/tailwind.ts +0 -13
- package/src/components/imports.ts +0 -3
- package/src/examples/index.ts +0 -4
- package/src/examples/registerExample.ts +0 -7
- package/src/examples/text-field.component.ts +0 -18
- package/src/types.ts +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { EventEmitter, Output, Input, Component,
|
|
2
|
+
import { EventEmitter, Output, Input, Component, ViewContainerRef, ViewChild, ChangeDetectionStrategy, HostListener, NgModule } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/common';
|
|
3
4
|
import { CommonModule, NgIf, NgClass, NgFor } from '@angular/common';
|
|
4
|
-
import { fieldRegistry } from '@dynamic-field-kit/core';
|
|
5
|
+
import { fieldRegistry, applyComputedValues, canAddGroupItem, canRemoveGroupItem, createGroupItem } from '@dynamic-field-kit/core';
|
|
5
6
|
export { fieldRegistry } from '@dynamic-field-kit/core';
|
|
6
7
|
|
|
7
8
|
class BaseInputComponent {
|
|
@@ -19,13 +20,21 @@ class BaseInputComponent {
|
|
|
19
20
|
maxLength;
|
|
20
21
|
minNumber;
|
|
21
22
|
maxNumber;
|
|
22
|
-
// Add more from mplis as needed
|
|
23
23
|
valueChange = new EventEmitter();
|
|
24
24
|
constructor(cdr) {
|
|
25
25
|
this.cdr = cdr;
|
|
26
26
|
}
|
|
27
|
+
ngOnChanges(_changes) {
|
|
28
|
+
this.detectChanges();
|
|
29
|
+
}
|
|
30
|
+
detectChanges() {
|
|
31
|
+
this.cdr.markForCheck();
|
|
32
|
+
}
|
|
33
|
+
hasChanges(changes, prop) {
|
|
34
|
+
return changes[prop] !== undefined;
|
|
35
|
+
}
|
|
27
36
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
28
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: BaseInputComponent, isStandalone: true, selector: "ng-component", inputs: { value: "value", label: "label", placeholder: "placeholder", required: "required", disabled: "disabled", options: "options", className: "className", description: "description", errorMessage: "errorMessage", acceptFile: "acceptFile", maxLength: "maxLength", minNumber: "minNumber", maxNumber: "maxNumber" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: '', isInline: true });
|
|
37
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: BaseInputComponent, isStandalone: true, selector: "ng-component", inputs: { value: "value", label: "label", placeholder: "placeholder", required: "required", disabled: "disabled", options: "options", className: "className", description: "description", errorMessage: "errorMessage", acceptFile: "acceptFile", maxLength: "maxLength", minNumber: "minNumber", maxNumber: "maxNumber" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true });
|
|
29
38
|
}
|
|
30
39
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, decorators: [{
|
|
31
40
|
type: Component,
|
|
@@ -62,29 +71,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
62
71
|
type: Output
|
|
63
72
|
}] } });
|
|
64
73
|
|
|
74
|
+
const KNOWN_PROPS = [
|
|
75
|
+
'value',
|
|
76
|
+
'label',
|
|
77
|
+
'placeholder',
|
|
78
|
+
'required',
|
|
79
|
+
'disabled',
|
|
80
|
+
'options',
|
|
81
|
+
'className',
|
|
82
|
+
'description',
|
|
83
|
+
'errorMessage',
|
|
84
|
+
'acceptFile',
|
|
85
|
+
'maxLength',
|
|
86
|
+
'minNumber',
|
|
87
|
+
'maxNumber',
|
|
88
|
+
];
|
|
65
89
|
class DynamicInput extends BaseInputComponent {
|
|
66
90
|
type;
|
|
67
91
|
valueChange = new EventEmitter();
|
|
68
|
-
onChange = new EventEmitter();
|
|
92
|
+
onChange = new EventEmitter();
|
|
69
93
|
host;
|
|
70
94
|
compRef;
|
|
71
95
|
inputInstance;
|
|
72
96
|
subscriptions = [];
|
|
73
97
|
ngOnChanges(changes) {
|
|
98
|
+
super.ngOnChanges(changes);
|
|
99
|
+
if (this.inputInstance) {
|
|
100
|
+
this.syncPropsToInstance(changes);
|
|
101
|
+
}
|
|
74
102
|
if (changes['type'] && !changes['type'].firstChange && this.host) {
|
|
75
103
|
this.render();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
if (this.inputInstance) {
|
|
79
|
-
this.applyKnownProps(this.inputInstance);
|
|
80
|
-
const childChanges = {};
|
|
81
|
-
for (const prop in changes) {
|
|
82
|
-
childChanges[prop] = new SimpleChange(changes[prop].previousValue, changes[prop].currentValue, changes[prop].firstChange);
|
|
83
|
-
}
|
|
84
|
-
this.inputInstance.ngOnChanges?.(childChanges);
|
|
85
|
-
this.compRef?.changeDetectorRef.detectChanges();
|
|
86
104
|
}
|
|
87
|
-
else if (this.host) {
|
|
105
|
+
else if (!this.inputInstance && this.host) {
|
|
88
106
|
this.render();
|
|
89
107
|
}
|
|
90
108
|
}
|
|
@@ -92,6 +110,20 @@ class DynamicInput extends BaseInputComponent {
|
|
|
92
110
|
this.render();
|
|
93
111
|
}
|
|
94
112
|
ngOnDestroy() {
|
|
113
|
+
this.cleanup();
|
|
114
|
+
}
|
|
115
|
+
syncPropsToInstance(changes) {
|
|
116
|
+
if (!this.inputInstance) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
for (const prop of KNOWN_PROPS) {
|
|
120
|
+
if (changes[prop] && this.inputInstance) {
|
|
121
|
+
this.inputInstance[prop] = this[prop];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.compRef?.changeDetectorRef?.detectChanges();
|
|
125
|
+
}
|
|
126
|
+
cleanup() {
|
|
95
127
|
this.cleanupSubscriptions();
|
|
96
128
|
this.cleanupRenderedComponent();
|
|
97
129
|
}
|
|
@@ -99,106 +131,111 @@ class DynamicInput extends BaseInputComponent {
|
|
|
99
131
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
100
132
|
this.subscriptions = [];
|
|
101
133
|
}
|
|
134
|
+
cleanupRenderedComponent() {
|
|
135
|
+
this.compRef?.destroy();
|
|
136
|
+
this.compRef = undefined;
|
|
137
|
+
this.inputInstance = undefined;
|
|
138
|
+
}
|
|
102
139
|
render() {
|
|
103
140
|
const Renderer = fieldRegistry.get(this.type);
|
|
104
|
-
this.
|
|
105
|
-
this.cleanupSubscriptions();
|
|
141
|
+
this.cleanup();
|
|
106
142
|
this.host.clear();
|
|
107
143
|
if (!Renderer) {
|
|
108
|
-
|
|
109
|
-
el.textContent = `Unknown field type: ${this.type}`;
|
|
110
|
-
this.host.element.nativeElement.appendChild(el);
|
|
144
|
+
this.renderError(`Unknown field type: ${this.type}`);
|
|
111
145
|
return;
|
|
112
146
|
}
|
|
147
|
+
if (this.isComponentType(Renderer)) {
|
|
148
|
+
this.renderComponent(Renderer);
|
|
149
|
+
}
|
|
150
|
+
else if (typeof Renderer === 'function') {
|
|
151
|
+
this.renderFallback(Renderer);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
this.renderError(`Invalid renderer for type: ${this.type}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
isComponentType(renderer) {
|
|
158
|
+
return (typeof renderer === 'object' && renderer !== null && 'cmp' in renderer);
|
|
159
|
+
}
|
|
160
|
+
renderComponent(compType) {
|
|
113
161
|
try {
|
|
114
|
-
const compType = Renderer;
|
|
115
162
|
const compRef = this.host.createComponent(compType);
|
|
116
163
|
const instance = compRef.instance;
|
|
117
164
|
if (!instance) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.applyKnownProps(instance);
|
|
121
|
-
const subA = this.bindOutput(instance, 'valueChange');
|
|
122
|
-
if (subA) {
|
|
123
|
-
this.subscriptions.push(subA);
|
|
124
|
-
}
|
|
125
|
-
const subB = this.bindOutput(instance, 'onValueChange');
|
|
126
|
-
if (subB) {
|
|
127
|
-
this.subscriptions.push(subB);
|
|
165
|
+
this.renderError(`Failed to create instance for ${this.type}`);
|
|
166
|
+
return;
|
|
128
167
|
}
|
|
129
|
-
|
|
168
|
+
this.applyProps(instance);
|
|
169
|
+
this.bindOutputs(instance);
|
|
130
170
|
this.compRef = compRef;
|
|
131
171
|
this.inputInstance = instance;
|
|
132
172
|
compRef.changeDetectorRef.detectChanges();
|
|
133
173
|
}
|
|
134
|
-
catch
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
options: this.options,
|
|
144
|
-
className: this.className,
|
|
145
|
-
description: this.description,
|
|
146
|
-
disabled: this.disabled,
|
|
147
|
-
errorMessage: this.errorMessage,
|
|
148
|
-
};
|
|
149
|
-
const out = Renderer(props);
|
|
150
|
-
if (typeof out === 'string') {
|
|
151
|
-
const el = document.createElement('div');
|
|
152
|
-
el.innerHTML = out;
|
|
153
|
-
this.host.element.nativeElement.appendChild(el);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
catch (e) {
|
|
174
|
+
catch {
|
|
175
|
+
this.renderError(`Failed to render field: ${this.type}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
renderFallback(renderer) {
|
|
179
|
+
try {
|
|
180
|
+
const props = this.getFallbackProps();
|
|
181
|
+
const result = renderer(props);
|
|
182
|
+
if (typeof result === 'string') {
|
|
157
183
|
const el = document.createElement('div');
|
|
158
|
-
el.
|
|
184
|
+
el.innerHTML = result;
|
|
159
185
|
this.host.element.nativeElement.appendChild(el);
|
|
160
186
|
}
|
|
161
187
|
}
|
|
188
|
+
catch {
|
|
189
|
+
this.renderError(`Failed to render field: ${this.type}`);
|
|
190
|
+
}
|
|
162
191
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
192
|
+
getFallbackProps() {
|
|
193
|
+
return {
|
|
194
|
+
value: this.value,
|
|
195
|
+
onValueChange: (v) => this.emitValue(v),
|
|
196
|
+
label: this.label ?? '',
|
|
197
|
+
placeholder: this.placeholder ?? '',
|
|
198
|
+
required: this.required ?? false,
|
|
199
|
+
options: this.options ?? [],
|
|
200
|
+
className: this.className ?? '',
|
|
201
|
+
description: this.description ?? '',
|
|
202
|
+
disabled: this.disabled ?? false,
|
|
203
|
+
errorMessage: this.errorMessage ?? '',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
applyProps(instance) {
|
|
207
|
+
const instanceObj = instance;
|
|
208
|
+
for (const prop of KNOWN_PROPS) {
|
|
209
|
+
if (prop in this && prop in instanceObj) {
|
|
210
|
+
instanceObj[prop] = this[prop];
|
|
178
211
|
}
|
|
179
212
|
}
|
|
180
213
|
}
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
214
|
+
bindOutputs(instance) {
|
|
215
|
+
const outputNames = [
|
|
216
|
+
'valueChange',
|
|
217
|
+
'onValueChange',
|
|
218
|
+
];
|
|
219
|
+
for (const outputName of outputNames) {
|
|
220
|
+
const output = instance[outputName];
|
|
221
|
+
if (output && typeof output === 'object' && 'subscribe' in output) {
|
|
222
|
+
const sub = output.subscribe((value) => this.emitValue(value));
|
|
223
|
+
this.subscriptions.push(sub);
|
|
224
|
+
}
|
|
185
225
|
}
|
|
186
|
-
const sub = output.subscribe((value) => {
|
|
187
|
-
this.emitValue(value);
|
|
188
|
-
});
|
|
189
|
-
return sub;
|
|
190
226
|
}
|
|
191
227
|
emitValue(value) {
|
|
192
228
|
this.valueChange.emit(value);
|
|
193
229
|
this.onChange.emit(value);
|
|
194
230
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
231
|
+
renderError(message) {
|
|
232
|
+
const el = document.createElement('div');
|
|
233
|
+
el.textContent = message;
|
|
234
|
+
el.style.color = 'red';
|
|
235
|
+
this.host.element.nativeElement.appendChild(el);
|
|
199
236
|
}
|
|
200
237
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DynamicInput, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
201
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DynamicInput, isStandalone: true, selector: "dfk-dynamic-input", inputs: { type: "type" }, outputs: { valueChange: "valueChange", onChange: "onChange" }, viewQueries: [{ propertyName: "host", first: true, predicate: ["host"], descendants: true, read: ViewContainerRef }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `<div #host style="display: contents;"></div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
238
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: DynamicInput, isStandalone: true, selector: "dfk-dynamic-input", inputs: { type: "type" }, outputs: { valueChange: "valueChange", onChange: "onChange" }, viewQueries: [{ propertyName: "host", first: true, predicate: ["host"], descendants: true, read: ViewContainerRef }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `<div #host style="display: contents;"></div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
202
239
|
}
|
|
203
240
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DynamicInput, decorators: [{
|
|
204
241
|
type: Component,
|
|
@@ -206,6 +243,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
206
243
|
selector: 'dfk-dynamic-input',
|
|
207
244
|
standalone: true,
|
|
208
245
|
imports: [CommonModule],
|
|
246
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
209
247
|
template: `<div #host style="display: contents;"></div>`,
|
|
210
248
|
}]
|
|
211
249
|
}], propDecorators: { type: [{
|
|
@@ -220,29 +258,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
220
258
|
}] } });
|
|
221
259
|
|
|
222
260
|
class FieldInput {
|
|
261
|
+
cdr;
|
|
223
262
|
fieldDescription;
|
|
224
|
-
|
|
263
|
+
value;
|
|
225
264
|
onValueChangeField = new EventEmitter();
|
|
265
|
+
shouldRender = false;
|
|
266
|
+
constructor(cdr) {
|
|
267
|
+
this.cdr = cdr;
|
|
268
|
+
}
|
|
269
|
+
ngOnChanges(_changes) {
|
|
270
|
+
this.shouldRender = !!this.fieldDescription;
|
|
271
|
+
this.cdr.markForCheck();
|
|
272
|
+
}
|
|
226
273
|
getFieldValue() {
|
|
227
|
-
if (!this.fieldDescription
|
|
274
|
+
if (!this.fieldDescription) {
|
|
228
275
|
return undefined;
|
|
229
276
|
}
|
|
230
|
-
|
|
231
|
-
if (value === undefined && this.fieldDescription.type === 'text') {
|
|
277
|
+
if (this.value === undefined && this.fieldDescription.type === 'text') {
|
|
232
278
|
return '';
|
|
233
279
|
}
|
|
234
|
-
return value;
|
|
280
|
+
return this.value;
|
|
235
281
|
}
|
|
236
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: FieldInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
237
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: FieldInput, isStandalone: true, selector: "dfk-field-input", inputs: { fieldDescription: "fieldDescription",
|
|
282
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: FieldInput, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
283
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: FieldInput, isStandalone: true, selector: "dfk-field-input", inputs: { fieldDescription: "fieldDescription", value: "value" }, outputs: { onValueChangeField: "onValueChangeField" }, usesOnChanges: true, ngImport: i0, template: `
|
|
238
284
|
<dfk-dynamic-input
|
|
239
|
-
*ngIf="
|
|
285
|
+
*ngIf="shouldRender"
|
|
240
286
|
[type]="fieldDescription!.type"
|
|
241
287
|
[value]="getFieldValue()"
|
|
242
288
|
[label]="fieldDescription!.label"
|
|
243
289
|
[placeholder]="fieldDescription!.placeholder"
|
|
244
290
|
[required]="fieldDescription!.required"
|
|
245
|
-
[description]="fieldDescription!.description"
|
|
291
|
+
[description]="$any(fieldDescription!.description)"
|
|
246
292
|
[options]="fieldDescription!.options"
|
|
247
293
|
[className]="fieldDescription!.className"
|
|
248
294
|
(valueChange)="
|
|
@@ -251,7 +297,7 @@ class FieldInput {
|
|
|
251
297
|
[disabled]="false"
|
|
252
298
|
[errorMessage]="''"
|
|
253
299
|
></dfk-dynamic-input>
|
|
254
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: DynamicInput, selector: "dfk-dynamic-input", inputs: ["type"], outputs: ["valueChange", "onChange"] }] });
|
|
300
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: DynamicInput, selector: "dfk-dynamic-input", inputs: ["type"], outputs: ["valueChange", "onChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
255
301
|
}
|
|
256
302
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: FieldInput, decorators: [{
|
|
257
303
|
type: Component,
|
|
@@ -259,15 +305,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
259
305
|
selector: 'dfk-field-input',
|
|
260
306
|
standalone: true,
|
|
261
307
|
imports: [NgIf, DynamicInput],
|
|
308
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
262
309
|
template: `
|
|
263
310
|
<dfk-dynamic-input
|
|
264
|
-
*ngIf="
|
|
311
|
+
*ngIf="shouldRender"
|
|
265
312
|
[type]="fieldDescription!.type"
|
|
266
313
|
[value]="getFieldValue()"
|
|
267
314
|
[label]="fieldDescription!.label"
|
|
268
315
|
[placeholder]="fieldDescription!.placeholder"
|
|
269
316
|
[required]="fieldDescription!.required"
|
|
270
|
-
[description]="fieldDescription!.description"
|
|
317
|
+
[description]="$any(fieldDescription!.description)"
|
|
271
318
|
[options]="fieldDescription!.options"
|
|
272
319
|
[className]="fieldDescription!.className"
|
|
273
320
|
(valueChange)="
|
|
@@ -278,33 +325,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
278
325
|
></dfk-dynamic-input>
|
|
279
326
|
`,
|
|
280
327
|
}]
|
|
281
|
-
}], propDecorators: { fieldDescription: [{
|
|
328
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { fieldDescription: [{
|
|
282
329
|
type: Input
|
|
283
|
-
}],
|
|
330
|
+
}], value: [{
|
|
284
331
|
type: Input
|
|
285
332
|
}], onValueChangeField: [{
|
|
286
333
|
type: Output
|
|
287
334
|
}] } });
|
|
288
335
|
|
|
336
|
+
const DEFAULT_BREAKPOINT = 768;
|
|
289
337
|
class MultiFieldInput {
|
|
338
|
+
cdr;
|
|
290
339
|
fieldDescriptions = [];
|
|
291
340
|
properties;
|
|
292
341
|
onChange = new EventEmitter();
|
|
293
342
|
layout = 'column';
|
|
294
343
|
data = {};
|
|
295
344
|
visibleFields = [];
|
|
345
|
+
isMobile = false;
|
|
346
|
+
constructor(cdr) {
|
|
347
|
+
this.cdr = cdr;
|
|
348
|
+
}
|
|
349
|
+
onWindowResize() {
|
|
350
|
+
const wasMobile = this.isMobile;
|
|
351
|
+
this.updateIsMobile();
|
|
352
|
+
if (wasMobile !== this.isMobile) {
|
|
353
|
+
this.cdr.markForCheck();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
get resolvedLayout() {
|
|
357
|
+
if (typeof this.layout === 'object' && this.layout.type === 'responsive') {
|
|
358
|
+
return this.isMobile ? this.layout.mobile : this.layout.desktop;
|
|
359
|
+
}
|
|
360
|
+
return this.layout;
|
|
361
|
+
}
|
|
362
|
+
get resolvedLayoutType() {
|
|
363
|
+
const resolved = this.resolvedLayout;
|
|
364
|
+
return typeof resolved === 'string' ? resolved : resolved.type;
|
|
365
|
+
}
|
|
366
|
+
get gap() {
|
|
367
|
+
const resolved = this.resolvedLayout;
|
|
368
|
+
if (typeof resolved === 'object' && resolved.gap !== undefined) {
|
|
369
|
+
return resolved.gap;
|
|
370
|
+
}
|
|
371
|
+
return 12;
|
|
372
|
+
}
|
|
373
|
+
get columns() {
|
|
374
|
+
const resolved = this.resolvedLayout;
|
|
375
|
+
if (typeof resolved === 'object' && resolved.type === 'grid') {
|
|
376
|
+
return resolved.columns ?? 2;
|
|
377
|
+
}
|
|
378
|
+
return 2;
|
|
379
|
+
}
|
|
296
380
|
trackByFn(index, field) {
|
|
297
381
|
return field.name || index;
|
|
298
382
|
}
|
|
383
|
+
trackByIndex(index) {
|
|
384
|
+
return index;
|
|
385
|
+
}
|
|
299
386
|
ngOnInit() {
|
|
387
|
+
this.updateIsMobile();
|
|
300
388
|
this.init();
|
|
301
389
|
}
|
|
302
390
|
ngOnChanges(_changes) {
|
|
303
391
|
this.init();
|
|
304
392
|
}
|
|
393
|
+
updateIsMobile() {
|
|
394
|
+
const breakpoint = typeof this.layout === 'object' && this.layout.type === 'responsive'
|
|
395
|
+
? this.layout.breakpoint ?? DEFAULT_BREAKPOINT
|
|
396
|
+
: DEFAULT_BREAKPOINT;
|
|
397
|
+
this.isMobile =
|
|
398
|
+
typeof window !== 'undefined' && window.innerWidth < breakpoint;
|
|
399
|
+
}
|
|
305
400
|
init() {
|
|
306
401
|
if (this.properties) {
|
|
307
|
-
this.data =
|
|
402
|
+
this.data = applyComputedValues(this.fieldDescriptions, {
|
|
403
|
+
...this.properties,
|
|
404
|
+
});
|
|
308
405
|
}
|
|
309
406
|
this.updateVisibleFields();
|
|
310
407
|
}
|
|
@@ -312,52 +409,177 @@ class MultiFieldInput {
|
|
|
312
409
|
this.visibleFields = this.fieldDescriptions.filter((f) => !f.appearCondition || f.appearCondition(this.data));
|
|
313
410
|
}
|
|
314
411
|
onFieldChange(event) {
|
|
315
|
-
this.
|
|
412
|
+
this.commitData({ ...this.data, [event.key]: event.value });
|
|
413
|
+
}
|
|
414
|
+
getItems(field) {
|
|
415
|
+
const value = this.data[field.name];
|
|
416
|
+
return Array.isArray(value) ? value : [];
|
|
417
|
+
}
|
|
418
|
+
canAddItem(field) {
|
|
419
|
+
return canAddGroupItem(field, this.getItems(field));
|
|
420
|
+
}
|
|
421
|
+
canRemoveItem(field) {
|
|
422
|
+
return canRemoveGroupItem(field, this.getItems(field));
|
|
423
|
+
}
|
|
424
|
+
onGroupItemAdd(field) {
|
|
425
|
+
if (!this.canAddItem(field)) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const items = this.getItems(field);
|
|
429
|
+
this.commitData({
|
|
430
|
+
...this.data,
|
|
431
|
+
[field.name]: [...items, createGroupItem(field)],
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
onGroupItemRemove(field, index) {
|
|
435
|
+
if (!this.canRemoveItem(field)) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const items = this.getItems(field).filter((_, i) => i !== index);
|
|
439
|
+
this.commitData({ ...this.data, [field.name]: items });
|
|
440
|
+
}
|
|
441
|
+
onGroupItemChange(field, index, next) {
|
|
442
|
+
const items = this.getItems(field).slice();
|
|
443
|
+
items[index] = next;
|
|
444
|
+
this.commitData({ ...this.data, [field.name]: items });
|
|
445
|
+
}
|
|
446
|
+
commitData(nextData) {
|
|
447
|
+
this.data = applyComputedValues(this.fieldDescriptions, nextData);
|
|
316
448
|
this.updateVisibleFields();
|
|
317
449
|
this.onChange.emit(this.data);
|
|
450
|
+
this.cdr.markForCheck();
|
|
318
451
|
}
|
|
319
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: MultiFieldInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
320
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: MultiFieldInput, isStandalone: true, selector: "dfk-multi-field-input", inputs: { fieldDescriptions: "fieldDescriptions", properties: "properties", layout: "layout" }, outputs: { onChange: "onChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
452
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: MultiFieldInput, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
453
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: MultiFieldInput, isStandalone: true, selector: "dfk-multi-field-input", inputs: { fieldDescriptions: "fieldDescriptions", properties: "properties", layout: "layout" }, outputs: { onChange: "onChange" }, host: { listeners: { "window:resize": "onWindowResize()" } }, usesOnChanges: true, ngImport: i0, template: `
|
|
321
454
|
<div
|
|
322
|
-
class="
|
|
455
|
+
class="p-4 border rounded-lg bg-gray-50"
|
|
323
456
|
[ngClass]="{
|
|
324
|
-
'flex
|
|
325
|
-
'
|
|
457
|
+
'flex flex-col': resolvedLayoutType === 'column',
|
|
458
|
+
'flex flex-row': resolvedLayoutType === 'row',
|
|
459
|
+
grid: resolvedLayoutType === 'grid'
|
|
326
460
|
}"
|
|
461
|
+
[style.gap.px]="gap"
|
|
462
|
+
[style.gridTemplateColumns]="
|
|
463
|
+
resolvedLayoutType === 'grid' ? 'repeat(' + columns + ', 1fr)' : null
|
|
464
|
+
"
|
|
327
465
|
>
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
466
|
+
<ng-container *ngFor="let field of visibleFields; trackBy: trackByFn">
|
|
467
|
+
<dfk-field-input
|
|
468
|
+
*ngIf="!field.fields"
|
|
469
|
+
[fieldDescription]="field"
|
|
470
|
+
[value]="data[field.name]"
|
|
471
|
+
(onValueChangeField)="onFieldChange($event)"
|
|
472
|
+
></dfk-field-input>
|
|
473
|
+
|
|
474
|
+
<div *ngIf="field.fields" [class]="field.className">
|
|
475
|
+
<div *ngIf="field.label">{{ field.label }}</div>
|
|
476
|
+
<div
|
|
477
|
+
*ngFor="
|
|
478
|
+
let item of getItems(field);
|
|
479
|
+
let i = index;
|
|
480
|
+
trackBy: trackByIndex
|
|
481
|
+
"
|
|
482
|
+
style="display: flex; align-items: flex-start; gap: 8px;"
|
|
483
|
+
>
|
|
484
|
+
<div style="flex: 1">
|
|
485
|
+
<dfk-multi-field-input
|
|
486
|
+
[fieldDescriptions]="field.fields"
|
|
487
|
+
[properties]="item"
|
|
488
|
+
(onChange)="onGroupItemChange(field, i, $event)"
|
|
489
|
+
></dfk-multi-field-input>
|
|
490
|
+
</div>
|
|
491
|
+
<button
|
|
492
|
+
type="button"
|
|
493
|
+
(click)="onGroupItemRemove(field, i)"
|
|
494
|
+
[disabled]="!canRemoveItem(field)"
|
|
495
|
+
>
|
|
496
|
+
{{ field.removeLabel || 'Remove' }}
|
|
497
|
+
</button>
|
|
498
|
+
</div>
|
|
499
|
+
<button
|
|
500
|
+
type="button"
|
|
501
|
+
(click)="onGroupItemAdd(field)"
|
|
502
|
+
[disabled]="!canAddItem(field)"
|
|
503
|
+
>
|
|
504
|
+
{{ field.addLabel || 'Add' }}
|
|
505
|
+
</button>
|
|
506
|
+
</div>
|
|
507
|
+
</ng-container>
|
|
334
508
|
</div>
|
|
335
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: FieldInput, selector: "dfk-field-input", inputs: ["fieldDescription", "
|
|
509
|
+
`, isInline: true, dependencies: [{ kind: "component", type: MultiFieldInput, selector: "dfk-multi-field-input", inputs: ["fieldDescriptions", "properties", "layout"], outputs: ["onChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FieldInput, selector: "dfk-field-input", inputs: ["fieldDescription", "value"], outputs: ["onValueChangeField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
336
510
|
}
|
|
337
511
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: MultiFieldInput, decorators: [{
|
|
338
512
|
type: Component,
|
|
339
513
|
args: [{
|
|
340
514
|
selector: 'dfk-multi-field-input',
|
|
341
515
|
standalone: true,
|
|
342
|
-
|
|
516
|
+
// Repeatable field groups render a nested <dfk-multi-field-input> per item
|
|
517
|
+
// (see the #groupTpl below), so this component imports itself. That's the
|
|
518
|
+
// supported way to give a standalone component recursive template usage
|
|
519
|
+
// without a cross-file circular import between FieldInput and a separate
|
|
520
|
+
// group component (whose `imports` arrays are evaluated eagerly at module
|
|
521
|
+
// load time and would deadlock on an actual circular module reference).
|
|
522
|
+
imports: [NgClass, NgFor, NgIf, FieldInput, MultiFieldInput],
|
|
523
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
343
524
|
template: `
|
|
344
525
|
<div
|
|
345
|
-
class="
|
|
526
|
+
class="p-4 border rounded-lg bg-gray-50"
|
|
346
527
|
[ngClass]="{
|
|
347
|
-
'flex
|
|
348
|
-
'
|
|
528
|
+
'flex flex-col': resolvedLayoutType === 'column',
|
|
529
|
+
'flex flex-row': resolvedLayoutType === 'row',
|
|
530
|
+
grid: resolvedLayoutType === 'grid'
|
|
349
531
|
}"
|
|
532
|
+
[style.gap.px]="gap"
|
|
533
|
+
[style.gridTemplateColumns]="
|
|
534
|
+
resolvedLayoutType === 'grid' ? 'repeat(' + columns + ', 1fr)' : null
|
|
535
|
+
"
|
|
350
536
|
>
|
|
351
|
-
<
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
537
|
+
<ng-container *ngFor="let field of visibleFields; trackBy: trackByFn">
|
|
538
|
+
<dfk-field-input
|
|
539
|
+
*ngIf="!field.fields"
|
|
540
|
+
[fieldDescription]="field"
|
|
541
|
+
[value]="data[field.name]"
|
|
542
|
+
(onValueChangeField)="onFieldChange($event)"
|
|
543
|
+
></dfk-field-input>
|
|
544
|
+
|
|
545
|
+
<div *ngIf="field.fields" [class]="field.className">
|
|
546
|
+
<div *ngIf="field.label">{{ field.label }}</div>
|
|
547
|
+
<div
|
|
548
|
+
*ngFor="
|
|
549
|
+
let item of getItems(field);
|
|
550
|
+
let i = index;
|
|
551
|
+
trackBy: trackByIndex
|
|
552
|
+
"
|
|
553
|
+
style="display: flex; align-items: flex-start; gap: 8px;"
|
|
554
|
+
>
|
|
555
|
+
<div style="flex: 1">
|
|
556
|
+
<dfk-multi-field-input
|
|
557
|
+
[fieldDescriptions]="field.fields"
|
|
558
|
+
[properties]="item"
|
|
559
|
+
(onChange)="onGroupItemChange(field, i, $event)"
|
|
560
|
+
></dfk-multi-field-input>
|
|
561
|
+
</div>
|
|
562
|
+
<button
|
|
563
|
+
type="button"
|
|
564
|
+
(click)="onGroupItemRemove(field, i)"
|
|
565
|
+
[disabled]="!canRemoveItem(field)"
|
|
566
|
+
>
|
|
567
|
+
{{ field.removeLabel || 'Remove' }}
|
|
568
|
+
</button>
|
|
569
|
+
</div>
|
|
570
|
+
<button
|
|
571
|
+
type="button"
|
|
572
|
+
(click)="onGroupItemAdd(field)"
|
|
573
|
+
[disabled]="!canAddItem(field)"
|
|
574
|
+
>
|
|
575
|
+
{{ field.addLabel || 'Add' }}
|
|
576
|
+
</button>
|
|
577
|
+
</div>
|
|
578
|
+
</ng-container>
|
|
357
579
|
</div>
|
|
358
580
|
`,
|
|
359
581
|
}]
|
|
360
|
-
}], propDecorators: { fieldDescriptions: [{
|
|
582
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { fieldDescriptions: [{
|
|
361
583
|
type: Input
|
|
362
584
|
}], properties: [{
|
|
363
585
|
type: Input
|
|
@@ -365,15 +587,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
365
587
|
type: Output
|
|
366
588
|
}], layout: [{
|
|
367
589
|
type: Input
|
|
590
|
+
}], onWindowResize: [{
|
|
591
|
+
type: HostListener,
|
|
592
|
+
args: ['window:resize']
|
|
368
593
|
}] } });
|
|
369
594
|
|
|
595
|
+
class LayoutRegistry {
|
|
596
|
+
layouts = new Map();
|
|
597
|
+
register(type, component) {
|
|
598
|
+
if (this.layouts.has(type)) {
|
|
599
|
+
console.warn(`[dynamic-field-kit] Layout "${type}" already exists`);
|
|
600
|
+
}
|
|
601
|
+
this.layouts.set(type, component);
|
|
602
|
+
}
|
|
603
|
+
get(type) {
|
|
604
|
+
return this.layouts.get(type);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
const layoutRegistry = new LayoutRegistry();
|
|
608
|
+
|
|
370
609
|
class ColumnLayout {
|
|
610
|
+
config;
|
|
611
|
+
template;
|
|
612
|
+
get gap() {
|
|
613
|
+
return this.config?.gap ?? 12;
|
|
614
|
+
}
|
|
371
615
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ColumnLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
372
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: ColumnLayout, isStandalone: true, selector: "dfk-column-layout", ngImport: i0, template: `<div
|
|
373
|
-
style="
|
|
616
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: ColumnLayout, isStandalone: true, selector: "dfk-column-layout", inputs: { config: "config", template: "template" }, ngImport: i0, template: `<div
|
|
617
|
+
[style.display]="'flex'"
|
|
618
|
+
[style.flexDirection]="'column'"
|
|
619
|
+
[style.gap]="gap + 'px'"
|
|
374
620
|
>
|
|
375
|
-
<ng-
|
|
376
|
-
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
621
|
+
<ng-container *ngTemplateOutlet="template"></ng-container>
|
|
622
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
377
623
|
}
|
|
378
624
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: ColumnLayout, decorators: [{
|
|
379
625
|
type: Component,
|
|
@@ -382,19 +628,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
382
628
|
standalone: true,
|
|
383
629
|
imports: [CommonModule],
|
|
384
630
|
template: `<div
|
|
385
|
-
style="
|
|
631
|
+
[style.display]="'flex'"
|
|
632
|
+
[style.flexDirection]="'column'"
|
|
633
|
+
[style.gap]="gap + 'px'"
|
|
386
634
|
>
|
|
387
|
-
<ng-
|
|
635
|
+
<ng-container *ngTemplateOutlet="template"></ng-container>
|
|
388
636
|
</div>`,
|
|
389
637
|
}]
|
|
390
|
-
}]
|
|
638
|
+
}], propDecorators: { config: [{
|
|
639
|
+
type: Input
|
|
640
|
+
}], template: [{
|
|
641
|
+
type: Input
|
|
642
|
+
}] } });
|
|
391
643
|
class RowLayout {
|
|
644
|
+
config;
|
|
645
|
+
template;
|
|
646
|
+
get gap() {
|
|
647
|
+
return this.config?.gap ?? 12;
|
|
648
|
+
}
|
|
392
649
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: RowLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
393
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: RowLayout, isStandalone: true, selector: "dfk-row-layout", ngImport: i0, template: `<div
|
|
394
|
-
style="
|
|
650
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: RowLayout, isStandalone: true, selector: "dfk-row-layout", inputs: { config: "config", template: "template" }, ngImport: i0, template: `<div
|
|
651
|
+
[style.display]="'flex'"
|
|
652
|
+
[style.flexDirection]="'row'"
|
|
653
|
+
[style.gap]="gap + 'px'"
|
|
395
654
|
>
|
|
396
|
-
<ng-
|
|
397
|
-
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
655
|
+
<ng-container *ngTemplateOutlet="template"></ng-container>
|
|
656
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
398
657
|
}
|
|
399
658
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: RowLayout, decorators: [{
|
|
400
659
|
type: Component,
|
|
@@ -403,19 +662,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
403
662
|
standalone: true,
|
|
404
663
|
imports: [CommonModule],
|
|
405
664
|
template: `<div
|
|
406
|
-
style="
|
|
665
|
+
[style.display]="'flex'"
|
|
666
|
+
[style.flexDirection]="'row'"
|
|
667
|
+
[style.gap]="gap + 'px'"
|
|
407
668
|
>
|
|
408
|
-
<ng-
|
|
669
|
+
<ng-container *ngTemplateOutlet="template"></ng-container>
|
|
409
670
|
</div>`,
|
|
410
671
|
}]
|
|
411
|
-
}]
|
|
672
|
+
}], propDecorators: { config: [{
|
|
673
|
+
type: Input
|
|
674
|
+
}], template: [{
|
|
675
|
+
type: Input
|
|
676
|
+
}] } });
|
|
412
677
|
class GridLayout {
|
|
678
|
+
config;
|
|
679
|
+
template;
|
|
680
|
+
get columns() {
|
|
681
|
+
return this.config?.columns ?? 2;
|
|
682
|
+
}
|
|
683
|
+
get gap() {
|
|
684
|
+
return this.config?.gap ?? 12;
|
|
685
|
+
}
|
|
413
686
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
414
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: GridLayout, isStandalone: true, selector: "dfk-grid-layout", ngImport: i0, template: `<div
|
|
415
|
-
style="
|
|
687
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: GridLayout, isStandalone: true, selector: "dfk-grid-layout", inputs: { config: "config", template: "template" }, ngImport: i0, template: `<div
|
|
688
|
+
[style.display]="'grid'"
|
|
689
|
+
[style.gridTemplateColumns]="'repeat(' + columns + ', 1fr)'"
|
|
690
|
+
[style.gap]="gap + 'px'"
|
|
416
691
|
>
|
|
417
|
-
<ng-
|
|
418
|
-
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
692
|
+
<ng-container *ngTemplateOutlet="template"></ng-container>
|
|
693
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
419
694
|
}
|
|
420
695
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: GridLayout, decorators: [{
|
|
421
696
|
type: Component,
|
|
@@ -424,12 +699,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
424
699
|
standalone: true,
|
|
425
700
|
imports: [CommonModule],
|
|
426
701
|
template: `<div
|
|
427
|
-
style="
|
|
702
|
+
[style.display]="'grid'"
|
|
703
|
+
[style.gridTemplateColumns]="'repeat(' + columns + ', 1fr)'"
|
|
704
|
+
[style.gap]="gap + 'px'"
|
|
428
705
|
>
|
|
429
|
-
<ng-
|
|
706
|
+
<ng-container *ngTemplateOutlet="template"></ng-container>
|
|
430
707
|
</div>`,
|
|
431
708
|
}]
|
|
432
|
-
}]
|
|
709
|
+
}], propDecorators: { config: [{
|
|
710
|
+
type: Input
|
|
711
|
+
}], template: [{
|
|
712
|
+
type: Input
|
|
713
|
+
}] } });
|
|
714
|
+
layoutRegistry.register('column', ColumnLayout);
|
|
715
|
+
layoutRegistry.register('row', RowLayout);
|
|
716
|
+
layoutRegistry.register('grid', GridLayout);
|
|
433
717
|
|
|
434
718
|
class DynamicFieldKitModule {
|
|
435
719
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DynamicFieldKitModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -483,5 +767,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
|
|
|
483
767
|
* Generated bundle index. Do not edit.
|
|
484
768
|
*/
|
|
485
769
|
|
|
486
|
-
export { BaseInputComponent, ColumnLayout, DynamicFieldKitModule, DynamicInput, FieldInput, GridLayout, MultiFieldInput, RowLayout };
|
|
770
|
+
export { BaseInputComponent, ColumnLayout, DynamicFieldKitModule, DynamicInput, FieldInput, GridLayout, LayoutRegistry, MultiFieldInput, RowLayout, layoutRegistry };
|
|
487
771
|
//# sourceMappingURL=dynamic-field-kit-angular.mjs.map
|