valtech-components 2.0.510 → 2.0.512
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/lib/components/molecules/refresher/refresher.component.mjs +254 -0
- package/esm2022/lib/components/molecules/refresher/types.mjs +15 -0
- package/esm2022/lib/components/organisms/infinite-list/infinite-list.component.mjs +618 -0
- package/esm2022/lib/components/organisms/infinite-list/types.mjs +15 -0
- package/esm2022/lib/components/templates/page-template/page-template.component.mjs +5 -5
- package/esm2022/lib/services/pagination/index.mjs +5 -0
- package/esm2022/lib/services/pagination/pagination.service.mjs +218 -0
- package/esm2022/lib/services/pagination/types.mjs +14 -0
- package/esm2022/lib/services/skeleton/config.mjs +79 -0
- package/esm2022/lib/services/skeleton/directives/loading.directive.mjs +215 -0
- package/esm2022/lib/services/skeleton/index.mjs +16 -0
- package/esm2022/lib/services/skeleton/skeleton.service.mjs +198 -0
- package/esm2022/lib/services/skeleton/templates/detail-skeleton.component.mjs +223 -0
- package/esm2022/lib/services/skeleton/templates/form-skeleton.component.mjs +127 -0
- package/esm2022/lib/services/skeleton/templates/grid-skeleton.component.mjs +154 -0
- package/esm2022/lib/services/skeleton/templates/list-skeleton.component.mjs +110 -0
- package/esm2022/lib/services/skeleton/templates/profile-skeleton.component.mjs +207 -0
- package/esm2022/lib/services/skeleton/templates/table-skeleton.component.mjs +116 -0
- package/esm2022/lib/services/skeleton/types.mjs +11 -0
- package/esm2022/public-api.mjs +12 -1
- package/fesm2022/valtech-components.mjs +3887 -1370
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/molecules/refresher/refresher.component.d.ts +79 -0
- package/lib/components/molecules/refresher/types.d.ts +86 -0
- package/lib/components/organisms/infinite-list/infinite-list.component.d.ts +111 -0
- package/lib/components/organisms/infinite-list/types.d.ts +197 -0
- package/lib/services/pagination/index.d.ts +2 -0
- package/lib/services/pagination/pagination.service.d.ts +43 -0
- package/lib/services/pagination/types.d.ts +113 -0
- package/lib/services/skeleton/config.d.ts +30 -0
- package/lib/services/skeleton/directives/loading.directive.d.ts +71 -0
- package/lib/services/skeleton/index.d.ts +10 -0
- package/lib/services/skeleton/skeleton.service.d.ts +127 -0
- package/lib/services/skeleton/templates/detail-skeleton.component.d.ts +18 -0
- package/lib/services/skeleton/templates/form-skeleton.component.d.ts +22 -0
- package/lib/services/skeleton/templates/grid-skeleton.component.d.ts +18 -0
- package/lib/services/skeleton/templates/list-skeleton.component.d.ts +17 -0
- package/lib/services/skeleton/templates/profile-skeleton.component.d.ts +20 -0
- package/lib/services/skeleton/templates/table-skeleton.component.d.ts +17 -0
- package/lib/services/skeleton/types.d.ts +111 -0
- package/package.json +1 -1
- package/public-api.d.ts +6 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { Directive, Input, TemplateRef, ViewContainerRef, inject, effect, signal, isSignal, DestroyRef, } from '@angular/core';
|
|
2
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
3
|
+
import { isObservable } from 'rxjs';
|
|
4
|
+
import { SkeletonService } from '../skeleton.service';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* Directiva estructural simplificada para estados de carga.
|
|
8
|
+
*
|
|
9
|
+
* Soporta multiples fuentes de estado de carga:
|
|
10
|
+
* - Angular Signal<boolean>
|
|
11
|
+
* - RxJS Observable<boolean>
|
|
12
|
+
* - Promise<any> (cargando hasta que se resuelve)
|
|
13
|
+
* - boolean literal
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <!-- Uso simple con signal -->
|
|
17
|
+
* <ng-container *valLoading="isLoading(); skeleton: 'list'">
|
|
18
|
+
* <app-list [items]="items()"></app-list>
|
|
19
|
+
* </ng-container>
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* <!-- Con configuracion -->
|
|
23
|
+
* <ng-container *valLoading="loading$; skeleton: 'grid-cards'; count: 8">
|
|
24
|
+
* <app-grid [data]="data"></app-grid>
|
|
25
|
+
* </ng-container>
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* <!-- Con template personalizado -->
|
|
29
|
+
* <ng-container *valLoading="isLoading(); skeletonTpl: customSkeleton">
|
|
30
|
+
* <app-content></app-content>
|
|
31
|
+
* </ng-container>
|
|
32
|
+
* <ng-template #customSkeleton>
|
|
33
|
+
* <val-skeleton [props]="{ type: 'card' }"></val-skeleton>
|
|
34
|
+
* </ng-template>
|
|
35
|
+
*/
|
|
36
|
+
export class LoadingDirective {
|
|
37
|
+
constructor() {
|
|
38
|
+
this.templateRef = inject((TemplateRef));
|
|
39
|
+
this.viewContainer = inject(ViewContainerRef);
|
|
40
|
+
this.skeletonService = inject(SkeletonService);
|
|
41
|
+
this.destroyRef = inject(DestroyRef);
|
|
42
|
+
this._loading = signal(false);
|
|
43
|
+
this.hasContentView = false;
|
|
44
|
+
this.skeletonComponentRef = null;
|
|
45
|
+
/** Template de skeleton a usar */
|
|
46
|
+
this.skeleton = 'list';
|
|
47
|
+
/** Template personalizado para skeleton */
|
|
48
|
+
this.skeletonTpl = null;
|
|
49
|
+
/** Cantidad de items skeleton */
|
|
50
|
+
this.count = 3;
|
|
51
|
+
/** Animacion habilitada */
|
|
52
|
+
this.animated = true;
|
|
53
|
+
/** Mostrar spinner en lugar de skeleton */
|
|
54
|
+
this.spinner = false;
|
|
55
|
+
effect(() => {
|
|
56
|
+
const isLoading = this._loading();
|
|
57
|
+
this.updateView(isLoading);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Input principal - puede ser boolean, Signal, Observable o Promise.
|
|
62
|
+
*/
|
|
63
|
+
set loading(source) {
|
|
64
|
+
this.resolveLoadingSource(source);
|
|
65
|
+
}
|
|
66
|
+
ngOnDestroy() {
|
|
67
|
+
this.viewContainer.clear();
|
|
68
|
+
this.skeletonComponentRef = null;
|
|
69
|
+
}
|
|
70
|
+
resolveLoadingSource(source) {
|
|
71
|
+
if (typeof source === 'boolean') {
|
|
72
|
+
this._loading.set(source);
|
|
73
|
+
}
|
|
74
|
+
else if (isSignal(source)) {
|
|
75
|
+
// Sincronizar signal con effect
|
|
76
|
+
effect(() => {
|
|
77
|
+
this._loading.set(source());
|
|
78
|
+
}, { injector: this.viewContainer.injector });
|
|
79
|
+
}
|
|
80
|
+
else if (isObservable(source)) {
|
|
81
|
+
// Convertir observable a signal
|
|
82
|
+
const signalValue = toSignal(source, {
|
|
83
|
+
initialValue: true,
|
|
84
|
+
injector: this.viewContainer.injector,
|
|
85
|
+
});
|
|
86
|
+
effect(() => {
|
|
87
|
+
this._loading.set(signalValue());
|
|
88
|
+
}, { injector: this.viewContainer.injector });
|
|
89
|
+
}
|
|
90
|
+
else if (source instanceof Promise) {
|
|
91
|
+
this._loading.set(true);
|
|
92
|
+
source.finally(() => this._loading.set(false));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
updateView(isLoading) {
|
|
96
|
+
if (isLoading) {
|
|
97
|
+
this.showSkeleton();
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
this.showContent();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
showSkeleton() {
|
|
104
|
+
// Limpiar contenido previo
|
|
105
|
+
this.viewContainer.clear();
|
|
106
|
+
this.hasContentView = false;
|
|
107
|
+
if (this.skeletonTpl) {
|
|
108
|
+
// Usar template personalizado
|
|
109
|
+
this.viewContainer.createEmbeddedView(this.skeletonTpl);
|
|
110
|
+
}
|
|
111
|
+
else if (this.spinner) {
|
|
112
|
+
// Mostrar spinner (usar val-content-loader si esta disponible)
|
|
113
|
+
this.showSpinner();
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Usar template de skeleton registrado
|
|
117
|
+
this.showSkeletonTemplate();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
showSkeletonTemplate() {
|
|
121
|
+
const template = this.skeletonService.getTemplate(this.skeleton);
|
|
122
|
+
if (template) {
|
|
123
|
+
this.skeletonComponentRef = this.viewContainer.createComponent(template.component);
|
|
124
|
+
// Combinar config por defecto con inputs
|
|
125
|
+
const config = {
|
|
126
|
+
...template.defaultConfig,
|
|
127
|
+
count: this.count,
|
|
128
|
+
animated: this.animated,
|
|
129
|
+
gap: this.gap,
|
|
130
|
+
variant: this.variant,
|
|
131
|
+
};
|
|
132
|
+
this.skeletonComponentRef.instance.config = config;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Fallback: mostrar texto de carga si no hay template
|
|
136
|
+
console.warn(`[valLoading] Template '${this.skeleton}' not found. Using fallback.`);
|
|
137
|
+
this.showFallback();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
showSpinner() {
|
|
141
|
+
// Crear un div con spinner simple
|
|
142
|
+
const element = document.createElement('div');
|
|
143
|
+
element.className = 'val-loading-spinner';
|
|
144
|
+
element.innerHTML = `
|
|
145
|
+
<ion-spinner name="crescent"></ion-spinner>
|
|
146
|
+
`;
|
|
147
|
+
element.style.cssText = 'display: flex; justify-content: center; padding: 20px;';
|
|
148
|
+
const hostElement = this.viewContainer.element.nativeElement;
|
|
149
|
+
hostElement.parentElement?.insertBefore(element, hostElement);
|
|
150
|
+
}
|
|
151
|
+
showFallback() {
|
|
152
|
+
// Fallback simple si no hay template registrado
|
|
153
|
+
const element = document.createElement('div');
|
|
154
|
+
element.className = 'val-loading-fallback';
|
|
155
|
+
element.style.cssText =
|
|
156
|
+
'display: flex; flex-direction: column; gap: 12px; padding: 16px;';
|
|
157
|
+
for (let i = 0; i < this.count; i++) {
|
|
158
|
+
const skeleton = document.createElement('div');
|
|
159
|
+
skeleton.style.cssText = `
|
|
160
|
+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
|
161
|
+
background-size: 200% 100%;
|
|
162
|
+
animation: skeleton-loading 1.5s infinite;
|
|
163
|
+
height: 56px;
|
|
164
|
+
border-radius: 8px;
|
|
165
|
+
`;
|
|
166
|
+
element.appendChild(skeleton);
|
|
167
|
+
}
|
|
168
|
+
const hostElement = this.viewContainer.element.nativeElement;
|
|
169
|
+
hostElement.parentElement?.insertBefore(element, hostElement);
|
|
170
|
+
}
|
|
171
|
+
showContent() {
|
|
172
|
+
// Limpiar skeleton
|
|
173
|
+
this.viewContainer.clear();
|
|
174
|
+
this.skeletonComponentRef = null;
|
|
175
|
+
// Mostrar contenido real
|
|
176
|
+
if (!this.hasContentView) {
|
|
177
|
+
this.viewContainer.createEmbeddedView(this.templateRef);
|
|
178
|
+
this.hasContentView = true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoadingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
182
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: LoadingDirective, isStandalone: true, selector: "[valLoading]", inputs: { skeleton: ["valLoadingSkeleton", "skeleton"], skeletonTpl: ["valLoadingSkeletonTpl", "skeletonTpl"], count: ["valLoadingCount", "count"], animated: ["valLoadingAnimated", "animated"], gap: ["valLoadingGap", "gap"], variant: ["valLoadingVariant", "variant"], spinner: ["valLoadingSpinner", "spinner"], loading: ["valLoading", "loading"] }, ngImport: i0 }); }
|
|
183
|
+
}
|
|
184
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LoadingDirective, decorators: [{
|
|
185
|
+
type: Directive,
|
|
186
|
+
args: [{
|
|
187
|
+
selector: '[valLoading]',
|
|
188
|
+
standalone: true,
|
|
189
|
+
}]
|
|
190
|
+
}], ctorParameters: () => [], propDecorators: { skeleton: [{
|
|
191
|
+
type: Input,
|
|
192
|
+
args: ['valLoadingSkeleton']
|
|
193
|
+
}], skeletonTpl: [{
|
|
194
|
+
type: Input,
|
|
195
|
+
args: ['valLoadingSkeletonTpl']
|
|
196
|
+
}], count: [{
|
|
197
|
+
type: Input,
|
|
198
|
+
args: ['valLoadingCount']
|
|
199
|
+
}], animated: [{
|
|
200
|
+
type: Input,
|
|
201
|
+
args: ['valLoadingAnimated']
|
|
202
|
+
}], gap: [{
|
|
203
|
+
type: Input,
|
|
204
|
+
args: ['valLoadingGap']
|
|
205
|
+
}], variant: [{
|
|
206
|
+
type: Input,
|
|
207
|
+
args: ['valLoadingVariant']
|
|
208
|
+
}], spinner: [{
|
|
209
|
+
type: Input,
|
|
210
|
+
args: ['valLoadingSpinner']
|
|
211
|
+
}], loading: [{
|
|
212
|
+
type: Input,
|
|
213
|
+
args: ['valLoading']
|
|
214
|
+
}] } });
|
|
215
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZGluZy5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3NrZWxldG9uL2RpcmVjdGl2ZXMvbG9hZGluZy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsV0FBVyxFQUNYLGdCQUFnQixFQUNoQixNQUFNLEVBQ04sTUFBTSxFQUNOLE1BQU0sRUFFTixRQUFRLEVBQ1IsVUFBVSxHQUVYLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7QUFHdEQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBS0gsTUFBTSxPQUFPLGdCQUFnQjtJQStCM0I7UUE5QmlCLGdCQUFXLEdBQUcsTUFBTSxDQUFDLENBQUEsV0FBb0IsQ0FBQSxDQUFDLENBQUM7UUFDM0Msa0JBQWEsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN6QyxvQkFBZSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUMxQyxlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRWhDLGFBQVEsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEMsbUJBQWMsR0FBRyxLQUFLLENBQUM7UUFDdkIseUJBQW9CLEdBQW1ELElBQUksQ0FBQztRQUVwRixrQ0FBa0M7UUFDTCxhQUFRLEdBQWtDLE1BQU0sQ0FBQztRQUU5RSwyQ0FBMkM7UUFDWCxnQkFBVyxHQUFnQyxJQUFJLENBQUM7UUFFaEYsaUNBQWlDO1FBQ1AsVUFBSyxHQUFHLENBQUMsQ0FBQztRQUVwQywyQkFB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Z0I7OzRGQUFoQixnQkFBZ0I7a0JBSjVCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGNBQWM7b0JBQ3hCLFVBQVUsRUFBRSxJQUFJO2lCQUNqQjt3REFZOEIsUUFBUTtzQkFBcEMsS0FBSzt1QkFBQyxvQkFBb0I7Z0JBR0ssV0FBVztzQkFBMUMsS0FBSzt1QkFBQyx1QkFBdUI7Z0JBR0osS0FBSztzQkFBOUIsS0FBSzt1QkFBQyxpQkFBaUI7Z0JBR0ssUUFBUTtzQkFBcEMsS0FBSzt1QkFBQyxvQkFBb0I7Z0JBR0gsR0FBRztzQkFBMUIsS0FBSzt1QkFBQyxlQUFlO2dCQUdNLE9BQU87c0JBQWxDLEtBQUs7dUJBQUMsbUJBQW1CO2dCQUdFLE9BQU87c0JBQWxDLEtBQUs7dUJBQUMsbUJBQW1CO2dCQWF0QixPQUFPO3NCQURWLEtBQUs7dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIERpcmVjdGl2ZSxcbiAgSW5wdXQsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBpbmplY3QsXG4gIGVmZmVjdCxcbiAgc2lnbmFsLFxuICBPbkRlc3Ryb3ksXG4gIGlzU2lnbmFsLFxuICBEZXN0cm95UmVmLFxuICBDb21wb25lbnRSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdG9TaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBpc09ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFNrZWxldG9uU2VydmljZSB9IGZyb20gJy4uL3NrZWxldG9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgTG9hZGluZ1NvdXJjZSwgU2tlbGV0b25UZW1wbGF0ZU5hbWUsIFNrZWxldG9uVGVtcGxhdGVDb21wb25lbnQgfSBmcm9tICcuLi90eXBlcyc7XG5cbi8qKlxuICogRGlyZWN0aXZhIGVzdHJ1Y3R1cmFsIHNpbXBsaWZpY2FkYSBwYXJhIGVzdGFkb3MgZGUgY2FyZ2EuXG4gKlxuICogU29wb3J0YSBtdWx0aXBsZXMgZnVlbnRlcyBkZSBlc3RhZG8gZGUgY2FyZ2E6XG4gKiAtIEFuZ3VsYXIgU2lnbmFsPGJvb2xlYW4+XG4gKiAtIFJ4SlMgT2JzZXJ2YWJsZTxib29sZWFuPlxuICogLSBQcm9taXNlPGFueT4gKGNhcmdhbmRvIGhhc3RhIHF1ZSBzZSByZXN1ZWx2ZSlcbiAqIC0gYm9vbGVhbiBsaXRlcmFsXG4gKlxuICogQGV4YW1wbGVcbiAqIDwhLS0gVXNvIHNpbXBsZSBjb24gc2lnbmFsIC0tPlxuICogPG5nLWNvbnRhaW5lciAqdmFsTG9hZGluZz1cImlzTG9hZGluZygpOyBza2VsZXRvbjogJ2xpc3QnXCI+XG4gKiAgIDxhcHAtbGlzdCBbaXRlbXNdPVwiaXRlbXMoKVwiPjwvYXBwLWxpc3Q+XG4gKiA8L25nLWNvbnRhaW5lcj5cbiAqXG4gKiBAZXhhbXBsZVxuICogPCEtLSBDb24gY29uZmlndXJhY2lvbiAtLT5cbiAqIDxuZy1jb250YWluZXIgKnZhbExvYWRpbmc9XCJsb2FkaW5nJDsgc2tlbGV0b246ICdncmlkLWNhcmRzJzsgY291bnQ6IDhcIj5cbiAqICAgPGFwcC1ncmlkIFtkYXRhXT1cImRhdGFcIj48L2FwcC1ncmlkPlxuICogPC9uZy1jb250YWluZXI+XG4gKlxuICogQGV4YW1wbGVcbiAqIDwhLS0gQ29uIHRlbXBsYXRlIHBlcnNvbmFsaXphZG8gLS0+XG4gKiA8bmctY29udGFpbmVyICp2YWxMb2FkaW5nPVwiaXNMb2FkaW5nKCk7IHNrZWxldG9uVHBsOiBjdXN0b21Ta2VsZXRvblwiPlxuICogICA8YXBwLWNvbnRlbnQ+PC9hcHAtY29udGVudD5cbiAqIDwvbmctY29udGFpbmVyPlxuICogPG5nLXRlbXBsYXRlICNjdXN0b21Ta2VsZXRvbj5cbiAqICAgPHZhbC1za2VsZXRvbiBbcHJvcHNdPVwieyB0eXBlOiAnY2FyZCcgfVwiPjwvdmFsLXNrZWxldG9uPlxuICogPC9uZy10ZW1wbGF0ZT5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW3ZhbExvYWRpbmddJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgTG9hZGluZ0RpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGVtcGxhdGVSZWYgPSBpbmplY3QoVGVtcGxhdGVSZWY8dW5rbm93bj4pO1xuICBwcml2YXRlIHJlYWRvbmx5IHZpZXdDb250YWluZXIgPSBpbmplY3QoVmlld0NvbnRhaW5lclJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2tlbGV0b25TZXJ2aWNlID0gaW5qZWN0KFNrZWxldG9uU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9sb2FkaW5nID0gc2lnbmFsKGZhbHNlKTtcbiAgcHJpdmF0ZSBoYXNDb250ZW50VmlldyA9IGZhbHNlO1xuICBwcml2YXRlIHNrZWxldG9uQ29tcG9uZW50UmVmOiBDb21wb25lbnRSZWY8U2tlbGV0b25UZW1wbGF0ZUNvbXBvbmVudD4gfCBudWxsID0gbnVsbDtcblxuICAvKiogVGVtcGxhdGUgZGUgc2tlbGV0b24gYSB1c2FyICovXG4gIEBJbnB1dCgndmFsTG9hZGluZ1NrZWxldG9uJykgc2tlbGV0b246IFNrZWxldG9uVGVtcGxhdGVOYW1lIHwgc3RyaW5nID0gJ2xpc3QnO1xuXG4gIC8qKiBUZW1wbGF0ZSBwZXJzb25hbGl6YWRvIHBhcmEgc2tlbGV0b24gKi9cbiAgQElucHV0KCd2YWxMb2FkaW5nU2tlbGV0b25UcGwnKSBza2VsZXRvblRwbDogVGVtcGxhdGVSZWY8dW5rbm93bj4gfCBudWxsID0gbnVsbDtcblxuICAvKiogQ2FudGlkYWQgZGUgaXRlbXMgc2tlbGV0b24gKi9cbiAgQElucHV0KCd2YWxMb2FkaW5nQ291bnQnKSBjb3VudCA9IDM7XG5cbiAgLyoqIEFuaW1hY2lvbiBoYWJpbGl0YWRhICovXG4gIEBJbnB1dCgndmFsTG9hZGluZ0FuaW1hdGVkJykgYW5pbWF0ZWQgPSB0cnVlO1xuXG4gIC8qKiBHYXAgZW50cmUgaXRlbXMgKi9cbiAgQElucHV0KCd2YWxMb2FkaW5nR2FwJykgZ2FwOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqIFZhcmlhbnRlIGRlbCB0ZW1wbGF0ZSAqL1xuICBASW5wdXQoJ3ZhbExvYWRpbmdWYXJpYW50JykgdmFyaWFudDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBNb3N0cmFyIHNwaW5uZXIgZW4gbHVnYXIgZGUgc2tlbGV0b24gKi9cbiAgQElucHV0KCd2YWxMb2FkaW5nU3Bpbm5lcicpIHNwaW5uZXIgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgY29uc3QgaXNMb2FkaW5nID0gdGhpcy5fbG9hZGluZygpO1xuICAgICAgdGhpcy51cGRhdGVWaWV3KGlzTG9hZGluZyk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW5wdXQgcHJpbmNpcGFsIC0gcHVlZGUgc2VyIGJvb2xlYW4sIFNpZ25hbCwgT2JzZXJ2YWJsZSBvIFByb21pc2UuXG4gICAqL1xuICBASW5wdXQoJ3ZhbExvYWRpbmcnKVxuICBzZXQgbG9hZGluZyhzb3VyY2U6IExvYWRpbmdTb3VyY2UpIHtcbiAgICB0aGlzLnJlc29sdmVMb2FkaW5nU291cmNlKHNvdXJjZSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdDb250YWluZXIuY2xlYXIoKTtcbiAgICB0aGlzLnNrZWxldG9uQ29tcG9uZW50UmVmID0gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZUxvYWRpbmdTb3VyY2Uoc291cmNlOiBMb2FkaW5nU291cmNlKTogdm9pZCB7XG4gICAgaWYgKHR5cGVvZiBzb3VyY2UgPT09ICdib29sZWFuJykge1xuICAgICAgdGhpcy5fbG9hZGluZy5zZXQoc291cmNlKTtcbiAgICB9IGVsc2UgaWYgKGlzU2lnbmFsKHNvdXJjZSkpIHtcbiAgICAgIC8vIFNpbmNyb25pemFyIHNpZ25hbCBjb24gZWZmZWN0XG4gICAgICBlZmZlY3QoXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICB0aGlzLl9sb2FkaW5nLnNldCgoc291cmNlIGFzICgpID0+IGJvb2xlYW4pKCkpO1xuICAgICAgICB9LFxuICAgICAgICB7IGluamVjdG9yOiB0aGlzLnZpZXdDb250YWluZXIuaW5qZWN0b3IgfVxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKGlzT2JzZXJ2YWJsZShzb3VyY2UpKSB7XG4gICAgICAvLyBDb252ZXJ0aXIgb2JzZXJ2YWJsZSBhIHNpZ25hbFxuICAgICAgY29uc3Qgc2lnbmFsVmFsdWUgPSB0b1NpZ25hbChzb3VyY2UsIHtcbiAgICAgICAgaW5pdGlhbFZhbHVlOiB0cnVlLFxuICAgICAgICBpbmplY3RvcjogdGhpcy52aWV3Q29udGFpbmVyLmluamVjdG9yLFxuICAgICAgfSk7XG4gICAgICBlZmZlY3QoXG4gICAgICAgICgpID0+IHtcbiAgICAgICAgICB0aGlzLl9sb2FkaW5nLnNldChzaWduYWxWYWx1ZSgpKTtcbiAgICAgICAgfSxcbiAgICAgICAgeyBpbmplY3RvcjogdGhpcy52aWV3Q29udGFpbmVyLmluamVjdG9yIH1cbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChzb3VyY2UgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICB0aGlzLl9sb2FkaW5nLnNldCh0cnVlKTtcbiAgICAgIHNvdXJjZS5maW5hbGx5KCgpID0+IHRoaXMuX2xvYWRpbmcuc2V0KGZhbHNlKSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVWaWV3KGlzTG9hZGluZzogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChpc0xvYWRpbmcpIHtcbiAgICAgIHRoaXMuc2hvd1NrZWxldG9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2hvd0NvbnRlbnQoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNob3dTa2VsZXRvbigpOiB2b2lkIHtcbiAgICAvLyBMaW1waWFyIGNvbnRlbmlkbyBwcmV2aW9cbiAgICB0aGlzLnZpZXdDb250YWluZXIuY2xlYXIoKTtcbiAgICB0aGlzLmhhc0NvbnRlbnRWaWV3ID0gZmFsc2U7XG5cbiAgICBpZiAodGhpcy5za2VsZXRvblRwbCkge1xuICAgICAgLy8gVXNhciB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRvXG4gICAgICB0aGlzLnZpZXdDb250YWluZXIuY3JlYXRlRW1iZWRkZWRWaWV3KHRoaXMuc2tlbGV0b25UcGwpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zcGlubmVyKSB7XG4gICAgICAvLyBNb3N0cmFyIHNwaW5uZXIgKHVzYXIgdmFsLWNvbnRlbnQtbG9hZGVyIHNpIGVzdGEgZGlzcG9uaWJsZSlcbiAgICAgIHRoaXMuc2hvd1NwaW5uZXIoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVXNhciB0ZW1wbGF0ZSBkZSBza2VsZXRvbiByZWdpc3RyYWRvXG4gICAgICB0aGlzLnNob3dTa2VsZXRvblRlbXBsYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzaG93U2tlbGV0b25UZW1wbGF0ZSgpOiB2b2lkIHtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9IHRoaXMuc2tlbGV0b25TZXJ2aWNlLmdldFRlbXBsYXRlKHRoaXMuc2tlbGV0b24pO1xuXG4gICAgaWYgKHRlbXBsYXRlKSB7XG4gICAgICB0aGlzLnNrZWxldG9uQ29tcG9uZW50UmVmID0gdGhpcy52aWV3Q29udGFpbmVyLmNyZWF0ZUNvbXBvbmVudChcbiAgICAgICAgdGVtcGxhdGUuY29tcG9uZW50IGFzIG5ldyAoKSA9PiBTa2VsZXRvblRlbXBsYXRlQ29tcG9uZW50XG4gICAgICApO1xuXG4gICAgICAvLyBDb21iaW5hciBjb25maWcgcG9yIGRlZmVjdG8gY29uIGlucHV0c1xuICAgICAgY29uc3QgY29uZmlnID0ge1xuICAgICAgICAuLi50ZW1wbGF0ZS5kZWZhdWx0Q29uZmlnLFxuICAgICAgICBjb3VudDogdGhpcy5jb3VudCxcbiAgICAgICAgYW5pbWF0ZWQ6IHRoaXMuYW5pbWF0ZWQsXG4gICAgICAgIGdhcDogdGhpcy5nYXAsXG4gICAgICAgIHZhcmlhbnQ6IHRoaXMudmFyaWFudCxcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuc2tlbGV0b25Db21wb25lbnRSZWYuaW5zdGFuY2UuY29uZmlnID0gY29uZmlnO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGYWxsYmFjazogbW9zdHJhciB0ZXh0byBkZSBjYXJnYSBzaSBubyBoYXkgdGVtcGxhdGVcbiAgICAgIGNvbnNvbGUud2FybihgW3ZhbExvYWRpbmddIFRlbXBsYXRlICcke3RoaXMuc2tlbGV0b259JyBub3QgZm91bmQuIFVzaW5nIGZhbGxiYWNrLmApO1xuICAgICAgdGhpcy5zaG93RmFsbGJhY2soKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNob3dTcGlubmVyKCk6IHZvaWQge1xuICAgIC8vIENyZWFyIHVuIGRpdiBjb24gc3Bpbm5lciBzaW1wbGVcbiAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZWxlbWVudC5jbGFzc05hbWUgPSAndmFsLWxvYWRpbmctc3Bpbm5lcic7XG4gICAgZWxlbWVudC5pbm5lckhUTUwgPSBgXG4gICAgICA8aW9uLXNwaW5uZXIgbmFtZT1cImNyZXNjZW50XCI+PC9pb24tc3Bpbm5lcj5cbiAgICBgO1xuICAgIGVsZW1lbnQuc3R5bGUuY3NzVGV4dCA9ICdkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsgcGFkZGluZzogMjBweDsnO1xuXG4gICAgY29uc3QgaG9zdEVsZW1lbnQgPSB0aGlzLnZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuICAgIGhvc3RFbGVtZW50LnBhcmVudEVsZW1lbnQ/Lmluc2VydEJlZm9yZShlbGVtZW50LCBob3N0RWxlbWVudCk7XG4gIH1cblxuICBwcml2YXRlIHNob3dGYWxsYmFjaygpOiB2b2lkIHtcbiAgICAvLyBGYWxsYmFjayBzaW1wbGUgc2kgbm8gaGF5IHRlbXBsYXRlIHJlZ2lzdHJhZG9cbiAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZWxlbWVudC5jbGFzc05hbWUgPSAndmFsLWxvYWRpbmctZmFsbGJhY2snO1xuICAgIGVsZW1lbnQuc3R5bGUuY3NzVGV4dCA9XG4gICAgICAnZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsgZ2FwOiAxMnB4OyBwYWRkaW5nOiAxNnB4Oyc7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY291bnQ7IGkrKykge1xuICAgICAgY29uc3Qgc2tlbGV0b24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHNrZWxldG9uLnN0eWxlLmNzc1RleHQgPSBgXG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCg5MGRlZywgI2YwZjBmMCAyNSUsICNlMGUwZTAgNTAlLCAjZjBmMGYwIDc1JSk7XG4gICAgICAgIGJhY2tncm91bmQtc2l6ZTogMjAwJSAxMDAlO1xuICAgICAgICBhbmltYXRpb246IHNrZWxldG9uLWxvYWRpbmcgMS41cyBpbmZpbml0ZTtcbiAgICAgICAgaGVpZ2h0OiA1NnB4O1xuICAgICAgICBib3JkZXItcmFkaXVzOiA4cHg7XG4gICAgICBgO1xuICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChza2VsZXRvbik7XG4gICAgfVxuXG4gICAgY29uc3QgaG9zdEVsZW1lbnQgPSB0aGlzLnZpZXdDb250YWluZXIuZWxlbWVudC5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xuICAgIGhvc3RFbGVtZW50LnBhcmVudEVsZW1lbnQ/Lmluc2VydEJlZm9yZShlbGVtZW50LCBob3N0RWxlbWVudCk7XG4gIH1cblxuICBwcml2YXRlIHNob3dDb250ZW50KCk6IHZvaWQge1xuICAgIC8vIExpbXBpYXIgc2tlbGV0b25cbiAgICB0aGlzLnZpZXdDb250YWluZXIuY2xlYXIoKTtcbiAgICB0aGlzLnNrZWxldG9uQ29tcG9uZW50UmVmID0gbnVsbDtcblxuICAgIC8vIE1vc3RyYXIgY29udGVuaWRvIHJlYWxcbiAgICBpZiAoIXRoaXMuaGFzQ29udGVudFZpZXcpIHtcbiAgICAgIHRoaXMudmlld0NvbnRhaW5lci5jcmVhdGVFbWJlZGRlZFZpZXcodGhpcy50ZW1wbGF0ZVJlZik7XG4gICAgICB0aGlzLmhhc0NvbnRlbnRWaWV3ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Types
|
|
2
|
+
export { DEFAULT_SKELETON_CONFIG, } from './types';
|
|
3
|
+
// Service
|
|
4
|
+
export { SkeletonService } from './skeleton.service';
|
|
5
|
+
// Directives
|
|
6
|
+
export { LoadingDirective } from './directives/loading.directive';
|
|
7
|
+
// Templates
|
|
8
|
+
export { ListSkeletonComponent } from './templates/list-skeleton.component';
|
|
9
|
+
export { GridSkeletonComponent } from './templates/grid-skeleton.component';
|
|
10
|
+
export { FormSkeletonComponent } from './templates/form-skeleton.component';
|
|
11
|
+
export { ProfileSkeletonComponent } from './templates/profile-skeleton.component';
|
|
12
|
+
export { TableSkeletonComponent } from './templates/table-skeleton.component';
|
|
13
|
+
export { DetailSkeletonComponent } from './templates/detail-skeleton.component';
|
|
14
|
+
// Config / Provider
|
|
15
|
+
export { provideValtechSkeleton } from './config';
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3NrZWxldG9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFFBQVE7QUFDUixPQUFPLEVBVUwsdUJBQXVCLEdBQ3hCLE1BQU0sU0FBUyxDQUFDO0FBRWpCLFVBQVU7QUFDVixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFckQsYUFBYTtBQUNiLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWxFLFlBQVk7QUFDWixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUNsRixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUM5RSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVoRixvQkFBb0I7QUFDcEIsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sVUFBVSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVHlwZXNcbmV4cG9ydCB7XG4gIFNrZWxldG9uVGVtcGxhdGVOYW1lLFxuICBTa2VsZXRvblRlbXBsYXRlQ29uZmlnLFxuICBMb2FkaW5nU291cmNlLFxuICBTa2VsZXRvbkRpcmVjdGl2ZUNvbmZpZyxcbiAgTG9hZGluZ0RpcmVjdGl2ZUNvbmZpZyxcbiAgUmVnaXN0ZXJlZFNrZWxldG9uVGVtcGxhdGUsXG4gIFNrZWxldG9uQ29uZmlnLFxuICBTa2VsZXRvblRlbXBsYXRlQ29udGV4dCxcbiAgU2tlbGV0b25UZW1wbGF0ZUNvbXBvbmVudCxcbiAgREVGQVVMVF9TS0VMRVRPTl9DT05GSUcsXG59IGZyb20gJy4vdHlwZXMnO1xuXG4vLyBTZXJ2aWNlXG5leHBvcnQgeyBTa2VsZXRvblNlcnZpY2UgfSBmcm9tICcuL3NrZWxldG9uLnNlcnZpY2UnO1xuXG4vLyBEaXJlY3RpdmVzXG5leHBvcnQgeyBMb2FkaW5nRGlyZWN0aXZlIH0gZnJvbSAnLi9kaXJlY3RpdmVzL2xvYWRpbmcuZGlyZWN0aXZlJztcblxuLy8gVGVtcGxhdGVzXG5leHBvcnQgeyBMaXN0U2tlbGV0b25Db21wb25lbnQgfSBmcm9tICcuL3RlbXBsYXRlcy9saXN0LXNrZWxldG9uLmNvbXBvbmVudCc7XG5leHBvcnQgeyBHcmlkU2tlbGV0b25Db21wb25lbnQgfSBmcm9tICcuL3RlbXBsYXRlcy9ncmlkLXNrZWxldG9uLmNvbXBvbmVudCc7XG5leHBvcnQgeyBGb3JtU2tlbGV0b25Db21wb25lbnQgfSBmcm9tICcuL3RlbXBsYXRlcy9mb3JtLXNrZWxldG9uLmNvbXBvbmVudCc7XG5leHBvcnQgeyBQcm9maWxlU2tlbGV0b25Db21wb25lbnQgfSBmcm9tICcuL3RlbXBsYXRlcy9wcm9maWxlLXNrZWxldG9uLmNvbXBvbmVudCc7XG5leHBvcnQgeyBUYWJsZVNrZWxldG9uQ29tcG9uZW50IH0gZnJvbSAnLi90ZW1wbGF0ZXMvdGFibGUtc2tlbGV0b24uY29tcG9uZW50JztcbmV4cG9ydCB7IERldGFpbFNrZWxldG9uQ29tcG9uZW50IH0gZnJvbSAnLi90ZW1wbGF0ZXMvZGV0YWlsLXNrZWxldG9uLmNvbXBvbmVudCc7XG5cbi8vIENvbmZpZyAvIFByb3ZpZGVyXG5leHBvcnQgeyBwcm92aWRlVmFsdGVjaFNrZWxldG9uIH0gZnJvbSAnLi9jb25maWcnO1xuIl19
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { Injectable, signal, computed } from '@angular/core';
|
|
2
|
+
import { DEFAULT_SKELETON_CONFIG, } from './types';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Servicio para gestionar templates de skeleton y estados de carga globales.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // En un componente
|
|
9
|
+
* skeleton = inject(SkeletonService);
|
|
10
|
+
*
|
|
11
|
+
* // Registrar template personalizado
|
|
12
|
+
* skeleton.registerTemplate('my-custom', MyCustomSkeletonComponent);
|
|
13
|
+
*
|
|
14
|
+
* // Obtener componente de template
|
|
15
|
+
* const component = skeleton.getTemplate('list');
|
|
16
|
+
*
|
|
17
|
+
* // Gestionar estados de carga globales
|
|
18
|
+
* skeleton.setLoadingState('dashboard', true);
|
|
19
|
+
* const isDashboardLoading = skeleton.loadingState('dashboard');
|
|
20
|
+
*/
|
|
21
|
+
export class SkeletonService {
|
|
22
|
+
constructor() {
|
|
23
|
+
this._config = signal(DEFAULT_SKELETON_CONFIG);
|
|
24
|
+
this._templates = signal(new Map());
|
|
25
|
+
this._loadingStates = signal(new Map());
|
|
26
|
+
this._initialized = false;
|
|
27
|
+
/** Configuracion actual (solo lectura) */
|
|
28
|
+
this.config = this._config.asReadonly();
|
|
29
|
+
/** Templates registrados (solo lectura) */
|
|
30
|
+
this.templates = this._templates.asReadonly();
|
|
31
|
+
/** Estado de carga global (cualquier estado registrado esta cargando) */
|
|
32
|
+
this.isAnyLoading = computed(() => {
|
|
33
|
+
const states = this._loadingStates();
|
|
34
|
+
return Array.from(states.values()).some((v) => v);
|
|
35
|
+
});
|
|
36
|
+
/** Cantidad de templates registrados */
|
|
37
|
+
this.templateCount = computed(() => this._templates().size);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Configura el servicio de skeleton.
|
|
41
|
+
* Llamado por provideValtechSkeleton().
|
|
42
|
+
*/
|
|
43
|
+
configure(config) {
|
|
44
|
+
if (this._initialized) {
|
|
45
|
+
console.warn('[SkeletonService] Service already configured. Ignoring reconfiguration.');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this._config.set({ ...DEFAULT_SKELETON_CONFIG, ...config });
|
|
49
|
+
// Registrar templates personalizados de la configuracion
|
|
50
|
+
config.templates?.forEach((t) => {
|
|
51
|
+
this.registerTemplate(t.name, t.component, t.defaultConfig);
|
|
52
|
+
});
|
|
53
|
+
this._initialized = true;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Registra un template de skeleton personalizado.
|
|
57
|
+
*
|
|
58
|
+
* @param name Nombre unico del template
|
|
59
|
+
* @param component Componente a usar
|
|
60
|
+
* @param defaultConfig Configuracion por defecto opcional
|
|
61
|
+
*/
|
|
62
|
+
registerTemplate(name, component, defaultConfig) {
|
|
63
|
+
this._templates.update((map) => {
|
|
64
|
+
const newMap = new Map(map);
|
|
65
|
+
newMap.set(name, { name, component, defaultConfig });
|
|
66
|
+
return newMap;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Obtiene un template de skeleton registrado.
|
|
71
|
+
*
|
|
72
|
+
* @param name Nombre del template
|
|
73
|
+
* @returns Template registrado o undefined si no existe
|
|
74
|
+
*/
|
|
75
|
+
getTemplate(name) {
|
|
76
|
+
return this._templates().get(name);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Verifica si un template esta registrado.
|
|
80
|
+
*
|
|
81
|
+
* @param name Nombre del template
|
|
82
|
+
* @returns true si el template existe
|
|
83
|
+
*/
|
|
84
|
+
hasTemplate(name) {
|
|
85
|
+
return this._templates().has(name);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Obtiene todos los nombres de templates registrados.
|
|
89
|
+
*
|
|
90
|
+
* @returns Array de nombres de templates
|
|
91
|
+
*/
|
|
92
|
+
getTemplateNames() {
|
|
93
|
+
return Array.from(this._templates().keys());
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Registra un estado de carga nombrado.
|
|
97
|
+
* Util para indicadores de carga globales.
|
|
98
|
+
*
|
|
99
|
+
* @param key Identificador unico del estado
|
|
100
|
+
* @param isLoading Estado de carga
|
|
101
|
+
*/
|
|
102
|
+
setLoadingState(key, isLoading) {
|
|
103
|
+
this._loadingStates.update((map) => {
|
|
104
|
+
const newMap = new Map(map);
|
|
105
|
+
if (isLoading) {
|
|
106
|
+
newMap.set(key, true);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
newMap.delete(key);
|
|
110
|
+
}
|
|
111
|
+
return newMap;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Obtiene el estado de carga para una clave especifica.
|
|
116
|
+
*
|
|
117
|
+
* @param key Identificador del estado
|
|
118
|
+
* @returns Estado de carga actual
|
|
119
|
+
*/
|
|
120
|
+
getLoadingState(key) {
|
|
121
|
+
return this._loadingStates().get(key) ?? false;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Crea un signal computado para un estado de carga especifico.
|
|
125
|
+
*
|
|
126
|
+
* @param key Identificador del estado
|
|
127
|
+
* @returns Signal reactivo del estado de carga
|
|
128
|
+
*/
|
|
129
|
+
loadingState(key) {
|
|
130
|
+
return computed(() => this._loadingStates().get(key) ?? false);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Obtiene todas las claves de estados de carga activos.
|
|
134
|
+
*
|
|
135
|
+
* @returns Array de claves con estado de carga activo
|
|
136
|
+
*/
|
|
137
|
+
getActiveLoadingKeys() {
|
|
138
|
+
const states = this._loadingStates();
|
|
139
|
+
return Array.from(states.entries())
|
|
140
|
+
.filter(([, isLoading]) => isLoading)
|
|
141
|
+
.map(([key]) => key);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Limpia todos los estados de carga.
|
|
145
|
+
*/
|
|
146
|
+
clearLoadingStates() {
|
|
147
|
+
this._loadingStates.set(new Map());
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Limpia un estado de carga especifico.
|
|
151
|
+
*
|
|
152
|
+
* @param key Identificador del estado a limpiar
|
|
153
|
+
*/
|
|
154
|
+
clearLoadingState(key) {
|
|
155
|
+
this.setLoadingState(key, false);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Ejecuta una funcion async con tracking de estado de carga.
|
|
159
|
+
*
|
|
160
|
+
* @param key Identificador del estado
|
|
161
|
+
* @param fn Funcion async a ejecutar
|
|
162
|
+
* @returns Resultado de la funcion
|
|
163
|
+
*/
|
|
164
|
+
async withLoading(key, fn) {
|
|
165
|
+
this.setLoadingState(key, true);
|
|
166
|
+
try {
|
|
167
|
+
return await fn();
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
this.setLoadingState(key, false);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Obtiene la configuracion de animacion por defecto.
|
|
175
|
+
*/
|
|
176
|
+
get animated() {
|
|
177
|
+
return this._config().animated ?? true;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Obtiene el delay por defecto.
|
|
181
|
+
*/
|
|
182
|
+
get defaultDelay() {
|
|
183
|
+
return this._config().defaultDelay ?? 0;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Obtiene el tiempo minimo por defecto.
|
|
187
|
+
*/
|
|
188
|
+
get defaultMinTime() {
|
|
189
|
+
return this._config().defaultMinTime ?? 300;
|
|
190
|
+
}
|
|
191
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SkeletonService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
192
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SkeletonService, providedIn: 'root' }); }
|
|
193
|
+
}
|
|
194
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SkeletonService, decorators: [{
|
|
195
|
+
type: Injectable,
|
|
196
|
+
args: [{ providedIn: 'root' }]
|
|
197
|
+
}] });
|
|
198
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tlbGV0b24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvc2tlbGV0b24vc2tlbGV0b24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQVEsTUFBTSxlQUFlLENBQUM7QUFDbkUsT0FBTyxFQUtMLHVCQUF1QixHQUN4QixNQUFNLFNBQVMsQ0FBQzs7QUFFakI7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFFSCxNQUFNLE9BQU8sZUFBZTtJQUQ1QjtRQUVtQixZQUFPLEdBQUcsTUFBTSxDQUFpQix1QkFBdUIsQ0FBQyxDQUFDO1FBQzFELGVBQVUsR0FBRyxNQUFNLENBQTBDLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN4RSxtQkFBYyxHQUFHLE1BQU0sQ0FBdUIsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ2xFLGlCQUFZLEdBQUcsS0FBSyxDQUFDO1FBRTdCLDBDQUEwQztRQUNqQyxXQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUU1QywyQ0FBMkM7UUFDbEMsY0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFbEQseUVBQXlFO1FBQ2hFLGlCQUFZLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUNwQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDckMsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDLENBQUM7UUFFSCx3Q0FBd0M7UUFDL0Isa0JBQWEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENB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R0FBRyxDQUFDO0lBQzlDLENBQUM7K0dBL0xVLGVBQWU7bUhBQWYsZUFBZSxjQURGLE1BQU07OzRGQUNuQixlQUFlO2tCQUQzQixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIHNpZ25hbCwgY29tcHV0ZWQsIFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIFNrZWxldG9uVGVtcGxhdGVOYW1lLFxuICBTa2VsZXRvblRlbXBsYXRlQ29uZmlnLFxuICBSZWdpc3RlcmVkU2tlbGV0b25UZW1wbGF0ZSxcbiAgU2tlbGV0b25Db25maWcsXG4gIERFRkFVTFRfU0tFTEVUT05fQ09ORklHLFxufSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBTZXJ2aWNpbyBwYXJhIGdlc3Rpb25hciB0ZW1wbGF0ZXMgZGUgc2tlbGV0b24geSBlc3RhZG9zIGRlIGNhcmdhIGdsb2JhbGVzLlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBFbiB1biBjb21wb25lbnRlXG4gKiBza2VsZXRvbiA9IGluamVjdChTa2VsZXRvblNlcnZpY2UpO1xuICpcbiAqIC8vIFJlZ2lzdHJhciB0ZW1wbGF0ZSBwZXJzb25hbGl6YWRvXG4gKiBza2VsZXRvbi5yZWdpc3RlclRlbXBsYXRlKCdteS1jdXN0b20nLCBNeUN1c3RvbVNrZWxldG9uQ29tcG9uZW50KTtcbiAqXG4gKiAvLyBPYnRlbmVyIGNvbXBvbmVudGUgZGUgdGVtcGxhdGVcbiAqIGNvbnN0IGNvbXBvbmVudCA9IHNrZWxldG9uLmdldFRlbXBsYXRlKCdsaXN0Jyk7XG4gKlxuICogLy8gR2VzdGlvbmFyIGVzdGFkb3MgZGUgY2FyZ2EgZ2xvYmFsZXNcbiAqIHNrZWxldG9uLnNldExvYWRpbmdTdGF0ZSgnZGFzaGJvYXJkJywgdHJ1ZSk7XG4gKiBjb25zdCBpc0Rhc2hib2FyZExvYWRpbmcgPSBza2VsZXRvbi5sb2FkaW5nU3RhdGUoJ2Rhc2hib2FyZCcpO1xuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFNrZWxldG9uU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2NvbmZpZyA9IHNpZ25hbDxTa2VsZXRvbkNvbmZpZz4oREVGQVVMVF9TS0VMRVRPTl9DT05GSUcpO1xuICBwcml2YXRlIHJlYWRvbmx5IF90ZW1wbGF0ZXMgPSBzaWduYWw8TWFwPHN0cmluZywgUmVnaXN0ZXJlZFNrZWxldG9uVGVtcGxhdGU+PihuZXcgTWFwKCkpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9sb2FkaW5nU3RhdGVzID0gc2lnbmFsPE1hcDxzdHJpbmcsIGJvb2xlYW4+PihuZXcgTWFwKCkpO1xuICBwcml2YXRlIF9pbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gIC8qKiBDb25maWd1cmFjaW9uIGFjdHVhbCAoc29sbyBsZWN0dXJhKSAqL1xuICByZWFkb25seSBjb25maWcgPSB0aGlzLl9jb25maWcuYXNSZWFkb25seSgpO1xuXG4gIC8qKiBUZW1wbGF0ZXMgcmVnaXN0cmFkb3MgKHNvbG8gbGVjdHVyYSkgKi9cbiAgcmVhZG9ubHkgdGVtcGxhdGVzID0gdGhpcy5fdGVtcGxhdGVzLmFzUmVhZG9ubHkoKTtcblxuICAvKiogRXN0YWRvIGRlIGNhcmdhIGdsb2JhbCAoY3VhbHF1aWVyIGVzdGFkbyByZWdpc3RyYWRvIGVzdGEgY2FyZ2FuZG8pICovXG4gIHJlYWRvbmx5IGlzQW55TG9hZGluZyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBzdGF0ZXMgPSB0aGlzLl9sb2FkaW5nU3RhdGVzKCk7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oc3RhdGVzLnZhbHVlcygpKS5zb21lKCh2KSA9PiB2KTtcbiAgfSk7XG5cbiAgLyoqIENhbnRpZGFkIGRlIHRlbXBsYXRlcyByZWdpc3RyYWRvcyAqL1xuICByZWFkb25seSB0ZW1wbGF0ZUNvdW50ID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5fdGVtcGxhdGVzKCkuc2l6ZSk7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyYSBlbCBzZXJ2aWNpbyBkZSBza2VsZXRvbi5cbiAgICogTGxhbWFkbyBwb3IgcHJvdmlkZVZhbHRlY2hTa2VsZXRvbigpLlxuICAgKi9cbiAgY29uZmlndXJlKGNvbmZpZzogU2tlbGV0b25Db25maWcpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5faW5pdGlhbGl6ZWQpIHtcbiAgICAgIGNvbnNvbGUud2FybignW1NrZWxldG9uU2VydmljZV0gU2VydmljZSBhbHJlYWR5IGNvbmZpZ3VyZWQuIElnbm9yaW5nIHJlY29uZmlndXJhdGlvbi4nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9jb25maWcuc2V0KHsgLi4uREVGQVVMVF9TS0VMRVRPTl9DT05GSUcsIC4uLmNvbmZpZyB9KTtcblxuICAgIC8vIFJlZ2lzdHJhciB0ZW1wbGF0ZXMgcGVyc29uYWxpemFkb3MgZGUgbGEgY29uZmlndXJhY2lvblxuICAgIGNvbmZpZy50ZW1wbGF0ZXM/LmZvckVhY2goKHQpID0+IHtcbiAgICAgIHRoaXMucmVnaXN0ZXJUZW1wbGF0ZSh0Lm5hbWUsIHQuY29tcG9uZW50LCB0LmRlZmF1bHRDb25maWcpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5faW5pdGlhbGl6ZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdHJhIHVuIHRlbXBsYXRlIGRlIHNrZWxldG9uIHBlcnNvbmFsaXphZG8uXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIE5vbWJyZSB1bmljbyBkZWwgdGVtcGxhdGVcbiAgICogQHBhcmFtIGNvbXBvbmVudCBDb21wb25lbnRlIGEgdXNhclxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpZyBDb25maWd1cmFjaW9uIHBvciBkZWZlY3RvIG9wY2lvbmFsXG4gICAqL1xuICByZWdpc3RlclRlbXBsYXRlKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBjb21wb25lbnQ6IFR5cGU8dW5rbm93bj4sXG4gICAgZGVmYXVsdENvbmZpZz86IFNrZWxldG9uVGVtcGxhdGVDb25maWdcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5fdGVtcGxhdGVzLnVwZGF0ZSgobWFwKSA9PiB7XG4gICAgICBjb25zdCBuZXdNYXAgPSBuZXcgTWFwKG1hcCk7XG4gICAgICBuZXdNYXAuc2V0KG5hbWUsIHsgbmFtZSwgY29tcG9uZW50LCBkZWZhdWx0Q29uZmlnIH0pO1xuICAgICAgcmV0dXJuIG5ld01hcDtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIHVuIHRlbXBsYXRlIGRlIHNrZWxldG9uIHJlZ2lzdHJhZG8uXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIE5vbWJyZSBkZWwgdGVtcGxhdGVcbiAgICogQHJldHVybnMgVGVtcGxhdGUgcmVnaXN0cmFkbyBvIHVuZGVmaW5lZCBzaSBubyBleGlzdGVcbiAgICovXG4gIGdldFRlbXBsYXRlKG5hbWU6IFNrZWxldG9uVGVtcGxhdGVOYW1lIHwgc3RyaW5nKTogUmVnaXN0ZXJlZFNrZWxldG9uVGVtcGxhdGUgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl90ZW1wbGF0ZXMoKS5nZXQobmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgdW4gdGVtcGxhdGUgZXN0YSByZWdpc3RyYWRvLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBOb21icmUgZGVsIHRlbXBsYXRlXG4gICAqIEByZXR1cm5zIHRydWUgc2kgZWwgdGVtcGxhdGUgZXhpc3RlXG4gICAqL1xuICBoYXNUZW1wbGF0ZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fdGVtcGxhdGVzKCkuaGFzKG5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgdG9kb3MgbG9zIG5vbWJyZXMgZGUgdGVtcGxhdGVzIHJlZ2lzdHJhZG9zLlxuICAgKlxuICAgKiBAcmV0dXJucyBBcnJheSBkZSBub21icmVzIGRlIHRlbXBsYXRlc1xuICAgKi9cbiAgZ2V0VGVtcGxhdGVOYW1lcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5fdGVtcGxhdGVzKCkua2V5cygpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RyYSB1biBlc3RhZG8gZGUgY2FyZ2Egbm9tYnJhZG8uXG4gICAqIFV0aWwgcGFyYSBpbmRpY2Fkb3JlcyBkZSBjYXJnYSBnbG9iYWxlcy5cbiAgICpcbiAgICogQHBhcmFtIGtleSBJZGVudGlmaWNhZG9yIHVuaWNvIGRlbCBlc3RhZG9cbiAgICogQHBhcmFtIGlzTG9hZGluZyBFc3RhZG8gZGUgY2FyZ2FcbiAgICovXG4gIHNldExvYWRpbmdTdGF0ZShrZXk6IHN0cmluZywgaXNMb2FkaW5nOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5fbG9hZGluZ1N0YXRlcy51cGRhdGUoKG1hcCkgPT4ge1xuICAgICAgY29uc3QgbmV3TWFwID0gbmV3IE1hcChtYXApO1xuICAgICAgaWYgKGlzTG9hZGluZykge1xuICAgICAgICBuZXdNYXAuc2V0KGtleSwgdHJ1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdNYXAuZGVsZXRlKGtleSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3TWFwO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgZXN0YWRvIGRlIGNhcmdhIHBhcmEgdW5hIGNsYXZlIGVzcGVjaWZpY2EuXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgSWRlbnRpZmljYWRvciBkZWwgZXN0YWRvXG4gICAqIEByZXR1cm5zIEVzdGFkbyBkZSBjYXJnYSBhY3R1YWxcbiAgICovXG4gIGdldExvYWRpbmdTdGF0ZShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9sb2FkaW5nU3RhdGVzKCkuZ2V0KGtleSkgPz8gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYSB1biBzaWduYWwgY29tcHV0YWRvIHBhcmEgdW4gZXN0YWRvIGRlIGNhcmdhIGVzcGVjaWZpY28uXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgSWRlbnRpZmljYWRvciBkZWwgZXN0YWRvXG4gICAqIEByZXR1cm5zIFNpZ25hbCByZWFjdGl2byBkZWwgZXN0YWRvIGRlIGNhcmdhXG4gICAqL1xuICBsb2FkaW5nU3RhdGUoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gY29tcHV0ZWQoKCkgPT4gdGhpcy5fbG9hZGluZ1N0YXRlcygpLmdldChrZXkpID8/IGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIHRvZGFzIGxhcyBjbGF2ZXMgZGUgZXN0YWRvcyBkZSBjYXJnYSBhY3Rpdm9zLlxuICAgKlxuICAgKiBAcmV0dXJucyBBcnJheSBkZSBjbGF2ZXMgY29uIGVzdGFkbyBkZSBjYXJnYSBhY3Rpdm9cbiAgICovXG4gIGdldEFjdGl2ZUxvYWRpbmdLZXlzKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBzdGF0ZXMgPSB0aGlzLl9sb2FkaW5nU3RhdGVzKCk7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oc3RhdGVzLmVudHJpZXMoKSlcbiAgICAgIC5maWx0ZXIoKFssIGlzTG9hZGluZ10pID0+IGlzTG9hZGluZylcbiAgICAgIC5tYXAoKFtrZXldKSA9PiBrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpbXBpYSB0b2RvcyBsb3MgZXN0YWRvcyBkZSBjYXJnYS5cbiAgICovXG4gIGNsZWFyTG9hZGluZ1N0YXRlcygpOiB2b2lkIHtcbiAgICB0aGlzLl9sb2FkaW5nU3RhdGVzLnNldChuZXcgTWFwKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpbXBpYSB1biBlc3RhZG8gZGUgY2FyZ2EgZXNwZWNpZmljby5cbiAgICpcbiAgICogQHBhcmFtIGtleSBJZGVudGlmaWNhZG9yIGRlbCBlc3RhZG8gYSBsaW1waWFyXG4gICAqL1xuICBjbGVhckxvYWRpbmdTdGF0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuc2V0TG9hZGluZ1N0YXRlKGtleSwgZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVqZWN1dGEgdW5hIGZ1bmNpb24gYXN5bmMgY29uIHRyYWNraW5nIGRlIGVzdGFkbyBkZSBjYXJnYS5cbiAgICpcbiAgICogQHBhcmFtIGtleSBJZGVudGlmaWNhZG9yIGRlbCBlc3RhZG9cbiAgICogQHBhcmFtIGZuIEZ1bmNpb24gYXN5bmMgYSBlamVjdXRhclxuICAgKiBAcmV0dXJucyBSZXN1bHRhZG8gZGUgbGEgZnVuY2lvblxuICAgKi9cbiAgYXN5bmMgd2l0aExvYWRpbmc8VD4oa2V5OiBzdHJpbmcsIGZuOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgdGhpcy5zZXRMb2FkaW5nU3RhdGUoa2V5LCB0cnVlKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGZuKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuc2V0TG9hZGluZ1N0YXRlKGtleSwgZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGxhIGNvbmZpZ3VyYWNpb24gZGUgYW5pbWFjaW9uIHBvciBkZWZlY3RvLlxuICAgKi9cbiAgZ2V0IGFuaW1hdGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9jb25maWcoKS5hbmltYXRlZCA/PyB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgZGVsYXkgcG9yIGRlZmVjdG8uXG4gICAqL1xuICBnZXQgZGVmYXVsdERlbGF5KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbmZpZygpLmRlZmF1bHREZWxheSA/PyAwO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgdGllbXBvIG1pbmltbyBwb3IgZGVmZWN0by5cbiAgICovXG4gIGdldCBkZWZhdWx0TWluVGltZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9jb25maWcoKS5kZWZhdWx0TWluVGltZSA/PyAzMDA7XG4gIH1cbn1cbiJdfQ==
|