@gnggln/ng-ui-system 1.0.0-alpha.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/esm2022/gnggln-ng-ui-system.mjs +5 -0
- package/esm2022/lib/components/accordion/accordion.component.mjs +353 -0
- package/esm2022/lib/components/accordion/accordion.types.mjs +6 -0
- package/esm2022/lib/components/accordion/index.mjs +2 -0
- package/esm2022/lib/components/base-layout/base-layout.component.mjs +218 -0
- package/esm2022/lib/components/base-layout/base-layout.types.mjs +6 -0
- package/esm2022/lib/components/base-layout/index.mjs +14 -0
- package/esm2022/lib/components/button/button-area.component.mjs +196 -0
- package/esm2022/lib/components/button/button.component.mjs +164 -0
- package/esm2022/lib/components/button/button.types.mjs +6 -0
- package/esm2022/lib/components/button/index.mjs +16 -0
- package/esm2022/lib/components/crud-table/crud-table.component.mjs +789 -0
- package/esm2022/lib/components/crud-table/crud-table.types.mjs +6 -0
- package/esm2022/lib/components/crud-table/index.mjs +16 -0
- package/esm2022/lib/components/form-builder/adapters/it-date-adapter.mjs +82 -0
- package/esm2022/lib/components/form-builder/directives/currency-input.directive.mjs +184 -0
- package/esm2022/lib/components/form-builder/form-builder.component.mjs +824 -0
- package/esm2022/lib/components/form-builder/form-wizard.component.mjs +510 -0
- package/esm2022/lib/components/form-builder/index.mjs +19 -0
- package/esm2022/lib/components/form-builder/services/form-condition.service.mjs +132 -0
- package/esm2022/lib/components/form-builder/services/form-validation.service.mjs +381 -0
- package/esm2022/lib/components/form-builder/services/location.service.mjs +140 -0
- package/esm2022/lib/components/form-builder/services/wizard-sync.service.mjs +84 -0
- package/esm2022/lib/components/form-builder/sub-components/error-summary/form-error-summary.component.mjs +161 -0
- package/esm2022/lib/components/form-builder/sub-components/file-input/file-input.component.mjs +310 -0
- package/esm2022/lib/components/form-builder/sub-components/specifica-territoriale/specifica-territoriale.component.mjs +648 -0
- package/esm2022/lib/components/form-builder/sub-components/table-territoriale/table-territoriale.component.mjs +432 -0
- package/esm2022/lib/components/form-builder/types/condition.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/field.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/index.mjs +2 -0
- package/esm2022/lib/components/form-builder/types/schema.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/territoriale.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/validation.types.mjs +6 -0
- package/esm2022/lib/components/form-builder-editor/form-builder-editor.component.mjs +730 -0
- package/esm2022/lib/components/form-builder-editor/form-builder-editor.service.mjs +56 -0
- package/esm2022/lib/components/form-builder-editor/index.mjs +21 -0
- package/esm2022/lib/components/form-builder-editor/services/editor-persistence.service.mjs +190 -0
- package/esm2022/lib/components/form-builder-editor/services/editor-state.service.mjs +324 -0
- package/esm2022/lib/components/form-builder-editor/services/field-factory.service.mjs +188 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/condition-editor/condition-editor.component.mjs +667 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/editor-toolbar/editor-toolbar.component.mjs +317 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/field-config-panel/field-config-panel.component.mjs +611 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/field-palette/field-palette.component.mjs +267 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/form-values-panel/form-values-panel.component.mjs +276 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/options-editor/options-editor.component.mjs +323 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/preview-container/preview-container.component.mjs +238 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/section-editor/section-editor.component.mjs +472 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/validation-editor/validation-editor.component.mjs +473 -0
- package/esm2022/lib/components/form-builder-editor/types/editor.types.mjs +6 -0
- package/esm2022/lib/components/layout-builder/index.mjs +18 -0
- package/esm2022/lib/components/layout-builder/layout-builder.component.mjs +1730 -0
- package/esm2022/lib/components/layout-builder/layout-builder.types.mjs +9 -0
- package/esm2022/lib/components/layout-builder/layout.service.mjs +239 -0
- package/esm2022/lib/components/modal/confirm-dialog.component.mjs +151 -0
- package/esm2022/lib/components/modal/index.mjs +4 -0
- package/esm2022/lib/components/modal/modal.component.mjs +139 -0
- package/esm2022/lib/components/modal/modal.service.mjs +194 -0
- package/esm2022/lib/components/modal/modal.types.mjs +6 -0
- package/esm2022/lib/components/page-header/breadcrumb.service.mjs +242 -0
- package/esm2022/lib/components/page-header/index.mjs +20 -0
- package/esm2022/lib/components/page-header/page-header.component.mjs +243 -0
- package/esm2022/lib/components/page-header/page-header.types.mjs +21 -0
- package/esm2022/lib/components/table/index.mjs +2 -0
- package/esm2022/lib/components/table/paginated-table.component.mjs +407 -0
- package/esm2022/lib/components/table/table.types.mjs +6 -0
- package/esm2022/lib/core/types/index.mjs +6 -0
- package/esm2022/lib/core/utils/index.mjs +53 -0
- package/esm2022/lib/sources/location-data.opt.json +8942 -0
- package/esm2022/lib/sources/nazioni.opt.json +215 -0
- package/esm2022/public-api.mjs +34 -0
- package/fesm2022/gnggln-ng-ui-system.mjs +55752 -0
- package/fesm2022/gnggln-ng-ui-system.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/accordion/accordion.component.d.ts +118 -0
- package/lib/components/accordion/accordion.types.d.ts +62 -0
- package/lib/components/accordion/index.d.ts +2 -0
- package/lib/components/base-layout/base-layout.component.d.ts +83 -0
- package/lib/components/base-layout/base-layout.types.d.ts +26 -0
- package/lib/components/base-layout/index.d.ts +13 -0
- package/lib/components/button/button-area.component.d.ts +88 -0
- package/lib/components/button/button.component.d.ts +55 -0
- package/lib/components/button/button.types.d.ts +70 -0
- package/lib/components/button/index.d.ts +15 -0
- package/lib/components/crud-table/crud-table.component.d.ts +143 -0
- package/lib/components/crud-table/crud-table.types.d.ts +207 -0
- package/lib/components/crud-table/index.d.ts +15 -0
- package/lib/components/form-builder/adapters/it-date-adapter.d.ts +32 -0
- package/lib/components/form-builder/directives/currency-input.directive.d.ts +48 -0
- package/lib/components/form-builder/form-builder.component.d.ts +183 -0
- package/lib/components/form-builder/form-wizard.component.d.ts +87 -0
- package/lib/components/form-builder/index.d.ts +13 -0
- package/lib/components/form-builder/services/form-condition.service.d.ts +46 -0
- package/lib/components/form-builder/services/form-validation.service.d.ts +63 -0
- package/lib/components/form-builder/services/location.service.d.ts +83 -0
- package/lib/components/form-builder/services/wizard-sync.service.d.ts +63 -0
- package/lib/components/form-builder/sub-components/error-summary/form-error-summary.component.d.ts +28 -0
- package/lib/components/form-builder/sub-components/file-input/file-input.component.d.ts +41 -0
- package/lib/components/form-builder/sub-components/specifica-territoriale/specifica-territoriale.component.d.ts +145 -0
- package/lib/components/form-builder/sub-components/table-territoriale/table-territoriale.component.d.ts +108 -0
- package/lib/components/form-builder/types/condition.types.d.ts +51 -0
- package/lib/components/form-builder/types/field.types.d.ts +288 -0
- package/lib/components/form-builder/types/index.d.ts +5 -0
- package/lib/components/form-builder/types/schema.types.d.ts +227 -0
- package/lib/components/form-builder/types/territoriale.types.d.ts +170 -0
- package/lib/components/form-builder/types/validation.types.d.ts +174 -0
- package/lib/components/form-builder-editor/form-builder-editor.component.d.ts +117 -0
- package/lib/components/form-builder-editor/form-builder-editor.service.d.ts +38 -0
- package/lib/components/form-builder-editor/index.d.ts +15 -0
- package/lib/components/form-builder-editor/services/editor-persistence.service.d.ts +42 -0
- package/lib/components/form-builder-editor/services/editor-state.service.d.ts +66 -0
- package/lib/components/form-builder-editor/services/field-factory.service.d.ts +28 -0
- package/lib/components/form-builder-editor/sub-components/condition-editor/condition-editor.component.d.ts +139 -0
- package/lib/components/form-builder-editor/sub-components/editor-toolbar/editor-toolbar.component.d.ts +43 -0
- package/lib/components/form-builder-editor/sub-components/field-config-panel/field-config-panel.component.d.ts +83 -0
- package/lib/components/form-builder-editor/sub-components/field-palette/field-palette.component.d.ts +40 -0
- package/lib/components/form-builder-editor/sub-components/form-values-panel/form-values-panel.component.d.ts +51 -0
- package/lib/components/form-builder-editor/sub-components/options-editor/options-editor.component.d.ts +63 -0
- package/lib/components/form-builder-editor/sub-components/preview-container/preview-container.component.d.ts +68 -0
- package/lib/components/form-builder-editor/sub-components/section-editor/section-editor.component.d.ts +82 -0
- package/lib/components/form-builder-editor/sub-components/validation-editor/validation-editor.component.d.ts +112 -0
- package/lib/components/form-builder-editor/types/editor.types.d.ts +124 -0
- package/lib/components/layout-builder/index.d.ts +16 -0
- package/lib/components/layout-builder/layout-builder.component.d.ts +85 -0
- package/lib/components/layout-builder/layout-builder.types.d.ts +436 -0
- package/lib/components/layout-builder/layout.service.d.ts +100 -0
- package/lib/components/modal/confirm-dialog.component.d.ts +46 -0
- package/lib/components/modal/index.d.ts +4 -0
- package/lib/components/modal/modal.component.d.ts +44 -0
- package/lib/components/modal/modal.service.d.ts +93 -0
- package/lib/components/modal/modal.types.d.ts +110 -0
- package/lib/components/page-header/breadcrumb.service.d.ts +96 -0
- package/lib/components/page-header/index.d.ts +16 -0
- package/lib/components/page-header/page-header.component.d.ts +59 -0
- package/lib/components/page-header/page-header.types.d.ts +96 -0
- package/lib/components/table/index.d.ts +2 -0
- package/lib/components/table/paginated-table.component.d.ts +85 -0
- package/lib/components/table/table.types.d.ts +81 -0
- package/lib/core/types/index.d.ts +57 -0
- package/lib/core/utils/index.d.ts +29 -0
- package/package.json +44 -0
- package/public-api.d.ts +22 -0
package/esm2022/lib/components/form-builder/sub-components/file-input/file-input.component.mjs
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, forwardRef, ChangeDetectionStrategy, ViewEncapsulation, signal, } from '@angular/core';
|
|
2
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
3
|
+
import { LucideAngularModule } from 'lucide-angular';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "lucide-angular";
|
|
6
|
+
/**
|
|
7
|
+
* Componente file input standalone con drag & drop,
|
|
8
|
+
* anteprima, validazione e supporto multiplo.
|
|
9
|
+
*
|
|
10
|
+
* Implementa `ControlValueAccessor` per integrazione
|
|
11
|
+
* diretta con Angular Reactive Forms.
|
|
12
|
+
*
|
|
13
|
+
* @selector ui-file-input
|
|
14
|
+
*/
|
|
15
|
+
export class UiFileInputComponent {
|
|
16
|
+
constructor() {
|
|
17
|
+
/** File rimosso dalla lista. */
|
|
18
|
+
this.fileRemoved = new EventEmitter();
|
|
19
|
+
/** Errore di validazione file. */
|
|
20
|
+
this.validationError = new EventEmitter();
|
|
21
|
+
// ── Stato interno (signals) ──
|
|
22
|
+
this.files = signal([]);
|
|
23
|
+
this.disabled = signal(false);
|
|
24
|
+
this.isDragOver = signal(false);
|
|
25
|
+
this.onChange = () => { };
|
|
26
|
+
this.onTouched = () => { };
|
|
27
|
+
}
|
|
28
|
+
/** Stringa accept per l'input nativo. */
|
|
29
|
+
get acceptString() {
|
|
30
|
+
return this.config?.acceptedTypes?.join(',') || '';
|
|
31
|
+
}
|
|
32
|
+
// ── ControlValueAccessor ──
|
|
33
|
+
writeValue(value) {
|
|
34
|
+
this.files.set(Array.isArray(value) ? value : []);
|
|
35
|
+
}
|
|
36
|
+
registerOnChange(fn) {
|
|
37
|
+
this.onChange = fn;
|
|
38
|
+
}
|
|
39
|
+
registerOnTouched(fn) {
|
|
40
|
+
this.onTouched = fn;
|
|
41
|
+
}
|
|
42
|
+
setDisabledState(isDisabled) {
|
|
43
|
+
this.disabled.set(isDisabled);
|
|
44
|
+
}
|
|
45
|
+
// ── Drag & drop ──
|
|
46
|
+
onDragOver(event) {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
event.stopPropagation();
|
|
49
|
+
this.isDragOver.set(true);
|
|
50
|
+
}
|
|
51
|
+
onDragLeave() {
|
|
52
|
+
this.isDragOver.set(false);
|
|
53
|
+
}
|
|
54
|
+
onDrop(event) {
|
|
55
|
+
event.preventDefault();
|
|
56
|
+
event.stopPropagation();
|
|
57
|
+
this.isDragOver.set(false);
|
|
58
|
+
if (this.disabled())
|
|
59
|
+
return;
|
|
60
|
+
const droppedFiles = event.dataTransfer?.files;
|
|
61
|
+
if (droppedFiles?.length) {
|
|
62
|
+
this.processFiles(droppedFiles);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
onFileSelected(event) {
|
|
66
|
+
const input = event.target;
|
|
67
|
+
if (input.files?.length) {
|
|
68
|
+
this.processFiles(input.files);
|
|
69
|
+
input.value = ''; // Reset per permettere la ri-selezione dello stesso file
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
removeFile(index) {
|
|
73
|
+
const current = [...this.files()];
|
|
74
|
+
const removed = current.splice(index, 1);
|
|
75
|
+
this.files.set(current);
|
|
76
|
+
this.onChange(current);
|
|
77
|
+
if (removed[0])
|
|
78
|
+
this.fileRemoved.emit(removed[0]);
|
|
79
|
+
}
|
|
80
|
+
formatSize(bytes) {
|
|
81
|
+
if (bytes === 0)
|
|
82
|
+
return '0 B';
|
|
83
|
+
const k = 1024;
|
|
84
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
85
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
86
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
87
|
+
}
|
|
88
|
+
// ── Processing ──
|
|
89
|
+
async processFiles(fileList) {
|
|
90
|
+
this.onTouched();
|
|
91
|
+
const maxFiles = this.config?.maxFiles || Infinity;
|
|
92
|
+
const current = this.config?.multiple ? [...this.files()] : [];
|
|
93
|
+
const remaining = maxFiles - current.length;
|
|
94
|
+
if (remaining <= 0) {
|
|
95
|
+
this.validationError.emit(`Numero massimo di file raggiunto (${maxFiles})`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const filesToProcess = Array.from(fileList).slice(0, remaining);
|
|
99
|
+
for (const file of filesToProcess) {
|
|
100
|
+
// Validazione dimensione
|
|
101
|
+
if (this.config?.maxFileSize && file.size > this.config.maxFileSize) {
|
|
102
|
+
this.validationError.emit(`Il file "${file.name}" supera la dimensione massima consentita`);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
// Validazione tipo
|
|
106
|
+
if (this.config?.acceptedTypes?.length) {
|
|
107
|
+
const isAccepted = this.config.acceptedTypes.some((type) => {
|
|
108
|
+
if (type.endsWith('/*')) {
|
|
109
|
+
return file.type.startsWith(type.split('/')[0] + '/');
|
|
110
|
+
}
|
|
111
|
+
return file.type === type;
|
|
112
|
+
});
|
|
113
|
+
if (!isAccepted) {
|
|
114
|
+
this.validationError.emit(`Il formato del file "${file.name}" non e accettato`);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const content = new Uint8Array(await file.arrayBuffer());
|
|
119
|
+
const ext = file.name.split('.').pop() || '';
|
|
120
|
+
const fileData = {
|
|
121
|
+
filename: file.name,
|
|
122
|
+
content,
|
|
123
|
+
mimeType: file.type,
|
|
124
|
+
extension: ext,
|
|
125
|
+
size: file.size,
|
|
126
|
+
needsUpload: true,
|
|
127
|
+
id: `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`, // NOSONAR - Used for non-cryptographic file ID generation in UI
|
|
128
|
+
timestamp: new Date(),
|
|
129
|
+
};
|
|
130
|
+
// Genera preview per immagini
|
|
131
|
+
if (this.config?.showPreview && file.type.startsWith('image/')) {
|
|
132
|
+
fileData.previewUrl = URL.createObjectURL(file);
|
|
133
|
+
}
|
|
134
|
+
current.push(fileData);
|
|
135
|
+
}
|
|
136
|
+
this.files.set(current);
|
|
137
|
+
this.onChange(current);
|
|
138
|
+
}
|
|
139
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFileInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
140
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: UiFileInputComponent, isStandalone: true, selector: "ui-file-input", inputs: { config: "config" }, outputs: { fileRemoved: "fileRemoved", validationError: "validationError" }, providers: [
|
|
141
|
+
{
|
|
142
|
+
provide: NG_VALUE_ACCESSOR,
|
|
143
|
+
useExisting: forwardRef(() => UiFileInputComponent),
|
|
144
|
+
multi: true,
|
|
145
|
+
},
|
|
146
|
+
], ngImport: i0, template: `
|
|
147
|
+
<div class="ui-file-input" [class.ui-file-input--disabled]="disabled()" [class.ui-file-input--drag-over]="isDragOver()">
|
|
148
|
+
<!-- Area drag & drop -->
|
|
149
|
+
@if (config?.enableDragDrop !== false) {
|
|
150
|
+
<div
|
|
151
|
+
class="ui-file-input__drop-zone"
|
|
152
|
+
(dragover)="onDragOver($event)"
|
|
153
|
+
(dragleave)="onDragLeave()"
|
|
154
|
+
(drop)="onDrop($event)"
|
|
155
|
+
(click)="fileInput.click()"
|
|
156
|
+
role="button"
|
|
157
|
+
tabindex="0"
|
|
158
|
+
[attr.aria-label]="config?.dragDropText || 'Trascina i file qui o clicca per selezionare'"
|
|
159
|
+
(keydown.enter)="fileInput.click()"
|
|
160
|
+
(keydown.space)="fileInput.click()"
|
|
161
|
+
>
|
|
162
|
+
<lucide-icon name="upload" [size]="24" aria-hidden="true" />
|
|
163
|
+
<span class="ui-file-input__drop-text">
|
|
164
|
+
{{ config?.dragDropText || 'Trascina i file qui o clicca per selezionare' }}
|
|
165
|
+
</span>
|
|
166
|
+
@if (config?.acceptedTypes?.length) {
|
|
167
|
+
<span class="ui-file-input__hint">
|
|
168
|
+
Formati: {{ config!.acceptedTypes!.join(', ') }}
|
|
169
|
+
</span>
|
|
170
|
+
}
|
|
171
|
+
</div>
|
|
172
|
+
} @else {
|
|
173
|
+
<button
|
|
174
|
+
class="ui-file-input__select-btn"
|
|
175
|
+
type="button"
|
|
176
|
+
[disabled]="disabled()"
|
|
177
|
+
(click)="fileInput.click()"
|
|
178
|
+
>
|
|
179
|
+
<lucide-icon name="paperclip" [size]="16" aria-hidden="true" />
|
|
180
|
+
{{ config?.placeholder || 'Seleziona file' }}
|
|
181
|
+
</button>
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
<input
|
|
185
|
+
#fileInput
|
|
186
|
+
type="file"
|
|
187
|
+
class="ui-file-input__native"
|
|
188
|
+
[accept]="acceptString"
|
|
189
|
+
[multiple]="config?.multiple ?? false"
|
|
190
|
+
[disabled]="disabled()"
|
|
191
|
+
(change)="onFileSelected($event)"
|
|
192
|
+
/>
|
|
193
|
+
|
|
194
|
+
<!-- Lista file selezionati -->
|
|
195
|
+
@if (files().length > 0) {
|
|
196
|
+
<div class="ui-file-input__file-list" role="list">
|
|
197
|
+
@for (file of files(); track file.id || $index) {
|
|
198
|
+
<div class="ui-file-input__file-item" role="listitem">
|
|
199
|
+
<div class="ui-file-input__file-info">
|
|
200
|
+
<lucide-icon name="file" [size]="16" aria-hidden="true" />
|
|
201
|
+
<span class="ui-file-input__file-name">{{ file.filename }}</span>
|
|
202
|
+
<span class="ui-file-input__file-size">{{ formatSize(file.size) }}</span>
|
|
203
|
+
</div>
|
|
204
|
+
@if (!disabled()) {
|
|
205
|
+
<button
|
|
206
|
+
class="ui-file-input__remove-btn"
|
|
207
|
+
type="button"
|
|
208
|
+
[attr.aria-label]="'Rimuovi ' + file.filename"
|
|
209
|
+
(click)="removeFile($index)"
|
|
210
|
+
>
|
|
211
|
+
<lucide-icon name="x" [size]="14" aria-hidden="true" />
|
|
212
|
+
</button>
|
|
213
|
+
}
|
|
214
|
+
</div>
|
|
215
|
+
}
|
|
216
|
+
</div>
|
|
217
|
+
}
|
|
218
|
+
</div>
|
|
219
|
+
`, isInline: true, styles: [".ui-file-input{display:flex;flex-direction:column;gap:var(--ui-spacing-2)}.ui-file-input--disabled{opacity:.55;pointer-events:none}.ui-file-input__native{display:none}.ui-file-input__drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--ui-spacing-2);padding:var(--ui-spacing-6) var(--ui-spacing-4);border:2px dashed var(--ui-color-border);border-radius:var(--ui-radius-lg);background:var(--ui-color-bg-subtle);cursor:pointer;transition:border-color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-file-input__drop-zone:focus{outline:none}.ui-file-input__drop-zone:focus-visible{outline:var(--ui-focus-ring-width) solid var(--ui-focus-ring-color);outline-offset:var(--ui-focus-ring-offset)}.ui-file-input__drop-zone:hover{border-color:var(--ui-color-primary);background:var(--ui-color-primary-subtle, rgba(37, 99, 235, .04))}.ui-file-input--drag-over .ui-file-input__drop-zone{border-color:var(--ui-color-primary);background:var(--ui-color-primary-subtle, rgba(37, 99, 235, .08))}.ui-file-input__drop-zone lucide-icon{color:var(--ui-color-text-muted)}.ui-file-input__drop-text{font-size:var(--ui-font-size-sm);color:var(--ui-color-text-secondary);text-align:center}.ui-file-input__hint{font-size:var(--ui-font-size-xs);color:var(--ui-color-text-muted)}.ui-file-input__select-btn{appearance:none;border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);background:var(--ui-color-surface);padding:var(--ui-spacing-2) var(--ui-spacing-3);display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;font-family:var(--ui-font-family);font-size:var(--ui-font-size-sm);color:var(--ui-color-text);transition:background-color var(--ui-transition-fast)}.ui-file-input__select-btn:focus{outline:none}.ui-file-input__select-btn:focus-visible{outline:var(--ui-focus-ring-width) solid var(--ui-focus-ring-color);outline-offset:var(--ui-focus-ring-offset)}.ui-file-input__select-btn:hover:not(:disabled){background:var(--ui-color-surface-hover)}.ui-file-input__file-list{display:flex;flex-direction:column;gap:var(--ui-spacing-1)}.ui-file-input__file-item{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-2) var(--ui-spacing-3);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);background:var(--ui-color-surface)}.ui-file-input__file-info{display:flex;align-items:center;gap:var(--ui-spacing-2);min-width:0}.ui-file-input__file-info lucide-icon{flex-shrink:0;color:var(--ui-color-text-muted)}.ui-file-input__file-name{font-size:var(--ui-font-size-sm);color:var(--ui-color-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-file-input__file-size{font-size:var(--ui-font-size-xs);color:var(--ui-color-text-muted);flex-shrink:0}.ui-file-input__remove-btn{appearance:none;border:none;background:transparent;cursor:pointer;padding:var(--ui-spacing-1);border-radius:var(--ui-radius-sm);color:var(--ui-color-text-muted);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-file-input__remove-btn:focus{outline:none}.ui-file-input__remove-btn:focus-visible{outline:var(--ui-focus-ring-width) solid var(--ui-focus-ring-color);outline-offset:var(--ui-focus-ring-offset)}.ui-file-input__remove-btn:hover{color:var(--ui-color-error, #dc2626);background:var(--ui-color-error-subtle, #fef2f2)}\n"], dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
220
|
+
}
|
|
221
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFileInputComponent, decorators: [{
|
|
222
|
+
type: Component,
|
|
223
|
+
args: [{ selector: 'ui-file-input', standalone: true, imports: [LucideAngularModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
|
|
224
|
+
{
|
|
225
|
+
provide: NG_VALUE_ACCESSOR,
|
|
226
|
+
useExisting: forwardRef(() => UiFileInputComponent),
|
|
227
|
+
multi: true,
|
|
228
|
+
},
|
|
229
|
+
], template: `
|
|
230
|
+
<div class="ui-file-input" [class.ui-file-input--disabled]="disabled()" [class.ui-file-input--drag-over]="isDragOver()">
|
|
231
|
+
<!-- Area drag & drop -->
|
|
232
|
+
@if (config?.enableDragDrop !== false) {
|
|
233
|
+
<div
|
|
234
|
+
class="ui-file-input__drop-zone"
|
|
235
|
+
(dragover)="onDragOver($event)"
|
|
236
|
+
(dragleave)="onDragLeave()"
|
|
237
|
+
(drop)="onDrop($event)"
|
|
238
|
+
(click)="fileInput.click()"
|
|
239
|
+
role="button"
|
|
240
|
+
tabindex="0"
|
|
241
|
+
[attr.aria-label]="config?.dragDropText || 'Trascina i file qui o clicca per selezionare'"
|
|
242
|
+
(keydown.enter)="fileInput.click()"
|
|
243
|
+
(keydown.space)="fileInput.click()"
|
|
244
|
+
>
|
|
245
|
+
<lucide-icon name="upload" [size]="24" aria-hidden="true" />
|
|
246
|
+
<span class="ui-file-input__drop-text">
|
|
247
|
+
{{ config?.dragDropText || 'Trascina i file qui o clicca per selezionare' }}
|
|
248
|
+
</span>
|
|
249
|
+
@if (config?.acceptedTypes?.length) {
|
|
250
|
+
<span class="ui-file-input__hint">
|
|
251
|
+
Formati: {{ config!.acceptedTypes!.join(', ') }}
|
|
252
|
+
</span>
|
|
253
|
+
}
|
|
254
|
+
</div>
|
|
255
|
+
} @else {
|
|
256
|
+
<button
|
|
257
|
+
class="ui-file-input__select-btn"
|
|
258
|
+
type="button"
|
|
259
|
+
[disabled]="disabled()"
|
|
260
|
+
(click)="fileInput.click()"
|
|
261
|
+
>
|
|
262
|
+
<lucide-icon name="paperclip" [size]="16" aria-hidden="true" />
|
|
263
|
+
{{ config?.placeholder || 'Seleziona file' }}
|
|
264
|
+
</button>
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
<input
|
|
268
|
+
#fileInput
|
|
269
|
+
type="file"
|
|
270
|
+
class="ui-file-input__native"
|
|
271
|
+
[accept]="acceptString"
|
|
272
|
+
[multiple]="config?.multiple ?? false"
|
|
273
|
+
[disabled]="disabled()"
|
|
274
|
+
(change)="onFileSelected($event)"
|
|
275
|
+
/>
|
|
276
|
+
|
|
277
|
+
<!-- Lista file selezionati -->
|
|
278
|
+
@if (files().length > 0) {
|
|
279
|
+
<div class="ui-file-input__file-list" role="list">
|
|
280
|
+
@for (file of files(); track file.id || $index) {
|
|
281
|
+
<div class="ui-file-input__file-item" role="listitem">
|
|
282
|
+
<div class="ui-file-input__file-info">
|
|
283
|
+
<lucide-icon name="file" [size]="16" aria-hidden="true" />
|
|
284
|
+
<span class="ui-file-input__file-name">{{ file.filename }}</span>
|
|
285
|
+
<span class="ui-file-input__file-size">{{ formatSize(file.size) }}</span>
|
|
286
|
+
</div>
|
|
287
|
+
@if (!disabled()) {
|
|
288
|
+
<button
|
|
289
|
+
class="ui-file-input__remove-btn"
|
|
290
|
+
type="button"
|
|
291
|
+
[attr.aria-label]="'Rimuovi ' + file.filename"
|
|
292
|
+
(click)="removeFile($index)"
|
|
293
|
+
>
|
|
294
|
+
<lucide-icon name="x" [size]="14" aria-hidden="true" />
|
|
295
|
+
</button>
|
|
296
|
+
}
|
|
297
|
+
</div>
|
|
298
|
+
}
|
|
299
|
+
</div>
|
|
300
|
+
}
|
|
301
|
+
</div>
|
|
302
|
+
`, styles: [".ui-file-input{display:flex;flex-direction:column;gap:var(--ui-spacing-2)}.ui-file-input--disabled{opacity:.55;pointer-events:none}.ui-file-input__native{display:none}.ui-file-input__drop-zone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--ui-spacing-2);padding:var(--ui-spacing-6) var(--ui-spacing-4);border:2px dashed var(--ui-color-border);border-radius:var(--ui-radius-lg);background:var(--ui-color-bg-subtle);cursor:pointer;transition:border-color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-file-input__drop-zone:focus{outline:none}.ui-file-input__drop-zone:focus-visible{outline:var(--ui-focus-ring-width) solid var(--ui-focus-ring-color);outline-offset:var(--ui-focus-ring-offset)}.ui-file-input__drop-zone:hover{border-color:var(--ui-color-primary);background:var(--ui-color-primary-subtle, rgba(37, 99, 235, .04))}.ui-file-input--drag-over .ui-file-input__drop-zone{border-color:var(--ui-color-primary);background:var(--ui-color-primary-subtle, rgba(37, 99, 235, .08))}.ui-file-input__drop-zone lucide-icon{color:var(--ui-color-text-muted)}.ui-file-input__drop-text{font-size:var(--ui-font-size-sm);color:var(--ui-color-text-secondary);text-align:center}.ui-file-input__hint{font-size:var(--ui-font-size-xs);color:var(--ui-color-text-muted)}.ui-file-input__select-btn{appearance:none;border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);background:var(--ui-color-surface);padding:var(--ui-spacing-2) var(--ui-spacing-3);display:inline-flex;align-items:center;gap:var(--ui-spacing-2);cursor:pointer;font-family:var(--ui-font-family);font-size:var(--ui-font-size-sm);color:var(--ui-color-text);transition:background-color var(--ui-transition-fast)}.ui-file-input__select-btn:focus{outline:none}.ui-file-input__select-btn:focus-visible{outline:var(--ui-focus-ring-width) solid var(--ui-focus-ring-color);outline-offset:var(--ui-focus-ring-offset)}.ui-file-input__select-btn:hover:not(:disabled){background:var(--ui-color-surface-hover)}.ui-file-input__file-list{display:flex;flex-direction:column;gap:var(--ui-spacing-1)}.ui-file-input__file-item{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-2) var(--ui-spacing-3);border:1px solid var(--ui-color-border);border-radius:var(--ui-radius-md);background:var(--ui-color-surface)}.ui-file-input__file-info{display:flex;align-items:center;gap:var(--ui-spacing-2);min-width:0}.ui-file-input__file-info lucide-icon{flex-shrink:0;color:var(--ui-color-text-muted)}.ui-file-input__file-name{font-size:var(--ui-font-size-sm);color:var(--ui-color-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-file-input__file-size{font-size:var(--ui-font-size-xs);color:var(--ui-color-text-muted);flex-shrink:0}.ui-file-input__remove-btn{appearance:none;border:none;background:transparent;cursor:pointer;padding:var(--ui-spacing-1);border-radius:var(--ui-radius-sm);color:var(--ui-color-text-muted);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-file-input__remove-btn:focus{outline:none}.ui-file-input__remove-btn:focus-visible{outline:var(--ui-focus-ring-width) solid var(--ui-focus-ring-color);outline-offset:var(--ui-focus-ring-offset)}.ui-file-input__remove-btn:hover{color:var(--ui-color-error, #dc2626);background:var(--ui-color-error-subtle, #fef2f2)}\n"] }]
|
|
303
|
+
}], propDecorators: { config: [{
|
|
304
|
+
type: Input
|
|
305
|
+
}], fileRemoved: [{
|
|
306
|
+
type: Output
|
|
307
|
+
}], validationError: [{
|
|
308
|
+
type: Output
|
|
309
|
+
}] } });
|
|
310
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9uZy11aS1zeXN0ZW0vc3JjL2xpYi9jb21wb25lbnRzL2Zvcm0tYnVpbGRlci9zdWItY29tcG9uZW50cy9maWxlLWlucHV0L2ZpbGUtaW5wdXQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBQ1osVUFBVSxFQUNWLHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBR3JEOzs7Ozs7OztHQVFHO0FBMEZILE1BQU0sT0FBTyxvQkFBb0I7SUF6RmpDO1FBNkZFLGdDQUFnQztRQUN0QixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFjLENBQUM7UUFFdkQsa0NBQWtDO1FBQ3hCLG9CQUFlLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUV2RCxnQ0FBZ0M7UUFDdkIsVUFBSyxHQUFHLE1BQU0sQ0FBZSxFQUFFLENBQUMsQ0FBQztRQUNqQyxhQUFRLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3pCLGVBQVUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFNUIsYUFBUSxHQUFrQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFDbkQsY0FBUyxHQUFlLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztLQWdJMUM7SUE5SEMseUNBQXlDO0lBQ3pDLElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJ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LE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHFCQUFxQixDQUFDOzRCQUNuRCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRixZQUNTOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeUVUOzhCQUtRLE1BQU07c0JBQWQsS0FBSztnQkFHSSxXQUFXO3NCQUFwQixNQUFNO2dCQUdHLGVBQWU7c0JBQXhCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBJbnB1dCxcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIGZvcndhcmRSZWYsXHJcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXHJcbiAgVmlld0VuY2Fwc3VsYXRpb24sXHJcbiAgc2lnbmFsLFxyXG4gIGNvbXB1dGVkLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IEx1Y2lkZUFuZ3VsYXJNb2R1bGUgfSBmcm9tICdsdWNpZGUtYW5ndWxhcic7XHJcbmltcG9ydCB7IFVpRmlsZURhdGEsIFVpRmlsZUlucHV0Q29uZmlnIH0gZnJvbSAnLi4vLi4vdHlwZXMvZmllbGQudHlwZXMnO1xyXG5cclxuLyoqXHJcbiAqIENvbXBvbmVudGUgZmlsZSBpbnB1dCBzdGFuZGFsb25lIGNvbiBkcmFnICYgZHJvcCxcclxuICogYW50ZXByaW1hLCB2YWxpZGF6aW9uZSBlIHN1cHBvcnRvIG11bHRpcGxvLlxyXG4gKlxyXG4gKiBJbXBsZW1lbnRhIGBDb250cm9sVmFsdWVBY2Nlc3NvcmAgcGVyIGludGVncmF6aW9uZVxyXG4gKiBkaXJldHRhIGNvbiBBbmd1bGFyIFJlYWN0aXZlIEZvcm1zLlxyXG4gKlxyXG4gKiBAc2VsZWN0b3IgdWktZmlsZS1pbnB1dFxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICd1aS1maWxlLWlucHV0JyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtMdWNpZGVBbmd1bGFyTW9kdWxlXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVWlGaWxlSW5wdXRDb21wb25lbnQpLFxyXG4gICAgICBtdWx0aTogdHJ1ZSxcclxuICAgIH0sXHJcbiAgXSxcclxuICB0ZW1wbGF0ZTogYFxyXG4gICAgPGRpdiBjbGFzcz1cInVpLWZpbGUtaW5wdXRcIiBbY2xhc3MudWktZmlsZS1pbnB1dC0tZGlzYWJsZWRdPVwiZGlzYWJsZWQoKVwiIFtjbGFzcy51aS1maWxlLWlucHV0LS1kcmFnLW92ZXJdPVwiaXNEcmFnT3ZlcigpXCI+XHJcbiAgICAgIDwhLS0gQXJlYSBkcmFnICYgZHJvcCAtLT5cclxuICAgICAgQGlmIChjb25maWc/LmVuYWJsZURyYWdEcm9wICE9PSBmYWxzZSkge1xyXG4gICAgICAgIDxkaXZcclxuICAgICAgICAgIGNsYXNzPVwidWktZmlsZS1pbnB1dF9fZHJvcC16b25lXCJcclxuICAgICAgICAgIChkcmFnb3Zlcik9XCJvbkRyYWdPdmVyKCRldmVudClcIlxyXG4gICAgICAgICAgKGRyYWdsZWF2ZSk9XCJvbkRyYWdMZWF2ZSgpXCJcclxuICAgICAgICAgIChkcm9wKT1cIm9uRHJvcCgkZXZlbnQpXCJcclxuICAgICAgICAgIChjbGljayk9XCJmaWxlSW5wdXQuY2xpY2soKVwiXHJcbiAgICAgICAgICByb2xlPVwiYnV0dG9uXCJcclxuICAgICAgICAgIHRhYmluZGV4PVwiMFwiXHJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImNvbmZpZz8uZHJhZ0Ryb3BUZXh0IHx8ICdUcmFzY2luYSBpIGZpbGUgcXVpIG8gY2xpY2NhIHBlciBzZWxlemlvbmFyZSdcIlxyXG4gICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiZmlsZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICAgICAgKGtleWRvd24uc3BhY2UpPVwiZmlsZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDxsdWNpZGUtaWNvbiBuYW1lPVwidXBsb2FkXCIgW3NpemVdPVwiMjRcIiBhcmlhLWhpZGRlbj1cInRydWVcIiAvPlxyXG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ1aS1maWxlLWlucHV0X19kcm9wLXRleHRcIj5cclxuICAgICAgICAgICAge3sgY29uZmlnPy5kcmFnRHJvcFRleHQgfHwgJ1RyYXNjaW5hIGkgZmlsZSBxdWkgbyBjbGljY2EgcGVyIHNlbGV6aW9uYXJlJyB9fVxyXG4gICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgQGlmIChjb25maWc/LmFjY2VwdGVkVHlwZXM/Lmxlbmd0aCkge1xyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInVpLWZpbGUtaW5wdXRfX2hpbnRcIj5cclxuICAgICAgICAgICAgICBGb3JtYXRpOiB7eyBjb25maWchLmFjY2VwdGVkVHlwZXMhLmpvaW4oJywgJykgfX1cclxuICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICB9IEBlbHNlIHtcclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICBjbGFzcz1cInVpLWZpbGUtaW5wdXRfX3NlbGVjdC1idG5cIlxyXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWQoKVwiXHJcbiAgICAgICAgICAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDxsdWNpZGUtaWNvbiBuYW1lPVwicGFwZXJjbGlwXCIgW3NpemVdPVwiMTZcIiBhcmlhLWhpZGRlbj1cInRydWVcIiAvPlxyXG4gICAgICAgICAge3sgY29uZmlnPy5wbGFjZWhvbGRlciB8fCAnU2VsZXppb25hIGZpbGUnIH19XHJcbiAgICAgICAgPC9idXR0b24+XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIDxpbnB1dFxyXG4gICAgICAgICNmaWxlSW5wdXRcclxuICAgICAgICB0eXBlPVwiZmlsZVwiXHJcbiAgICAgICAgY2xhc3M9XCJ1aS1maWxlLWlucHV0X19uYXRpdmVcIlxyXG4gICAgICAgIFthY2NlcHRdPVwiYWNjZXB0U3RyaW5nXCJcclxuICAgICAgICBbbXVsdGlwbGVdPVwiY29uZmlnPy5tdWx0aXBsZSA/PyBmYWxzZVwiXHJcbiAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkKClcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwib25GaWxlU2VsZWN0ZWQoJGV2ZW50KVwiXHJcbiAgICAgIC8+XHJcblxyXG4gICAgICA8IS0tIExpc3RhIGZpbGUgc2VsZXppb25hdGkgLS0+XHJcbiAgICAgIEBpZiAoZmlsZXMoKS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInVpLWZpbGUtaW5wdXRfX2ZpbGUtbGlzdFwiIHJvbGU9XCJsaXN0XCI+XHJcbiAgICAgICAgICBAZm9yIChmaWxlIG9mIGZpbGVzKCk7IHRyYWNrIGZpbGUuaWQgfHwgJGluZGV4KSB7XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ1aS1maWxlLWlucHV0X19maWxlLWl0ZW1cIiByb2xlPVwibGlzdGl0ZW1cIj5cclxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidWktZmlsZS1pbnB1dF9fZmlsZS1pbmZvXCI+XHJcbiAgICAgICAgICAgICAgICA8bHVjaWRlLWljb24gbmFtZT1cImZpbGVcIiBbc2l6ZV09XCIxNlwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIC8+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInVpLWZpbGUtaW5wdXRfX2ZpbGUtbmFtZVwiPnt7IGZpbGUuZmlsZW5hbWUgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInVpLWZpbGUtaW5wdXRfX2ZpbGUtc2l6ZVwiPnt7IGZvcm1hdFNpemUoZmlsZS5zaXplKSB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICBAaWYgKCFkaXNhYmxlZCgpKSB7XHJcbiAgICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidWktZmlsZS1pbnB1dF9fcmVtb3ZlLWJ0blwiXHJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidSaW11b3ZpICcgKyBmaWxlLmZpbGVuYW1lXCJcclxuICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUZpbGUoJGluZGV4KVwiXHJcbiAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgIDxsdWNpZGUtaWNvbiBuYW1lPVwieFwiIFtzaXplXT1cIjE0XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCIgLz5cclxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIH1cclxuICAgIDwvZGl2PlxyXG4gIGAsXHJcbiAgc3R5bGVVcmw6ICcuL2ZpbGUtaW5wdXQuY29tcG9uZW50LnNjc3MnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgVWlGaWxlSW5wdXRDb21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciB7XHJcbiAgLyoqIENvbmZpZ3VyYXppb25lIGRlbCBmaWxlIGlucHV0LiAqL1xyXG4gIEBJbnB1dCgpIGNvbmZpZzogVWlGaWxlSW5wdXRDb25maWcgfCB1bmRlZmluZWQ7XHJcblxyXG4gIC8qKiBGaWxlIHJpbW9zc28gZGFsbGEgbGlzdGEuICovXHJcbiAgQE91dHB1dCgpIGZpbGVSZW1vdmVkID0gbmV3IEV2ZW50RW1pdHRlcjxVaUZpbGVEYXRhPigpO1xyXG5cclxuICAvKiogRXJyb3JlIGRpIHZhbGlkYXppb25lIGZpbGUuICovXHJcbiAgQE91dHB1dCgpIHZhbGlkYXRpb25FcnJvciA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG5cclxuICAvLyDilIDilIAgU3RhdG8gaW50ZXJubyAoc2lnbmFscykg4pSA4pSAXHJcbiAgcmVhZG9ubHkgZmlsZXMgPSBzaWduYWw8VWlGaWxlRGF0YVtdPihbXSk7XHJcbiAgcmVhZG9ubHkgZGlzYWJsZWQgPSBzaWduYWwoZmFsc2UpO1xyXG4gIHJlYWRvbmx5IGlzRHJhZ092ZXIgPSBzaWduYWwoZmFsc2UpO1xyXG5cclxuICBwcml2YXRlIG9uQ2hhbmdlOiAodmFsdWU6IFVpRmlsZURhdGFbXSkgPT4gdm9pZCA9ICgpID0+IHt9O1xyXG4gIHByaXZhdGUgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XHJcblxyXG4gIC8qKiBTdHJpbmdhIGFjY2VwdCBwZXIgbCdpbnB1dCBuYXRpdm8uICovXHJcbiAgZ2V0IGFjY2VwdFN0cmluZygpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnPy5hY2NlcHRlZFR5cGVzPy5qb2luKCcsJykgfHwgJyc7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIAgQ29udHJvbFZhbHVlQWNjZXNzb3Ig4pSA4pSAXHJcbiAgd3JpdGVWYWx1ZSh2YWx1ZTogVWlGaWxlRGF0YVtdKTogdm9pZCB7XHJcbiAgICB0aGlzLmZpbGVzLnNldChBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW10pO1xyXG4gIH1cclxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcclxuICB9XHJcbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmRpc2FibGVkLnNldChpc0Rpc2FibGVkKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgCBEcmFnICYgZHJvcCDilIDilIBcclxuICBvbkRyYWdPdmVyKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIHRoaXMuaXNEcmFnT3Zlci5zZXQodHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBvbkRyYWdMZWF2ZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuaXNEcmFnT3Zlci5zZXQoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgb25Ecm9wKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIHRoaXMuaXNEcmFnT3Zlci5zZXQoZmFsc2UpO1xyXG4gICAgaWYgKHRoaXMuZGlzYWJsZWQoKSkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGRyb3BwZWRGaWxlcyA9IGV2ZW50LmRhdGFUcmFuc2Zlcj8uZmlsZXM7XHJcbiAgICBpZiAoZHJvcHBlZEZpbGVzPy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5wcm9jZXNzRmlsZXMoZHJvcHBlZEZpbGVzKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uRmlsZVNlbGVjdGVkKGV2ZW50OiBFdmVudCk6IHZvaWQge1xyXG4gICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICAgIGlmIChpbnB1dC5maWxlcz8ubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMucHJvY2Vzc0ZpbGVzKGlucHV0LmZpbGVzKTtcclxuICAgICAgaW5wdXQudmFsdWUgPSAnJzsgLy8gUmVzZXQgcGVyIHBlcm1ldHRlcmUgbGEgcmktc2VsZXppb25lIGRlbGxvIHN0ZXNzbyBmaWxlXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZW1vdmVGaWxlKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnQgPSBbLi4udGhpcy5maWxlcygpXTtcclxuICAgIGNvbnN0IHJlbW92ZWQgPSBjdXJyZW50LnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB0aGlzLmZpbGVzLnNldChjdXJyZW50KTtcclxuICAgIHRoaXMub25DaGFuZ2UoY3VycmVudCk7XHJcbiAgICBpZiAocmVtb3ZlZFswXSkgdGhpcy5maWxlUmVtb3ZlZC5lbWl0KHJlbW92ZWRbMF0pO1xyXG4gIH1cclxuXHJcbiAgZm9ybWF0U2l6ZShieXRlczogbnVtYmVyKTogc3RyaW5nIHtcclxuICAgIGlmIChieXRlcyA9PT0gMCkgcmV0dXJuICcwIEInO1xyXG4gICAgY29uc3QgayA9IDEwMjQ7XHJcbiAgICBjb25zdCBzaXplcyA9IFsnQicsICdLQicsICdNQicsICdHQiddO1xyXG4gICAgY29uc3QgaSA9IE1hdGguZmxvb3IoTWF0aC5sb2coYnl0ZXMpIC8gTWF0aC5sb2coaykpO1xyXG4gICAgcmV0dXJuIHBhcnNlRmxvYXQoKGJ5dGVzIC8gTWF0aC5wb3coaywgaSkpLnRvRml4ZWQoMSkpICsgJyAnICsgc2l6ZXNbaV07XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIAgUHJvY2Vzc2luZyDilIDilIBcclxuICBwcml2YXRlIGFzeW5jIHByb2Nlc3NGaWxlcyhmaWxlTGlzdDogRmlsZUxpc3QpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIHRoaXMub25Ub3VjaGVkKCk7XHJcbiAgICBjb25zdCBtYXhGaWxlcyA9IHRoaXMuY29uZmlnPy5tYXhGaWxlcyB8fCBJbmZpbml0eTtcclxuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmNvbmZpZz8ubXVsdGlwbGUgPyBbLi4udGhpcy5maWxlcygpXSA6IFtdO1xyXG4gICAgY29uc3QgcmVtYWluaW5nID0gbWF4RmlsZXMgLSBjdXJyZW50Lmxlbmd0aDtcclxuXHJcbiAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcclxuICAgICAgdGhpcy52YWxpZGF0aW9uRXJyb3IuZW1pdChgTnVtZXJvIG1hc3NpbW8gZGkgZmlsZSByYWdnaXVudG8gKCR7bWF4RmlsZXN9KWApO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgZmlsZXNUb1Byb2Nlc3MgPSBBcnJheS5mcm9tKGZpbGVMaXN0KS5zbGljZSgwLCByZW1haW5pbmcpO1xyXG5cclxuICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlc1RvUHJvY2Vzcykge1xyXG4gICAgICAvLyBWYWxpZGF6aW9uZSBkaW1lbnNpb25lXHJcbiAgICAgIGlmICh0aGlzLmNvbmZpZz8ubWF4RmlsZVNpemUgJiYgZmlsZS5zaXplID4gdGhpcy5jb25maWcubWF4RmlsZVNpemUpIHtcclxuICAgICAgICB0aGlzLnZhbGlkYXRpb25FcnJvci5lbWl0KGBJbCBmaWxlIFwiJHtmaWxlLm5hbWV9XCIgc3VwZXJhIGxhIGRpbWVuc2lvbmUgbWFzc2ltYSBjb25zZW50aXRhYCk7XHJcbiAgICAgICAgY29udGludWU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFZhbGlkYXppb25lIHRpcG9cclxuICAgICAgaWYgKHRoaXMuY29uZmlnPy5hY2NlcHRlZFR5cGVzPy5sZW5ndGgpIHtcclxuICAgICAgICBjb25zdCBpc0FjY2VwdGVkID0gdGhpcy5jb25maWcuYWNjZXB0ZWRUeXBlcy5zb21lKCh0eXBlKSA9PiB7XHJcbiAgICAgICAgICBpZiAodHlwZS5lbmRzV2l0aCgnLyonKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmlsZS50eXBlLnN0YXJ0c1dpdGgodHlwZS5zcGxpdCgnLycpWzBdICsgJy8nKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiBmaWxlLnR5cGUgPT09IHR5cGU7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgaWYgKCFpc0FjY2VwdGVkKSB7XHJcbiAgICAgICAgICB0aGlzLnZhbGlkYXRpb25FcnJvci5lbWl0KGBJbCBmb3JtYXRvIGRlbCBmaWxlIFwiJHtmaWxlLm5hbWV9XCIgbm9uIGUgYWNjZXR0YXRvYCk7XHJcbiAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBuZXcgVWludDhBcnJheShhd2FpdCBmaWxlLmFycmF5QnVmZmVyKCkpO1xyXG4gICAgICBjb25zdCBleHQgPSBmaWxlLm5hbWUuc3BsaXQoJy4nKS5wb3AoKSB8fCAnJztcclxuXHJcbiAgICAgIGNvbnN0IGZpbGVEYXRhOiBVaUZpbGVEYXRhID0ge1xyXG4gICAgICAgIGZpbGVuYW1lOiBmaWxlLm5hbWUsXHJcbiAgICAgICAgY29udGVudCxcclxuICAgICAgICBtaW1lVHlwZTogZmlsZS50eXBlLFxyXG4gICAgICAgIGV4dGVuc2lvbjogZXh0LFxyXG4gICAgICAgIHNpemU6IGZpbGUuc2l6ZSxcclxuICAgICAgICBuZWVkc1VwbG9hZDogdHJ1ZSxcclxuICAgICAgICBpZDogYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHJpbmcoMiwgOSl9YCwgLy8gTk9TT05BUiAtIFVzZWQgZm9yIG5vbi1jcnlwdG9ncmFwaGljIGZpbGUgSUQgZ2VuZXJhdGlvbiBpbiBVSVxyXG4gICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKSxcclxuICAgICAgfTtcclxuXHJcbiAgICAgIC8vIEdlbmVyYSBwcmV2aWV3IHBlciBpbW1hZ2luaVxyXG4gICAgICBpZiAodGhpcy5jb25maWc/LnNob3dQcmV2aWV3ICYmIGZpbGUudHlwZS5zdGFydHNXaXRoKCdpbWFnZS8nKSkge1xyXG4gICAgICAgIGZpbGVEYXRhLnByZXZpZXdVcmwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGZpbGUpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjdXJyZW50LnB1c2goZmlsZURhdGEpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZmlsZXMuc2V0KGN1cnJlbnQpO1xyXG4gICAgdGhpcy5vbkNoYW5nZShjdXJyZW50KTtcclxuICB9XHJcbn1cclxuIl19
|