@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.
Files changed (141) hide show
  1. package/esm2022/gnggln-ng-ui-system.mjs +5 -0
  2. package/esm2022/lib/components/accordion/accordion.component.mjs +353 -0
  3. package/esm2022/lib/components/accordion/accordion.types.mjs +6 -0
  4. package/esm2022/lib/components/accordion/index.mjs +2 -0
  5. package/esm2022/lib/components/base-layout/base-layout.component.mjs +218 -0
  6. package/esm2022/lib/components/base-layout/base-layout.types.mjs +6 -0
  7. package/esm2022/lib/components/base-layout/index.mjs +14 -0
  8. package/esm2022/lib/components/button/button-area.component.mjs +196 -0
  9. package/esm2022/lib/components/button/button.component.mjs +164 -0
  10. package/esm2022/lib/components/button/button.types.mjs +6 -0
  11. package/esm2022/lib/components/button/index.mjs +16 -0
  12. package/esm2022/lib/components/crud-table/crud-table.component.mjs +789 -0
  13. package/esm2022/lib/components/crud-table/crud-table.types.mjs +6 -0
  14. package/esm2022/lib/components/crud-table/index.mjs +16 -0
  15. package/esm2022/lib/components/form-builder/adapters/it-date-adapter.mjs +82 -0
  16. package/esm2022/lib/components/form-builder/directives/currency-input.directive.mjs +184 -0
  17. package/esm2022/lib/components/form-builder/form-builder.component.mjs +824 -0
  18. package/esm2022/lib/components/form-builder/form-wizard.component.mjs +510 -0
  19. package/esm2022/lib/components/form-builder/index.mjs +19 -0
  20. package/esm2022/lib/components/form-builder/services/form-condition.service.mjs +132 -0
  21. package/esm2022/lib/components/form-builder/services/form-validation.service.mjs +381 -0
  22. package/esm2022/lib/components/form-builder/services/location.service.mjs +140 -0
  23. package/esm2022/lib/components/form-builder/services/wizard-sync.service.mjs +84 -0
  24. package/esm2022/lib/components/form-builder/sub-components/error-summary/form-error-summary.component.mjs +161 -0
  25. package/esm2022/lib/components/form-builder/sub-components/file-input/file-input.component.mjs +310 -0
  26. package/esm2022/lib/components/form-builder/sub-components/specifica-territoriale/specifica-territoriale.component.mjs +648 -0
  27. package/esm2022/lib/components/form-builder/sub-components/table-territoriale/table-territoriale.component.mjs +432 -0
  28. package/esm2022/lib/components/form-builder/types/condition.types.mjs +6 -0
  29. package/esm2022/lib/components/form-builder/types/field.types.mjs +6 -0
  30. package/esm2022/lib/components/form-builder/types/index.mjs +2 -0
  31. package/esm2022/lib/components/form-builder/types/schema.types.mjs +6 -0
  32. package/esm2022/lib/components/form-builder/types/territoriale.types.mjs +6 -0
  33. package/esm2022/lib/components/form-builder/types/validation.types.mjs +6 -0
  34. package/esm2022/lib/components/form-builder-editor/form-builder-editor.component.mjs +730 -0
  35. package/esm2022/lib/components/form-builder-editor/form-builder-editor.service.mjs +56 -0
  36. package/esm2022/lib/components/form-builder-editor/index.mjs +21 -0
  37. package/esm2022/lib/components/form-builder-editor/services/editor-persistence.service.mjs +190 -0
  38. package/esm2022/lib/components/form-builder-editor/services/editor-state.service.mjs +324 -0
  39. package/esm2022/lib/components/form-builder-editor/services/field-factory.service.mjs +188 -0
  40. package/esm2022/lib/components/form-builder-editor/sub-components/condition-editor/condition-editor.component.mjs +667 -0
  41. package/esm2022/lib/components/form-builder-editor/sub-components/editor-toolbar/editor-toolbar.component.mjs +317 -0
  42. package/esm2022/lib/components/form-builder-editor/sub-components/field-config-panel/field-config-panel.component.mjs +611 -0
  43. package/esm2022/lib/components/form-builder-editor/sub-components/field-palette/field-palette.component.mjs +267 -0
  44. package/esm2022/lib/components/form-builder-editor/sub-components/form-values-panel/form-values-panel.component.mjs +276 -0
  45. package/esm2022/lib/components/form-builder-editor/sub-components/options-editor/options-editor.component.mjs +323 -0
  46. package/esm2022/lib/components/form-builder-editor/sub-components/preview-container/preview-container.component.mjs +238 -0
  47. package/esm2022/lib/components/form-builder-editor/sub-components/section-editor/section-editor.component.mjs +472 -0
  48. package/esm2022/lib/components/form-builder-editor/sub-components/validation-editor/validation-editor.component.mjs +473 -0
  49. package/esm2022/lib/components/form-builder-editor/types/editor.types.mjs +6 -0
  50. package/esm2022/lib/components/layout-builder/index.mjs +18 -0
  51. package/esm2022/lib/components/layout-builder/layout-builder.component.mjs +1730 -0
  52. package/esm2022/lib/components/layout-builder/layout-builder.types.mjs +9 -0
  53. package/esm2022/lib/components/layout-builder/layout.service.mjs +239 -0
  54. package/esm2022/lib/components/modal/confirm-dialog.component.mjs +151 -0
  55. package/esm2022/lib/components/modal/index.mjs +4 -0
  56. package/esm2022/lib/components/modal/modal.component.mjs +139 -0
  57. package/esm2022/lib/components/modal/modal.service.mjs +194 -0
  58. package/esm2022/lib/components/modal/modal.types.mjs +6 -0
  59. package/esm2022/lib/components/page-header/breadcrumb.service.mjs +242 -0
  60. package/esm2022/lib/components/page-header/index.mjs +20 -0
  61. package/esm2022/lib/components/page-header/page-header.component.mjs +243 -0
  62. package/esm2022/lib/components/page-header/page-header.types.mjs +21 -0
  63. package/esm2022/lib/components/table/index.mjs +2 -0
  64. package/esm2022/lib/components/table/paginated-table.component.mjs +407 -0
  65. package/esm2022/lib/components/table/table.types.mjs +6 -0
  66. package/esm2022/lib/core/types/index.mjs +6 -0
  67. package/esm2022/lib/core/utils/index.mjs +53 -0
  68. package/esm2022/lib/sources/location-data.opt.json +8942 -0
  69. package/esm2022/lib/sources/nazioni.opt.json +215 -0
  70. package/esm2022/public-api.mjs +34 -0
  71. package/fesm2022/gnggln-ng-ui-system.mjs +55752 -0
  72. package/fesm2022/gnggln-ng-ui-system.mjs.map +1 -0
  73. package/index.d.ts +5 -0
  74. package/lib/components/accordion/accordion.component.d.ts +118 -0
  75. package/lib/components/accordion/accordion.types.d.ts +62 -0
  76. package/lib/components/accordion/index.d.ts +2 -0
  77. package/lib/components/base-layout/base-layout.component.d.ts +83 -0
  78. package/lib/components/base-layout/base-layout.types.d.ts +26 -0
  79. package/lib/components/base-layout/index.d.ts +13 -0
  80. package/lib/components/button/button-area.component.d.ts +88 -0
  81. package/lib/components/button/button.component.d.ts +55 -0
  82. package/lib/components/button/button.types.d.ts +70 -0
  83. package/lib/components/button/index.d.ts +15 -0
  84. package/lib/components/crud-table/crud-table.component.d.ts +143 -0
  85. package/lib/components/crud-table/crud-table.types.d.ts +207 -0
  86. package/lib/components/crud-table/index.d.ts +15 -0
  87. package/lib/components/form-builder/adapters/it-date-adapter.d.ts +32 -0
  88. package/lib/components/form-builder/directives/currency-input.directive.d.ts +48 -0
  89. package/lib/components/form-builder/form-builder.component.d.ts +183 -0
  90. package/lib/components/form-builder/form-wizard.component.d.ts +87 -0
  91. package/lib/components/form-builder/index.d.ts +13 -0
  92. package/lib/components/form-builder/services/form-condition.service.d.ts +46 -0
  93. package/lib/components/form-builder/services/form-validation.service.d.ts +63 -0
  94. package/lib/components/form-builder/services/location.service.d.ts +83 -0
  95. package/lib/components/form-builder/services/wizard-sync.service.d.ts +63 -0
  96. package/lib/components/form-builder/sub-components/error-summary/form-error-summary.component.d.ts +28 -0
  97. package/lib/components/form-builder/sub-components/file-input/file-input.component.d.ts +41 -0
  98. package/lib/components/form-builder/sub-components/specifica-territoriale/specifica-territoriale.component.d.ts +145 -0
  99. package/lib/components/form-builder/sub-components/table-territoriale/table-territoriale.component.d.ts +108 -0
  100. package/lib/components/form-builder/types/condition.types.d.ts +51 -0
  101. package/lib/components/form-builder/types/field.types.d.ts +288 -0
  102. package/lib/components/form-builder/types/index.d.ts +5 -0
  103. package/lib/components/form-builder/types/schema.types.d.ts +227 -0
  104. package/lib/components/form-builder/types/territoriale.types.d.ts +170 -0
  105. package/lib/components/form-builder/types/validation.types.d.ts +174 -0
  106. package/lib/components/form-builder-editor/form-builder-editor.component.d.ts +117 -0
  107. package/lib/components/form-builder-editor/form-builder-editor.service.d.ts +38 -0
  108. package/lib/components/form-builder-editor/index.d.ts +15 -0
  109. package/lib/components/form-builder-editor/services/editor-persistence.service.d.ts +42 -0
  110. package/lib/components/form-builder-editor/services/editor-state.service.d.ts +66 -0
  111. package/lib/components/form-builder-editor/services/field-factory.service.d.ts +28 -0
  112. package/lib/components/form-builder-editor/sub-components/condition-editor/condition-editor.component.d.ts +139 -0
  113. package/lib/components/form-builder-editor/sub-components/editor-toolbar/editor-toolbar.component.d.ts +43 -0
  114. package/lib/components/form-builder-editor/sub-components/field-config-panel/field-config-panel.component.d.ts +83 -0
  115. package/lib/components/form-builder-editor/sub-components/field-palette/field-palette.component.d.ts +40 -0
  116. package/lib/components/form-builder-editor/sub-components/form-values-panel/form-values-panel.component.d.ts +51 -0
  117. package/lib/components/form-builder-editor/sub-components/options-editor/options-editor.component.d.ts +63 -0
  118. package/lib/components/form-builder-editor/sub-components/preview-container/preview-container.component.d.ts +68 -0
  119. package/lib/components/form-builder-editor/sub-components/section-editor/section-editor.component.d.ts +82 -0
  120. package/lib/components/form-builder-editor/sub-components/validation-editor/validation-editor.component.d.ts +112 -0
  121. package/lib/components/form-builder-editor/types/editor.types.d.ts +124 -0
  122. package/lib/components/layout-builder/index.d.ts +16 -0
  123. package/lib/components/layout-builder/layout-builder.component.d.ts +85 -0
  124. package/lib/components/layout-builder/layout-builder.types.d.ts +436 -0
  125. package/lib/components/layout-builder/layout.service.d.ts +100 -0
  126. package/lib/components/modal/confirm-dialog.component.d.ts +46 -0
  127. package/lib/components/modal/index.d.ts +4 -0
  128. package/lib/components/modal/modal.component.d.ts +44 -0
  129. package/lib/components/modal/modal.service.d.ts +93 -0
  130. package/lib/components/modal/modal.types.d.ts +110 -0
  131. package/lib/components/page-header/breadcrumb.service.d.ts +96 -0
  132. package/lib/components/page-header/index.d.ts +16 -0
  133. package/lib/components/page-header/page-header.component.d.ts +59 -0
  134. package/lib/components/page-header/page-header.types.d.ts +96 -0
  135. package/lib/components/table/index.d.ts +2 -0
  136. package/lib/components/table/paginated-table.component.d.ts +85 -0
  137. package/lib/components/table/table.types.d.ts +81 -0
  138. package/lib/core/types/index.d.ts +57 -0
  139. package/lib/core/utils/index.d.ts +29 -0
  140. package/package.json +44 -0
  141. package/public-api.d.ts +22 -0
@@ -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