@dynamic-field-kit/angular 1.2.4 → 1.2.10
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 +54 -46
- package/dist/README.md +126 -0
- package/dist/components/BaseInput.d.ts +22 -0
- package/{components → dist/components}/DynamicInput.d.ts +24 -28
- package/dist/components/FieldInput.d.ts +14 -0
- package/{components → dist/components}/MultiFieldInput.d.ts +23 -23
- package/dist/esm2022/components/BaseInput.mjs +60 -0
- package/dist/esm2022/components/DynamicInput.mjs +162 -0
- package/dist/esm2022/components/FieldInput.mjs +71 -0
- package/dist/esm2022/components/MultiFieldInput.mjs +85 -0
- package/{esm2020 → dist/esm2022}/dynamic-field-kit-angular.mjs +4 -4
- package/dist/esm2022/layout/defaultLayouts.mjs +67 -0
- package/{esm2020 → dist/esm2022}/layout/index.mjs +2 -2
- package/dist/esm2022/lib/dynamic-field-kit.module.mjs +52 -0
- package/{esm2020 → dist/esm2022}/public-api.mjs +14 -14
- package/{esm2020 → dist/esm2022}/types/layout.mjs +2 -2
- package/{fesm2020 → dist/fesm2022}/dynamic-field-kit-angular.mjs +434 -337
- package/dist/fesm2022/dynamic-field-kit-angular.mjs.map +1 -0
- package/{index.d.ts → dist/index.d.ts} +5 -5
- package/{layout → dist/layout}/defaultLayouts.d.ts +13 -13
- package/dist/layout/index.d.ts +1 -0
- package/{lib → dist/lib}/dynamic-field-kit.module.d.ts +11 -11
- package/{public-api.d.ts → dist/public-api.d.ts} +9 -9
- package/dist/types/layout.d.ts +1 -0
- package/ng-package.json +7 -0
- package/package.json +31 -28
- package/src/adapters/tailwind.ts +13 -0
- package/src/components/BaseInput.ts +31 -0
- package/src/components/DynamicInput.ts +188 -0
- package/src/components/FieldInput.ts +49 -0
- package/src/components/MultiFieldInput.ts +75 -0
- package/src/components/imports.ts +3 -0
- package/src/examples/index.ts +4 -0
- package/src/examples/registerExample.ts +7 -0
- package/src/examples/text-field.component.ts +18 -0
- package/src/layout/defaultLayouts.ts +38 -0
- package/src/layout/index.ts +1 -0
- package/src/lib/dynamic-field-kit.module.ts +29 -0
- package/src/public-api.ts +24 -0
- package/src/types/layout.ts +1 -0
- package/src/types.ts +1 -0
- package/tsconfig.json +13 -0
- package/components/BaseInput.d.ts +0 -22
- package/components/FieldInput.d.ts +0 -14
- package/esm2020/components/BaseInput.mjs +0 -46
- package/esm2020/components/DynamicInput.mjs +0 -146
- package/esm2020/components/FieldInput.mjs +0 -66
- package/esm2020/components/MultiFieldInput.mjs +0 -79
- package/esm2020/layout/defaultLayouts.mjs +0 -43
- package/esm2020/lib/dynamic-field-kit.module.mjs +0 -20
- package/fesm2015/dynamic-field-kit-angular.mjs +0 -393
- package/fesm2015/dynamic-field-kit-angular.mjs.map +0 -1
- package/fesm2020/dynamic-field-kit-angular.mjs.map +0 -1
- package/layout/index.d.ts +0 -1
- package/types/layout.d.ts +0 -1
package/README.md
CHANGED
|
@@ -12,6 +12,10 @@ Demo app: https://github.com/vannt-dev/dynamic-field-kit-demo
|
|
|
12
12
|
npm install @dynamic-field-kit/core @dynamic-field-kit/angular
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
Note: Core is shared runtime. Install core separately and ensure a single version is used across adapters to avoid duplicate registries.
|
|
16
|
+
|
|
17
|
+
- Install with core: `npm install @dynamic-field-kit/core @dynamic-field-kit/angular`
|
|
18
|
+
|
|
15
19
|
If you need to pin versions explicitly:
|
|
16
20
|
|
|
17
21
|
```bash
|
|
@@ -26,37 +30,52 @@ npm install @dynamic-field-kit/core@^1.0.12 @dynamic-field-kit/angular@^1.2.3
|
|
|
26
30
|
- `DynamicFieldKitModule`
|
|
27
31
|
- `fieldRegistry`
|
|
28
32
|
|
|
29
|
-
## Basic setup
|
|
33
|
+
## Basic setup (Angular 19+)
|
|
30
34
|
|
|
31
|
-
1. Import
|
|
35
|
+
1. Import the component and register fields before bootstrap.
|
|
32
36
|
|
|
33
37
|
```ts
|
|
34
|
-
import
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
import 'zone.js';
|
|
39
|
+
import { bootstrapApplication } from '@angular/platform-browser';
|
|
40
|
+
import { fieldRegistry } from '@dynamic-field-kit/angular';
|
|
41
|
+
import { AppComponent } from './app/app.component';
|
|
42
|
+
import { TextFieldComponent } from './app/components/text-field.component';
|
|
43
|
+
import { NumberFieldComponent } from './app/components/number-field.component';
|
|
44
|
+
|
|
45
|
+
fieldRegistry.register('text', TextFieldComponent as any);
|
|
46
|
+
fieldRegistry.register('number', NumberFieldComponent as any);
|
|
47
|
+
|
|
48
|
+
bootstrapApplication(AppComponent, {
|
|
49
|
+
providers: [],
|
|
50
|
+
}).catch((err) => console.error(err));
|
|
42
51
|
```
|
|
43
52
|
|
|
44
|
-
2.
|
|
53
|
+
2. Use the component in a standalone component.
|
|
45
54
|
|
|
46
55
|
```ts
|
|
47
|
-
import
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
import { Component } from '@angular/core';
|
|
57
|
+
import { CommonModule } from '@angular/common';
|
|
58
|
+
import { FieldDescription } from '@dynamic-field-kit/core';
|
|
59
|
+
import { MultiFieldInput } from '@dynamic-field-kit/angular';
|
|
60
|
+
|
|
61
|
+
@Component({
|
|
62
|
+
selector: 'app-root',
|
|
63
|
+
standalone: true,
|
|
64
|
+
imports: [CommonModule, MultiFieldInput],
|
|
65
|
+
templateUrl: './app.component.html',
|
|
66
|
+
})
|
|
67
|
+
export class AppComponent {
|
|
68
|
+
fields: FieldDescription[] = [
|
|
69
|
+
{ name: 'name', type: 'text', label: 'Name' },
|
|
70
|
+
{ name: 'age', type: 'number', label: 'Age' },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
data: any = {};
|
|
74
|
+
|
|
75
|
+
onChange(data: any) {
|
|
76
|
+
this.data = data;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
60
79
|
```
|
|
61
80
|
|
|
62
81
|
3. Render your schema in a template.
|
|
@@ -69,39 +88,28 @@ platformBrowserDynamic()
|
|
|
69
88
|
></dfk-multi-field-input>
|
|
70
89
|
```
|
|
71
90
|
|
|
72
|
-
|
|
91
|
+
## Legacy setup (Angular 14 and earlier with NgModule)
|
|
73
92
|
|
|
74
93
|
```ts
|
|
75
|
-
import {
|
|
76
|
-
import {
|
|
94
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
95
|
+
import { NgModule } from '@angular/core';
|
|
96
|
+
import { DynamicFieldKitModule } from '@dynamic-field-kit/angular';
|
|
77
97
|
|
|
78
|
-
@
|
|
79
|
-
|
|
80
|
-
templateUrl: "./app.component.html",
|
|
98
|
+
@NgModule({
|
|
99
|
+
imports: [BrowserModule, DynamicFieldKitModule],
|
|
81
100
|
})
|
|
82
|
-
export class
|
|
83
|
-
fields: FieldDescription[] = [
|
|
84
|
-
{ name: "name", type: "text", label: "Name" },
|
|
85
|
-
{ name: "age", type: "number", label: "Age" },
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
data: any = {}
|
|
89
|
-
|
|
90
|
-
onChange(data: any) {
|
|
91
|
-
this.data = data
|
|
92
|
-
}
|
|
93
|
-
}
|
|
101
|
+
export class AppModule {}
|
|
94
102
|
```
|
|
95
103
|
|
|
96
104
|
## Type augmentation
|
|
97
105
|
|
|
98
106
|
```ts
|
|
99
|
-
import
|
|
107
|
+
import '@dynamic-field-kit/core';
|
|
100
108
|
|
|
101
|
-
declare module
|
|
109
|
+
declare module '@dynamic-field-kit/core' {
|
|
102
110
|
interface FieldTypeMap {
|
|
103
|
-
text: string
|
|
104
|
-
number: number
|
|
111
|
+
text: string;
|
|
112
|
+
number: number;
|
|
105
113
|
}
|
|
106
114
|
}
|
|
107
115
|
```
|
package/dist/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# @dynamic-field-kit/angular
|
|
2
|
+
|
|
3
|
+
Angular adapter for `@dynamic-field-kit/core`.
|
|
4
|
+
|
|
5
|
+
This package provides Angular components and a convenience module that render field schemas defined with `@dynamic-field-kit/core`.
|
|
6
|
+
|
|
7
|
+
Demo app: https://github.com/vannt-dev/dynamic-field-kit-demo
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @dynamic-field-kit/core @dynamic-field-kit/angular
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Note: Core is shared runtime. Install core separately and ensure a single version is used across adapters to avoid duplicate registries.
|
|
16
|
+
|
|
17
|
+
- Install with core: `npm install @dynamic-field-kit/core @dynamic-field-kit/angular`
|
|
18
|
+
|
|
19
|
+
If you need to pin versions explicitly:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @dynamic-field-kit/core@^1.0.12 @dynamic-field-kit/angular@^1.2.3
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## What it exports
|
|
26
|
+
|
|
27
|
+
- `DynamicInput`
|
|
28
|
+
- `FieldInput`
|
|
29
|
+
- `MultiFieldInput`
|
|
30
|
+
- `DynamicFieldKitModule`
|
|
31
|
+
- `fieldRegistry`
|
|
32
|
+
|
|
33
|
+
## Basic setup (Angular 19+)
|
|
34
|
+
|
|
35
|
+
1. Import the component and register fields before bootstrap.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import 'zone.js';
|
|
39
|
+
import { bootstrapApplication } from '@angular/platform-browser';
|
|
40
|
+
import { fieldRegistry } from '@dynamic-field-kit/angular';
|
|
41
|
+
import { AppComponent } from './app/app.component';
|
|
42
|
+
import { TextFieldComponent } from './app/components/text-field.component';
|
|
43
|
+
import { NumberFieldComponent } from './app/components/number-field.component';
|
|
44
|
+
|
|
45
|
+
fieldRegistry.register('text', TextFieldComponent as any);
|
|
46
|
+
fieldRegistry.register('number', NumberFieldComponent as any);
|
|
47
|
+
|
|
48
|
+
bootstrapApplication(AppComponent, {
|
|
49
|
+
providers: [],
|
|
50
|
+
}).catch((err) => console.error(err));
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. Use the component in a standalone component.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { Component } from '@angular/core';
|
|
57
|
+
import { CommonModule } from '@angular/common';
|
|
58
|
+
import { FieldDescription } from '@dynamic-field-kit/core';
|
|
59
|
+
import { MultiFieldInput } from '@dynamic-field-kit/angular';
|
|
60
|
+
|
|
61
|
+
@Component({
|
|
62
|
+
selector: 'app-root',
|
|
63
|
+
standalone: true,
|
|
64
|
+
imports: [CommonModule, MultiFieldInput],
|
|
65
|
+
templateUrl: './app.component.html',
|
|
66
|
+
})
|
|
67
|
+
export class AppComponent {
|
|
68
|
+
fields: FieldDescription[] = [
|
|
69
|
+
{ name: 'name', type: 'text', label: 'Name' },
|
|
70
|
+
{ name: 'age', type: 'number', label: 'Age' },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
data: any = {};
|
|
74
|
+
|
|
75
|
+
onChange(data: any) {
|
|
76
|
+
this.data = data;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
3. Render your schema in a template.
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<dfk-multi-field-input
|
|
85
|
+
[fieldDescriptions]="fields"
|
|
86
|
+
[properties]="data"
|
|
87
|
+
(onChange)="onChange($event)"
|
|
88
|
+
></dfk-multi-field-input>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Legacy setup (Angular 14 and earlier with NgModule)
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
95
|
+
import { NgModule } from '@angular/core';
|
|
96
|
+
import { DynamicFieldKitModule } from '@dynamic-field-kit/angular';
|
|
97
|
+
|
|
98
|
+
@NgModule({
|
|
99
|
+
imports: [BrowserModule, DynamicFieldKitModule],
|
|
100
|
+
})
|
|
101
|
+
export class AppModule {}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Type augmentation
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import '@dynamic-field-kit/core';
|
|
108
|
+
|
|
109
|
+
declare module '@dynamic-field-kit/core' {
|
|
110
|
+
interface FieldTypeMap {
|
|
111
|
+
text: string;
|
|
112
|
+
number: number;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Notes
|
|
118
|
+
|
|
119
|
+
- Register Angular component classes in `fieldRegistry`.
|
|
120
|
+
- Do not register React or Vue renderers in the Angular adapter.
|
|
121
|
+
- `MultiFieldInput` supports `column`, `row`, and `grid` layouts.
|
|
122
|
+
- The shared schema and field types still come from `@dynamic-field-kit/core`.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ChangeDetectorRef, EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare abstract class BaseInputComponent {
|
|
4
|
+
protected cdr: ChangeDetectorRef;
|
|
5
|
+
value?: any;
|
|
6
|
+
label?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
options?: any[];
|
|
11
|
+
className?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
errorMessage?: string;
|
|
14
|
+
acceptFile?: string;
|
|
15
|
+
maxLength?: number;
|
|
16
|
+
minNumber?: number;
|
|
17
|
+
maxNumber?: number;
|
|
18
|
+
valueChange: EventEmitter<any>;
|
|
19
|
+
constructor(cdr: ChangeDetectorRef);
|
|
20
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BaseInputComponent, never>;
|
|
21
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BaseInputComponent, "ng-component", never, { "value": { "alias": "value"; "required": false; }; "label": { "alias": "label"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "required": { "alias": "required"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "options": { "alias": "options"; "required": false; }; "className": { "alias": "className"; "required": false; }; "description": { "alias": "description"; "required": false; }; "errorMessage": { "alias": "errorMessage"; "required": false; }; "acceptFile": { "alias": "acceptFile"; "required": false; }; "maxLength": { "alias": "maxLength"; "required": false; }; "minNumber": { "alias": "minNumber"; "required": false; }; "maxNumber": { "alias": "maxNumber"; "required": false; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
|
|
22
|
+
}
|
|
@@ -1,28 +1,24 @@
|
|
|
1
|
-
import { EventEmitter, ViewContainerRef, OnChanges, AfterViewInit, SimpleChanges } from
|
|
2
|
-
import { FieldTypeKey } from
|
|
3
|
-
import { BaseInputComponent } from
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export declare class DynamicInput extends BaseInputComponent implements OnChanges, AfterViewInit {
|
|
6
|
-
type: FieldTypeKey;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
private cleanupRenderedComponent;
|
|
26
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicInput, never>;
|
|
27
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicInput, "dfk-dynamic-input", never, { "type": "type"; "value": "value"; "label": "label"; "placeholder": "placeholder"; "required": "required"; "options": "options"; "className": "className"; "description": "description"; }, { "valueChange": "valueChange"; "onChange": "onChange"; }, never, never, true, never>;
|
|
28
|
-
}
|
|
1
|
+
import { EventEmitter, ViewContainerRef, OnChanges, AfterViewInit, OnDestroy, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { FieldTypeKey } from '@dynamic-field-kit/core';
|
|
3
|
+
import { BaseInputComponent } from './BaseInput';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class DynamicInput extends BaseInputComponent implements OnChanges, AfterViewInit, OnDestroy {
|
|
6
|
+
type: FieldTypeKey;
|
|
7
|
+
valueChange: EventEmitter<any>;
|
|
8
|
+
onChange: EventEmitter<any>;
|
|
9
|
+
host: ViewContainerRef;
|
|
10
|
+
private compRef?;
|
|
11
|
+
private inputInstance?;
|
|
12
|
+
private subscriptions;
|
|
13
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
14
|
+
ngAfterViewInit(): void;
|
|
15
|
+
ngOnDestroy(): void;
|
|
16
|
+
private cleanupSubscriptions;
|
|
17
|
+
private render;
|
|
18
|
+
private applyKnownProps;
|
|
19
|
+
private bindOutput;
|
|
20
|
+
private emitValue;
|
|
21
|
+
private cleanupRenderedComponent;
|
|
22
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicInput, never>;
|
|
23
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicInput, "dfk-dynamic-input", never, { "type": { "alias": "type"; "required": false; }; }, { "valueChange": "valueChange"; "onChange": "onChange"; }, never, never, true, never>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import { FieldDescription, Properties } from '@dynamic-field-kit/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class FieldInput {
|
|
5
|
+
fieldDescription?: FieldDescription;
|
|
6
|
+
renderInfos?: Properties;
|
|
7
|
+
onValueChangeField: EventEmitter<{
|
|
8
|
+
value: any;
|
|
9
|
+
key: string;
|
|
10
|
+
}>;
|
|
11
|
+
getFieldValue(): unknown;
|
|
12
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FieldInput, never>;
|
|
13
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<FieldInput, "dfk-field-input", never, { "fieldDescription": { "alias": "fieldDescription"; "required": false; }; "renderInfos": { "alias": "renderInfos"; "required": false; }; }, { "onValueChangeField": "onValueChangeField"; }, never, never, true, never>;
|
|
14
|
+
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { EventEmitter, OnChanges, OnInit, SimpleChanges } from
|
|
2
|
-
import { FieldDescription, Properties } from
|
|
3
|
-
import { LayoutConfig } from
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export declare class MultiFieldInput implements OnInit, OnChanges {
|
|
6
|
-
fieldDescriptions: FieldDescription[];
|
|
7
|
-
properties?: Properties;
|
|
8
|
-
onChange: EventEmitter<Properties>;
|
|
9
|
-
layout: LayoutConfig;
|
|
10
|
-
data: Properties;
|
|
11
|
-
visibleFields: FieldDescription[];
|
|
12
|
-
trackByFn(index: number, field: FieldDescription): string | number;
|
|
13
|
-
ngOnInit(): void;
|
|
14
|
-
ngOnChanges(_changes: SimpleChanges): void;
|
|
15
|
-
private init;
|
|
16
|
-
private updateVisibleFields;
|
|
17
|
-
onFieldChange(event: {
|
|
18
|
-
value: any;
|
|
19
|
-
key: string;
|
|
20
|
-
}): void;
|
|
21
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<MultiFieldInput, never>;
|
|
22
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<MultiFieldInput, "dfk-multi-field-input", never, { "fieldDescriptions": "fieldDescriptions"; "properties": "properties"; "layout": "layout"; }, { "onChange": "onChange"; }, never, never, true, never>;
|
|
23
|
-
}
|
|
1
|
+
import { EventEmitter, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { FieldDescription, Properties } from '@dynamic-field-kit/core';
|
|
3
|
+
import { LayoutConfig } from '../types/layout';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class MultiFieldInput implements OnInit, OnChanges {
|
|
6
|
+
fieldDescriptions: FieldDescription[];
|
|
7
|
+
properties?: Properties;
|
|
8
|
+
onChange: EventEmitter<Properties>;
|
|
9
|
+
layout: LayoutConfig;
|
|
10
|
+
data: Properties;
|
|
11
|
+
visibleFields: FieldDescription[];
|
|
12
|
+
trackByFn(index: number, field: FieldDescription): string | number;
|
|
13
|
+
ngOnInit(): void;
|
|
14
|
+
ngOnChanges(_changes: SimpleChanges): void;
|
|
15
|
+
private init;
|
|
16
|
+
private updateVisibleFields;
|
|
17
|
+
onFieldChange(event: {
|
|
18
|
+
value: any;
|
|
19
|
+
key: string;
|
|
20
|
+
}): void;
|
|
21
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MultiFieldInput, never>;
|
|
22
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MultiFieldInput, "dfk-multi-field-input", never, { "fieldDescriptions": { "alias": "fieldDescriptions"; "required": false; }; "properties": { "alias": "properties"; "required": false; }; "layout": { "alias": "layout"; "required": false; }; }, { "onChange": "onChange"; }, never, never, true, never>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output, } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export class BaseInputComponent {
|
|
4
|
+
cdr;
|
|
5
|
+
value;
|
|
6
|
+
label;
|
|
7
|
+
placeholder;
|
|
8
|
+
required;
|
|
9
|
+
disabled;
|
|
10
|
+
options;
|
|
11
|
+
className;
|
|
12
|
+
description;
|
|
13
|
+
errorMessage;
|
|
14
|
+
acceptFile;
|
|
15
|
+
maxLength;
|
|
16
|
+
minNumber;
|
|
17
|
+
maxNumber;
|
|
18
|
+
// Add more from mplis as needed
|
|
19
|
+
valueChange = new EventEmitter();
|
|
20
|
+
constructor(cdr) {
|
|
21
|
+
this.cdr = cdr;
|
|
22
|
+
}
|
|
23
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
24
|
+
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 });
|
|
25
|
+
}
|
|
26
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, decorators: [{
|
|
27
|
+
type: Component,
|
|
28
|
+
args: [{
|
|
29
|
+
template: '',
|
|
30
|
+
}]
|
|
31
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { value: [{
|
|
32
|
+
type: Input
|
|
33
|
+
}], label: [{
|
|
34
|
+
type: Input
|
|
35
|
+
}], placeholder: [{
|
|
36
|
+
type: Input
|
|
37
|
+
}], required: [{
|
|
38
|
+
type: Input
|
|
39
|
+
}], disabled: [{
|
|
40
|
+
type: Input
|
|
41
|
+
}], options: [{
|
|
42
|
+
type: Input
|
|
43
|
+
}], className: [{
|
|
44
|
+
type: Input
|
|
45
|
+
}], description: [{
|
|
46
|
+
type: Input
|
|
47
|
+
}], errorMessage: [{
|
|
48
|
+
type: Input
|
|
49
|
+
}], acceptFile: [{
|
|
50
|
+
type: Input
|
|
51
|
+
}], maxLength: [{
|
|
52
|
+
type: Input
|
|
53
|
+
}], minNumber: [{
|
|
54
|
+
type: Input
|
|
55
|
+
}], maxNumber: [{
|
|
56
|
+
type: Input
|
|
57
|
+
}], valueChange: [{
|
|
58
|
+
type: Output
|
|
59
|
+
}] } });
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzZUlucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvQmFzZUlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7O0FBS3ZCLE1BQU0sT0FBZ0Isa0JBQWtCO0lBa0JoQjtJQWpCYixLQUFLLENBQU87SUFDWixLQUFLLENBQVU7SUFDZixXQUFXLENBQVU7SUFDckIsUUFBUSxDQUFXO0lBQ25CLFFBQVEsQ0FBVztJQUNuQixPQUFPLENBQVM7SUFDaEIsU0FBUyxDQUFVO0lBQ25CLFdBQVcsQ0FBVTtJQUNyQixZQUFZLENBQVU7SUFDdEIsVUFBVSxDQUFVO0lBQ3BCLFNBQVMsQ0FBVTtJQUNuQixTQUFTLENBQVU7SUFDbkIsU0FBUyxDQUFVO0lBQzVCLGdDQUFnQztJQUV0QixXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztJQUVoRCxZQUFzQixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtJQUFHLENBQUM7d0dBbEI1QixrQkFBa0I7NEZBQWxCLGtCQUFrQiw2YUFGNUIsRUFBRTs7NEZBRVEsa0JBQWtCO2tCQUh2QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxFQUFFO2lCQUNiO3NGQUVVLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR0ksV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE91dHB1dCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZTogJycsXG59KVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VJbnB1dENvbXBvbmVudCB7XG4gIEBJbnB1dCgpIHZhbHVlPzogYW55O1xuICBASW5wdXQoKSBsYWJlbD86IHN0cmluZztcbiAgQElucHV0KCkgcGxhY2Vob2xkZXI/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHJlcXVpcmVkPzogYm9vbGVhbjtcbiAgQElucHV0KCkgZGlzYWJsZWQ/OiBib29sZWFuO1xuICBASW5wdXQoKSBvcHRpb25zPzogYW55W107XG4gIEBJbnB1dCgpIGNsYXNzTmFtZT86IHN0cmluZztcbiAgQElucHV0KCkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGVycm9yTWVzc2FnZT86IHN0cmluZztcbiAgQElucHV0KCkgYWNjZXB0RmlsZT86IHN0cmluZztcbiAgQElucHV0KCkgbWF4TGVuZ3RoPzogbnVtYmVyO1xuICBASW5wdXQoKSBtaW5OdW1iZXI/OiBudW1iZXI7XG4gIEBJbnB1dCgpIG1heE51bWJlcj86IG51bWJlcjtcbiAgLy8gQWRkIG1vcmUgZnJvbSBtcGxpcyBhcyBuZWVkZWRcblxuICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cbn1cbiJdfQ==
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, Input, Output, EventEmitter, ViewChild, ViewContainerRef, SimpleChange, } from '@angular/core';
|
|
3
|
+
import { fieldRegistry } from '@dynamic-field-kit/core';
|
|
4
|
+
import { BaseInputComponent } from './BaseInput';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export class DynamicInput extends BaseInputComponent {
|
|
7
|
+
type;
|
|
8
|
+
valueChange = new EventEmitter();
|
|
9
|
+
onChange = new EventEmitter(); // backward compat
|
|
10
|
+
host;
|
|
11
|
+
compRef;
|
|
12
|
+
inputInstance;
|
|
13
|
+
subscriptions = [];
|
|
14
|
+
ngOnChanges(changes) {
|
|
15
|
+
if (changes['type'] && !changes['type'].firstChange && this.host) {
|
|
16
|
+
this.render();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (this.inputInstance) {
|
|
20
|
+
this.applyKnownProps(this.inputInstance);
|
|
21
|
+
const childChanges = {};
|
|
22
|
+
for (const prop in changes) {
|
|
23
|
+
childChanges[prop] = new SimpleChange(changes[prop].previousValue, changes[prop].currentValue, changes[prop].firstChange);
|
|
24
|
+
}
|
|
25
|
+
this.inputInstance.ngOnChanges?.(childChanges);
|
|
26
|
+
this.compRef?.changeDetectorRef.detectChanges();
|
|
27
|
+
}
|
|
28
|
+
else if (this.host) {
|
|
29
|
+
this.render();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
ngAfterViewInit() {
|
|
33
|
+
this.render();
|
|
34
|
+
}
|
|
35
|
+
ngOnDestroy() {
|
|
36
|
+
this.cleanupSubscriptions();
|
|
37
|
+
this.cleanupRenderedComponent();
|
|
38
|
+
}
|
|
39
|
+
cleanupSubscriptions() {
|
|
40
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
41
|
+
this.subscriptions = [];
|
|
42
|
+
}
|
|
43
|
+
render() {
|
|
44
|
+
const Renderer = fieldRegistry.get(this.type);
|
|
45
|
+
this.cleanupRenderedComponent();
|
|
46
|
+
this.cleanupSubscriptions();
|
|
47
|
+
this.host.clear();
|
|
48
|
+
if (!Renderer) {
|
|
49
|
+
const el = document.createElement('div');
|
|
50
|
+
el.textContent = `Unknown field type: ${this.type}`;
|
|
51
|
+
this.host.element.nativeElement.appendChild(el);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const compType = Renderer;
|
|
56
|
+
const compRef = this.host.createComponent(compType);
|
|
57
|
+
const instance = compRef.instance;
|
|
58
|
+
if (!instance) {
|
|
59
|
+
throw new Error(`Failed to create instance for ${this.type}`);
|
|
60
|
+
}
|
|
61
|
+
this.applyKnownProps(instance);
|
|
62
|
+
const subA = this.bindOutput(instance, 'valueChange');
|
|
63
|
+
if (subA) {
|
|
64
|
+
this.subscriptions.push(subA);
|
|
65
|
+
}
|
|
66
|
+
const subB = this.bindOutput(instance, 'onValueChange');
|
|
67
|
+
if (subB) {
|
|
68
|
+
this.subscriptions.push(subB);
|
|
69
|
+
}
|
|
70
|
+
instance.changeDetectorRef?.detectChanges();
|
|
71
|
+
this.compRef = compRef;
|
|
72
|
+
this.inputInstance = instance;
|
|
73
|
+
compRef.changeDetectorRef.detectChanges();
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
// Fallback to function renderer
|
|
77
|
+
try {
|
|
78
|
+
const props = {
|
|
79
|
+
value: this.value,
|
|
80
|
+
onValueChange: (v) => this.emitValue(v),
|
|
81
|
+
label: this.label,
|
|
82
|
+
placeholder: this.placeholder,
|
|
83
|
+
required: this.required,
|
|
84
|
+
options: this.options,
|
|
85
|
+
className: this.className,
|
|
86
|
+
description: this.description,
|
|
87
|
+
disabled: this.disabled,
|
|
88
|
+
errorMessage: this.errorMessage,
|
|
89
|
+
};
|
|
90
|
+
const out = Renderer(props);
|
|
91
|
+
if (typeof out === 'string') {
|
|
92
|
+
const el = document.createElement('div');
|
|
93
|
+
el.innerHTML = out;
|
|
94
|
+
this.host.element.nativeElement.appendChild(el);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
const el = document.createElement('div');
|
|
99
|
+
el.textContent = `Failed to render field: ${this.type}`;
|
|
100
|
+
this.host.element.nativeElement.appendChild(el);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
applyKnownProps(instance) {
|
|
105
|
+
const knownProps = [
|
|
106
|
+
'value',
|
|
107
|
+
'label',
|
|
108
|
+
'placeholder',
|
|
109
|
+
'required',
|
|
110
|
+
'disabled',
|
|
111
|
+
'options',
|
|
112
|
+
'className',
|
|
113
|
+
'description',
|
|
114
|
+
'errorMessage',
|
|
115
|
+
];
|
|
116
|
+
for (const prop of knownProps) {
|
|
117
|
+
if (prop in this && prop in instance) {
|
|
118
|
+
instance[prop] = this[prop];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
bindOutput(instance, outputName) {
|
|
123
|
+
const output = instance?.[outputName];
|
|
124
|
+
if (!output || typeof output.subscribe !== 'function') {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const sub = output.subscribe((value) => {
|
|
128
|
+
this.emitValue(value);
|
|
129
|
+
});
|
|
130
|
+
return sub;
|
|
131
|
+
}
|
|
132
|
+
emitValue(value) {
|
|
133
|
+
this.valueChange.emit(value);
|
|
134
|
+
this.onChange.emit(value);
|
|
135
|
+
}
|
|
136
|
+
cleanupRenderedComponent() {
|
|
137
|
+
this.compRef?.destroy();
|
|
138
|
+
this.compRef = undefined;
|
|
139
|
+
this.inputInstance = undefined;
|
|
140
|
+
}
|
|
141
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DynamicInput, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
142
|
+
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 }] });
|
|
143
|
+
}
|
|
144
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: DynamicInput, decorators: [{
|
|
145
|
+
type: Component,
|
|
146
|
+
args: [{
|
|
147
|
+
selector: 'dfk-dynamic-input',
|
|
148
|
+
standalone: true,
|
|
149
|
+
imports: [CommonModule],
|
|
150
|
+
template: `<div #host style="display: contents;"></div>`,
|
|
151
|
+
}]
|
|
152
|
+
}], propDecorators: { type: [{
|
|
153
|
+
type: Input
|
|
154
|
+
}], valueChange: [{
|
|
155
|
+
type: Output
|
|
156
|
+
}], onChange: [{
|
|
157
|
+
type: Output
|
|
158
|
+
}], host: [{
|
|
159
|
+
type: ViewChild,
|
|
160
|
+
args: ['host', { read: ViewContainerRef, static: false }]
|
|
161
|
+
}] } });
|
|
162
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRHluYW1pY0lucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvRHluYW1pY0lucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsU0FBUyxFQUVULEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUNaLFNBQVMsRUFDVCxnQkFBZ0IsRUFNaEIsWUFBWSxHQUNiLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxhQUFhLEVBQWdCLE1BQU0seUJBQXlCLENBQUM7QUFFdEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDOztBQVFqRCxNQUFNLE9BQU8sWUFDWCxTQUFRLGtCQUFrQjtJQUdqQixJQUFJLENBQWdCO0lBQ1YsV0FBVyxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7SUFDL0MsUUFBUSxHQUFHLElBQUksWUFBWSxFQUFPLENBQUMsQ0FBQyxrQkFBa0I7SUFHaEUsSUFBSSxDQUFvQjtJQUNoQixPQUFPLENBQXFCO0lBQzVCLGFBQWEsQ0FBTztJQUNwQixhQUFhLEdBQW1CLEVBQUUsQ0FBQztJQUUzQyxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNqRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDZCxPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRXpDLE1BQU0sWUFBWSxHQUFrQixFQUFFLENBQUM7WUFDdkMsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLEVB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O0lBQzVCLENBQUM7SUFFTyx3QkFBd0I7UUFDOUIsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQztRQUN6QixJQUFJLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQztJQUNqQyxDQUFDO3dHQWhLVSxZQUFZOzRGQUFaLFlBQVksK09BUUksZ0JBQWdCLHlFQVZqQyw4Q0FBOEMsMkRBRDlDLFlBQVk7OzRGQUdYLFlBQVk7a0JBTnhCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLG1CQUFtQjtvQkFDN0IsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLE9BQU8sRUFBRSxDQUFDLFlBQVksQ0FBQztvQkFDdkIsUUFBUSxFQUFFLDhDQUE4QztpQkFDekQ7OEJBS1UsSUFBSTtzQkFBWixLQUFLO2dCQUNhLFdBQVc7c0JBQTdCLE1BQU07Z0JBQ0csUUFBUTtzQkFBakIsTUFBTTtnQkFHUCxJQUFJO3NCQURILFNBQVM7dUJBQUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBDb21wb25lbnRSZWYsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgVmlld0NoaWxkLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBPbkNoYW5nZXMsXG4gIEFmdGVyVmlld0luaXQsXG4gIE9uRGVzdHJveSxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVHlwZSxcbiAgU2ltcGxlQ2hhbmdlLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGZpZWxkUmVnaXN0cnksIEZpZWxkVHlwZUtleSB9IGZyb20gJ0BkeW5hbWljLWZpZWxkLWtpdC9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgQmFzZUlucHV0Q29tcG9uZW50IH0gZnJvbSAnLi9CYXNlSW5wdXQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdkZmstZHluYW1pYy1pbnB1dCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICB0ZW1wbGF0ZTogYDxkaXYgI2hvc3Qgc3R5bGU9XCJkaXNwbGF5OiBjb250ZW50cztcIj48L2Rpdj5gLFxufSlcbmV4cG9ydCBjbGFzcyBEeW5hbWljSW5wdXRcbiAgZXh0ZW5kcyBCYXNlSW5wdXRDb21wb25lbnRcbiAgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveVxue1xuICBASW5wdXQoKSB0eXBlITogRmllbGRUeXBlS2V5O1xuICBAT3V0cHV0KCkgb3ZlcnJpZGUgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIG9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7IC8vIGJhY2t3YXJkIGNvbXBhdFxuXG4gIEBWaWV3Q2hpbGQoJ2hvc3QnLCB7IHJlYWQ6IFZpZXdDb250YWluZXJSZWYsIHN0YXRpYzogZmFsc2UgfSlcbiAgaG9zdCE6IFZpZXdDb250YWluZXJSZWY7XG4gIHByaXZhdGUgY29tcFJlZj86IENvbXBvbmVudFJlZjxhbnk+O1xuICBwcml2YXRlIGlucHV0SW5zdGFuY2U/OiBhbnk7XG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXNbJ3R5cGUnXSAmJiAhY2hhbmdlc1sndHlwZSddLmZpcnN0Q2hhbmdlICYmIHRoaXMuaG9zdCkge1xuICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5pbnB1dEluc3RhbmNlKSB7XG4gICAgICB0aGlzLmFwcGx5S25vd25Qcm9wcyh0aGlzLmlucHV0SW5zdGFuY2UpO1xuXG4gICAgICBjb25zdCBjaGlsZENoYW5nZXM6IFNpbXBsZUNoYW5nZXMgPSB7fTtcbiAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBjaGFuZ2VzKSB7XG4gICAgICAgIGNoaWxkQ2hhbmdlc1twcm9wXSA9IG5ldyBTaW1wbGVDaGFuZ2UoXG4gICAgICAgICAgY2hhbmdlc1twcm9wXS5wcmV2aW91c1ZhbHVlLFxuICAgICAgICAgIGNoYW5nZXNbcHJvcF0uY3VycmVudFZhbHVlLFxuICAgICAgICAgIGNoYW5nZXNbcHJvcF0uZmlyc3RDaGFuZ2VcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5pbnB1dEluc3RhbmNlLm5nT25DaGFuZ2VzPy4oY2hpbGRDaGFuZ2VzKTtcbiAgICAgIHRoaXMuY29tcFJlZj8uY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5ob3N0KSB7XG4gICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5jbGVhbnVwU3Vic2NyaXB0aW9ucygpO1xuICAgIHRoaXMuY2xlYW51cFJlbmRlcmVkQ29tcG9uZW50KCk7XG4gIH1cblxuICBwcml2YXRlIGNsZWFudXBTdWJzY3JpcHRpb25zKCkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKChzKSA9PiBzLnVuc3Vic2NyaWJlKCkpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucyA9IFtdO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXIoKSB7XG4gICAgY29uc3QgUmVuZGVyZXIgPSBmaWVsZFJlZ2lzdHJ5LmdldCh0aGlzLnR5cGUgYXMgRmllbGRUeXBlS2V5KTtcbiAgICB0aGlzLmNsZWFudXBSZW5kZXJlZENvbXBvbmVudCgpO1xuICAgIHRoaXMuY2xlYW51cFN1YnNjcmlwdGlvbnMoKTtcbiAgICB0aGlzLmhvc3QuY2xlYXIoKTtcbiAgICBpZiAoIVJlbmRlcmVyKSB7XG4gICAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgZWwudGV4dENvbnRlbnQgPSBgVW5rbm93biBmaWVsZCB0eXBlOiAke3RoaXMudHlwZX1gO1xuICAgICAgdGhpcy5ob3N0LmVsZW1lbnQubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZChlbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNvbXBUeXBlID0gUmVuZGVyZXIgYXMgdW5rbm93biBhcyBUeXBlPGFueT47XG4gICAgICBjb25zdCBjb21wUmVmID0gdGhpcy5ob3N0LmNyZWF0ZUNvbXBvbmVudChjb21wVHlwZSk7XG4gICAgICBjb25zdCBpbnN0YW5jZSA9IGNvbXBSZWYuaW5zdGFuY2U7XG4gICAgICBpZiAoIWluc3RhbmNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGNyZWF0ZSBpbnN0YW5jZSBmb3IgJHt0aGlzLnR5cGV9YCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYXBwbHlLbm93blByb3BzKGluc3RhbmNlKTtcblxuICAgICAgY29uc3Qgc3ViQSA9IHRoaXMuYmluZE91dHB1dChpbnN0YW5jZSwgJ3ZhbHVlQ2hhbmdlJyk7XG4gICAgICBpZiAoc3ViQSkge1xuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChzdWJBKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHN1YkIgPSB0aGlzLmJpbmRPdXRwdXQoaW5zdGFuY2UsICdvblZhbHVlQ2hhbmdlJyk7XG4gICAgICBpZiAoc3ViQikge1xuICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChzdWJCKTtcbiAgICAgIH1cblxuICAgICAgaW5zdGFuY2UuY2hhbmdlRGV0ZWN0b3JSZWY/LmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHRoaXMuY29tcFJlZiA9IGNvbXBSZWY7XG4gICAgICB0aGlzLmlucHV0SW5zdGFuY2UgPSBpbnN0YW5jZTtcbiAgICAgIGNvbXBSZWYuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgLy8gRmFsbGJhY2sgdG8gZnVuY3Rpb24gcmVuZGVyZXJcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHByb3BzOiBhbnkgPSB7XG4gICAgICAgICAgdmFsdWU6IHRoaXMudmFsdWUsXG4gICAgICAgICAgb25WYWx1ZUNoYW5nZTogKHY6IGFueSkgPT4gdGhpcy5lbWl0VmFsdWUodiksXG4gICAgICAgICAgbGFiZWw6IHRoaXMubGFiZWwsXG4gICAgICAgICAgcGxhY2Vob2xkZXI6IHRoaXMucGxhY2Vob2xkZXIsXG4gICAgICAgICAgcmVxdWlyZWQ6IHRoaXMucmVxdWlyZWQsXG4gICAgICAgICAgb3B0aW9uczogdGhpcy5vcHRpb25zLFxuICAgICAgICAgIGNsYXNzTmFtZTogdGhpcy5jbGFzc05hbWUsXG4gICAgICAgICAgZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24sXG4gICAgICAgICAgZGlzYWJsZWQ6IHRoaXMuZGlzYWJsZWQsXG4gICAgICAgICAgZXJyb3JNZXNzYWdlOiB0aGlzLmVycm9yTWVzc2FnZSxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgb3V0ID0gKFJlbmRlcmVyIGFzIChwcm9wczogdW5rbm93bikgPT4gdW5rbm93bikocHJvcHMpO1xuICAgICAgICBpZiAodHlwZW9mIG91dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgIGVsLmlubmVySFRNTCA9IG91dDtcbiAgICAgICAgICB0aGlzLmhvc3QuZWxlbWVudC5uYXRpdmVFbGVtZW50LmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBlbC50ZXh0Q29udGVudCA9IGBGYWlsZWQgdG8gcmVuZGVyIGZpZWxkOiAke3RoaXMudHlwZX1gO1xuICAgICAgICB0aGlzLmhvc3QuZWxlbWVudC5uYXRpdmVFbGVtZW50LmFwcGVuZENoaWxkKGVsKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFwcGx5S25vd25Qcm9wcyhpbnN0YW5jZTogYW55KSB7XG4gICAgY29uc3Qga25vd25Qcm9wcyA9IFtcbiAgICAgICd2YWx1ZScsXG4gICAgICAnbGFiZWwnLFxuICAgICAgJ3BsYWNlaG9sZGVyJyxcbiAgICAgICdyZXF1aXJlZCcsXG4gICAgICAnZGlzYWJsZWQnLFxuICAgICAgJ29wdGlvbnMnLFxuICAgICAgJ2NsYXNzTmFtZScsXG4gICAgICAnZGVzY3JpcHRpb24nLFxuICAgICAgJ2Vycm9yTWVzc2FnZScsXG4gICAgXTtcbiAgICBmb3IgKGNvbnN0IHByb3Agb2Yga25vd25Qcm9wcykge1xuICAgICAgaWYgKHByb3AgaW4gdGhpcyAmJiBwcm9wIGluIGluc3RhbmNlKSB7XG4gICAgICAgIGluc3RhbmNlW3Byb3BdID0gKHRoaXMgYXMgYW55KVtwcm9wXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGJpbmRPdXRwdXQoXG4gICAgaW5zdGFuY2U6IGFueSxcbiAgICBvdXRwdXROYW1lOiAndmFsdWVDaGFuZ2UnIHwgJ29uVmFsdWVDaGFuZ2UnXG4gICk6IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgb3V0cHV0ID0gaW5zdGFuY2U/LltvdXRwdXROYW1lXTtcbiAgICBpZiAoIW91dHB1dCB8fCB0eXBlb2Ygb3V0cHV0LnN1YnNjcmliZSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHN1YiA9IChvdXRwdXQgYXMgRXZlbnRFbWl0dGVyPGFueT4pLnN1YnNjcmliZSgodmFsdWUpID0+IHtcbiAgICAgIHRoaXMuZW1pdFZhbHVlKHZhbHVlKTtcbiAgICB9KTtcbiAgICByZXR1cm4gc3ViO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0VmFsdWUodmFsdWU6IGFueSkge1xuICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gICAgdGhpcy5vbkNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xlYW51cFJlbmRlcmVkQ29tcG9uZW50KCkge1xuICAgIHRoaXMuY29tcFJlZj8uZGVzdHJveSgpO1xuICAgIHRoaXMuY29tcFJlZiA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmlucHV0SW5zdGFuY2UgPSB1bmRlZmluZWQ7XG4gIH1cbn1cbiJdfQ==
|