ngx-dynamic-entity 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/fesm2022/ngx-dynamic-entity.mjs +512 -161
- package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
- package/package.json +6 -7
- package/types/ngx-dynamic-entity.d.ts +1719 -0
- package/esm2022/lib/field-types/array-field.component.mjs +0 -168
- package/esm2022/lib/field-types/boolean-field.component.mjs +0 -101
- package/esm2022/lib/field-types/checkbox-field.component.mjs +0 -82
- package/esm2022/lib/field-types/currency-field.component.mjs +0 -102
- package/esm2022/lib/field-types/date-field.component.mjs +0 -91
- package/esm2022/lib/field-types/dropdown-field.component.mjs +0 -176
- package/esm2022/lib/field-types/email-field.component.mjs +0 -102
- package/esm2022/lib/field-types/entity-ref-field.component.mjs +0 -195
- package/esm2022/lib/field-types/field-component.contract.mjs +0 -2
- package/esm2022/lib/field-types/file-field.component.mjs +0 -157
- package/esm2022/lib/field-types/group-field.component.mjs +0 -89
- package/esm2022/lib/field-types/image-field.component.mjs +0 -169
- package/esm2022/lib/field-types/month-year-field.component.mjs +0 -152
- package/esm2022/lib/field-types/multi-select-field.component.mjs +0 -146
- package/esm2022/lib/field-types/number-field.component.mjs +0 -112
- package/esm2022/lib/field-types/password-field.component.mjs +0 -110
- package/esm2022/lib/field-types/radio-field.component.mjs +0 -153
- package/esm2022/lib/field-types/text-field.component.mjs +0 -121
- package/esm2022/lib/field-types/textarea-field.component.mjs +0 -85
- package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +0 -151
- package/esm2022/lib/form/dynamic-form.component.mjs +0 -890
- package/esm2022/lib/form/dynamic-record-form.component.mjs +0 -494
- package/esm2022/lib/providers/provide-field-types.mjs +0 -72
- package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +0 -27
- package/esm2022/lib/services/cascade-data.service.mjs +0 -129
- package/esm2022/lib/services/config-source.service.mjs +0 -67
- package/esm2022/lib/services/entity-ref-cache.mjs +0 -20
- package/esm2022/lib/services/entity-ref-registry.service.mjs +0 -31
- package/esm2022/lib/services/entity-ref-selection.service.mjs +0 -27
- package/esm2022/lib/services/entity-reference.service.mjs +0 -168
- package/esm2022/lib/services/field-registry.service.mjs +0 -55
- package/esm2022/lib/services/file-upload.service.mjs +0 -89
- package/esm2022/lib/services/hook-registry.service.mjs +0 -26
- package/esm2022/lib/services/lookup-registry.service.mjs +0 -246
- package/esm2022/lib/services/rbac.service.mjs +0 -46
- package/esm2022/lib/services/rules-evaluation.service.mjs +0 -27
- package/esm2022/lib/services/validation-messages.service.mjs +0 -56
- package/esm2022/lib/services/validator-registry.service.mjs +0 -99
- package/esm2022/lib/tokens/injection-tokens.mjs +0 -126
- package/esm2022/ngx-dynamic-entity.mjs +0 -5
- package/esm2022/public-api.mjs +0 -56
- package/index.d.ts +0 -5
- package/lib/field-types/array-field.component.d.ts +0 -28
- package/lib/field-types/boolean-field.component.d.ts +0 -18
- package/lib/field-types/checkbox-field.component.d.ts +0 -13
- package/lib/field-types/currency-field.component.d.ts +0 -17
- package/lib/field-types/date-field.component.d.ts +0 -15
- package/lib/field-types/dropdown-field.component.d.ts +0 -34
- package/lib/field-types/email-field.component.d.ts +0 -15
- package/lib/field-types/entity-ref-field.component.d.ts +0 -49
- package/lib/field-types/field-component.contract.d.ts +0 -49
- package/lib/field-types/file-field.component.d.ts +0 -25
- package/lib/field-types/group-field.component.d.ts +0 -17
- package/lib/field-types/image-field.component.d.ts +0 -30
- package/lib/field-types/month-year-field.component.d.ts +0 -28
- package/lib/field-types/multi-select-field.component.d.ts +0 -27
- package/lib/field-types/number-field.component.d.ts +0 -16
- package/lib/field-types/password-field.component.d.ts +0 -17
- package/lib/field-types/radio-field.component.d.ts +0 -33
- package/lib/field-types/text-field.component.d.ts +0 -23
- package/lib/field-types/textarea-field.component.d.ts +0 -14
- package/lib/form/dynamic-field/dynamic-field.component.d.ts +0 -78
- package/lib/form/dynamic-form.component.d.ts +0 -291
- package/lib/form/dynamic-record-form.component.d.ts +0 -180
- package/lib/providers/provide-field-types.d.ts +0 -24
- package/lib/providers/provide-ngx-dynamic-entity.d.ts +0 -56
- package/lib/services/cascade-data.service.d.ts +0 -45
- package/lib/services/config-source.service.d.ts +0 -14
- package/lib/services/entity-ref-cache.d.ts +0 -27
- package/lib/services/entity-ref-registry.service.d.ts +0 -21
- package/lib/services/entity-ref-selection.service.d.ts +0 -24
- package/lib/services/entity-reference.service.d.ts +0 -49
- package/lib/services/field-registry.service.d.ts +0 -32
- package/lib/services/file-upload.service.d.ts +0 -27
- package/lib/services/hook-registry.service.d.ts +0 -12
- package/lib/services/lookup-registry.service.d.ts +0 -94
- package/lib/services/rbac.service.d.ts +0 -27
- package/lib/services/rules-evaluation.service.d.ts +0 -17
- package/lib/services/validation-messages.service.d.ts +0 -43
- package/lib/services/validator-registry.service.d.ts +0 -32
- package/lib/tokens/injection-tokens.d.ts +0 -134
- package/public-api.d.ts +0 -40
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
-
import { getOptionStoredValue, resolveLabel, resolveOptionLabel, valuesMatch, } from '@dynamic-entity/core';
|
|
4
|
-
import { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
import * as i1 from "@angular/forms";
|
|
7
|
-
export class MultiSelectFieldComponent {
|
|
8
|
-
lookups = inject(LookupRegistryService);
|
|
9
|
-
_field;
|
|
10
|
-
_language = 'en';
|
|
11
|
-
/** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */
|
|
12
|
-
set field(value) {
|
|
13
|
-
this._field = value;
|
|
14
|
-
refreshChoiceOptions(this, this.lookups);
|
|
15
|
-
}
|
|
16
|
-
get field() {
|
|
17
|
-
return this._field;
|
|
18
|
-
}
|
|
19
|
-
set language(value) {
|
|
20
|
-
this._language = value || 'en';
|
|
21
|
-
refreshChoiceOptions(this, this.lookups);
|
|
22
|
-
}
|
|
23
|
-
get language() {
|
|
24
|
-
return this._language;
|
|
25
|
-
}
|
|
26
|
-
control;
|
|
27
|
-
readonly = false;
|
|
28
|
-
masked = false;
|
|
29
|
-
/** Inline `options`, or the field's named list resolved through the registry (§6.3). */
|
|
30
|
-
options = signal([]);
|
|
31
|
-
compareFn = (o1, o2) => valuesMatch(o1, o2, this.language);
|
|
32
|
-
isObjectVal(option) {
|
|
33
|
-
const val = getOptionStoredValue(option);
|
|
34
|
-
return typeof val === 'object' && val !== null;
|
|
35
|
-
}
|
|
36
|
-
get label() {
|
|
37
|
-
return resolveLabel(this.field?.label, this.language);
|
|
38
|
-
}
|
|
39
|
-
getOptStoredVal(option) {
|
|
40
|
-
return getOptionStoredValue(option);
|
|
41
|
-
}
|
|
42
|
-
getOptLabel(option) {
|
|
43
|
-
return resolveOptionLabel(option, this.language);
|
|
44
|
-
}
|
|
45
|
-
/** Read-only display — synchronous, per §6.2. See `DropdownFieldComponent.getLabel`. */
|
|
46
|
-
getLabels(values) {
|
|
47
|
-
if (!Array.isArray(values) || !values.length)
|
|
48
|
-
return '—';
|
|
49
|
-
return values
|
|
50
|
-
.map(v => {
|
|
51
|
-
const opt = this.options().find(o => valuesMatch(getOptionStoredValue(o), v, this.language));
|
|
52
|
-
if (opt)
|
|
53
|
-
return this.getOptLabel(opt);
|
|
54
|
-
const cached = this.lookups.labelFor(this.field?.listName, v, this.language);
|
|
55
|
-
if (cached)
|
|
56
|
-
return cached;
|
|
57
|
-
return typeof v === 'object' ? resolveLabel(v, this.language) : String(v);
|
|
58
|
-
})
|
|
59
|
-
.join(', ');
|
|
60
|
-
}
|
|
61
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
62
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: MultiSelectFieldComponent, isStandalone: true, selector: "ngx-multi-select-field", inputs: { field: "field", language: "language", control: "control", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
63
|
-
<div class="ngx-field ngx-field--multiSelect"
|
|
64
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
65
|
-
<label class="ngx-field__label">{{ label }}</label>
|
|
66
|
-
@if (masked) {
|
|
67
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
68
|
-
} @else if (readonly) {
|
|
69
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ getLabels(control.value) }}</span>
|
|
70
|
-
} @else {
|
|
71
|
-
<select
|
|
72
|
-
[id]="field.id"
|
|
73
|
-
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
74
|
-
[formControl]="$any(control)"
|
|
75
|
-
[compareWith]="compareFn"
|
|
76
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
77
|
-
multiple
|
|
78
|
-
size="4"
|
|
79
|
-
>
|
|
80
|
-
@for (option of options(); track getOptLabel(option)) {
|
|
81
|
-
@if (isObjectVal(option)) {
|
|
82
|
-
<option [ngValue]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
83
|
-
} @else {
|
|
84
|
-
<option [value]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
</select>
|
|
88
|
-
@if (control.invalid && control.touched) {
|
|
89
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
</div>
|
|
93
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectMultipleControlValueAccessor, selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
94
|
-
}
|
|
95
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MultiSelectFieldComponent, decorators: [{
|
|
96
|
-
type: Component,
|
|
97
|
-
args: [{
|
|
98
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
99
|
-
selector: 'ngx-multi-select-field',
|
|
100
|
-
standalone: true,
|
|
101
|
-
imports: [ReactiveFormsModule],
|
|
102
|
-
template: `
|
|
103
|
-
<div class="ngx-field ngx-field--multiSelect"
|
|
104
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
105
|
-
<label class="ngx-field__label">{{ label }}</label>
|
|
106
|
-
@if (masked) {
|
|
107
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
108
|
-
} @else if (readonly) {
|
|
109
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ getLabels(control.value) }}</span>
|
|
110
|
-
} @else {
|
|
111
|
-
<select
|
|
112
|
-
[id]="field.id"
|
|
113
|
-
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
114
|
-
[formControl]="$any(control)"
|
|
115
|
-
[compareWith]="compareFn"
|
|
116
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
117
|
-
multiple
|
|
118
|
-
size="4"
|
|
119
|
-
>
|
|
120
|
-
@for (option of options(); track getOptLabel(option)) {
|
|
121
|
-
@if (isObjectVal(option)) {
|
|
122
|
-
<option [ngValue]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
123
|
-
} @else {
|
|
124
|
-
<option [value]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
</select>
|
|
128
|
-
@if (control.invalid && control.touched) {
|
|
129
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
</div>
|
|
133
|
-
`,
|
|
134
|
-
}]
|
|
135
|
-
}], propDecorators: { field: [{
|
|
136
|
-
type: Input
|
|
137
|
-
}], language: [{
|
|
138
|
-
type: Input
|
|
139
|
-
}], control: [{
|
|
140
|
-
type: Input
|
|
141
|
-
}], readonly: [{
|
|
142
|
-
type: Input
|
|
143
|
-
}], masked: [{
|
|
144
|
-
type: Input
|
|
145
|
-
}] } });
|
|
146
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGktc2VsZWN0LWZpZWxkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZmllbGQtdHlwZXMvbXVsdGktc2VsZWN0LWZpZWxkLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFGLE9BQU8sRUFBbUIsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0RSxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLFlBQVksRUFDWixrQkFBa0IsRUFDbEIsV0FBVyxHQUNaLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLHFCQUFxQixFQUFFLG9CQUFvQixFQUFFLE1BQU0scUNBQXFDLENBQUM7OztBQXdDbEcsTUFBTSxPQUFPLHlCQUF5QjtJQUNuQixPQUFPLEdBQUcsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFFakQsTUFBTSxDQUFxQjtJQUMzQixTQUFTLEdBQUcsSUFBSSxDQUFDO0lBRXpCLDZGQUE2RjtJQUM3RixJQUFhLEtBQUssQ0FBQyxLQUF3QjtRQUN6QyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFDRCxJQUFJLEtBQUs7UUFDUCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDckIsQ0FBQztJQUVELElBQWEsUUFBUSxDQUFDLEtBQWE7UUFDakMsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLElBQUksSUFBSSxDQUFDO1FBQy9CLG9CQUFvQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELElBQUksUUFBUTtRQUNWLE9B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IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIGluamVjdCwgc2lnbmFsLCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHR5cGUgeyBEcm9wZG93bk9wdGlvbiwgTmVzdGVkRmllbGRDb25maWcgfSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQge1xuICBnZXRPcHRpb25TdG9yZWRWYWx1ZSxcbiAgcmVzb2x2ZUxhYmVsLFxuICByZXNvbHZlT3B0aW9uTGFiZWwsXG4gIHZhbHVlc01hdGNoLFxufSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQgeyBMb29rdXBSZWdpc3RyeVNlcnZpY2UsIHJlZnJlc2hDaG9pY2VPcHRpb25zIH0gZnJvbSAnLi4vc2VydmljZXMvbG9va3VwLXJlZ2lzdHJ5LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHNlbGVjdG9yOiAnbmd4LW11bHRpLXNlbGVjdC1maWVsZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkIG5neC1maWVsZC0tbXVsdGlTZWxlY3RcIlxuICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZFwiIFthdHRyLmRhdGEtZmllbGQtdHlwZV09XCJmaWVsZC50eXBlXCIgW2NsYXNzLm5neC1maWVsZC0tcmVhZG9ubHldPVwicmVhZG9ubHlcIiBbY2xhc3Mubmd4LWZpZWxkLS1tYXNrZWRdPVwibWFza2VkXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX2xhYmVsXCI+e3sgbGFiZWwgfX08L2xhYmVsPlxuICAgICAgQGlmIChtYXNrZWQpIHtcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlIG5neC1maWVsZF9fdmFsdWUtLW1hc2tlZFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLW1hc2tlZCdcIj5YWFhYWFhYWFg8L3NwYW4+XG4gICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWVcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy12YWx1ZSdcIj57eyBnZXRMYWJlbHMoY29udHJvbC52YWx1ZSkgfX08L3NwYW4+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPHNlbGVjdFxuICAgICAgICAgIFtpZF09XCJmaWVsZC5pZFwiXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtZmllbGRfX2lucHV0XCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctaW5wdXQnXCJcbiAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiJGFueShjb250cm9sKVwiXG4gICAgICAgICAgW2NvbXBhcmVXaXRoXT1cImNvbXBhcmVGblwiXG4gICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZmllbGQuZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXG4gICAgICAgICAgbXVsdGlwbGVcbiAgICAgICAgICBzaXplPVwiNFwiXG4gICAgICAgID5cbiAgICAgICAgICBAZm9yIChvcHRpb24gb2Ygb3B0aW9ucygpOyB0cmFjayBnZXRPcHRMYWJlbChvcHRpb24pKSB7XG4gICAgICAgICAgICBAaWYgKGlzT2JqZWN0VmFsKG9wdGlvbikpIHtcbiAgICAgICAgICAgICAgPG9wdGlvbiBbbmdWYWx1ZV09XCJnZXRPcHRTdG9yZWRWYWwob3B0aW9uKVwiPnt7IGdldE9wdExhYmVsKG9wdGlvbikgfX08L29wdGlvbj5cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJnZXRPcHRTdG9yZWRWYWwob3B0aW9uKVwiPnt7IGdldE9wdExhYmVsKG9wdGlvbikgfX08L29wdGlvbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIDwvc2VsZWN0PlxuICAgICAgICBAaWYgKGNvbnRyb2wuaW52YWxpZCAmJiBjb250cm9sLnRvdWNoZWQpIHtcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fZXJyb3JcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy1lcnJvcidcIj5UaGlzIGZpZWxkIGhhcyBhbiBlcnJvcjwvc3Bhbj5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBNdWx0aVNlbGVjdEZpZWxkQ29tcG9uZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBsb29rdXBzID0gaW5qZWN0KExvb2t1cFJlZ2lzdHJ5U2VydmljZSk7XG5cbiAgcHJpdmF0ZSBfZmllbGQhOiBOZXN0ZWRGaWVsZENvbmZpZztcbiAgcHJpdmF0ZSBfbGFuZ3VhZ2UgPSAnZW4nO1xuXG4gIC8qKiBTZXR0ZXItYmFzZWQgc28gb3B0aW9ucyByZXNvbHZlIGhvd2V2ZXIgdGhlIGlucHV0IGlzIHNldCDigJQgc2VlIGByZWZyZXNoQ2hvaWNlT3B0aW9uc2AuICovXG4gIEBJbnB1dCgpIHNldCBmaWVsZCh2YWx1ZTogTmVzdGVkRmllbGRDb25maWcpIHtcbiAgICB0aGlzLl9maWVsZCA9IHZhbHVlO1xuICAgIHJlZnJlc2hDaG9pY2VPcHRpb25zKHRoaXMsIHRoaXMubG9va3Vwcyk7XG4gIH1cbiAgZ2V0IGZpZWxkKCk6IE5lc3RlZEZpZWxkQ29uZmlnIHtcbiAgICByZXR1cm4gdGhpcy5fZmllbGQ7XG4gIH1cblxuICBASW5wdXQoKSBzZXQgbGFuZ3VhZ2UodmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuX2xhbmd1YWdlID0gdmFsdWUgfHwgJ2VuJztcbiAgICByZWZyZXNoQ2hvaWNlT3B0aW9ucyh0aGlzLCB0aGlzLmxvb2t1cHMpO1xuICB9XG4gIGdldCBsYW5ndWFnZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9sYW5ndWFnZTtcbiAgfVxuXG4gIEBJbnB1dCgpIGNvbnRyb2whOiBBYnN0cmFjdENvbnRyb2w7XG4gIEBJbnB1dCgpIHJlYWRvbmx5OiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIG1hc2tlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBJbmxpbmUgYG9wdGlvbnNgLCBvciB0aGUgZmllbGQncyBuYW1lZCBsaXN0IHJlc29sdmVkIHRocm91Z2ggdGhlIHJlZ2lzdHJ5ICjCpzYuMykuICovXG4gIHJlYWRvbmx5IG9wdGlvbnMgPSBzaWduYWw8RHJvcGRvd25PcHRpb25bXT4oW10pO1xuXG4gIHJlYWRvbmx5IGNvbXBhcmVGbiA9IChvMTogYW55LCBvMjogYW55KTogYm9vbGVhbiA9PiB2YWx1ZXNNYXRjaChvMSwgbzIsIHRoaXMubGFuZ3VhZ2UpO1xuXG4gIGlzT2JqZWN0VmFsKG9wdGlvbjogYW55KTogYm9vbGVhbiB7XG4gICAgY29uc3QgdmFsID0gZ2V0T3B0aW9uU3RvcmVkVmFsdWUob3B0aW9uKTtcbiAgICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ29iamVjdCcgJiYgdmFsICE9PSBudWxsO1xuICB9XG5cbiAgZ2V0IGxhYmVsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbCh0aGlzLmZpZWxkPy5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XG4gIH1cblxuICBnZXRPcHRTdG9yZWRWYWwob3B0aW9uOiBhbnkpOiBhbnkge1xuICAgIHJldHVybiBnZXRPcHRpb25TdG9yZWRWYWx1ZShvcHRpb24pO1xuICB9XG5cbiAgZ2V0T3B0TGFiZWwob3B0aW9uOiBhbnkpOiBzdHJpbmcge1xuICAgIHJldHVybiByZXNvbHZlT3B0aW9uTGFiZWwob3B0aW9uLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIC8qKiBSZWFkLW9ubHkgZGlzcGxheSDigJQgc3luY2hyb25vdXMsIHBlciDCpzYuMi4gU2VlIGBEcm9wZG93bkZpZWxkQ29tcG9uZW50LmdldExhYmVsYC4gKi9cbiAgZ2V0TGFiZWxzKHZhbHVlczogYW55W10pOiBzdHJpbmcge1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZXMpIHx8ICF2YWx1ZXMubGVuZ3RoKSByZXR1cm4gJ+KAlCc7XG4gICAgcmV0dXJuIHZhbHVlc1xuICAgICAgLm1hcCh2ID0+IHtcbiAgICAgICAgY29uc3Qgb3B0ID0gdGhpcy5vcHRpb25zKCkuZmluZChvID0+IHZhbHVlc01hdGNoKGdldE9wdGlvblN0b3JlZFZhbHVlKG8pLCB2LCB0aGlzLmxhbmd1YWdlKSk7XG4gICAgICAgIGlmIChvcHQpIHJldHVybiB0aGlzLmdldE9wdExhYmVsKG9wdCk7XG4gICAgICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMubG9va3Vwcy5sYWJlbEZvcih0aGlzLmZpZWxkPy5saXN0TmFtZSwgdiwgdGhpcy5sYW5ndWFnZSk7XG4gICAgICAgIGlmIChjYWNoZWQpIHJldHVybiBjYWNoZWQ7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdiA9PT0gJ29iamVjdCcgPyByZXNvbHZlTGFiZWwodiwgdGhpcy5sYW5ndWFnZSkgOiBTdHJpbmcodik7XG4gICAgICB9KVxuICAgICAgLmpvaW4oJywgJyk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { Component, Input, inject, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
-
import { resolveLabel } from '@dynamic-entity/core';
|
|
4
|
-
import { ValidationMessagesService } from '../services/validation-messages.service';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
import * as i1 from "@angular/forms";
|
|
7
|
-
export class NumberFieldComponent {
|
|
8
|
-
messages = inject(ValidationMessagesService);
|
|
9
|
-
field;
|
|
10
|
-
control;
|
|
11
|
-
language = 'en';
|
|
12
|
-
readonly = false;
|
|
13
|
-
masked = false;
|
|
14
|
-
get label() {
|
|
15
|
-
return resolveLabel(this.field?.label, this.language);
|
|
16
|
-
}
|
|
17
|
-
get placeholder() {
|
|
18
|
-
return resolveLabel(this.field?.placeholder, this.language);
|
|
19
|
-
}
|
|
20
|
-
get errorMessage() {
|
|
21
|
-
if (!this.control || !this.control.errors || !this.control.touched)
|
|
22
|
-
return '';
|
|
23
|
-
return this.messages.resolve(this.control.errors, this.language, ['required', 'min', 'max'], 'invalidNumber');
|
|
24
|
-
}
|
|
25
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
26
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NumberFieldComponent, isStandalone: true, selector: "ngx-number-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
27
|
-
<div
|
|
28
|
-
class="ngx-field ngx-field--number"
|
|
29
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type"
|
|
30
|
-
[class.ngx-field--readonly]="readonly"
|
|
31
|
-
[class.ngx-field--masked]="masked"
|
|
32
|
-
[class.ngx-field--invalid]="control && control.invalid && control.touched"
|
|
33
|
-
>
|
|
34
|
-
<label class="ngx-field__label" [attr.for]="field.id">
|
|
35
|
-
{{ label }}
|
|
36
|
-
@if (field.validators?.required) { <span class="ngx-field__req">*</span> }
|
|
37
|
-
</label>
|
|
38
|
-
@if (masked) {
|
|
39
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
40
|
-
} @else if (readonly) {
|
|
41
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value ?? '—' }}</span>
|
|
42
|
-
} @else {
|
|
43
|
-
<input
|
|
44
|
-
[id]="field.id"
|
|
45
|
-
type="number"
|
|
46
|
-
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
47
|
-
[formControl]="$any(control)"
|
|
48
|
-
[placeholder]="placeholder"
|
|
49
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
50
|
-
[attr.aria-invalid]="control.invalid && control.touched"
|
|
51
|
-
[attr.aria-describedby]="errorMessage ? field.id + '-error' : null"
|
|
52
|
-
/>
|
|
53
|
-
@if (errorMessage) {
|
|
54
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'" [id]="field.id + '-error'" role="alert">{{ errorMessage }}</span>
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
</div>
|
|
58
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
59
|
-
}
|
|
60
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NumberFieldComponent, decorators: [{
|
|
61
|
-
type: Component,
|
|
62
|
-
args: [{
|
|
63
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
64
|
-
selector: 'ngx-number-field',
|
|
65
|
-
standalone: true,
|
|
66
|
-
imports: [ReactiveFormsModule],
|
|
67
|
-
template: `
|
|
68
|
-
<div
|
|
69
|
-
class="ngx-field ngx-field--number"
|
|
70
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type"
|
|
71
|
-
[class.ngx-field--readonly]="readonly"
|
|
72
|
-
[class.ngx-field--masked]="masked"
|
|
73
|
-
[class.ngx-field--invalid]="control && control.invalid && control.touched"
|
|
74
|
-
>
|
|
75
|
-
<label class="ngx-field__label" [attr.for]="field.id">
|
|
76
|
-
{{ label }}
|
|
77
|
-
@if (field.validators?.required) { <span class="ngx-field__req">*</span> }
|
|
78
|
-
</label>
|
|
79
|
-
@if (masked) {
|
|
80
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
81
|
-
} @else if (readonly) {
|
|
82
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value ?? '—' }}</span>
|
|
83
|
-
} @else {
|
|
84
|
-
<input
|
|
85
|
-
[id]="field.id"
|
|
86
|
-
type="number"
|
|
87
|
-
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
88
|
-
[formControl]="$any(control)"
|
|
89
|
-
[placeholder]="placeholder"
|
|
90
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
91
|
-
[attr.aria-invalid]="control.invalid && control.touched"
|
|
92
|
-
[attr.aria-describedby]="errorMessage ? field.id + '-error' : null"
|
|
93
|
-
/>
|
|
94
|
-
@if (errorMessage) {
|
|
95
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'" [id]="field.id + '-error'" role="alert">{{ errorMessage }}</span>
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
</div>
|
|
99
|
-
`,
|
|
100
|
-
}]
|
|
101
|
-
}], propDecorators: { field: [{
|
|
102
|
-
type: Input
|
|
103
|
-
}], control: [{
|
|
104
|
-
type: Input
|
|
105
|
-
}], language: [{
|
|
106
|
-
type: Input
|
|
107
|
-
}], readonly: [{
|
|
108
|
-
type: Input
|
|
109
|
-
}], masked: [{
|
|
110
|
-
type: Input
|
|
111
|
-
}] } });
|
|
112
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnVtYmVyLWZpZWxkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZmllbGQtdHlwZXMvbnVtYmVyLWZpZWxkLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEYsT0FBTyxFQUFtQixtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXRFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQzs7O0FBeUNwRixNQUFNLE9BQU8sb0JBQW9CO0lBQ2QsUUFBUSxHQUFHLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBRXJELEtBQUssQ0FBcUI7SUFDMUIsT0FBTyxDQUFtQjtJQUMxQixRQUFRLEdBQVcsSUFBSSxDQUFDO0lBQ3hCLFFBQVEsR0FBWSxLQUFLLENBQUM7SUFDMUIsTUFBTSxHQUFZLEtBQUssQ0FBQztJQUVqQyxJQUFJLEtBQUs7UUFDUCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELElBQUksV0FBVztRQUNiLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRUQsSUFBSSxZQUFZO1FBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTztZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQzlFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQzFCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUNuQixJQUFJLENBQUMsUUFBUSxFQUNiLENBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsRUFDMUIsZUFBZSxDQUNoQixDQUFDO0lBQ0osQ0FBQzt3R0F6QlUsb0JBQW9COzRGQUFwQixvQkFBb0IsMExBbENyQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ1QsMkRBakNTLG1CQUFtQjs7NEZBbUNsQixvQkFBb0I7a0JBdkNoQyxTQUFTO21CQUFDO29CQUNULGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxRQUFRLEVBQUUsa0JBQWtCO29CQUM1QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsT0FBTyxFQUFFLENBQUMsbUJBQW1CLENBQUM7b0JBQzlCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ1Q7aUJBQ0Y7OEJBSVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgaW5qZWN0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHR5cGUgeyBOZXN0ZWRGaWVsZENvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IHJlc29sdmVMYWJlbCB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IFZhbGlkYXRpb25NZXNzYWdlc1NlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy92YWxpZGF0aW9uLW1lc3NhZ2VzLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHNlbGVjdG9yOiAnbmd4LW51bWJlci1maWVsZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cIm5neC1maWVsZCBuZ3gtZmllbGQtLW51bWJlclwiXG4gICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkXCIgW2F0dHIuZGF0YS1maWVsZC10eXBlXT1cImZpZWxkLnR5cGVcIlxuICAgICAgW2NsYXNzLm5neC1maWVsZC0tcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuICAgICAgW2NsYXNzLm5neC1maWVsZC0tbWFza2VkXT1cIm1hc2tlZFwiXG4gICAgICBbY2xhc3Mubmd4LWZpZWxkLS1pbnZhbGlkXT1cImNvbnRyb2wgJiYgY29udHJvbC5pbnZhbGlkICYmIGNvbnRyb2wudG91Y2hlZFwiXG4gICAgPlxuICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX19sYWJlbFwiIFthdHRyLmZvcl09XCJmaWVsZC5pZFwiPlxuICAgICAgICB7eyBsYWJlbCB9fVxuICAgICAgICBAaWYgKGZpZWxkLnZhbGlkYXRvcnM/LnJlcXVpcmVkKSB7IDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX19yZXFcIj4qPC9zcGFuPiB9XG4gICAgICA8L2xhYmVsPlxuICAgICAgQGlmIChtYXNrZWQpIHtcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlIG5neC1maWVsZF9fdmFsdWUtLW1hc2tlZFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLW1hc2tlZCdcIj5YWFhYWFhYWFg8L3NwYW4+XG4gICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWVcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy12YWx1ZSdcIj57eyBjb250cm9sLnZhbHVlID8/ICfigJQnIH19PC9zcGFuPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIFtpZF09XCJmaWVsZC5pZFwiXG4gICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtZmllbGRfX2lucHV0XCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctaW5wdXQnXCJcbiAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiJGFueShjb250cm9sKVwiXG4gICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICAgICAgICBbYXR0ci5kaXNhYmxlZF09XCJmaWVsZC5kaXNhYmxlZCA/IHRydWUgOiBudWxsXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWludmFsaWRdPVwiY29udHJvbC5pbnZhbGlkICYmIGNvbnRyb2wudG91Y2hlZFwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJlcnJvck1lc3NhZ2UgPyBmaWVsZC5pZCArICctZXJyb3InIDogbnVsbFwiXG4gICAgICAgIC8+XG4gICAgICAgIEBpZiAoZXJyb3JNZXNzYWdlKSB7XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2Vycm9yXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctZXJyb3InXCIgW2lkXT1cImZpZWxkLmlkICsgJy1lcnJvcidcIiByb2xlPVwiYWxlcnRcIj57eyBlcnJvck1lc3NhZ2UgfX08L3NwYW4+XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgTnVtYmVyRmllbGRDb21wb25lbnQge1xuICBwcml2YXRlIHJlYWRvbmx5IG1lc3NhZ2VzID0gaW5qZWN0KFZhbGlkYXRpb25NZXNzYWdlc1NlcnZpY2UpO1xuXG4gIEBJbnB1dCgpIGZpZWxkITogTmVzdGVkRmllbGRDb25maWc7XG4gIEBJbnB1dCgpIGNvbnRyb2whOiBBYnN0cmFjdENvbnRyb2w7XG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmcgPSAnZW4nO1xuICBASW5wdXQoKSByZWFkb25seTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBtYXNrZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBnZXQgbGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKHRoaXMuZmllbGQ/LmxhYmVsLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIGdldCBwbGFjZWhvbGRlcigpOiBzdHJpbmcge1xuICAgIHJldHVybiByZXNvbHZlTGFiZWwodGhpcy5maWVsZD8ucGxhY2Vob2xkZXIsIHRoaXMubGFuZ3VhZ2UpO1xuICB9XG5cbiAgZ2V0IGVycm9yTWVzc2FnZSgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5jb250cm9sIHx8ICF0aGlzLmNvbnRyb2wuZXJyb3JzIHx8ICF0aGlzLmNvbnRyb2wudG91Y2hlZCkgcmV0dXJuICcnO1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzLnJlc29sdmUoXG4gICAgICB0aGlzLmNvbnRyb2wuZXJyb3JzLFxuICAgICAgdGhpcy5sYW5ndWFnZSxcbiAgICAgIFsncmVxdWlyZWQnLCAnbWluJywgJ21heCddLFxuICAgICAgJ2ludmFsaWROdW1iZXInLFxuICAgICk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { Component, Input, signal, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
-
import { resolveLabel } from '@dynamic-entity/core';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
import * as i1 from "@angular/forms";
|
|
6
|
-
/** Password field: masked input with show/hide eye toggle. */
|
|
7
|
-
export class PasswordFieldComponent {
|
|
8
|
-
field;
|
|
9
|
-
control;
|
|
10
|
-
language = 'en';
|
|
11
|
-
readonly = false;
|
|
12
|
-
masked = false;
|
|
13
|
-
visible = signal(false);
|
|
14
|
-
get label() {
|
|
15
|
-
return resolveLabel(this.field?.label, this.language);
|
|
16
|
-
}
|
|
17
|
-
get placeholder() {
|
|
18
|
-
return resolveLabel(this.field?.placeholder, this.language);
|
|
19
|
-
}
|
|
20
|
-
toggleVisibility() {
|
|
21
|
-
this.visible.update(v => !v);
|
|
22
|
-
}
|
|
23
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PasswordFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
24
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: PasswordFieldComponent, isStandalone: true, selector: "ngx-password-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
25
|
-
<div class="ngx-field ngx-field--password"
|
|
26
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
27
|
-
<label class="ngx-field__label">{{ label }}</label>
|
|
28
|
-
@if (masked) {
|
|
29
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
30
|
-
} @else if (readonly) {
|
|
31
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">••••••••</span>
|
|
32
|
-
} @else {
|
|
33
|
-
<div class="ngx-field__password-wrap">
|
|
34
|
-
<input
|
|
35
|
-
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
36
|
-
[type]="visible() ? 'text' : 'password'"
|
|
37
|
-
autocomplete="current-password"
|
|
38
|
-
[formControl]="$any(control)"
|
|
39
|
-
[placeholder]="placeholder || '••••••••'"
|
|
40
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
41
|
-
/>
|
|
42
|
-
<button
|
|
43
|
-
type="button"
|
|
44
|
-
class="ngx-field__eye-btn"
|
|
45
|
-
(click)="toggleVisibility()"
|
|
46
|
-
[attr.aria-label]="visible() ? 'Hide password' : 'Show password'"
|
|
47
|
-
>
|
|
48
|
-
{{ visible() ? '🙈' : '👁' }}
|
|
49
|
-
</button>
|
|
50
|
-
</div>
|
|
51
|
-
@if (control.invalid && control.touched) {
|
|
52
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
</div>
|
|
56
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
57
|
-
}
|
|
58
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PasswordFieldComponent, decorators: [{
|
|
59
|
-
type: Component,
|
|
60
|
-
args: [{
|
|
61
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
62
|
-
selector: 'ngx-password-field',
|
|
63
|
-
standalone: true,
|
|
64
|
-
imports: [ReactiveFormsModule],
|
|
65
|
-
template: `
|
|
66
|
-
<div class="ngx-field ngx-field--password"
|
|
67
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
68
|
-
<label class="ngx-field__label">{{ label }}</label>
|
|
69
|
-
@if (masked) {
|
|
70
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
71
|
-
} @else if (readonly) {
|
|
72
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">••••••••</span>
|
|
73
|
-
} @else {
|
|
74
|
-
<div class="ngx-field__password-wrap">
|
|
75
|
-
<input
|
|
76
|
-
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
77
|
-
[type]="visible() ? 'text' : 'password'"
|
|
78
|
-
autocomplete="current-password"
|
|
79
|
-
[formControl]="$any(control)"
|
|
80
|
-
[placeholder]="placeholder || '••••••••'"
|
|
81
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
82
|
-
/>
|
|
83
|
-
<button
|
|
84
|
-
type="button"
|
|
85
|
-
class="ngx-field__eye-btn"
|
|
86
|
-
(click)="toggleVisibility()"
|
|
87
|
-
[attr.aria-label]="visible() ? 'Hide password' : 'Show password'"
|
|
88
|
-
>
|
|
89
|
-
{{ visible() ? '🙈' : '👁' }}
|
|
90
|
-
</button>
|
|
91
|
-
</div>
|
|
92
|
-
@if (control.invalid && control.touched) {
|
|
93
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
</div>
|
|
97
|
-
`,
|
|
98
|
-
}]
|
|
99
|
-
}], propDecorators: { field: [{
|
|
100
|
-
type: Input
|
|
101
|
-
}], control: [{
|
|
102
|
-
type: Input
|
|
103
|
-
}], language: [{
|
|
104
|
-
type: Input
|
|
105
|
-
}], readonly: [{
|
|
106
|
-
type: Input
|
|
107
|
-
}], masked: [{
|
|
108
|
-
type: Input
|
|
109
|
-
}] } });
|
|
110
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFzc3dvcmQtZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9wYXNzd29yZC1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xGLE9BQU8sRUFBbUIsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7OztBQUVwRCw4REFBOEQ7QUF3QzlELE1BQU0sT0FBTyxzQkFBc0I7SUFDeEIsS0FBSyxDQUFxQjtJQUMxQixPQUFPLENBQW1CO0lBQzFCLFFBQVEsR0FBVyxJQUFJLENBQUM7SUFDeEIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUMxQixNQUFNLEdBQVksS0FBSyxDQUFDO0lBRXhCLE9BQU8sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFakMsSUFBSSxLQUFLO1FBQ1AsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVELGdCQUFnQjtRQUNkLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvQixDQUFDO3dHQW5CVSxzQkFBc0I7NEZBQXRCLHNCQUFzQiw0TEFsQ3ZCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWdDVCwyREFqQ1MsbUJBQW1COzs0RkFtQ2xCLHNCQUFzQjtrQkF2Q2xDLFNBQVM7bUJBQUM7b0JBQ1QsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07b0JBQy9DLFFBQVEsRUFBRSxvQkFBb0I7b0JBQzlCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixPQUFPLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztvQkFDOUIsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWdDVDtpQkFDRjs4QkFFVSxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBzaWduYWwsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgdHlwZSB7IE5lc3RlZEZpZWxkQ29uZmlnIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgcmVzb2x2ZUxhYmVsIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuXG4vKiogUGFzc3dvcmQgZmllbGQ6IG1hc2tlZCBpbnB1dCB3aXRoIHNob3cvaGlkZSBleWUgdG9nZ2xlLiAqL1xuQENvbXBvbmVudCh7XG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzZWxlY3RvcjogJ25neC1wYXNzd29yZC1maWVsZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkIG5neC1maWVsZC0tcGFzc3dvcmRcIlxuICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZFwiIFthdHRyLmRhdGEtZmllbGQtdHlwZV09XCJmaWVsZC50eXBlXCIgW2NsYXNzLm5neC1maWVsZC0tcmVhZG9ubHldPVwicmVhZG9ubHlcIiBbY2xhc3Mubmd4LWZpZWxkLS1tYXNrZWRdPVwibWFza2VkXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX2xhYmVsXCI+e3sgbGFiZWwgfX08L2xhYmVsPlxuICAgICAgQGlmIChtYXNrZWQpIHtcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlIG5neC1maWVsZF9fdmFsdWUtLW1hc2tlZFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLW1hc2tlZCdcIj5YWFhYWFhYWFg8L3NwYW4+XG4gICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWVcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy12YWx1ZSdcIj7igKLigKLigKLigKLigKLigKLigKLigKI8L3NwYW4+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZF9fcGFzc3dvcmQtd3JhcFwiPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgY2xhc3M9XCJuZ3gtZmllbGRfX2lucHV0XCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctaW5wdXQnXCJcbiAgICAgICAgICAgIFt0eXBlXT1cInZpc2libGUoKSA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwiY3VycmVudC1wYXNzd29yZFwiXG4gICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiJGFueShjb250cm9sKVwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXIgfHwgJ+KAouKAouKAouKAouKAouKAouKAouKAoidcIlxuICAgICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZmllbGQuZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwibmd4LWZpZWxkX19leWUtYnRuXCJcbiAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVWaXNpYmlsaXR5KClcIlxuICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJ2aXNpYmxlKCkgPyAnSGlkZSBwYXNzd29yZCcgOiAnU2hvdyBwYXNzd29yZCdcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7IHZpc2libGUoKSA/ICfwn5mIJyA6ICfwn5GBJyB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgQGlmIChjb250cm9sLmludmFsaWQgJiYgY29udHJvbC50b3VjaGVkKSB7XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2Vycm9yXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctZXJyb3InXCI+VGhpcyBmaWVsZCBoYXMgYW4gZXJyb3I8L3NwYW4+XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgUGFzc3dvcmRGaWVsZENvbXBvbmVudCB7XG4gIEBJbnB1dCgpIGZpZWxkITogTmVzdGVkRmllbGRDb25maWc7XG4gIEBJbnB1dCgpIGNvbnRyb2whOiBBYnN0cmFjdENvbnRyb2w7XG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmcgPSAnZW4nO1xuICBASW5wdXQoKSByZWFkb25seTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBtYXNrZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICByZWFkb25seSB2aXNpYmxlID0gc2lnbmFsKGZhbHNlKTtcblxuICBnZXQgbGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKHRoaXMuZmllbGQ/LmxhYmVsLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIGdldCBwbGFjZWhvbGRlcigpOiBzdHJpbmcge1xuICAgIHJldHVybiByZXNvbHZlTGFiZWwodGhpcy5maWVsZD8ucGxhY2Vob2xkZXIsIHRoaXMubGFuZ3VhZ2UpO1xuICB9XG5cbiAgdG9nZ2xlVmlzaWJpbGl0eSgpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2libGUudXBkYXRlKHYgPT4gIXYpO1xuICB9XG59XG4iXX0=
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { Component, Input, inject, signal, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
-
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
-
import { getOptionStoredValue, resolveLabel, resolveOptionLabel, resolveOptionValue, valuesMatch, } from '@dynamic-entity/core';
|
|
4
|
-
import { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
import * as i1 from "@angular/forms";
|
|
7
|
-
/** Radio field: a group of radio buttons built from field.options. */
|
|
8
|
-
export class RadioFieldComponent {
|
|
9
|
-
lookups = inject(LookupRegistryService);
|
|
10
|
-
_field;
|
|
11
|
-
_language = 'en';
|
|
12
|
-
/** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */
|
|
13
|
-
set field(value) {
|
|
14
|
-
this._field = value;
|
|
15
|
-
refreshChoiceOptions(this, this.lookups);
|
|
16
|
-
}
|
|
17
|
-
get field() {
|
|
18
|
-
return this._field;
|
|
19
|
-
}
|
|
20
|
-
set language(value) {
|
|
21
|
-
this._language = value || 'en';
|
|
22
|
-
refreshChoiceOptions(this, this.lookups);
|
|
23
|
-
}
|
|
24
|
-
get language() {
|
|
25
|
-
return this._language;
|
|
26
|
-
}
|
|
27
|
-
control;
|
|
28
|
-
readonly = false;
|
|
29
|
-
masked = false;
|
|
30
|
-
/** Inline `options`, or the field's named list resolved through the registry (§6.3). */
|
|
31
|
-
options = signal([]);
|
|
32
|
-
get label() {
|
|
33
|
-
return resolveLabel(this.field?.label, this.language);
|
|
34
|
-
}
|
|
35
|
-
getOptStoredVal(option) {
|
|
36
|
-
return getOptionStoredValue(option);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Stable DOM id for one radio, so the <label for> association works.
|
|
40
|
-
* Slugified because the option text is the value now — "On Leave" must not put a space
|
|
41
|
-
* into an id attribute.
|
|
42
|
-
*/
|
|
43
|
-
getRadioId(option) {
|
|
44
|
-
const text = String(this.getOptVal(option) ?? 'opt');
|
|
45
|
-
return `${this.field.id}-${text.trim().replace(/\s+/g, '_').toLowerCase()}`;
|
|
46
|
-
}
|
|
47
|
-
getOptVal(option) {
|
|
48
|
-
return resolveOptionValue(option, this.language);
|
|
49
|
-
}
|
|
50
|
-
getOptLabel(option) {
|
|
51
|
-
return resolveOptionLabel(option, this.language);
|
|
52
|
-
}
|
|
53
|
-
/** Read-only display — synchronous, per §6.2. See `DropdownFieldComponent.getLabel`. */
|
|
54
|
-
getSelectedLabel() {
|
|
55
|
-
const value = this.control?.value;
|
|
56
|
-
// `typeof null === 'object'`, so without this guard an empty value fell through to
|
|
57
|
-
// `resolveLabel(null)` and rendered as blank — dropdown and multiSelect both show an em dash.
|
|
58
|
-
if (value === null || value === undefined || value === '')
|
|
59
|
-
return '—';
|
|
60
|
-
const selected = this.options().find(o => valuesMatch(getOptionStoredValue(o), value, this.language));
|
|
61
|
-
if (selected)
|
|
62
|
-
return this.getOptLabel(selected);
|
|
63
|
-
const cached = this.lookups.labelFor(this.field?.listName, value, this.language);
|
|
64
|
-
if (cached)
|
|
65
|
-
return cached;
|
|
66
|
-
return typeof value === 'object' ? resolveLabel(value, this.language) : (value ?? '—');
|
|
67
|
-
}
|
|
68
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
69
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: RadioFieldComponent, isStandalone: true, selector: "ngx-radio-field", inputs: { field: "field", language: "language", control: "control", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
70
|
-
<div class="ngx-field ngx-field--radio"
|
|
71
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
72
|
-
<fieldset class="ngx-field__fieldset">
|
|
73
|
-
<legend class="ngx-field__label">{{ label }}</legend>
|
|
74
|
-
@if (masked) {
|
|
75
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
76
|
-
} @else if (readonly) {
|
|
77
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ getSelectedLabel() }}</span>
|
|
78
|
-
} @else {
|
|
79
|
-
<div class="ngx-field__radio-group">
|
|
80
|
-
@for (option of options(); track getOptLabel(option)) {
|
|
81
|
-
<label class="ngx-field__radio-option" [attr.for]="getRadioId(option)">
|
|
82
|
-
<input
|
|
83
|
-
[id]="getRadioId(option)"
|
|
84
|
-
type="radio"
|
|
85
|
-
class="ngx-field__radio-input"
|
|
86
|
-
[formControl]="$any(control)"
|
|
87
|
-
[value]="getOptStoredVal(option)"
|
|
88
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
89
|
-
/>
|
|
90
|
-
<span class="ngx-field__radio-label">{{ getOptLabel(option) }}</span>
|
|
91
|
-
</label>
|
|
92
|
-
}
|
|
93
|
-
</div>
|
|
94
|
-
@if (control.invalid && control.touched) {
|
|
95
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
</fieldset>
|
|
99
|
-
</div>
|
|
100
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
101
|
-
}
|
|
102
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RadioFieldComponent, decorators: [{
|
|
103
|
-
type: Component,
|
|
104
|
-
args: [{
|
|
105
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
106
|
-
selector: 'ngx-radio-field',
|
|
107
|
-
standalone: true,
|
|
108
|
-
imports: [ReactiveFormsModule],
|
|
109
|
-
template: `
|
|
110
|
-
<div class="ngx-field ngx-field--radio"
|
|
111
|
-
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
112
|
-
<fieldset class="ngx-field__fieldset">
|
|
113
|
-
<legend class="ngx-field__label">{{ label }}</legend>
|
|
114
|
-
@if (masked) {
|
|
115
|
-
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
116
|
-
} @else if (readonly) {
|
|
117
|
-
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ getSelectedLabel() }}</span>
|
|
118
|
-
} @else {
|
|
119
|
-
<div class="ngx-field__radio-group">
|
|
120
|
-
@for (option of options(); track getOptLabel(option)) {
|
|
121
|
-
<label class="ngx-field__radio-option" [attr.for]="getRadioId(option)">
|
|
122
|
-
<input
|
|
123
|
-
[id]="getRadioId(option)"
|
|
124
|
-
type="radio"
|
|
125
|
-
class="ngx-field__radio-input"
|
|
126
|
-
[formControl]="$any(control)"
|
|
127
|
-
[value]="getOptStoredVal(option)"
|
|
128
|
-
[attr.disabled]="field.disabled ? true : null"
|
|
129
|
-
/>
|
|
130
|
-
<span class="ngx-field__radio-label">{{ getOptLabel(option) }}</span>
|
|
131
|
-
</label>
|
|
132
|
-
}
|
|
133
|
-
</div>
|
|
134
|
-
@if (control.invalid && control.touched) {
|
|
135
|
-
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
</fieldset>
|
|
139
|
-
</div>
|
|
140
|
-
`,
|
|
141
|
-
}]
|
|
142
|
-
}], propDecorators: { field: [{
|
|
143
|
-
type: Input
|
|
144
|
-
}], language: [{
|
|
145
|
-
type: Input
|
|
146
|
-
}], control: [{
|
|
147
|
-
type: Input
|
|
148
|
-
}], readonly: [{
|
|
149
|
-
type: Input
|
|
150
|
-
}], masked: [{
|
|
151
|
-
type: Input
|
|
152
|
-
}] } });
|
|
153
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFkaW8tZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9yYWRpby1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxRixPQUFPLEVBQW1CLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEUsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixZQUFZLEVBQ1osa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQixXQUFXLEdBQ1osTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUscUJBQXFCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQzs7O0FBRWxHLHNFQUFzRTtBQXVDdEUsTUFBTSxPQUFPLG1CQUFtQjtJQUNiLE9BQU8sR0FBRyxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUVqRCxNQUFNLENBQXFCO0lBQzNCLFNBQVMsR0FBRyxJQUFJLENBQUM7SUFFekIsNkZBQTZGO0lBQzdGLElBQWEsS0FBSyxDQUFDLEtBQXdCO1FBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLG9CQUFvQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsSUFBYSxRQUFRLENBQUMsS0FBYTtRQUNqQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssSUFBSSxJQUFJLENBQUM7UUFDL0Isb0JBQW9CLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsSUFBSSxR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SztnQkFRRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBpbmplY3QsIHNpZ25hbCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB0eXBlIHsgRHJvcGRvd25PcHRpb24sIE5lc3RlZEZpZWxkQ29uZmlnIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHtcbiAgZ2V0T3B0aW9uU3RvcmVkVmFsdWUsXG4gIHJlc29sdmVMYWJlbCxcbiAgcmVzb2x2ZU9wdGlvbkxhYmVsLFxuICByZXNvbHZlT3B0aW9uVmFsdWUsXG4gIHZhbHVlc01hdGNoLFxufSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQgeyBMb29rdXBSZWdpc3RyeVNlcnZpY2UsIHJlZnJlc2hDaG9pY2VPcHRpb25zIH0gZnJvbSAnLi4vc2VydmljZXMvbG9va3VwLXJlZ2lzdHJ5LnNlcnZpY2UnO1xuXG4vKiogUmFkaW8gZmllbGQ6IGEgZ3JvdXAgb2YgcmFkaW8gYnV0dG9ucyBidWlsdCBmcm9tIGZpZWxkLm9wdGlvbnMuICovXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHNlbGVjdG9yOiAnbmd4LXJhZGlvLWZpZWxkJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1JlYWN0aXZlRm9ybXNNb2R1bGVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJuZ3gtZmllbGQgbmd4LWZpZWxkLS1yYWRpb1wiXG4gICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkXCIgW2F0dHIuZGF0YS1maWVsZC10eXBlXT1cImZpZWxkLnR5cGVcIiBbY2xhc3Mubmd4LWZpZWxkLS1yZWFkb25seV09XCJyZWFkb25seVwiIFtjbGFzcy5uZ3gtZmllbGQtLW1hc2tlZF09XCJtYXNrZWRcIj5cbiAgICAgIDxmaWVsZHNldCBjbGFzcz1cIm5neC1maWVsZF9fZmllbGRzZXRcIj5cbiAgICAgICAgPGxlZ2VuZCBjbGFzcz1cIm5neC1maWVsZF9fbGFiZWxcIj57eyBsYWJlbCB9fTwvbGVnZW5kPlxuICAgICAgICBAaWYgKG1hc2tlZCkge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZSBuZ3gtZmllbGRfX3ZhbHVlLS1tYXNrZWRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy1tYXNrZWQnXCI+WFhYWFhYWFhYPC9zcGFuPlxuICAgICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZVwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLXZhbHVlJ1wiPnt7IGdldFNlbGVjdGVkTGFiZWwoKSB9fTwvc3Bhbj5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZF9fcmFkaW8tZ3JvdXBcIj5cbiAgICAgICAgICAgIEBmb3IgKG9wdGlvbiBvZiBvcHRpb25zKCk7IHRyYWNrIGdldE9wdExhYmVsKG9wdGlvbikpIHtcbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX19yYWRpby1vcHRpb25cIiBbYXR0ci5mb3JdPVwiZ2V0UmFkaW9JZChvcHRpb24pXCI+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICBbaWRdPVwiZ2V0UmFkaW9JZChvcHRpb24pXCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJyYWRpb1wiXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cIm5neC1maWVsZF9fcmFkaW8taW5wdXRcIlxuICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cIiRhbnkoY29udHJvbClcIlxuICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cImdldE9wdFN0b3JlZFZhbChvcHRpb24pXCJcbiAgICAgICAgICAgICAgICAgIFthdHRyLmRpc2FibGVkXT1cImZpZWxkLmRpc2FibGVkID8gdHJ1ZSA6IG51bGxcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3JhZGlvLWxhYmVsXCI+e3sgZ2V0T3B0TGFiZWwob3B0aW9uKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICBAaWYgKGNvbnRyb2wuaW52YWxpZCAmJiBjb250cm9sLnRvdWNoZWQpIHtcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX19lcnJvclwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWVycm9yJ1wiPlRoaXMgZmllbGQgaGFzIGFuIGVycm9yPC9zcGFuPlxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgPC9maWVsZHNldD5cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgUmFkaW9GaWVsZENvbXBvbmVudCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgbG9va3VwcyA9IGluamVjdChMb29rdXBSZWdpc3RyeVNlcnZpY2UpO1xuXG4gIHByaXZhdGUgX2ZpZWxkITogTmVzdGVkRmllbGRDb25maWc7XG4gIHByaXZhdGUgX2xhbmd1YWdlID0gJ2VuJztcblxuICAvKiogU2V0dGVyLWJhc2VkIHNvIG9wdGlvbnMgcmVzb2x2ZSBob3dldmVyIHRoZSBpbnB1dCBpcyBzZXQg4oCUIHNlZSBgcmVmcmVzaENob2ljZU9wdGlvbnNgLiAqL1xuICBASW5wdXQoKSBzZXQgZmllbGQodmFsdWU6IE5lc3RlZEZpZWxkQ29uZmlnKSB7XG4gICAgdGhpcy5fZmllbGQgPSB2YWx1ZTtcbiAgICByZWZyZXNoQ2hvaWNlT3B0aW9ucyh0aGlzLCB0aGlzLmxvb2t1cHMpO1xuICB9XG4gIGdldCBmaWVsZCgpOiBOZXN0ZWRGaWVsZENvbmZpZyB7XG4gICAgcmV0dXJuIHRoaXMuX2ZpZWxkO1xuICB9XG5cbiAgQElucHV0KCkgc2V0IGxhbmd1YWdlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9sYW5ndWFnZSA9IHZhbHVlIHx8ICdlbic7XG4gICAgcmVmcmVzaENob2ljZU9wdGlvbnModGhpcywgdGhpcy5sb29rdXBzKTtcbiAgfVxuICBnZXQgbGFuZ3VhZ2UoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fbGFuZ3VhZ2U7XG4gIH1cblxuICBASW5wdXQoKSBjb250cm9sITogQWJzdHJhY3RDb250cm9sO1xuICBASW5wdXQoKSByZWFkb25seTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBtYXNrZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogSW5saW5lIGBvcHRpb25zYCwgb3IgdGhlIGZpZWxkJ3MgbmFtZWQgbGlzdCByZXNvbHZlZCB0aHJvdWdoIHRoZSByZWdpc3RyeSAowqc2LjMpLiAqL1xuICByZWFkb25seSBvcHRpb25zID0gc2lnbmFsPERyb3Bkb3duT3B0aW9uW10+KFtdKTtcblxuICBnZXQgbGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKHRoaXMuZmllbGQ/LmxhYmVsLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIGdldE9wdFN0b3JlZFZhbChvcHRpb246IGFueSk6IGFueSB7XG4gICAgcmV0dXJuIGdldE9wdGlvblN0b3JlZFZhbHVlKG9wdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogU3RhYmxlIERPTSBpZCBmb3Igb25lIHJhZGlvLCBzbyB0aGUgPGxhYmVsIGZvcj4gYXNzb2NpYXRpb24gd29ya3MuXG4gICAqIFNsdWdpZmllZCBiZWNhdXNlIHRoZSBvcHRpb24gdGV4dCBpcyB0aGUgdmFsdWUgbm93IOKAlCBcIk9uIExlYXZlXCIgbXVzdCBub3QgcHV0IGEgc3BhY2VcbiAgICogaW50byBhbiBpZCBhdHRyaWJ1dGUuXG4gICAqL1xuICBnZXRSYWRpb0lkKG9wdGlvbjogYW55KTogc3RyaW5nIHtcbiAgICBjb25zdCB0ZXh0ID0gU3RyaW5nKHRoaXMuZ2V0T3B0VmFsKG9wdGlvbikgPz8gJ29wdCcpO1xuICAgIHJldHVybiBgJHt0aGlzLmZpZWxkLmlkfS0ke3RleHQudHJpbSgpLnJlcGxhY2UoL1xccysvZywgJ18nKS50b0xvd2VyQ2FzZSgpfWA7XG4gIH1cblxuICBnZXRPcHRWYWwob3B0aW9uOiBhbnkpOiBhbnkge1xuICAgIHJldHVybiByZXNvbHZlT3B0aW9uVmFsdWUob3B0aW9uLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIGdldE9wdExhYmVsKG9wdGlvbjogYW55KTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZU9wdGlvbkxhYmVsKG9wdGlvbiwgdGhpcy5sYW5ndWFnZSk7XG4gIH1cblxuICAvKiogUmVhZC1vbmx5IGRpc3BsYXkg4oCUIHN5bmNocm9ub3VzLCBwZXIgwqc2LjIuIFNlZSBgRHJvcGRvd25GaWVsZENvbXBvbmVudC5nZXRMYWJlbGAuICovXG4gIGdldFNlbGVjdGVkTGFiZWwoKTogc3RyaW5nIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuY29udHJvbD8udmFsdWU7XG4gICAgLy8gYHR5cGVvZiBudWxsID09PSAnb2JqZWN0J2AsIHNvIHdpdGhvdXQgdGhpcyBndWFyZCBhbiBlbXB0eSB2YWx1ZSBmZWxsIHRocm91Z2ggdG9cbiAgICAvLyBgcmVzb2x2ZUxhYmVsKG51bGwpYCBhbmQgcmVuZGVyZWQgYXMgYmxhbmsg4oCUIGRyb3Bkb3duIGFuZCBtdWx0aVNlbGVjdCBib3RoIHNob3cgYW4gZW0gZGFzaC5cbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHJldHVybiAn4oCUJztcbiAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMub3B0aW9ucygpLmZpbmQobyA9PiB2YWx1ZXNNYXRjaChnZXRPcHRpb25TdG9yZWRWYWx1ZShvKSwgdmFsdWUsIHRoaXMubGFuZ3VhZ2UpKTtcbiAgICBpZiAoc2VsZWN0ZWQpIHJldHVybiB0aGlzLmdldE9wdExhYmVsKHNlbGVjdGVkKTtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmxvb2t1cHMubGFiZWxGb3IodGhpcy5maWVsZD8ubGlzdE5hbWUsIHZhbHVlLCB0aGlzLmxhbmd1YWdlKTtcbiAgICBpZiAoY2FjaGVkKSByZXR1cm4gY2FjaGVkO1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnID8gcmVzb2x2ZUxhYmVsKHZhbHVlLCB0aGlzLmxhbmd1YWdlKSA6ICh2YWx1ZSA/PyAn4oCUJyk7XG4gIH1cbn1cbiJdfQ==
|