ngx-dynamic-entity 0.0.1 → 1.0.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 +139 -0
- package/esm2022/lib/field-types/array-field.component.mjs +160 -0
- package/esm2022/lib/field-types/boolean-field.component.mjs +100 -0
- package/esm2022/lib/field-types/checkbox-field.component.mjs +49 -41
- package/esm2022/lib/field-types/currency-field.component.mjs +101 -0
- package/esm2022/lib/field-types/date-field.component.mjs +47 -39
- package/esm2022/lib/field-types/dropdown-field.component.mjs +145 -54
- package/esm2022/lib/field-types/email-field.component.mjs +101 -0
- package/esm2022/lib/field-types/entity-ref-field.component.mjs +134 -70
- package/esm2022/lib/field-types/file-field.component.mjs +156 -0
- package/esm2022/lib/field-types/group-field.component.mjs +89 -0
- package/esm2022/lib/field-types/image-field.component.mjs +168 -0
- package/esm2022/lib/field-types/month-year-field.component.mjs +151 -0
- package/esm2022/lib/field-types/multi-select-field.component.mjs +110 -56
- package/esm2022/lib/field-types/number-field.component.mjs +84 -41
- package/esm2022/lib/field-types/password-field.component.mjs +109 -0
- package/esm2022/lib/field-types/radio-field.component.mjs +152 -0
- package/esm2022/lib/field-types/text-field.component.mjs +82 -42
- package/esm2022/lib/field-types/textarea-field.component.mjs +52 -41
- package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +44 -26
- package/esm2022/lib/form/dynamic-form.component.mjs +501 -67
- package/esm2022/lib/form/dynamic-record-form.component.mjs +469 -0
- package/esm2022/lib/providers/provide-field-types.mjs +72 -0
- package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +3 -5
- package/esm2022/lib/services/cascade-data.service.mjs +129 -0
- package/esm2022/lib/services/config-source.service.mjs +67 -0
- package/esm2022/lib/services/entity-ref-cache.mjs +20 -0
- package/esm2022/lib/services/entity-ref-registry.service.mjs +3 -3
- package/esm2022/lib/services/entity-ref-selection.service.mjs +27 -0
- package/esm2022/lib/services/entity-reference.service.mjs +168 -0
- package/esm2022/lib/services/field-registry.service.mjs +35 -30
- package/esm2022/lib/services/file-upload.service.mjs +89 -0
- package/esm2022/lib/services/lookup-registry.service.mjs +246 -0
- package/esm2022/lib/services/rbac.service.mjs +5 -11
- package/esm2022/lib/services/rules-evaluation.service.mjs +27 -0
- package/esm2022/lib/services/validator-registry.service.mjs +24 -7
- package/esm2022/lib/tokens/injection-tokens.mjs +88 -7
- package/esm2022/public-api.mjs +14 -5
- package/fesm2022/ngx-dynamic-entity.mjs +3985 -876
- package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
- package/lib/field-types/array-field.component.d.ts +22 -0
- package/lib/field-types/boolean-field.component.d.ts +18 -0
- package/lib/field-types/checkbox-field.component.d.ts +3 -2
- package/lib/field-types/currency-field.component.d.ts +17 -0
- package/lib/field-types/date-field.component.d.ts +3 -2
- package/lib/field-types/dropdown-field.component.d.ts +24 -4
- package/lib/field-types/email-field.component.d.ts +15 -0
- package/lib/field-types/entity-ref-field.component.d.ts +24 -11
- package/lib/field-types/file-field.component.d.ts +25 -0
- package/lib/field-types/group-field.component.d.ts +17 -0
- package/lib/field-types/image-field.component.d.ts +30 -0
- package/lib/field-types/month-year-field.component.d.ts +28 -0
- package/lib/field-types/multi-select-field.component.d.ts +18 -4
- package/lib/field-types/number-field.component.d.ts +5 -2
- package/lib/field-types/password-field.component.d.ts +17 -0
- package/lib/field-types/radio-field.component.d.ts +33 -0
- package/lib/field-types/text-field.component.d.ts +5 -3
- package/lib/field-types/textarea-field.component.d.ts +4 -2
- package/lib/form/dynamic-field/dynamic-field.component.d.ts +20 -7
- package/lib/form/dynamic-form.component.d.ts +111 -19
- package/lib/form/dynamic-record-form.component.d.ts +169 -0
- package/lib/providers/provide-field-types.d.ts +24 -0
- package/lib/providers/provide-ngx-dynamic-entity.d.ts +12 -7
- package/lib/services/cascade-data.service.d.ts +45 -0
- package/lib/services/config-source.service.d.ts +14 -0
- package/lib/services/entity-ref-cache.d.ts +27 -0
- package/lib/services/entity-ref-registry.service.d.ts +4 -3
- package/lib/services/entity-ref-selection.service.d.ts +24 -0
- package/lib/services/entity-reference.service.d.ts +49 -0
- package/lib/services/field-registry.service.d.ts +17 -7
- package/lib/services/file-upload.service.d.ts +27 -0
- package/lib/services/lookup-registry.service.d.ts +94 -0
- package/lib/services/rbac.service.d.ts +4 -9
- package/lib/services/rules-evaluation.service.d.ts +17 -0
- package/lib/services/validator-registry.service.d.ts +5 -4
- package/lib/tokens/injection-tokens.d.ts +90 -7
- package/package.json +14 -3
- package/public-api.d.ts +11 -4
- package/esm2022/lib/services/config.service.mjs +0 -58
- package/esm2022/lib/services/version.service.mjs +0 -40
- package/esm2022/lib/table/dynamic-table.component.mjs +0 -160
- package/lib/services/config.service.d.ts +0 -25
- package/lib/services/version.service.d.ts +0 -26
- package/lib/table/dynamic-table.component.d.ts +0 -56
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# ngx-dynamic-entity
|
|
2
|
+
|
|
3
|
+
Angular dynamic form renderer and tabbed record editor, powered by `@dynamic-entity/core`.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
- **DynamicFormComponent** — rich tabbed forms from `EntityFormConfig`, built on signals and reactive forms.
|
|
7
|
+
- **DynamicRecordFormComponent** — record editor with summary drawer (`showOnMinimize`), profile header, and session-baseline tracking.
|
|
8
|
+
- **Rules engine** — condition evaluation, info/warning/error banners, field and tab hiding.
|
|
9
|
+
- **Entity references with cascades** — consumer-registered loaders, parent→child filtering, `autoPatch`.
|
|
10
|
+
- **19 field type keys** across 18 components — including date, month-year, entity-ref, file, and image.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
```bash
|
|
14
|
+
npm install ngx-dynamic-entity @dynamic-entity/core
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
Two providers: one for services and registries, one for field components.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import {
|
|
23
|
+
provideNgxDynamicEntity,
|
|
24
|
+
provideBuiltInFieldTypes,
|
|
25
|
+
} from 'ngx-dynamic-entity';
|
|
26
|
+
|
|
27
|
+
export const appConfig: ApplicationConfig = {
|
|
28
|
+
providers: [
|
|
29
|
+
provideNgxDynamicEntity({
|
|
30
|
+
maskedRoles: ['IT_SUPPORT'],
|
|
31
|
+
entityRefs: { countries: ctx => api.listCountries(ctx) },
|
|
32
|
+
}),
|
|
33
|
+
provideBuiltInFieldTypes(),
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Field components are opt-in (tree-shaking)
|
|
39
|
+
|
|
40
|
+
`FieldRegistryService` imports no components. Only what you register is bundled — so an app
|
|
41
|
+
that renders three field types does not ship nineteen.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
// Everything (simplest):
|
|
45
|
+
provideBuiltInFieldTypes()
|
|
46
|
+
|
|
47
|
+
// Or only what this app renders:
|
|
48
|
+
provideFieldTypes({
|
|
49
|
+
text: TextFieldComponent,
|
|
50
|
+
number: NumberFieldComponent,
|
|
51
|
+
dropdown: DropdownFieldComponent,
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`provideFieldTypes` is a multi-provider: several calls compose, and a later set wins on a key
|
|
56
|
+
collision. `provideNgxDynamicEntity({ fieldTypes })` still overrides everything — use it to
|
|
57
|
+
swap a built-in for your own component. An unregistered type renders nothing and logs a
|
|
58
|
+
console warning in dev builds.
|
|
59
|
+
|
|
60
|
+
## Rendering
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<ngx-dynamic-form
|
|
64
|
+
[config]="formConfig"
|
|
65
|
+
[rules]="formRules"
|
|
66
|
+
[initialData]="initialRecord"
|
|
67
|
+
[originalData]="sessionBaseline"
|
|
68
|
+
(formSubmit)="onSave($event)"
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Entity references and cascades
|
|
73
|
+
|
|
74
|
+
Register a loader per entity key. It receives `{ parentValue, filters, lang }` and may return
|
|
75
|
+
an array, a Promise, or an Observable of `ReferenceOption[]`:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
provideNgxDynamicEntity({
|
|
79
|
+
entityRefs: {
|
|
80
|
+
countries: () => http.get<ReferenceOption[]>('/api/countries'),
|
|
81
|
+
cities: ctx => http.get<ReferenceOption[]>('/api/cities', { params: { country: ctx?.parentValue } }),
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
A field cascades when its `entityReference.parentField` names a sibling. The child reloads on
|
|
87
|
+
every parent change, drops a now-invalid selection, and shows nothing until the parent has a
|
|
88
|
+
value. Filtering happens server-side (via `parentValue`) or client-side:
|
|
89
|
+
|
|
90
|
+
- `lookupFilter` — keep options whose record matches the parent value at that dot-path.
|
|
91
|
+
- `lookupPath` — take options from a nested array on the selected parent's record.
|
|
92
|
+
|
|
93
|
+
Raw records are labelled through `entityReference.displayFields`; the full record rides along on
|
|
94
|
+
`ReferenceOption.record`, which is what `autoPatch` copies from.
|
|
95
|
+
|
|
96
|
+
## autoPatch and patchOnTrue
|
|
97
|
+
|
|
98
|
+
```jsonc
|
|
99
|
+
// Selecting a company fills in its address on the "address" tab
|
|
100
|
+
{ "id": "company", "type": "entity-ref",
|
|
101
|
+
"autoPatch": { "targetTab": "address", "mappings": [{ "source": "city", "target": "city" }] } }
|
|
102
|
+
|
|
103
|
+
// Ticking "same as home" copies one field into another
|
|
104
|
+
{ "id": "billingSame", "type": "boolean", "patchOnTrue": [{ "from": "home", "to": "billing" }] }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`patchOnTrue` fires on the false→true transition only, so a later manual edit is not clobbered.
|
|
108
|
+
|
|
109
|
+
## criticalField
|
|
110
|
+
|
|
111
|
+
A field marked `criticalField` renders read-only behind a lock toggle. Once unlocked and
|
|
112
|
+
changed, the form shows a deferred notice naming the field — compared against the session
|
|
113
|
+
baseline (`originalData`, or the values captured at first build). The same baseline feeds
|
|
114
|
+
`VALUE_CHANGED` rules.
|
|
115
|
+
|
|
116
|
+
## File and image fields
|
|
117
|
+
|
|
118
|
+
Both store a `FileRef`. Register an upload handler to persist on select:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
{ provide: UPLOAD_HANDLER, useValue: (file: File) => http.post<{url: string}>('/upload', file) }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
With a handler the value is `{ url, name, size, mimeType }`; without one it is
|
|
125
|
+
`{ file, name, size, mimeType }` for you to upload at submit time. Image previews use object
|
|
126
|
+
URLs for unpersisted files and revoke them automatically.
|
|
127
|
+
|
|
128
|
+
## Injection tokens
|
|
129
|
+
|
|
130
|
+
| Token | Purpose |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `MASKED_ROLES` | Roles that see `XXXXXXXXX` for masked fields |
|
|
133
|
+
| `FIELD_TYPE_REGISTRY` | Consumer overrides: field type → component (highest priority) |
|
|
134
|
+
| `FIELD_TYPE_SETS` | Multi: field-type sets contributed by `provideFieldTypes()` |
|
|
135
|
+
| `ENTITY_REF_REGISTRY` | Entity key → `EntityReferenceLoader` |
|
|
136
|
+
| `VALIDATOR_REGISTRY` | Validator name → `ValidatorFn` |
|
|
137
|
+
| `HOOK_REGISTRY` | Hook key → handler (e.g. `entity:beforeSave`) |
|
|
138
|
+
| `COMMON_MODULES_REGISTRY` | Consumer-provided shared tab modules |
|
|
139
|
+
| `UPLOAD_HANDLER` | `(file) => UploadResult \| Promise \| Observable` |
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Component, Input, inject, forwardRef } from '@angular/core';
|
|
2
|
+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { resolveLabel } from '@dynamic-entity/core';
|
|
4
|
+
import { DynamicFieldComponent } from '../form/dynamic-field/dynamic-field.component';
|
|
5
|
+
import { ValidatorRegistryService } from '../services/validator-registry.service';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/** ADR-008: ArrayFieldComponent — renders repeating rows for FormArray with + Add Item and Remove */
|
|
8
|
+
export class ArrayFieldComponent {
|
|
9
|
+
field;
|
|
10
|
+
control;
|
|
11
|
+
config;
|
|
12
|
+
language = 'en';
|
|
13
|
+
readonly = false;
|
|
14
|
+
masked = false;
|
|
15
|
+
userRoles = [];
|
|
16
|
+
fb = inject(FormBuilder);
|
|
17
|
+
validatorRegistry = inject(ValidatorRegistryService);
|
|
18
|
+
get label() {
|
|
19
|
+
return resolveLabel(this.field?.label, this.language);
|
|
20
|
+
}
|
|
21
|
+
get formArray() {
|
|
22
|
+
return this.control;
|
|
23
|
+
}
|
|
24
|
+
getItemChildControl(itemGroup, childId) {
|
|
25
|
+
return itemGroup.get(childId);
|
|
26
|
+
}
|
|
27
|
+
addItem() {
|
|
28
|
+
const controls = {};
|
|
29
|
+
for (const child of this.field.children ?? []) {
|
|
30
|
+
const validators = this.validatorRegistry.resolveFromConfig(child.validators);
|
|
31
|
+
controls[child.id] = [child.defaultValue ?? null, validators];
|
|
32
|
+
}
|
|
33
|
+
const group = this.fb.group(controls);
|
|
34
|
+
this.formArray.push(group);
|
|
35
|
+
}
|
|
36
|
+
removeItem(index) {
|
|
37
|
+
this.formArray.removeAt(index);
|
|
38
|
+
}
|
|
39
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ArrayFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
40
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: ArrayFieldComponent, isStandalone: true, selector: "ngx-array-field", inputs: { field: "field", control: "control", config: "config", language: "language", readonly: "readonly", masked: "masked", userRoles: "userRoles" }, ngImport: i0, template: `
|
|
41
|
+
<div class="ngx-field ngx-field--array"
|
|
42
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
43
|
+
<div class="ngx-field__array-header">
|
|
44
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
45
|
+
@if (!readonly && !masked) {
|
|
46
|
+
<button type="button" class="ngx-field__array-add-btn"
|
|
47
|
+
[attr.data-testid]="'field-' + field.id + '-add'" (click)="addItem()">
|
|
48
|
+
+ Add Item
|
|
49
|
+
</button>
|
|
50
|
+
}
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
@if (masked) {
|
|
54
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
55
|
+
} @else {
|
|
56
|
+
<div class="ngx-field__array-list">
|
|
57
|
+
@for (itemGroup of formArray.controls; track idx; let idx = $index) {
|
|
58
|
+
<div class="ngx-field__array-item" [attr.data-testid]="'field-' + field.id + '-row'">
|
|
59
|
+
<div class="ngx-field__array-item-header">
|
|
60
|
+
<span class="ngx-field__array-item-title">Item #{{ idx + 1 }}</span>
|
|
61
|
+
@if (!readonly) {
|
|
62
|
+
<button type="button" class="ngx-field__array-remove-btn"
|
|
63
|
+
[attr.data-testid]="'field-' + field.id + '-remove-' + idx" (click)="removeItem(idx)">
|
|
64
|
+
Remove
|
|
65
|
+
</button>
|
|
66
|
+
}
|
|
67
|
+
</div>
|
|
68
|
+
<div class="ngx-field__array-item-fields">
|
|
69
|
+
@for (child of field.children ?? []; track child.id) {
|
|
70
|
+
@if (child.visibility !== false) {
|
|
71
|
+
<ngx-dynamic-field
|
|
72
|
+
[field]="child"
|
|
73
|
+
[control]="getItemChildControl(itemGroup, child.id)"
|
|
74
|
+
[config]="config"
|
|
75
|
+
[language]="language"
|
|
76
|
+
[readonly]="readonly || !!child.readonly"
|
|
77
|
+
[userRoles]="userRoles"
|
|
78
|
+
/>
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
}
|
|
84
|
+
@if (formArray.controls.length === 0) {
|
|
85
|
+
<div class="ngx-field__array-empty" [attr.data-testid]="'field-' + field.id + '-empty'">No items added yet.</div>
|
|
86
|
+
}
|
|
87
|
+
</div>
|
|
88
|
+
}
|
|
89
|
+
</div>
|
|
90
|
+
`, isInline: true, styles: [".ngx-field--array{border:1px solid #e2e8f0;border-radius:8px;padding:16px;margin-bottom:16px;background:#f8fafc}.ngx-field__array-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.ngx-field__array-add-btn{background:#2563eb;color:#fff;border:none;padding:6px 12px;border-radius:4px;font-weight:500;cursor:pointer}.ngx-field__array-add-btn:hover{background:#1d4ed8}.ngx-field__array-list{display:flex;flex-direction:column;gap:12px}.ngx-field__array-item{background:#fff;border:1px solid #cbd5e1;border-radius:6px;padding:12px}.ngx-field__array-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;border-bottom:1px solid #f1f5f9;padding-bottom:6px}.ngx-field__array-item-title{font-weight:600;font-size:13px;color:#475569}.ngx-field__array-remove-btn{background:#ef4444;color:#fff;border:none;padding:4px 8px;border-radius:4px;font-size:12px;cursor:pointer}.ngx-field__array-empty{color:#94a3b8;font-style:italic;font-size:13px}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "component", type: i0.forwardRef(() => DynamicFieldComponent), selector: "ngx-dynamic-field", inputs: ["field", "control", "config", "currentTabId", "language", "readonly", "userRoles"] }] });
|
|
91
|
+
}
|
|
92
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ArrayFieldComponent, decorators: [{
|
|
93
|
+
type: Component,
|
|
94
|
+
args: [{ selector: 'ngx-array-field', standalone: true, imports: [ReactiveFormsModule, forwardRef(() => DynamicFieldComponent)], template: `
|
|
95
|
+
<div class="ngx-field ngx-field--array"
|
|
96
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
97
|
+
<div class="ngx-field__array-header">
|
|
98
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
99
|
+
@if (!readonly && !masked) {
|
|
100
|
+
<button type="button" class="ngx-field__array-add-btn"
|
|
101
|
+
[attr.data-testid]="'field-' + field.id + '-add'" (click)="addItem()">
|
|
102
|
+
+ Add Item
|
|
103
|
+
</button>
|
|
104
|
+
}
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
@if (masked) {
|
|
108
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
109
|
+
} @else {
|
|
110
|
+
<div class="ngx-field__array-list">
|
|
111
|
+
@for (itemGroup of formArray.controls; track idx; let idx = $index) {
|
|
112
|
+
<div class="ngx-field__array-item" [attr.data-testid]="'field-' + field.id + '-row'">
|
|
113
|
+
<div class="ngx-field__array-item-header">
|
|
114
|
+
<span class="ngx-field__array-item-title">Item #{{ idx + 1 }}</span>
|
|
115
|
+
@if (!readonly) {
|
|
116
|
+
<button type="button" class="ngx-field__array-remove-btn"
|
|
117
|
+
[attr.data-testid]="'field-' + field.id + '-remove-' + idx" (click)="removeItem(idx)">
|
|
118
|
+
Remove
|
|
119
|
+
</button>
|
|
120
|
+
}
|
|
121
|
+
</div>
|
|
122
|
+
<div class="ngx-field__array-item-fields">
|
|
123
|
+
@for (child of field.children ?? []; track child.id) {
|
|
124
|
+
@if (child.visibility !== false) {
|
|
125
|
+
<ngx-dynamic-field
|
|
126
|
+
[field]="child"
|
|
127
|
+
[control]="getItemChildControl(itemGroup, child.id)"
|
|
128
|
+
[config]="config"
|
|
129
|
+
[language]="language"
|
|
130
|
+
[readonly]="readonly || !!child.readonly"
|
|
131
|
+
[userRoles]="userRoles"
|
|
132
|
+
/>
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
}
|
|
138
|
+
@if (formArray.controls.length === 0) {
|
|
139
|
+
<div class="ngx-field__array-empty" [attr.data-testid]="'field-' + field.id + '-empty'">No items added yet.</div>
|
|
140
|
+
}
|
|
141
|
+
</div>
|
|
142
|
+
}
|
|
143
|
+
</div>
|
|
144
|
+
`, styles: [".ngx-field--array{border:1px solid #e2e8f0;border-radius:8px;padding:16px;margin-bottom:16px;background:#f8fafc}.ngx-field__array-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.ngx-field__array-add-btn{background:#2563eb;color:#fff;border:none;padding:6px 12px;border-radius:4px;font-weight:500;cursor:pointer}.ngx-field__array-add-btn:hover{background:#1d4ed8}.ngx-field__array-list{display:flex;flex-direction:column;gap:12px}.ngx-field__array-item{background:#fff;border:1px solid #cbd5e1;border-radius:6px;padding:12px}.ngx-field__array-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;border-bottom:1px solid #f1f5f9;padding-bottom:6px}.ngx-field__array-item-title{font-weight:600;font-size:13px;color:#475569}.ngx-field__array-remove-btn{background:#ef4444;color:#fff;border:none;padding:4px 8px;border-radius:4px;font-size:12px;cursor:pointer}.ngx-field__array-empty{color:#94a3b8;font-style:italic;font-size:13px}\n"] }]
|
|
145
|
+
}], propDecorators: { field: [{
|
|
146
|
+
type: Input
|
|
147
|
+
}], control: [{
|
|
148
|
+
type: Input
|
|
149
|
+
}], config: [{
|
|
150
|
+
type: Input
|
|
151
|
+
}], language: [{
|
|
152
|
+
type: Input
|
|
153
|
+
}], readonly: [{
|
|
154
|
+
type: Input
|
|
155
|
+
}], masked: [{
|
|
156
|
+
type: Input
|
|
157
|
+
}], userRoles: [{
|
|
158
|
+
type: Input
|
|
159
|
+
}] } });
|
|
160
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJyYXktZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9hcnJheS1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNyRSxPQUFPLEVBQThCLFdBQVcsRUFBYSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXpHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQztBQUN0RixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQzs7QUFFbEYscUdBQXFHO0FBNEhyRyxNQUFNLE9BQU8sbUJBQW1CO0lBQ3JCLEtBQUssQ0FBcUI7SUFDMUIsT0FBTyxDQUFtQjtJQUMxQixNQUFNLENBQW9CO0lBQzFCLFFBQVEsR0FBVyxJQUFJLENBQUM7SUFDeEIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUMxQixNQUFNLEdBQVksS0FBSyxDQUFDO0lBQ3hCLFNBQVMsR0FBYSxFQUFFLENBQUM7SUFFakIsRUFBRSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN6QixpQkFBaUIsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUV0RSxJQUFJLEtBQUs7UUFDUCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVELElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLE9BQW9CLENBQUM7SUFDbkMsQ0FBQztJQUVELG1CQUFtQixDQUFDLFNBQTBCLEVBQUUsT0FBZTtRQUM3RCxPQUFRLFNBQXVCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBb0IsQ0FBQztJQUNsRSxDQUFDO0lBRUQsT0FBTztRQUNMLE1BQU0sUUFBUSxHQUF3QixFQUFFLENBQUM7UUFDekMsS0FBSyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUM5QyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzlFLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsWUFBWSxJQUFJLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNoRSxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELFVBQVUsQ0FBQyxLQUFhO1FBQ3RCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pDLENBQUM7d0dBcENVLG1CQUFtQjs0RkFBbkIsbUJBQW1CLG1PQXZIcEI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0RULDZrQ0FuRFMsbUJBQW1CLG9EQUFtQixxQkFBcUI7OzRGQXdIMUQsbUJBQW1CO2tCQTNIL0IsU0FBUzsrQkFDRSxpQkFBaUIsY0FDZixJQUFJLFdBQ1AsQ0FBQyxtQkFBbUIsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMscUJBQXFCLENBQUMsQ0FBQyxZQUM3RDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrRFQ7OEJBc0VRLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIGluamVjdCwgZm9yd2FyZFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIEZvcm1BcnJheSwgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHR5cGUgeyBOZXN0ZWRGaWVsZENvbmZpZywgRW50aXR5Rm9ybUNvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgcmVzb2x2ZUxhYmVsIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xyXG5pbXBvcnQgeyBEeW5hbWljRmllbGRDb21wb25lbnQgfSBmcm9tICcuLi9mb3JtL2R5bmFtaWMtZmllbGQvZHluYW1pYy1maWVsZC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBWYWxpZGF0b3JSZWdpc3RyeVNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy92YWxpZGF0b3ItcmVnaXN0cnkuc2VydmljZSc7XHJcblxyXG4vKiogQURSLTAwODogQXJyYXlGaWVsZENvbXBvbmVudCDigJQgcmVuZGVycyByZXBlYXRpbmcgcm93cyBmb3IgRm9ybUFycmF5IHdpdGggKyBBZGQgSXRlbSBhbmQgUmVtb3ZlICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmd4LWFycmF5LWZpZWxkJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlLCBmb3J3YXJkUmVmKCgpID0+IER5bmFtaWNGaWVsZENvbXBvbmVudCldLFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkIG5neC1maWVsZC0tYXJyYXlcIlxyXG4gICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkXCIgW2F0dHIuZGF0YS1maWVsZC10eXBlXT1cImZpZWxkLnR5cGVcIiBbY2xhc3Mubmd4LWZpZWxkLS1yZWFkb25seV09XCJyZWFkb25seVwiIFtjbGFzcy5uZ3gtZmllbGQtLW1hc2tlZF09XCJtYXNrZWRcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZF9fYXJyYXktaGVhZGVyXCI+XHJcbiAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX19sYWJlbFwiPnt7IGxhYmVsIH19PC9sYWJlbD5cclxuICAgICAgICBAaWYgKCFyZWFkb25seSAmJiAhbWFza2VkKSB7XHJcbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIm5neC1maWVsZF9fYXJyYXktYWRkLWJ0blwiXHJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWFkZCdcIiAoY2xpY2spPVwiYWRkSXRlbSgpXCI+XHJcbiAgICAgICAgICAgICsgQWRkIEl0ZW1cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcblxyXG4gICAgICBAaWYgKG1hc2tlZCkge1xyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZSBuZ3gtZmllbGRfX3ZhbHVlLS1tYXNrZWRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy1tYXNrZWQnXCI+WFhYWFhYWFhYPC9zcGFuPlxyXG4gICAgICB9IEBlbHNlIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkX19hcnJheS1saXN0XCI+XHJcbiAgICAgICAgICBAZm9yIChpdGVtR3JvdXAgb2YgZm9ybUFycmF5LmNvbnRyb2xzOyB0cmFjayBpZHg7IGxldCBpZHggPSAkaW5kZXgpIHtcclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZF9fYXJyYXktaXRlbVwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLXJvdydcIj5cclxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkX19hcnJheS1pdGVtLWhlYWRlclwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2FycmF5LWl0ZW0tdGl0bGVcIj5JdGVtICN7eyBpZHggKyAxIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgQGlmICghcmVhZG9ubHkpIHtcclxuICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJuZ3gtZmllbGRfX2FycmF5LXJlbW92ZS1idG5cIlxyXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLXJlbW92ZS0nICsgaWR4XCIgKGNsaWNrKT1cInJlbW92ZUl0ZW0oaWR4KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIFJlbW92ZVxyXG4gICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkX19hcnJheS1pdGVtLWZpZWxkc1wiPlxyXG4gICAgICAgICAgICAgICAgQGZvciAoY2hpbGQgb2YgZmllbGQuY2hpbGRyZW4gPz8gW107IHRyYWNrIGNoaWxkLmlkKSB7XHJcbiAgICAgICAgICAgICAgICAgIEBpZiAoY2hpbGQudmlzaWJpbGl0eSAhPT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICA8bmd4LWR5bmFtaWMtZmllbGRcclxuICAgICAgICAgICAgICAgICAgICAgIFtmaWVsZF09XCJjaGlsZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBbY29udHJvbF09XCJnZXRJdGVtQ2hpbGRDb250cm9sKGl0ZW1Hcm91cCwgY2hpbGQuaWQpXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtjb25maWddPVwiY29uZmlnXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtsYW5ndWFnZV09XCJsYW5ndWFnZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHkgfHwgISFjaGlsZC5yZWFkb25seVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBbdXNlclJvbGVzXT1cInVzZXJSb2xlc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIEBpZiAoZm9ybUFycmF5LmNvbnRyb2xzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkX19hcnJheS1lbXB0eVwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWVtcHR5J1wiPk5vIGl0ZW1zIGFkZGVkIHlldC48L2Rpdj5cclxuICAgICAgICAgIH1cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgfVxyXG4gICAgPC9kaXY+XHJcbiAgYCxcclxuICBzdHlsZXM6IFtcclxuICAgIGBcclxuICAgICAgLm5neC1maWVsZC0tYXJyYXkge1xyXG4gICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNlMmU4ZjA7XHJcbiAgICAgICAgYm9yZGVyLXJhZGl1czogOHB4O1xyXG4gICAgICAgIHBhZGRpbmc6IDE2cHg7XHJcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMTZweDtcclxuICAgICAgICBiYWNrZ3JvdW5kOiAjZjhmYWZjO1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZmllbGRfX2FycmF5LWhlYWRlciB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XHJcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcclxuICAgICAgICBtYXJnaW4tYm90dG9tOiAxMnB4O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZmllbGRfX2FycmF5LWFkZC1idG4ge1xyXG4gICAgICAgIGJhY2tncm91bmQ6ICMyNTYzZWI7XHJcbiAgICAgICAgY29sb3I6ICNmZmY7XHJcbiAgICAgICAgYm9yZGVyOiBub25lO1xyXG4gICAgICAgIHBhZGRpbmc6IDZweCAxMnB4O1xyXG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcclxuICAgICAgICBmb250LXdlaWdodDogNTAwO1xyXG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgfVxyXG4gICAgICAubmd4LWZpZWxkX19hcnJheS1hZGQtYnRuOmhvdmVyIHtcclxuICAgICAgICBiYWNrZ3JvdW5kOiAjMWQ0ZWQ4O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZmllbGRfX2FycmF5LWxpc3Qge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgICBnYXA6IDEycHg7XHJcbiAgICAgIH1cclxuICAgICAgLm5neC1maWVsZF9fYXJyYXktaXRlbSB7XHJcbiAgICAgICAgYmFja2dyb3VuZDogI2ZmZjtcclxuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjY2JkNWUxO1xyXG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDtcclxuICAgICAgICBwYWRkaW5nOiAxMnB4O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZmllbGRfX2FycmF5LWl0ZW0taGVhZGVyIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcclxuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xyXG4gICAgICAgIG1hcmdpbi1ib3R0b206IDhweDtcclxuICAgICAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2YxZjVmOTtcclxuICAgICAgICBwYWRkaW5nLWJvdHRvbTogNnB4O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZmllbGRfX2FycmF5LWl0ZW0tdGl0bGUge1xyXG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XHJcbiAgICAgICAgZm9udC1zaXplOiAxM3B4O1xyXG4gICAgICAgIGNvbG9yOiAjNDc1NTY5O1xyXG4gICAgICB9XHJcbiAgICAgIC5uZ3gtZmllbGRfX2FycmF5LXJlbW92ZS1idG4ge1xyXG4gICAgICAgIGJhY2tncm91bmQ6ICNlZjQ0NDQ7XHJcbiAgICAgICAgY29sb3I6ICNmZmY7XHJcbiAgICAgICAgYm9yZGVyOiBub25lO1xyXG4gICAgICAgIHBhZGRpbmc6IDRweCA4cHg7XHJcbiAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xyXG4gICAgICAgIGZvbnQtc2l6ZTogMTJweDtcclxuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XHJcbiAgICAgIH1cclxuICAgICAgLm5neC1maWVsZF9fYXJyYXktZW1wdHkge1xyXG4gICAgICAgIGNvbG9yOiAjOTRhM2I4O1xyXG4gICAgICAgIGZvbnQtc3R5bGU6IGl0YWxpYztcclxuICAgICAgICBmb250LXNpemU6IDEzcHg7XHJcbiAgICAgIH1cclxuICAgIGAsXHJcbiAgXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIEFycmF5RmllbGRDb21wb25lbnQge1xyXG4gIEBJbnB1dCgpIGZpZWxkITogTmVzdGVkRmllbGRDb25maWc7XHJcbiAgQElucHV0KCkgY29udHJvbCE6IEFic3RyYWN0Q29udHJvbDtcclxuICBASW5wdXQoKSBjb25maWchOiBFbnRpdHlGb3JtQ29uZmlnO1xyXG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmcgPSAnZW4nO1xyXG4gIEBJbnB1dCgpIHJlYWRvbmx5OiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgbWFza2VkOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgdXNlclJvbGVzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICBwcml2YXRlIHJlYWRvbmx5IGZiID0gaW5qZWN0KEZvcm1CdWlsZGVyKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IHZhbGlkYXRvclJlZ2lzdHJ5ID0gaW5qZWN0KFZhbGlkYXRvclJlZ2lzdHJ5U2VydmljZSk7XHJcblxyXG4gIGdldCBsYWJlbCgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbCh0aGlzLmZpZWxkPy5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XHJcbiAgfVxyXG5cclxuICBnZXQgZm9ybUFycmF5KCk6IEZvcm1BcnJheSB7XHJcbiAgICByZXR1cm4gdGhpcy5jb250cm9sIGFzIEZvcm1BcnJheTtcclxuICB9XHJcblxyXG4gIGdldEl0ZW1DaGlsZENvbnRyb2woaXRlbUdyb3VwOiBBYnN0cmFjdENvbnRyb2wsIGNoaWxkSWQ6IHN0cmluZyk6IEFic3RyYWN0Q29udHJvbCB7XHJcbiAgICByZXR1cm4gKGl0ZW1Hcm91cCBhcyBGb3JtR3JvdXApLmdldChjaGlsZElkKSBhcyBBYnN0cmFjdENvbnRyb2w7XHJcbiAgfVxyXG5cclxuICBhZGRJdGVtKCk6IHZvaWQge1xyXG4gICAgY29uc3QgY29udHJvbHM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5maWVsZC5jaGlsZHJlbiA/PyBbXSkge1xyXG4gICAgICBjb25zdCB2YWxpZGF0b3JzID0gdGhpcy52YWxpZGF0b3JSZWdpc3RyeS5yZXNvbHZlRnJvbUNvbmZpZyhjaGlsZC52YWxpZGF0b3JzKTtcclxuICAgICAgY29udHJvbHNbY2hpbGQuaWRdID0gW2NoaWxkLmRlZmF1bHRWYWx1ZSA/PyBudWxsLCB2YWxpZGF0b3JzXTtcclxuICAgIH1cclxuICAgIGNvbnN0IGdyb3VwID0gdGhpcy5mYi5ncm91cChjb250cm9scyk7XHJcbiAgICB0aGlzLmZvcm1BcnJheS5wdXNoKGdyb3VwKTtcclxuICB9XHJcblxyXG4gIHJlbW92ZUl0ZW0oaW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5mb3JtQXJyYXkucmVtb3ZlQXQoaW5kZXgpO1xyXG4gIH1cclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Component, Input } 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
|
+
/**
|
|
7
|
+
* Boolean field: a slide-toggle style switch (true/false).
|
|
8
|
+
* Distinct from `checkbox` (which is a standalone bool) in that it renders as a
|
|
9
|
+
* toggle switch with Yes/No labels for clearer binary state communication.
|
|
10
|
+
*/
|
|
11
|
+
export class BooleanFieldComponent {
|
|
12
|
+
field;
|
|
13
|
+
control;
|
|
14
|
+
language = 'en';
|
|
15
|
+
readonly = false;
|
|
16
|
+
masked = false;
|
|
17
|
+
get label() {
|
|
18
|
+
return resolveLabel(this.field?.label, this.language);
|
|
19
|
+
}
|
|
20
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BooleanFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
21
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: BooleanFieldComponent, isStandalone: true, selector: "ngx-boolean-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
22
|
+
<div class="ngx-field ngx-field--boolean"
|
|
23
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
24
|
+
@if (masked) {
|
|
25
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
26
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
27
|
+
} @else if (readonly) {
|
|
28
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
29
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value ? 'Yes' : 'No' }}</span>
|
|
30
|
+
} @else {
|
|
31
|
+
<div class="ngx-field__toggle-wrap">
|
|
32
|
+
<label class="ngx-field__toggle-label">{{ label }}</label>
|
|
33
|
+
<label class="ngx-field__toggle-switch" [class.ngx-field__toggle-switch--checked]="control.value">
|
|
34
|
+
<input
|
|
35
|
+
class="ngx-field__toggle-input"
|
|
36
|
+
type="checkbox"
|
|
37
|
+
role="switch"
|
|
38
|
+
[formControl]="$any(control)"
|
|
39
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
40
|
+
[attr.aria-checked]="control.value"
|
|
41
|
+
/>
|
|
42
|
+
<span class="ngx-field__toggle-track">
|
|
43
|
+
<span class="ngx-field__toggle-thumb"></span>
|
|
44
|
+
</span>
|
|
45
|
+
<span class="ngx-field__toggle-text">{{ control.value ? 'Yes' : 'No' }}</span>
|
|
46
|
+
</label>
|
|
47
|
+
</div>
|
|
48
|
+
}
|
|
49
|
+
</div>
|
|
50
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][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"] }] });
|
|
51
|
+
}
|
|
52
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BooleanFieldComponent, decorators: [{
|
|
53
|
+
type: Component,
|
|
54
|
+
args: [{
|
|
55
|
+
selector: 'ngx-boolean-field',
|
|
56
|
+
standalone: true,
|
|
57
|
+
imports: [ReactiveFormsModule],
|
|
58
|
+
template: `
|
|
59
|
+
<div class="ngx-field ngx-field--boolean"
|
|
60
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
61
|
+
@if (masked) {
|
|
62
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
63
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
64
|
+
} @else if (readonly) {
|
|
65
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
66
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value ? 'Yes' : 'No' }}</span>
|
|
67
|
+
} @else {
|
|
68
|
+
<div class="ngx-field__toggle-wrap">
|
|
69
|
+
<label class="ngx-field__toggle-label">{{ label }}</label>
|
|
70
|
+
<label class="ngx-field__toggle-switch" [class.ngx-field__toggle-switch--checked]="control.value">
|
|
71
|
+
<input
|
|
72
|
+
class="ngx-field__toggle-input"
|
|
73
|
+
type="checkbox"
|
|
74
|
+
role="switch"
|
|
75
|
+
[formControl]="$any(control)"
|
|
76
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
77
|
+
[attr.aria-checked]="control.value"
|
|
78
|
+
/>
|
|
79
|
+
<span class="ngx-field__toggle-track">
|
|
80
|
+
<span class="ngx-field__toggle-thumb"></span>
|
|
81
|
+
</span>
|
|
82
|
+
<span class="ngx-field__toggle-text">{{ control.value ? 'Yes' : 'No' }}</span>
|
|
83
|
+
</label>
|
|
84
|
+
</div>
|
|
85
|
+
}
|
|
86
|
+
</div>
|
|
87
|
+
`,
|
|
88
|
+
}]
|
|
89
|
+
}], propDecorators: { field: [{
|
|
90
|
+
type: Input
|
|
91
|
+
}], control: [{
|
|
92
|
+
type: Input
|
|
93
|
+
}], language: [{
|
|
94
|
+
type: Input
|
|
95
|
+
}], readonly: [{
|
|
96
|
+
type: Input
|
|
97
|
+
}], masked: [{
|
|
98
|
+
type: Input
|
|
99
|
+
}] } });
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vbGVhbi1maWVsZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2ZpZWxkLXR5cGVzL2Jvb2xlYW4tZmllbGQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pELE9BQU8sRUFBbUIsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7OztBQUVwRDs7OztHQUlHO0FBb0NILE1BQU0sT0FBTyxxQkFBcUI7SUFDdkIsS0FBSyxDQUFxQjtJQUMxQixPQUFPLENBQW1CO0lBQzFCLFFBQVEsR0FBVyxJQUFJLENBQUM7SUFDeEIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUMxQixNQUFNLEdBQVksS0FBSyxDQUFDO0lBRWpDLElBQUksS0FBSztRQUNQLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN4RCxDQUFDO3dHQVRVLHFCQUFxQjs0RkFBckIscUJBQXFCLDJMQS9CdEI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJULDJEQTlCUyxtQkFBbUI7OzRGQWdDbEIscUJBQXFCO2tCQW5DakMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsbUJBQW1CO29CQUM3QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsT0FBTyxFQUFFLENBQUMsbUJBQW1CLENBQUM7b0JBQzlCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2QlQ7aUJBQ0Y7OEJBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB0eXBlIHsgTmVzdGVkRmllbGRDb25maWcgfSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XHJcbmltcG9ydCB7IHJlc29sdmVMYWJlbCB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuXHJcbi8qKlxyXG4gKiBCb29sZWFuIGZpZWxkOiBhIHNsaWRlLXRvZ2dsZSBzdHlsZSBzd2l0Y2ggKHRydWUvZmFsc2UpLlxyXG4gKiBEaXN0aW5jdCBmcm9tIGBjaGVja2JveGAgKHdoaWNoIGlzIGEgc3RhbmRhbG9uZSBib29sKSBpbiB0aGF0IGl0IHJlbmRlcnMgYXMgYVxyXG4gKiB0b2dnbGUgc3dpdGNoIHdpdGggWWVzL05vIGxhYmVscyBmb3IgY2xlYXJlciBiaW5hcnkgc3RhdGUgY29tbXVuaWNhdGlvbi5cclxuICovXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmd4LWJvb2xlYW4tZmllbGQnLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW1JlYWN0aXZlRm9ybXNNb2R1bGVdLFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkIG5neC1maWVsZC0tYm9vbGVhblwiXHJcbiAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWRcIiBbYXR0ci5kYXRhLWZpZWxkLXR5cGVdPVwiZmllbGQudHlwZVwiIFtjbGFzcy5uZ3gtZmllbGQtLXJlYWRvbmx5XT1cInJlYWRvbmx5XCIgW2NsYXNzLm5neC1maWVsZC0tbWFza2VkXT1cIm1hc2tlZFwiPlxyXG4gICAgICBAaWYgKG1hc2tlZCkge1xyXG4gICAgICAgIDxsYWJlbCBjbGFzcz1cIm5neC1maWVsZF9fbGFiZWxcIj57eyBsYWJlbCB9fTwvbGFiZWw+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlIG5neC1maWVsZF9fdmFsdWUtLW1hc2tlZFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLW1hc2tlZCdcIj5YWFhYWFhYWFg8L3NwYW4+XHJcbiAgICAgIH0gQGVsc2UgaWYgKHJlYWRvbmx5KSB7XHJcbiAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX19sYWJlbFwiPnt7IGxhYmVsIH19PC9sYWJlbD5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWVcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy12YWx1ZSdcIj57eyBjb250cm9sLnZhbHVlID8gJ1llcycgOiAnTm8nIH19PC9zcGFuPlxyXG4gICAgICB9IEBlbHNlIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkX190b2dnbGUtd3JhcFwiPlxyXG4gICAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX190b2dnbGUtbGFiZWxcIj57eyBsYWJlbCB9fTwvbGFiZWw+XHJcbiAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX3RvZ2dsZS1zd2l0Y2hcIiBbY2xhc3Mubmd4LWZpZWxkX190b2dnbGUtc3dpdGNoLS1jaGVja2VkXT1cImNvbnRyb2wudmFsdWVcIj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJuZ3gtZmllbGRfX3RvZ2dsZS1pbnB1dFwiXHJcbiAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcclxuICAgICAgICAgICAgICByb2xlPVwic3dpdGNoXCJcclxuICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiJGFueShjb250cm9sKVwiXHJcbiAgICAgICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZmllbGQuZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXHJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1jaGVja2VkXT1cImNvbnRyb2wudmFsdWVcIlxyXG4gICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdG9nZ2xlLXRyYWNrXCI+XHJcbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3RvZ2dsZS10aHVtYlwiPjwvc3Bhbj5cclxuICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdG9nZ2xlLXRleHRcIj57eyBjb250cm9sLnZhbHVlID8gJ1llcycgOiAnTm8nIH19PC9zcGFuPlxyXG4gICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgfVxyXG4gICAgPC9kaXY+XHJcbiAgYCxcclxufSlcclxuZXhwb3J0IGNsYXNzIEJvb2xlYW5GaWVsZENvbXBvbmVudCB7XHJcbiAgQElucHV0KCkgZmllbGQhOiBOZXN0ZWRGaWVsZENvbmZpZztcclxuICBASW5wdXQoKSBjb250cm9sITogQWJzdHJhY3RDb250cm9sO1xyXG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmcgPSAnZW4nO1xyXG4gIEBJbnB1dCgpIHJlYWRvbmx5OiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgbWFza2VkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIGdldCBsYWJlbCgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbCh0aGlzLmZpZWxkPy5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XHJcbiAgfVxyXG59XHJcbiJdfQ==
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component, Input } from '@angular/core';
|
|
2
2
|
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { resolveLabel } from '@dynamic-entity/core';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
import * as i1 from "@angular/forms";
|
|
5
6
|
export class CheckboxFieldComponent {
|
|
@@ -8,27 +9,32 @@ export class CheckboxFieldComponent {
|
|
|
8
9
|
language = 'en';
|
|
9
10
|
readonly = false;
|
|
10
11
|
masked = false;
|
|
12
|
+
get label() {
|
|
13
|
+
return resolveLabel(this.field?.label, this.language);
|
|
14
|
+
}
|
|
11
15
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CheckboxFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CheckboxFieldComponent, isStandalone: true, selector: "ngx-checkbox-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
13
|
-
<div class="ngx-field ngx-field--checkbox"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
[
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CheckboxFieldComponent, isStandalone: true, selector: "ngx-checkbox-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
17
|
+
<div class="ngx-field ngx-field--checkbox"
|
|
18
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
19
|
+
@if (masked) {
|
|
20
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
21
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
22
|
+
} @else if (readonly) {
|
|
23
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
24
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value ? 'Yes' : 'No' }}</span>
|
|
25
|
+
} @else {
|
|
26
|
+
<label class="ngx-field__label" [attr.for]="field.id">
|
|
27
|
+
<input
|
|
28
|
+
[id]="field.id"
|
|
29
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
30
|
+
type="checkbox"
|
|
31
|
+
[formControl]="$any(control)"
|
|
32
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
33
|
+
/>
|
|
34
|
+
{{ label }}
|
|
35
|
+
</label>
|
|
36
|
+
}
|
|
37
|
+
</div>
|
|
32
38
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][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"] }] });
|
|
33
39
|
}
|
|
34
40
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CheckboxFieldComponent, decorators: [{
|
|
@@ -37,26 +43,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
37
43
|
selector: 'ngx-checkbox-field',
|
|
38
44
|
standalone: true,
|
|
39
45
|
imports: [ReactiveFormsModule],
|
|
40
|
-
template: `
|
|
41
|
-
<div class="ngx-field ngx-field--checkbox"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
[
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
template: `
|
|
47
|
+
<div class="ngx-field ngx-field--checkbox"
|
|
48
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
49
|
+
@if (masked) {
|
|
50
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
51
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
52
|
+
} @else if (readonly) {
|
|
53
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
54
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ control.value ? 'Yes' : 'No' }}</span>
|
|
55
|
+
} @else {
|
|
56
|
+
<label class="ngx-field__label" [attr.for]="field.id">
|
|
57
|
+
<input
|
|
58
|
+
[id]="field.id"
|
|
59
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
60
|
+
type="checkbox"
|
|
61
|
+
[formControl]="$any(control)"
|
|
62
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
63
|
+
/>
|
|
64
|
+
{{ label }}
|
|
65
|
+
</label>
|
|
66
|
+
}
|
|
67
|
+
</div>
|
|
60
68
|
`,
|
|
61
69
|
}]
|
|
62
70
|
}], propDecorators: { field: [{
|
|
@@ -70,4 +78,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
70
78
|
}], masked: [{
|
|
71
79
|
type: Input
|
|
72
80
|
}] } });
|
|
73
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2tib3gtZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9jaGVja2JveC1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFtQixtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXRFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7O0FBOEJwRCxNQUFNLE9BQU8sc0JBQXNCO0lBQ3hCLEtBQUssQ0FBcUI7SUFDMUIsT0FBTyxDQUFtQjtJQUMxQixRQUFRLEdBQVcsSUFBSSxDQUFDO0lBQ3hCLFFBQVEsR0FBWSxLQUFLLENBQUM7SUFDMUIsTUFBTSxHQUFZLEtBQUssQ0FBQztJQUVqQyxJQUFJLEtBQUs7UUFDUCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDeEQsQ0FBQzt3R0FUVSxzQkFBc0I7NEZBQXRCLHNCQUFzQiw0TEF4QnZCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JULDJEQXZCUyxtQkFBbUI7OzRGQXlCbEIsc0JBQXNCO2tCQTVCbEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsb0JBQW9CO29CQUM5QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsT0FBTyxFQUFFLENBQUMsbUJBQW1CLENBQUM7b0JBQzlCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCVDtpQkFDRjs4QkFFVSxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHR5cGUgeyBOZXN0ZWRGaWVsZENvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgcmVzb2x2ZUxhYmVsIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduZ3gtY2hlY2tib3gtZmllbGQnLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW1JlYWN0aXZlRm9ybXNNb2R1bGVdLFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICA8ZGl2IGNsYXNzPVwibmd4LWZpZWxkIG5neC1maWVsZC0tY2hlY2tib3hcIlxyXG4gICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkXCIgW2F0dHIuZGF0YS1maWVsZC10eXBlXT1cImZpZWxkLnR5cGVcIiBbY2xhc3Mubmd4LWZpZWxkLS1yZWFkb25seV09XCJyZWFkb25seVwiIFtjbGFzcy5uZ3gtZmllbGQtLW1hc2tlZF09XCJtYXNrZWRcIj5cclxuICAgICAgQGlmIChtYXNrZWQpIHtcclxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX2xhYmVsXCI+e3sgbGFiZWwgfX08L2xhYmVsPlxyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZSBuZ3gtZmllbGRfX3ZhbHVlLS1tYXNrZWRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy1tYXNrZWQnXCI+WFhYWFhYWFhYPC9zcGFuPlxyXG4gICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xyXG4gICAgICAgIDxsYWJlbCBjbGFzcz1cIm5neC1maWVsZF9fbGFiZWxcIj57eyBsYWJlbCB9fTwvbGFiZWw+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctdmFsdWUnXCI+e3sgY29udHJvbC52YWx1ZSA/ICdZZXMnIDogJ05vJyB9fTwvc3Bhbj5cclxuICAgICAgfSBAZWxzZSB7XHJcbiAgICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX19sYWJlbFwiIFthdHRyLmZvcl09XCJmaWVsZC5pZFwiPlxyXG4gICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgIFtpZF09XCJmaWVsZC5pZFwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwibmd4LWZpZWxkX19pbnB1dFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWlucHV0J1wiXHJcbiAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCIkYW55KGNvbnRyb2wpXCJcclxuICAgICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZmllbGQuZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXHJcbiAgICAgICAgICAvPlxyXG4gICAgICAgICAge3sgbGFiZWwgfX1cclxuICAgICAgICA8L2xhYmVsPlxyXG4gICAgICB9XHJcbiAgICA8L2Rpdj5cclxuICBgLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgQ2hlY2tib3hGaWVsZENvbXBvbmVudCB7XHJcbiAgQElucHV0KCkgZmllbGQhOiBOZXN0ZWRGaWVsZENvbmZpZztcclxuICBASW5wdXQoKSBjb250cm9sITogQWJzdHJhY3RDb250cm9sO1xyXG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmcgPSAnZW4nO1xyXG4gIEBJbnB1dCgpIHJlYWRvbmx5OiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgbWFza2VkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIGdldCBsYWJlbCgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbCh0aGlzLmZpZWxkPy5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XHJcbiAgfVxyXG59XHJcbiJdfQ==
|