valtech-components 4.0.219 → 4.0.220

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 (55) hide show
  1. package/esm2022/lib/components/molecules/chat-input/chat-input.component.mjs +157 -0
  2. package/esm2022/lib/components/molecules/chat-input/types.mjs +2 -0
  3. package/esm2022/lib/components/molecules/message-bubble/message-bubble.component.mjs +244 -0
  4. package/esm2022/lib/components/molecules/message-bubble/types.mjs +2 -0
  5. package/esm2022/lib/components/molecules/typing-indicator/typing-indicator.component.mjs +76 -0
  6. package/esm2022/lib/components/organisms/chat-window/chat-window.component.mjs +246 -0
  7. package/esm2022/lib/components/organisms/chat-window/types.mjs +2 -0
  8. package/esm2022/lib/components/organisms/thread-panel/thread-panel.component.mjs +211 -0
  9. package/esm2022/lib/services/chat/config.mjs +35 -0
  10. package/esm2022/lib/services/chat/conversation.service.mjs +274 -0
  11. package/esm2022/lib/services/chat/types.mjs +10 -0
  12. package/esm2022/lib/services/entity-feed/entity-feed.service.mjs +103 -0
  13. package/esm2022/lib/services/entity-feed/index.mjs +2 -0
  14. package/esm2022/lib/services/entity-feed/types.mjs +2 -0
  15. package/esm2022/lib/services/i18n/default-content.mjs +65 -1
  16. package/esm2022/public-api.mjs +16 -1
  17. package/fesm2022/valtech-components.mjs +1369 -2
  18. package/fesm2022/valtech-components.mjs.map +1 -1
  19. package/lib/components/atoms/glow/glow.component.d.ts +1 -1
  20. package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +2 -2
  21. package/lib/components/atoms/text/text.component.d.ts +1 -1
  22. package/lib/components/atoms/user-avatar/user-avatar.component.d.ts +2 -2
  23. package/lib/components/molecules/article-card/article-card.component.d.ts +1 -1
  24. package/lib/components/molecules/chat-input/chat-input.component.d.ts +38 -0
  25. package/lib/components/molecules/chat-input/types.d.ts +20 -0
  26. package/lib/components/molecules/content-reaction/content-reaction.component.d.ts +2 -2
  27. package/lib/components/molecules/cta-card/cta-card.component.d.ts +1 -1
  28. package/lib/components/molecules/features-list/features-list.component.d.ts +4 -4
  29. package/lib/components/molecules/load-more/load-more.component.d.ts +1 -1
  30. package/lib/components/molecules/media-object/media-object.component.d.ts +1 -1
  31. package/lib/components/molecules/message-bubble/message-bubble.component.d.ts +40 -0
  32. package/lib/components/molecules/message-bubble/types.d.ts +64 -0
  33. package/lib/components/molecules/metric-card/metric-card.component.d.ts +1 -1
  34. package/lib/components/molecules/typing-indicator/typing-indicator.component.d.ts +19 -0
  35. package/lib/components/organisms/account-view/account-view.component.d.ts +1 -1
  36. package/lib/components/organisms/article/article.component.d.ts +6 -6
  37. package/lib/components/organisms/auth-cta/auth-cta.component.d.ts +1 -1
  38. package/lib/components/organisms/bottom-nav/bottom-nav.component.d.ts +1 -1
  39. package/lib/components/organisms/chat-window/chat-window.component.d.ts +63 -0
  40. package/lib/components/organisms/chat-window/types.d.ts +36 -0
  41. package/lib/components/organisms/landing-steps/landing-steps.component.d.ts +1 -1
  42. package/lib/components/organisms/login/login.component.d.ts +1 -1
  43. package/lib/components/organisms/member-import-modal/member-import-modal.component.d.ts +1 -1
  44. package/lib/components/organisms/notification-preferences-view/notification-preferences-view.component.d.ts +1 -1
  45. package/lib/components/organisms/organization-view/organization-view.component.d.ts +1 -1
  46. package/lib/components/organisms/thread-panel/thread-panel.component.d.ts +55 -0
  47. package/lib/components/templates/page-wrapper/page-wrapper.component.d.ts +2 -2
  48. package/lib/services/chat/config.d.ts +37 -0
  49. package/lib/services/chat/conversation.service.d.ts +147 -0
  50. package/lib/services/chat/types.d.ts +145 -0
  51. package/lib/services/entity-feed/entity-feed.service.d.ts +71 -0
  52. package/lib/services/entity-feed/index.d.ts +2 -0
  53. package/lib/services/entity-feed/types.d.ts +26 -0
  54. package/package.json +1 -1
  55. package/public-api.d.ts +13 -0
@@ -0,0 +1,246 @@
1
+ import { Component, Input, Output, EventEmitter, inject, computed, ViewChild, } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { IonIcon, IonSpinner } from '@ionic/angular/standalone';
4
+ import { addIcons } from 'ionicons';
5
+ import { chatbubblesOutline } from 'ionicons/icons';
6
+ import { I18nService } from '../../../services/i18n';
7
+ import { MessageBubbleComponent } from '../../molecules/message-bubble/message-bubble.component';
8
+ import { ChatInputComponent } from '../../molecules/chat-input/chat-input.component';
9
+ import { TypingIndicatorComponent } from '../../molecules/typing-indicator/typing-indicator.component';
10
+ import * as i0 from "@angular/core";
11
+ addIcons({ chatbubblesOutline });
12
+ const CHAT_WINDOW_I18N = {
13
+ es: {
14
+ conversationClosed: 'Esta conversacion esta cerrada',
15
+ loading: 'Cargando mensajes...',
16
+ noMessages: 'No hay mensajes aun',
17
+ },
18
+ en: {
19
+ conversationClosed: 'This conversation is closed',
20
+ loading: 'Loading messages...',
21
+ noMessages: 'No messages yet',
22
+ },
23
+ };
24
+ /**
25
+ * val-chat-window
26
+ *
27
+ * Ventana de chat completa. Muestra la lista de mensajes agrupados por fecha,
28
+ * el indicador de escritura, el input de mensaje (solo si isOpen) y un banner
29
+ * cuando la conversacion esta cerrada. Auto-scroll al ultimo mensaje cuando
30
+ * llegan mensajes nuevos.
31
+ *
32
+ * @example
33
+ * <val-chat-window
34
+ * [convId]="conv.id"
35
+ * [messages]="messages()"
36
+ * [currentUserId]="userId"
37
+ * [isOpen]="conv.status === 'open'"
38
+ * [typingUsers]="typingUsers()"
39
+ * (sendMessage)="onSend($event)"
40
+ * (reactionClick)="onReaction($event)"
41
+ * />
42
+ */
43
+ export class ChatWindowComponent {
44
+ constructor() {
45
+ this.i18n = inject(I18nService);
46
+ this.convId = '';
47
+ this.messages = [];
48
+ this.participants = [];
49
+ this.currentUserId = '';
50
+ this.isOpen = true;
51
+ this.typingUsers = [];
52
+ this.isLoading = false;
53
+ this.sendMessage = new EventEmitter();
54
+ this.loadMore = new EventEmitter();
55
+ this.reactionClick = new EventEmitter();
56
+ this.deleteMessage = new EventEmitter();
57
+ this.replyTo = new EventEmitter();
58
+ this.prevMessageCount = 0;
59
+ this.shouldScrollToBottom = false;
60
+ this.messageGroups = computed(() => {
61
+ const msgs = this.messages ?? [];
62
+ if (msgs.length === 0)
63
+ return [];
64
+ const groups = [];
65
+ let currentLabel = '';
66
+ let currentGroup = [];
67
+ for (const msg of msgs) {
68
+ const label = this.formatDateLabel(msg.createdAt);
69
+ if (label !== currentLabel) {
70
+ if (currentGroup.length > 0) {
71
+ groups.push({ dateLabel: currentLabel, messages: currentGroup });
72
+ }
73
+ currentLabel = label;
74
+ currentGroup = [msg];
75
+ }
76
+ else {
77
+ currentGroup.push(msg);
78
+ }
79
+ }
80
+ if (currentGroup.length > 0) {
81
+ groups.push({ dateLabel: currentLabel, messages: currentGroup });
82
+ }
83
+ return groups;
84
+ });
85
+ this.closedText = computed(() => {
86
+ this.i18n.lang();
87
+ return this.i18n.t('conversationClosed', 'ChatWindow');
88
+ });
89
+ this.loadingText = computed(() => {
90
+ this.i18n.lang();
91
+ return this.i18n.t('loading', 'ChatWindow');
92
+ });
93
+ this.i18n.registerDefaults('ChatWindow', CHAT_WINDOW_I18N);
94
+ }
95
+ ngOnChanges(changes) {
96
+ if (changes['messages']) {
97
+ const current = changes['messages'].currentValue ?? [];
98
+ if (current.length !== this.prevMessageCount) {
99
+ this.prevMessageCount = current.length;
100
+ this.shouldScrollToBottom = true;
101
+ }
102
+ }
103
+ }
104
+ ngAfterViewChecked() {
105
+ if (this.shouldScrollToBottom) {
106
+ this.scrollToBottom();
107
+ this.shouldScrollToBottom = false;
108
+ }
109
+ }
110
+ onReactionClick(event) {
111
+ this.reactionClick.emit({ msgId: event.msgId, token: event.token });
112
+ }
113
+ onEditClick(_msgId) {
114
+ // Implementacion futura: emitir evento de edicion
115
+ }
116
+ onTyping() {
117
+ // El padre puede suscribirse al output typing si necesita propagar a Firestore
118
+ }
119
+ scrollToBottom() {
120
+ const el = this.messagesListRef?.nativeElement;
121
+ if (el) {
122
+ el.scrollTop = el.scrollHeight;
123
+ }
124
+ }
125
+ formatDateLabel(date) {
126
+ if (!date)
127
+ return '';
128
+ const d = date instanceof Date ? date : new Date(date);
129
+ const now = new Date();
130
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
131
+ const msgDay = new Date(d.getFullYear(), d.getMonth(), d.getDate());
132
+ const diffMs = today.getTime() - msgDay.getTime();
133
+ const diffDays = Math.round(diffMs / 86400000);
134
+ if (diffDays === 0)
135
+ return this.i18n.t('today', '_global') || 'Hoy';
136
+ if (diffDays === 1)
137
+ return this.i18n.t('yesterday', '_global') || 'Ayer';
138
+ return d.toLocaleDateString([], { day: '2-digit', month: 'short', year: 'numeric' });
139
+ }
140
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChatWindowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
141
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ChatWindowComponent, isStandalone: true, selector: "val-chat-window", inputs: { convId: "convId", messages: "messages", participants: "participants", currentUserId: "currentUserId", isOpen: "isOpen", typingUsers: "typingUsers", isLoading: "isLoading" }, outputs: { sendMessage: "sendMessage", loadMore: "loadMore", reactionClick: "reactionClick", deleteMessage: "deleteMessage", replyTo: "replyTo" }, viewQueries: [{ propertyName: "messagesListRef", first: true, predicate: ["messagesList"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
142
+ <div class="chat-window">
143
+ <div class="messages-list" #messagesList>
144
+ @if (isLoading) {
145
+ <div class="loading-state">
146
+ <ion-spinner name="dots"></ion-spinner>
147
+ <span>{{ loadingText() }}</span>
148
+ </div>
149
+ } @else {
150
+ @for (group of messageGroups(); track group.dateLabel) {
151
+ <div class="date-separator">
152
+ <div class="date-line"></div>
153
+ <span class="date-label">{{ group.dateLabel }}</span>
154
+ <div class="date-line"></div>
155
+ </div>
156
+ @for (msg of group.messages; track msg.msgId) {
157
+ <val-message-bubble
158
+ [props]="msg"
159
+ (reactionClick)="onReactionClick($event)"
160
+ (replyClick)="replyTo.emit($event.msgId)"
161
+ (deleteClick)="deleteMessage.emit($event.msgId)"
162
+ (editClick)="onEditClick($event.msgId)"
163
+ />
164
+ }
165
+ }
166
+ }
167
+ </div>
168
+
169
+ <val-typing-indicator [typingUsers]="typingUsers" />
170
+
171
+ @if (!isOpen) {
172
+ <div class="closed-banner">{{ closedText() }}</div>
173
+ } @else {
174
+ <val-chat-input [props]="{ disabled: isLoading }" (send)="sendMessage.emit($event)" (typing)="onTyping()" />
175
+ }
176
+ </div>
177
+ `, isInline: true, styles: [".chat-window{display:flex;flex-direction:column;height:100%;background:var(--ion-background-color, #f4f5f8);overflow:hidden}.messages-list{flex:1;overflow-y:auto;padding:12px 8px;scroll-behavior:smooth}.messages-list::-webkit-scrollbar{width:4px}.messages-list::-webkit-scrollbar-thumb{background:var(--ion-color-light-shade, #d7d8da);border-radius:2px}.date-separator{display:flex;align-items:center;gap:8px;margin:12px 0}.date-separator .date-line{flex:1;height:1px;background:var(--ion-border-color, rgba(0, 0, 0, .1))}.date-separator .date-label{font-size:.75rem;color:var(--ion-color-medium, #92949c);white-space:nowrap;padding:0 4px}.loading-state{display:flex;align-items:center;justify-content:center;padding:24px;color:var(--ion-color-medium, #92949c);font-size:.875rem;gap:8px}.closed-banner{padding:10px 16px;background:var(--ion-color-warning-tint, #fff9e6);border-top:1px solid var(--ion-color-warning, #ffc409);text-align:center;font-size:.875rem;color:var(--ion-color-warning-shade, #b29500)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: MessageBubbleComponent, selector: "val-message-bubble", inputs: ["props"], outputs: ["reactionClick", "replyClick", "deleteClick", "editClick"] }, { kind: "component", type: ChatInputComponent, selector: "val-chat-input", inputs: ["props"], outputs: ["send", "typing"] }, { kind: "component", type: TypingIndicatorComponent, selector: "val-typing-indicator", inputs: ["typingUsers"] }] }); }
178
+ }
179
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChatWindowComponent, decorators: [{
180
+ type: Component,
181
+ args: [{ selector: 'val-chat-window', standalone: true, imports: [CommonModule, IonIcon, IonSpinner, MessageBubbleComponent, ChatInputComponent, TypingIndicatorComponent], template: `
182
+ <div class="chat-window">
183
+ <div class="messages-list" #messagesList>
184
+ @if (isLoading) {
185
+ <div class="loading-state">
186
+ <ion-spinner name="dots"></ion-spinner>
187
+ <span>{{ loadingText() }}</span>
188
+ </div>
189
+ } @else {
190
+ @for (group of messageGroups(); track group.dateLabel) {
191
+ <div class="date-separator">
192
+ <div class="date-line"></div>
193
+ <span class="date-label">{{ group.dateLabel }}</span>
194
+ <div class="date-line"></div>
195
+ </div>
196
+ @for (msg of group.messages; track msg.msgId) {
197
+ <val-message-bubble
198
+ [props]="msg"
199
+ (reactionClick)="onReactionClick($event)"
200
+ (replyClick)="replyTo.emit($event.msgId)"
201
+ (deleteClick)="deleteMessage.emit($event.msgId)"
202
+ (editClick)="onEditClick($event.msgId)"
203
+ />
204
+ }
205
+ }
206
+ }
207
+ </div>
208
+
209
+ <val-typing-indicator [typingUsers]="typingUsers" />
210
+
211
+ @if (!isOpen) {
212
+ <div class="closed-banner">{{ closedText() }}</div>
213
+ } @else {
214
+ <val-chat-input [props]="{ disabled: isLoading }" (send)="sendMessage.emit($event)" (typing)="onTyping()" />
215
+ }
216
+ </div>
217
+ `, styles: [".chat-window{display:flex;flex-direction:column;height:100%;background:var(--ion-background-color, #f4f5f8);overflow:hidden}.messages-list{flex:1;overflow-y:auto;padding:12px 8px;scroll-behavior:smooth}.messages-list::-webkit-scrollbar{width:4px}.messages-list::-webkit-scrollbar-thumb{background:var(--ion-color-light-shade, #d7d8da);border-radius:2px}.date-separator{display:flex;align-items:center;gap:8px;margin:12px 0}.date-separator .date-line{flex:1;height:1px;background:var(--ion-border-color, rgba(0, 0, 0, .1))}.date-separator .date-label{font-size:.75rem;color:var(--ion-color-medium, #92949c);white-space:nowrap;padding:0 4px}.loading-state{display:flex;align-items:center;justify-content:center;padding:24px;color:var(--ion-color-medium, #92949c);font-size:.875rem;gap:8px}.closed-banner{padding:10px 16px;background:var(--ion-color-warning-tint, #fff9e6);border-top:1px solid var(--ion-color-warning, #ffc409);text-align:center;font-size:.875rem;color:var(--ion-color-warning-shade, #b29500)}\n"] }]
218
+ }], ctorParameters: () => [], propDecorators: { convId: [{
219
+ type: Input
220
+ }], messages: [{
221
+ type: Input
222
+ }], participants: [{
223
+ type: Input
224
+ }], currentUserId: [{
225
+ type: Input
226
+ }], isOpen: [{
227
+ type: Input
228
+ }], typingUsers: [{
229
+ type: Input
230
+ }], isLoading: [{
231
+ type: Input
232
+ }], sendMessage: [{
233
+ type: Output
234
+ }], loadMore: [{
235
+ type: Output
236
+ }], reactionClick: [{
237
+ type: Output
238
+ }], deleteMessage: [{
239
+ type: Output
240
+ }], replyTo: [{
241
+ type: Output
242
+ }], messagesListRef: [{
243
+ type: ViewChild,
244
+ args: ['messagesList']
245
+ }] } });
246
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC13aW5kb3cuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL29yZ2FuaXNtcy9jaGF0LXdpbmRvdy9jaGF0LXdpbmRvdy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixNQUFNLEVBQ04sUUFBUSxFQUlSLFNBQVMsR0FHVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx5REFBeUQsQ0FBQztBQUNqRyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpREFBaUQsQ0FBQztBQUNyRixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw2REFBNkQsQ0FBQzs7QUFHdkcsUUFBUSxDQUFDLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO0FBRWpDLE1BQU0sZ0JBQWdCLEdBQUc7SUFDdkIsRUFBRSxFQUFFO1FBQ0Ysa0JBQWtCLEVBQUUsZ0NBQWdDO1FBQ3BELE9BQU8sRUFBRSxzQkFBc0I7UUFDL0IsVUFBVSxFQUFFLHFCQUFxQjtLQUNsQztJQUNELEVBQUUsRUFBRTtRQUNGLGtCQUFrQixFQUFFLDZCQUE2QjtRQUNqRCxPQUFPLEVBQUUscUJBQXFCO1FBQzlCLFVBQVUsRUFBRSxpQkFBaUI7S0FDOUI7Q0FD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Q1MsWUFBWSwrQkFBVyxVQUFVLHlHQUFFLHNCQUFzQix3SkFBRSxrQkFBa0IsMkdBQUUsd0JBQXdCOzs0RkF3Q3RHLG1CQUFtQjtrQkEzQy9CLFNBQVM7K0JBQ0UsaUJBQWlCLGNBQ2YsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsc0JBQXNCLEVBQUUsa0JBQWtCLEVBQUUsd0JBQXdCLENBQUMsWUFDeEc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9DVDt3REFNUSxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFFSSxXQUFXO3NCQUFwQixNQUFNO2dCQUNHLFFBQVE7c0JBQWpCLE1BQU07Z0JBQ0csYUFBYTtzQkFBdEIsTUFBTTtnQkFDRyxhQUFhO3NCQUF0QixNQUFNO2dCQUNHLE9BQU87c0JBQWhCLE1BQU07Z0JBRTRCLGVBQWU7c0JBQWpELFNBQVM7dUJBQUMsY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBpbmplY3QsXG4gIGNvbXB1dGVkLFxuICBzaWduYWwsXG4gIE9uQ2hhbmdlcyxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0NoaWxkLFxuICBFbGVtZW50UmVmLFxuICBBZnRlclZpZXdDaGVja2VkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBJb25JY29uLCBJb25TcGlubmVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXIvc3RhbmRhbG9uZSc7XG5pbXBvcnQgeyBhZGRJY29ucyB9IGZyb20gJ2lvbmljb25zJztcbmltcG9ydCB7IGNoYXRidWJibGVzT3V0bGluZSB9IGZyb20gJ2lvbmljb25zL2ljb25zJztcbmltcG9ydCB7IEkxOG5TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvaTE4bic7XG5pbXBvcnQgeyBNZXNzYWdlQnViYmxlQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vbW9sZWN1bGVzL21lc3NhZ2UtYnViYmxlL21lc3NhZ2UtYnViYmxlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDaGF0SW5wdXRDb21wb25lbnQgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvY2hhdC1pbnB1dC9jaGF0LWlucHV0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUeXBpbmdJbmRpY2F0b3JDb21wb25lbnQgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvdHlwaW5nLWluZGljYXRvci90eXBpbmctaW5kaWNhdG9yLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBNZXNzYWdlQnViYmxlTWV0YWRhdGEsIE1lc3NhZ2VSZWFjdGlvbkNsaWNrRXZlbnQgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvbWVzc2FnZS1idWJibGUvdHlwZXMnO1xuXG5hZGRJY29ucyh7IGNoYXRidWJibGVzT3V0bGluZSB9KTtcblxuY29uc3QgQ0hBVF9XSU5ET1dfSTE4TiA9IHtcbiAgZXM6IHtcbiAgICBjb252ZXJzYXRpb25DbG9zZWQ6ICdFc3RhIGNvbnZlcnNhY2lvbiBlc3RhIGNlcnJhZGEnLFxuICAgIGxvYWRpbmc6ICdDYXJnYW5kbyBtZW5zYWplcy4uLicsXG4gICAgbm9NZXNzYWdlczogJ05vIGhheSBtZW5zYWplcyBhdW4nLFxuICB9LFxuICBlbjoge1xuICAgIGNvbnZlcnNhdGlvbkNsb3NlZDogJ1RoaXMgY29udmVyc2F0aW9uIGlzIGNsb3NlZCcsXG4gICAgbG9hZGluZzogJ0xvYWRpbmcgbWVzc2FnZXMuLi4nLFxuICAgIG5vTWVzc2FnZXM6ICdObyBtZXNzYWdlcyB5ZXQnLFxuICB9LFxufTtcblxuLyoqIEVzdHJ1Y3R1cmEgaW50ZXJuYSBwYXJhIGFncnVwYXIgbWVuc2FqZXMgcG9yIGZlY2hhLiAqL1xuaW50ZXJmYWNlIE1lc3NhZ2VHcm91cCB7XG4gIGRhdGVMYWJlbDogc3RyaW5nO1xuICBtZXNzYWdlczogTWVzc2FnZUJ1YmJsZU1ldGFkYXRhW107XG59XG5cbi8qKlxuICogdmFsLWNoYXQtd2luZG93XG4gKlxuICogVmVudGFuYSBkZSBjaGF0IGNvbXBsZXRhLiBNdWVzdHJhIGxhIGxpc3RhIGRlIG1lbnNhamVzIGFncnVwYWRvcyBwb3IgZmVjaGEsXG4gKiBlbCBpbmRpY2Fkb3IgZGUgZXNjcml0dXJhLCBlbCBpbnB1dCBkZSBtZW5zYWplIChzb2xvIHNpIGlzT3BlbikgeSB1biBiYW5uZXJcbiAqIGN1YW5kbyBsYSBjb252ZXJzYWNpb24gZXN0YSBjZXJyYWRhLiBBdXRvLXNjcm9sbCBhbCB1bHRpbW8gbWVuc2FqZSBjdWFuZG9cbiAqIGxsZWdhbiBtZW5zYWplcyBudWV2b3MuXG4gKlxuICogQGV4YW1wbGVcbiAqIDx2YWwtY2hhdC13aW5kb3dcbiAqICAgW2NvbnZJZF09XCJjb252LmlkXCJcbiAqICAgW21lc3NhZ2VzXT1cIm1lc3NhZ2VzKClcIlxuICogICBbY3VycmVudFVzZXJJZF09XCJ1c2VySWRcIlxuICogICBbaXNPcGVuXT1cImNvbnYuc3RhdHVzID09PSAnb3BlbidcIlxuICogICBbdHlwaW5nVXNlcnNdPVwidHlwaW5nVXNlcnMoKVwiXG4gKiAgIChzZW5kTWVzc2FnZSk9XCJvblNlbmQoJGV2ZW50KVwiXG4gKiAgIChyZWFjdGlvbkNsaWNrKT1cIm9uUmVhY3Rpb24oJGV2ZW50KVwiXG4gKiAvPlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtY2hhdC13aW5kb3cnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBJb25JY29uLCBJb25TcGlubmVyLCBNZXNzYWdlQnViYmxlQ29tcG9uZW50LCBDaGF0SW5wdXRDb21wb25lbnQsIFR5cGluZ0luZGljYXRvckNvbXBvbmVudF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImNoYXQtd2luZG93XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibWVzc2FnZXMtbGlzdFwiICNtZXNzYWdlc0xpc3Q+XG4gICAgICAgIEBpZiAoaXNMb2FkaW5nKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImxvYWRpbmctc3RhdGVcIj5cbiAgICAgICAgICAgIDxpb24tc3Bpbm5lciBuYW1lPVwiZG90c1wiPjwvaW9uLXNwaW5uZXI+XG4gICAgICAgICAgICA8c3Bhbj57eyBsb2FkaW5nVGV4dCgpIH19PC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICBAZm9yIChncm91cCBvZiBtZXNzYWdlR3JvdXBzKCk7IHRyYWNrIGdyb3VwLmRhdGVMYWJlbCkge1xuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtc2VwYXJhdG9yXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLWxpbmVcIj48L2Rpdj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkYXRlLWxhYmVsXCI+e3sgZ3JvdXAuZGF0ZUxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1saW5lXCI+PC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIEBmb3IgKG1zZyBvZiBncm91cC5tZXNzYWdlczsgdHJhY2sgbXNnLm1zZ0lkKSB7XG4gICAgICAgICAgICAgIDx2YWwtbWVzc2FnZS1idWJibGVcbiAgICAgICAgICAgICAgICBbcHJvcHNdPVwibXNnXCJcbiAgICAgICAgICAgICAgICAocmVhY3Rpb25DbGljayk9XCJvblJlYWN0aW9uQ2xpY2soJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgKHJlcGx5Q2xpY2spPVwicmVwbHlUby5lbWl0KCRldmVudC5tc2dJZClcIlxuICAgICAgICAgICAgICAgIChkZWxldGVDbGljayk9XCJkZWxldGVNZXNzYWdlLmVtaXQoJGV2ZW50Lm1zZ0lkKVwiXG4gICAgICAgICAgICAgICAgKGVkaXRDbGljayk9XCJvbkVkaXRDbGljaygkZXZlbnQubXNnSWQpXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8dmFsLXR5cGluZy1pbmRpY2F0b3IgW3R5cGluZ1VzZXJzXT1cInR5cGluZ1VzZXJzXCIgLz5cblxuICAgICAgQGlmICghaXNPcGVuKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjbG9zZWQtYmFubmVyXCI+e3sgY2xvc2VkVGV4dCgpIH19PC9kaXY+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPHZhbC1jaGF0LWlucHV0IFtwcm9wc109XCJ7IGRpc2FibGVkOiBpc0xvYWRpbmcgfVwiIChzZW5kKT1cInNlbmRNZXNzYWdlLmVtaXQoJGV2ZW50KVwiICh0eXBpbmcpPVwib25UeXBpbmcoKVwiIC8+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlVXJsczogWycuL2NoYXQtd2luZG93LmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIENoYXRXaW5kb3dDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0NoZWNrZWQge1xuICBwcm90ZWN0ZWQgaTE4biA9IGluamVjdChJMThuU2VydmljZSk7XG5cbiAgQElucHV0KCkgY29udklkOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KCkgbWVzc2FnZXM6IE1lc3NhZ2VCdWJibGVNZXRhZGF0YVtdID0gW107XG4gIEBJbnB1dCgpIHBhcnRpY2lwYW50czogc3RyaW5nW10gPSBbXTtcbiAgQElucHV0KCkgY3VycmVudFVzZXJJZDogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGlzT3BlbjogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIHR5cGluZ1VzZXJzOiBzdHJpbmdbXSA9IFtdO1xuICBASW5wdXQoKSBpc0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBAT3V0cHV0KCkgc2VuZE1lc3NhZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgQE91dHB1dCgpIGxvYWRNb3JlID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICBAT3V0cHV0KCkgcmVhY3Rpb25DbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8eyBtc2dJZDogc3RyaW5nOyB0b2tlbjogc3RyaW5nIH0+KCk7XG4gIEBPdXRwdXQoKSBkZWxldGVNZXNzYWdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gIEBPdXRwdXQoKSByZXBseVRvID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgQFZpZXdDaGlsZCgnbWVzc2FnZXNMaXN0JykgcHJpdmF0ZSBtZXNzYWdlc0xpc3RSZWY/OiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcblxuICBwcml2YXRlIHByZXZNZXNzYWdlQ291bnQgPSAwO1xuICBwcml2YXRlIHNob3VsZFNjcm9sbFRvQm90dG9tID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5pMThuLnJlZ2lzdGVyRGVmYXVsdHMoJ0NoYXRXaW5kb3cnLCBDSEFUX1dJTkRPV19JMThOKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoY2hhbmdlc1snbWVzc2FnZXMnXSkge1xuICAgICAgY29uc3QgY3VycmVudCA9IChjaGFuZ2VzWydtZXNzYWdlcyddLmN1cnJlbnRWYWx1ZSBhcyBNZXNzYWdlQnViYmxlTWV0YWRhdGFbXSkgPz8gW107XG4gICAgICBpZiAoY3VycmVudC5sZW5ndGggIT09IHRoaXMucHJldk1lc3NhZ2VDb3VudCkge1xuICAgICAgICB0aGlzLnByZXZNZXNzYWdlQ291bnQgPSBjdXJyZW50Lmxlbmd0aDtcbiAgICAgICAgdGhpcy5zaG91bGRTY3JvbGxUb0JvdHRvbSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlclZpZXdDaGVja2VkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNob3VsZFNjcm9sbFRvQm90dG9tKSB7XG4gICAgICB0aGlzLnNjcm9sbFRvQm90dG9tKCk7XG4gICAgICB0aGlzLnNob3VsZFNjcm9sbFRvQm90dG9tID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIG1lc3NhZ2VHcm91cHMgPSBjb21wdXRlZCgoKTogTWVzc2FnZUdyb3VwW10gPT4ge1xuICAgIGNvbnN0IG1zZ3MgPSB0aGlzLm1lc3NhZ2VzID8/IFtdO1xuICAgIGlmIChtc2dzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuXG4gICAgY29uc3QgZ3JvdXBzOiBNZXNzYWdlR3JvdXBbXSA9IFtdO1xuICAgIGxldCBjdXJyZW50TGFiZWwgPSAnJztcbiAgICBsZXQgY3VycmVudEdyb3VwOiBNZXNzYWdlQnViYmxlTWV0YWRhdGFbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBtc2cgb2YgbXNncykge1xuICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLmZvcm1hdERhdGVMYWJlbChtc2cuY3JlYXRlZEF0KTtcbiAgICAgIGlmIChsYWJlbCAhPT0gY3VycmVudExhYmVsKSB7XG4gICAgICAgIGlmIChjdXJyZW50R3JvdXAubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGdyb3Vwcy5wdXNoKHsgZGF0ZUxhYmVsOiBjdXJyZW50TGFiZWwsIG1lc3NhZ2VzOiBjdXJyZW50R3JvdXAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudExhYmVsID0gbGFiZWw7XG4gICAgICAgIGN1cnJlbnRHcm91cCA9IFttc2ddO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3VycmVudEdyb3VwLnB1c2gobXNnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY3VycmVudEdyb3VwLmxlbmd0aCA+IDApIHtcbiAgICAgIGdyb3Vwcy5wdXNoKHsgZGF0ZUxhYmVsOiBjdXJyZW50TGFiZWwsIG1lc3NhZ2VzOiBjdXJyZW50R3JvdXAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGdyb3VwcztcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIGNsb3NlZFRleHQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgdGhpcy5pMThuLmxhbmcoKTtcbiAgICByZXR1cm4gdGhpcy5pMThuLnQoJ2NvbnZlcnNhdGlvbkNsb3NlZCcsICdDaGF0V2luZG93Jyk7XG4gIH0pO1xuXG4gIHByb3RlY3RlZCBsb2FkaW5nVGV4dCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICB0aGlzLmkxOG4ubGFuZygpO1xuICAgIHJldHVybiB0aGlzLmkxOG4udCgnbG9hZGluZycsICdDaGF0V2luZG93Jyk7XG4gIH0pO1xuXG4gIHByb3RlY3RlZCBvblJlYWN0aW9uQ2xpY2soZXZlbnQ6IE1lc3NhZ2VSZWFjdGlvbkNsaWNrRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLnJlYWN0aW9uQ2xpY2suZW1pdCh7IG1zZ0lkOiBldmVudC5tc2dJZCwgdG9rZW46IGV2ZW50LnRva2VuIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRWRpdENsaWNrKF9tc2dJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgLy8gSW1wbGVtZW50YWNpb24gZnV0dXJhOiBlbWl0aXIgZXZlbnRvIGRlIGVkaWNpb25cbiAgfVxuXG4gIHByb3RlY3RlZCBvblR5cGluZygpOiB2b2lkIHtcbiAgICAvLyBFbCBwYWRyZSBwdWVkZSBzdXNjcmliaXJzZSBhbCBvdXRwdXQgdHlwaW5nIHNpIG5lY2VzaXRhIHByb3BhZ2FyIGEgRmlyZXN0b3JlXG4gIH1cblxuICBwcml2YXRlIHNjcm9sbFRvQm90dG9tKCk6IHZvaWQge1xuICAgIGNvbnN0IGVsID0gdGhpcy5tZXNzYWdlc0xpc3RSZWY/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKGVsKSB7XG4gICAgICBlbC5zY3JvbGxUb3AgPSBlbC5zY3JvbGxIZWlnaHQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmb3JtYXREYXRlTGFiZWwoZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gJyc7XG4gICAgY29uc3QgZCA9IGRhdGUgaW5zdGFuY2VvZiBEYXRlID8gZGF0ZSA6IG5ldyBEYXRlKGRhdGUpO1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZShub3cuZ2V0RnVsbFllYXIoKSwgbm93LmdldE1vbnRoKCksIG5vdy5nZXREYXRlKCkpO1xuICAgIGNvbnN0IG1zZ0RheSA9IG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSwgZC5nZXRNb250aCgpLCBkLmdldERhdGUoKSk7XG4gICAgY29uc3QgZGlmZk1zID0gdG9kYXkuZ2V0VGltZSgpIC0gbXNnRGF5LmdldFRpbWUoKTtcbiAgICBjb25zdCBkaWZmRGF5cyA9IE1hdGgucm91bmQoZGlmZk1zIC8gODY0MDAwMDApO1xuXG4gICAgaWYgKGRpZmZEYXlzID09PSAwKSByZXR1cm4gdGhpcy5pMThuLnQoJ3RvZGF5JywgJ19nbG9iYWwnKSB8fCAnSG95JztcbiAgICBpZiAoZGlmZkRheXMgPT09IDEpIHJldHVybiB0aGlzLmkxOG4udCgneWVzdGVyZGF5JywgJ19nbG9iYWwnKSB8fCAnQXllcic7XG4gICAgcmV0dXJuIGQudG9Mb2NhbGVEYXRlU3RyaW5nKFtdLCB7IGRheTogJzItZGlnaXQnLCBtb250aDogJ3Nob3J0JywgeWVhcjogJ251bWVyaWMnIH0pO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvb3JnYW5pc21zL2NoYXQtd2luZG93L3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNZXNzYWdlQnViYmxlTWV0YWRhdGEgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvbWVzc2FnZS1idWJibGUvdHlwZXMnO1xuXG4vKipcbiAqIENvbmZpZ3VyYWNpb24gZGVsIGNvbXBvbmVudGUgZGUgdmVudGFuYSBkZSBjaGF0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENoYXRXaW5kb3dNZXRhZGF0YSB7XG4gIC8qKiBJRCBkZSBsYSBjb252ZXJzYWNpb24uICovXG4gIGNvbnZJZDogc3RyaW5nO1xuICAvKiogTGlzdGEgZGUgbWVuc2FqZXMgYSBtb3N0cmFyLiAqL1xuICBtZXNzYWdlcz86IE1lc3NhZ2VCdWJibGVNZXRhZGF0YVtdO1xuICAvKiogSURzIG8gbm9tYnJlcyBkZSBwYXJ0aWNpcGFudGVzLiAqL1xuICBwYXJ0aWNpcGFudHM/OiBzdHJpbmdbXTtcbiAgLyoqIElEIGRlbCB1c3VhcmlvIGFjdHVhbCAocGFyYSBtYXJjYXIgbWVuc2FqZXMgcHJvcGlvcykuICovXG4gIGN1cnJlbnRVc2VySWQ/OiBzdHJpbmc7XG4gIC8qKiBTaSBsYSBjb252ZXJzYWNpb24gZXN0YSBhYmllcnRhIHBhcmEgZW52aWFyIG1lbnNhamVzLiAqL1xuICBpc09wZW4/OiBib29sZWFuO1xuICAvKiogVXN1YXJpb3MgcXVlIGVzdGFuIGVzY3JpYmllbmRvIGVuIGVzdGUgbW9tZW50by4gKi9cbiAgdHlwaW5nVXNlcnM/OiBzdHJpbmdbXTtcbiAgLyoqIFNpIGVzdGEgY2FyZ2FuZG8gbWVuc2FqZXMuICovXG4gIGlzTG9hZGluZz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogRXZlbnRvIGVtaXRpZG8gYWwgZW52aWFyIHVuIG1lbnNhamUgZGVzZGUgbGEgdmVudGFuYSBkZSBjaGF0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENoYXRXaW5kb3dTZW5kRXZlbnQge1xuICAvKiogQ3VlcnBvIGRlbCBtZW5zYWplLiAqL1xuICBib2R5OiBzdHJpbmc7XG59XG5cbi8qKlxuICogRXZlbnRvIGVtaXRpZG8gYWwgaGFjZXIgY2xpYyBlbiB1bmEgcmVhY2Npb24gZGUgdW4gbWVuc2FqZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaGF0V2luZG93UmVhY3Rpb25FdmVudCB7XG4gIC8qKiBJRCBkZWwgbWVuc2FqZS4gKi9cbiAgbXNnSWQ6IHN0cmluZztcbiAgLyoqIFRva2VuIGRlIGxhIHJlYWNjaW9uLiAqL1xuICB0b2tlbjogc3RyaW5nO1xufVxuIl19
@@ -0,0 +1,211 @@
1
+ import { Component, Input, inject, signal, computed } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { IonSpinner } from '@ionic/angular/standalone';
4
+ import { firstValueFrom } from 'rxjs';
5
+ import { I18nService } from '../../../services/i18n';
6
+ import { ConversationService } from '../../../services/chat/conversation.service';
7
+ import { VALTECH_CHAT_CONFIG } from '../../../services/chat/config';
8
+ import { AuthService } from '../../../services/auth/auth.service';
9
+ import { ChatWindowComponent } from '../chat-window/chat-window.component';
10
+ import * as i0 from "@angular/core";
11
+ const THREAD_PANEL_I18N = {
12
+ es: {
13
+ loading: 'Cargando conversacion...',
14
+ thread: 'Hilo',
15
+ },
16
+ en: {
17
+ loading: 'Loading conversation...',
18
+ thread: 'Thread',
19
+ },
20
+ };
21
+ /**
22
+ * val-thread-panel
23
+ *
24
+ * Panel de hilo de conversacion asociado a una entidad (post, request, etc.).
25
+ * Internamente usa ConversationService.getOrCreateForEntity() para inicializar
26
+ * la conversacion y luego watchMessages() para escuchar en tiempo real.
27
+ * Renderiza val-chat-window con los mensajes ya mapeados.
28
+ *
29
+ * Requiere provideValtechChat() y provideValtechFirebase() en main.ts.
30
+ *
31
+ * @example
32
+ * <val-thread-panel
33
+ * entityType="post"
34
+ * entityId="post-abc123"
35
+ * currentUserId="user-xyz"
36
+ * title="Comentarios"
37
+ * />
38
+ */
39
+ export class ThreadPanelComponent {
40
+ constructor() {
41
+ this.i18n = inject(I18nService);
42
+ this.conversationSvc = inject(ConversationService, { optional: true });
43
+ this.chatConfig = inject(VALTECH_CHAT_CONFIG, { optional: true });
44
+ this.auth = inject(AuthService, { optional: true });
45
+ this.entityType = '';
46
+ this.entityId = '';
47
+ this.currentUserId = '';
48
+ this.loading = signal(true);
49
+ this.conv = signal(null);
50
+ this.messages = signal([]);
51
+ this.typingUsers = signal([]);
52
+ this.isConvOpen = computed(() => this.conv()?.status === 'open');
53
+ this.loadingText = computed(() => {
54
+ this.i18n.lang();
55
+ return this.i18n.t('loading', 'ThreadPanel');
56
+ });
57
+ this.bubbleMessages = computed(() => {
58
+ const uid = this.currentUserId || this.auth?.user()?.userId || '';
59
+ return this.messages().map(msg => ({
60
+ msgId: msg.id,
61
+ senderId: msg.senderId,
62
+ senderName: msg.senderName,
63
+ senderAvatar: msg.senderAvatar,
64
+ body: msg.body,
65
+ type: msg.type,
66
+ createdAt: msg.createdAt,
67
+ isMine: msg.senderId === uid,
68
+ isDeleted: msg.isDeleted,
69
+ isEdited: msg.isEdited,
70
+ replyTo: msg.replyTo,
71
+ attachments: msg.attachments,
72
+ reactions: msg.reactions,
73
+ status: msg.status,
74
+ }));
75
+ });
76
+ this.i18n.registerDefaults('ThreadPanel', THREAD_PANEL_I18N);
77
+ }
78
+ async ngOnInit() {
79
+ if (!this.conversationSvc || !this.entityType || !this.entityId) {
80
+ this.loading.set(false);
81
+ return;
82
+ }
83
+ try {
84
+ const conversation = await firstValueFrom(this.conversationSvc.getOrCreateForEntity(this.entityType, this.entityId));
85
+ this.conv.set(conversation);
86
+ const orgId = this.getOrgId();
87
+ const appId = this.chatConfig?.appId ?? '';
88
+ if (orgId && appId) {
89
+ this.msgSub = this.conversationSvc
90
+ .watchMessages(conversation.id, orgId, appId)
91
+ .subscribe(msgs => this.messages.set(msgs));
92
+ this.typingSub = this.conversationSvc
93
+ .watchTyping(conversation.id, orgId, appId)
94
+ .subscribe(users => this.typingUsers.set(users));
95
+ }
96
+ }
97
+ catch (err) {
98
+ console.error('[ThreadPanel] Error al inicializar conversacion:', err);
99
+ }
100
+ finally {
101
+ this.loading.set(false);
102
+ }
103
+ }
104
+ ngOnDestroy() {
105
+ this.msgSub?.unsubscribe();
106
+ this.typingSub?.unsubscribe();
107
+ const conv = this.conv();
108
+ const orgId = this.getOrgId();
109
+ const appId = this.chatConfig?.appId ?? '';
110
+ if (conv && orgId && appId && this.conversationSvc) {
111
+ this.conversationSvc.stopTyping(conv.id, orgId, appId);
112
+ }
113
+ }
114
+ onSend(body) {
115
+ const conv = this.conv();
116
+ if (!conv || !this.conversationSvc)
117
+ return;
118
+ this.conversationSvc.sendMessage(conv.id, body).subscribe();
119
+ }
120
+ onReactionClick(event) {
121
+ // Reacciones se implementan a nivel de app consumer
122
+ console.debug('[ThreadPanel] reactionClick', event);
123
+ }
124
+ onDeleteMessage(msgId) {
125
+ const conv = this.conv();
126
+ if (!conv || !this.conversationSvc)
127
+ return;
128
+ this.conversationSvc.deleteMessage(conv.id, msgId).subscribe();
129
+ }
130
+ onReplyTo(_msgId) {
131
+ // Implementacion futura: seleccionar mensaje de respuesta
132
+ }
133
+ getOrgId() {
134
+ return this.auth?.user()?.activeOrg ?? '';
135
+ }
136
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThreadPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
137
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ThreadPanelComponent, isStandalone: true, selector: "val-thread-panel", inputs: { entityType: "entityType", entityId: "entityId", currentUserId: "currentUserId", title: "title" }, ngImport: i0, template: `
138
+ <div class="thread-panel">
139
+ @if (title) {
140
+ <div class="thread-header">
141
+ <p class="thread-title">{{ title }}</p>
142
+ </div>
143
+ }
144
+
145
+ @if (loading()) {
146
+ <div class="thread-loading">
147
+ <ion-spinner name="dots"></ion-spinner>
148
+ <span>{{ loadingText() }}</span>
149
+ </div>
150
+ } @else {
151
+ <div class="thread-chat">
152
+ <val-chat-window
153
+ [convId]="conv()?.id ?? ''"
154
+ [messages]="bubbleMessages()"
155
+ [currentUserId]="currentUserId"
156
+ [isOpen]="isConvOpen()"
157
+ [typingUsers]="typingUsers()"
158
+ [isLoading]="false"
159
+ (sendMessage)="onSend($event)"
160
+ (reactionClick)="onReactionClick($event)"
161
+ (deleteMessage)="onDeleteMessage($event)"
162
+ (replyTo)="onReplyTo($event)"
163
+ />
164
+ </div>
165
+ }
166
+ </div>
167
+ `, isInline: true, styles: [".thread-panel{display:flex;flex-direction:column;height:100%;background:var(--ion-background-color, #f4f5f8)}.thread-header{padding:12px 16px;border-bottom:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff))}.thread-header .thread-title{font-size:1rem;font-weight:600;color:var(--ion-text-color, #000);margin:0}.thread-loading{display:flex;align-items:center;justify-content:center;flex:1;gap:10px;color:var(--ion-color-medium, #92949c);font-size:.875rem}.thread-chat{flex:1;overflow:hidden;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: ChatWindowComponent, selector: "val-chat-window", inputs: ["convId", "messages", "participants", "currentUserId", "isOpen", "typingUsers", "isLoading"], outputs: ["sendMessage", "loadMore", "reactionClick", "deleteMessage", "replyTo"] }] }); }
168
+ }
169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThreadPanelComponent, decorators: [{
170
+ type: Component,
171
+ args: [{ selector: 'val-thread-panel', standalone: true, imports: [CommonModule, IonSpinner, ChatWindowComponent], template: `
172
+ <div class="thread-panel">
173
+ @if (title) {
174
+ <div class="thread-header">
175
+ <p class="thread-title">{{ title }}</p>
176
+ </div>
177
+ }
178
+
179
+ @if (loading()) {
180
+ <div class="thread-loading">
181
+ <ion-spinner name="dots"></ion-spinner>
182
+ <span>{{ loadingText() }}</span>
183
+ </div>
184
+ } @else {
185
+ <div class="thread-chat">
186
+ <val-chat-window
187
+ [convId]="conv()?.id ?? ''"
188
+ [messages]="bubbleMessages()"
189
+ [currentUserId]="currentUserId"
190
+ [isOpen]="isConvOpen()"
191
+ [typingUsers]="typingUsers()"
192
+ [isLoading]="false"
193
+ (sendMessage)="onSend($event)"
194
+ (reactionClick)="onReactionClick($event)"
195
+ (deleteMessage)="onDeleteMessage($event)"
196
+ (replyTo)="onReplyTo($event)"
197
+ />
198
+ </div>
199
+ }
200
+ </div>
201
+ `, styles: [".thread-panel{display:flex;flex-direction:column;height:100%;background:var(--ion-background-color, #f4f5f8)}.thread-header{padding:12px 16px;border-bottom:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff))}.thread-header .thread-title{font-size:1rem;font-weight:600;color:var(--ion-text-color, #000);margin:0}.thread-loading{display:flex;align-items:center;justify-content:center;flex:1;gap:10px;color:var(--ion-color-medium, #92949c);font-size:.875rem}.thread-chat{flex:1;overflow:hidden;display:flex;flex-direction:column}\n"] }]
202
+ }], ctorParameters: () => [], propDecorators: { entityType: [{
203
+ type: Input
204
+ }], entityId: [{
205
+ type: Input
206
+ }], currentUserId: [{
207
+ type: Input
208
+ }], title: [{
209
+ type: Input
210
+ }] } });
211
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhyZWFkLXBhbmVsLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9vcmdhbmlzbXMvdGhyZWFkLXBhbmVsL3RocmVhZC1wYW5lbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkQsT0FBTyxFQUFnQixjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUdsRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQzs7QUFFM0UsTUFBTSxpQkFBaUIsR0FBRztJQUN4QixFQUFFLEVBQUU7UUFDRixPQUFPLEVBQUUsMEJBQTBCO1FBQ25DLE1BQU0sRUFBRSxNQUFNO0tBQ2Y7SUFDRCxFQUFFLEVBQUU7UUFDRixPQUFPLEVBQUUseUJBQXlCO1FBQ2xDLE1BQU0sRUFBRSxRQUFRO0tBQ2pCO0NBQ0YsQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQXNDSCxNQUFNLE9BQU8sb0JBQW9CO0lBbUIvQjtRQWxCVSxTQUFJLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzdCLG9CQUFlLEdBQUcsTUFB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LElBQUksRUFBRSxDQUFDO0lBQzVDLENBQUM7K0dBcEhVLG9CQUFvQjttR0FBcEIsb0JBQW9CLHdMQWpDckI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThCVCxtcUJBL0JTLFlBQVksK0JBQUUsVUFBVSx5R0FBRSxtQkFBbUI7OzRGQWtDNUMsb0JBQW9CO2tCQXJDaEMsU0FBUzsrQkFDRSxrQkFBa0IsY0FDaEIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFVBQVUsRUFBRSxtQkFBbUIsQ0FBQyxZQUM5Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEJUO3dEQVNRLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCwgT25EZXN0cm95LCBpbmplY3QsIHNpZ25hbCwgY29tcHV0ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBJb25TcGlubmVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXIvc3RhbmRhbG9uZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24sIGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBJMThuU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2kxOG4nO1xuaW1wb3J0IHsgQ29udmVyc2F0aW9uU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2NoYXQvY29udmVyc2F0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgVkFMVEVDSF9DSEFUX0NPTkZJRyB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2NoYXQvY29uZmlnJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvYXV0aC9hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ29udmVyc2F0aW9uLCBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvY2hhdC90eXBlcyc7XG5pbXBvcnQgeyBNZXNzYWdlQnViYmxlTWV0YWRhdGEgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvbWVzc2FnZS1idWJibGUvdHlwZXMnO1xuaW1wb3J0IHsgQ2hhdFdpbmRvd0NvbXBvbmVudCB9IGZyb20gJy4uL2NoYXQtd2luZG93L2NoYXQtd2luZG93LmNvbXBvbmVudCc7XG5cbmNvbnN0IFRIUkVBRF9QQU5FTF9JMThOID0ge1xuICBlczoge1xuICAgIGxvYWRpbmc6ICdDYXJnYW5kbyBjb252ZXJzYWNpb24uLi4nLFxuICAgIHRocmVhZDogJ0hpbG8nLFxuICB9LFxuICBlbjoge1xuICAgIGxvYWRpbmc6ICdMb2FkaW5nIGNvbnZlcnNhdGlvbi4uLicsXG4gICAgdGhyZWFkOiAnVGhyZWFkJyxcbiAgfSxcbn07XG5cbi8qKlxuICogdmFsLXRocmVhZC1wYW5lbFxuICpcbiAqIFBhbmVsIGRlIGhpbG8gZGUgY29udmVyc2FjaW9uIGFzb2NpYWRvIGEgdW5hIGVudGlkYWQgKHBvc3QsIHJlcXVlc3QsIGV0Yy4pLlxuICogSW50ZXJuYW1lbnRlIHVzYSBDb252ZXJzYXRpb25TZXJ2aWNlLmdldE9yQ3JlYXRlRm9yRW50aXR5KCkgcGFyYSBpbmljaWFsaXphclxuICogbGEgY29udmVyc2FjaW9uIHkgbHVlZ28gd2F0Y2hNZXNzYWdlcygpIHBhcmEgZXNjdWNoYXIgZW4gdGllbXBvIHJlYWwuXG4gKiBSZW5kZXJpemEgdmFsLWNoYXQtd2luZG93IGNvbiBsb3MgbWVuc2FqZXMgeWEgbWFwZWFkb3MuXG4gKlxuICogUmVxdWllcmUgcHJvdmlkZVZhbHRlY2hDaGF0KCkgeSBwcm92aWRlVmFsdGVjaEZpcmViYXNlKCkgZW4gbWFpbi50cy5cbiAqXG4gKiBAZXhhbXBsZVxuICogPHZhbC10aHJlYWQtcGFuZWxcbiAqICAgZW50aXR5VHlwZT1cInBvc3RcIlxuICogICBlbnRpdHlJZD1cInBvc3QtYWJjMTIzXCJcbiAqICAgY3VycmVudFVzZXJJZD1cInVzZXIteHl6XCJcbiAqICAgdGl0bGU9XCJDb21lbnRhcmlvc1wiXG4gKiAvPlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtdGhyZWFkLXBhbmVsJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgSW9uU3Bpbm5lciwgQ2hhdFdpbmRvd0NvbXBvbmVudF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cInRocmVhZC1wYW5lbFwiPlxuICAgICAgQGlmICh0aXRsZSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidGhyZWFkLWhlYWRlclwiPlxuICAgICAgICAgIDxwIGNsYXNzPVwidGhyZWFkLXRpdGxlXCI+e3sgdGl0bGUgfX08L3A+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuXG4gICAgICBAaWYgKGxvYWRpbmcoKSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidGhyZWFkLWxvYWRpbmdcIj5cbiAgICAgICAgICA8aW9uLXNwaW5uZXIgbmFtZT1cImRvdHNcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICAgIDxzcGFuPnt7IGxvYWRpbmdUZXh0KCkgfX08L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0aHJlYWQtY2hhdFwiPlxuICAgICAgICAgIDx2YWwtY2hhdC13aW5kb3dcbiAgICAgICAgICAgIFtjb252SWRdPVwiY29udigpPy5pZCA/PyAnJ1wiXG4gICAgICAgICAgICBbbWVzc2FnZXNdPVwiYnViYmxlTWVzc2FnZXMoKVwiXG4gICAgICAgICAgICBbY3VycmVudFVzZXJJZF09XCJjdXJyZW50VXNlcklkXCJcbiAgICAgICAgICAgIFtpc09wZW5dPVwiaXNDb252T3BlbigpXCJcbiAgICAgICAgICAgIFt0eXBpbmdVc2Vyc109XCJ0eXBpbmdVc2VycygpXCJcbiAgICAgICAgICAgIFtpc0xvYWRpbmddPVwiZmFsc2VcIlxuICAgICAgICAgICAgKHNlbmRNZXNzYWdlKT1cIm9uU2VuZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChyZWFjdGlvbkNsaWNrKT1cIm9uUmVhY3Rpb25DbGljaygkZXZlbnQpXCJcbiAgICAgICAgICAgIChkZWxldGVNZXNzYWdlKT1cIm9uRGVsZXRlTWVzc2FnZSgkZXZlbnQpXCJcbiAgICAgICAgICAgIChyZXBseVRvKT1cIm9uUmVwbHlUbygkZXZlbnQpXCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJy4vdGhyZWFkLXBhbmVsLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIFRocmVhZFBhbmVsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBwcm90ZWN0ZWQgaTE4biA9IGluamVjdChJMThuU2VydmljZSk7XG4gIHByaXZhdGUgY29udmVyc2F0aW9uU3ZjID0gaW5qZWN0KENvbnZlcnNhdGlvblNlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG4gIHByaXZhdGUgY2hhdENvbmZpZyA9IGluamVjdChWQUxURUNIX0NIQVRfQ09ORklHLCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuICBwcml2YXRlIGF1dGggPSBpbmplY3QoQXV0aFNlcnZpY2UsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgQElucHV0KCkgZW50aXR5VHlwZTogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGVudGl0eUlkOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KCkgY3VycmVudFVzZXJJZDogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIHRpdGxlPzogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCBsb2FkaW5nID0gc2lnbmFsKHRydWUpO1xuICBwcm90ZWN0ZWQgY29udiA9IHNpZ25hbDxDb252ZXJzYXRpb24gfCBudWxsPihudWxsKTtcbiAgcHJvdGVjdGVkIG1lc3NhZ2VzID0gc2lnbmFsPE1lc3NhZ2VbXT4oW10pO1xuICBwcm90ZWN0ZWQgdHlwaW5nVXNlcnMgPSBzaWduYWw8c3RyaW5nW10+KFtdKTtcblxuICBwcml2YXRlIG1zZ1N1Yj86IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSB0eXBpbmdTdWI/OiBTdWJzY3JpcHRpb247XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5pMThuLnJlZ2lzdGVyRGVmYXVsdHMoJ1RocmVhZFBhbmVsJywgVEhSRUFEX1BBTkVMX0kxOE4pO1xuICB9XG5cbiAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLmNvbnZlcnNhdGlvblN2YyB8fCAhdGhpcy5lbnRpdHlUeXBlIHx8ICF0aGlzLmVudGl0eUlkKSB7XG4gICAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgY29udmVyc2F0aW9uID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oXG4gICAgICAgIHRoaXMuY29udmVyc2F0aW9uU3ZjLmdldE9yQ3JlYXRlRm9yRW50aXR5KHRoaXMuZW50aXR5VHlwZSwgdGhpcy5lbnRpdHlJZClcbiAgICAgICk7XG4gICAgICB0aGlzLmNvbnYuc2V0KGNvbnZlcnNhdGlvbik7XG5cbiAgICAgIGNvbnN0IG9yZ0lkID0gdGhpcy5nZXRPcmdJZCgpO1xuICAgICAgY29uc3QgYXBwSWQgPSB0aGlzLmNoYXRDb25maWc/LmFwcElkID8/ICcnO1xuXG4gICAgICBpZiAob3JnSWQgJiYgYXBwSWQpIHtcbiAgICAgICAgdGhpcy5tc2dTdWIgPSB0aGlzLmNvbnZlcnNhdGlvblN2Y1xuICAgICAgICAgIC53YXRjaE1lc3NhZ2VzKGNvbnZlcnNhdGlvbi5pZCwgb3JnSWQsIGFwcElkKVxuICAgICAgICAgIC5zdWJzY3JpYmUobXNncyA9PiB0aGlzLm1lc3NhZ2VzLnNldChtc2dzKSk7XG5cbiAgICAgICAgdGhpcy50eXBpbmdTdWIgPSB0aGlzLmNvbnZlcnNhdGlvblN2Y1xuICAgICAgICAgIC53YXRjaFR5cGluZyhjb252ZXJzYXRpb24uaWQsIG9yZ0lkLCBhcHBJZClcbiAgICAgICAgICAuc3Vic2NyaWJlKHVzZXJzID0+IHRoaXMudHlwaW5nVXNlcnMuc2V0KHVzZXJzKSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdbVGhyZWFkUGFuZWxdIEVycm9yIGFsIGluaWNpYWxpemFyIGNvbnZlcnNhY2lvbjonLCBlcnIpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLm1zZ1N1Yj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnR5cGluZ1N1Yj8udW5zdWJzY3JpYmUoKTtcblxuICAgIGNvbnN0IGNvbnYgPSB0aGlzLmNvbnYoKTtcbiAgICBjb25zdCBvcmdJZCA9IHRoaXMuZ2V0T3JnSWQoKTtcbiAgICBjb25zdCBhcHBJZCA9IHRoaXMuY2hhdENvbmZpZz8uYXBwSWQgPz8gJyc7XG4gICAgaWYgKGNvbnYgJiYgb3JnSWQgJiYgYXBwSWQgJiYgdGhpcy5jb252ZXJzYXRpb25TdmMpIHtcbiAgICAgIHRoaXMuY29udmVyc2F0aW9uU3ZjLnN0b3BUeXBpbmcoY29udi5pZCwgb3JnSWQsIGFwcElkKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgaXNDb252T3BlbiA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY29udigpPy5zdGF0dXMgPT09ICdvcGVuJyk7XG5cbiAgcHJvdGVjdGVkIGxvYWRpbmdUZXh0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIHRoaXMuaTE4bi5sYW5nKCk7XG4gICAgcmV0dXJuIHRoaXMuaTE4bi50KCdsb2FkaW5nJywgJ1RocmVhZFBhbmVsJyk7XG4gIH0pO1xuXG4gIHByb3RlY3RlZCBidWJibGVNZXNzYWdlcyA9IGNvbXB1dGVkKCgpOiBNZXNzYWdlQnViYmxlTWV0YWRhdGFbXSA9PiB7XG4gICAgY29uc3QgdWlkID0gdGhpcy5jdXJyZW50VXNlcklkIHx8IHRoaXMuYXV0aD8udXNlcigpPy51c2VySWQgfHwgJyc7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMoKS5tYXAobXNnID0+ICh7XG4gICAgICBtc2dJZDogbXNnLmlkLFxuICAgICAgc2VuZGVySWQ6IG1zZy5zZW5kZXJJZCxcbiAgICAgIHNlbmRlck5hbWU6IG1zZy5zZW5kZXJOYW1lLFxuICAgICAgc2VuZGVyQXZhdGFyOiBtc2cuc2VuZGVyQXZhdGFyLFxuICAgICAgYm9keTogbXNnLmJvZHksXG4gICAgICB0eXBlOiBtc2cudHlwZSxcbiAgICAgIGNyZWF0ZWRBdDogbXNnLmNyZWF0ZWRBdCxcbiAgICAgIGlzTWluZTogbXNnLnNlbmRlcklkID09PSB1aWQsXG4gICAgICBpc0RlbGV0ZWQ6IG1zZy5pc0RlbGV0ZWQsXG4gICAgICBpc0VkaXRlZDogbXNnLmlzRWRpdGVkLFxuICAgICAgcmVwbHlUbzogbXNnLnJlcGx5VG8sXG4gICAgICBhdHRhY2htZW50czogbXNnLmF0dGFjaG1lbnRzLFxuICAgICAgcmVhY3Rpb25zOiBtc2cucmVhY3Rpb25zLFxuICAgICAgc3RhdHVzOiBtc2cuc3RhdHVzLFxuICAgIH0pKTtcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIG9uU2VuZChib2R5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjb252ID0gdGhpcy5jb252KCk7XG4gICAgaWYgKCFjb252IHx8ICF0aGlzLmNvbnZlcnNhdGlvblN2YykgcmV0dXJuO1xuICAgIHRoaXMuY29udmVyc2F0aW9uU3ZjLnNlbmRNZXNzYWdlKGNvbnYuaWQsIGJvZHkpLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uUmVhY3Rpb25DbGljayhldmVudDogeyBtc2dJZDogc3RyaW5nOyB0b2tlbjogc3RyaW5nIH0pOiB2b2lkIHtcbiAgICAvLyBSZWFjY2lvbmVzIHNlIGltcGxlbWVudGFuIGEgbml2ZWwgZGUgYXBwIGNvbnN1bWVyXG4gICAgY29uc29sZS5kZWJ1ZygnW1RocmVhZFBhbmVsXSByZWFjdGlvbkNsaWNrJywgZXZlbnQpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9uRGVsZXRlTWVzc2FnZShtc2dJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29udiA9IHRoaXMuY29udigpO1xuICAgIGlmICghY29udiB8fCAhdGhpcy5jb252ZXJzYXRpb25TdmMpIHJldHVybjtcbiAgICB0aGlzLmNvbnZlcnNhdGlvblN2Yy5kZWxldGVNZXNzYWdlKGNvbnYuaWQsIG1zZ0lkKS5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblJlcGx5VG8oX21zZ0lkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBJbXBsZW1lbnRhY2lvbiBmdXR1cmE6IHNlbGVjY2lvbmFyIG1lbnNhamUgZGUgcmVzcHVlc3RhXG4gIH1cblxuICBwcml2YXRlIGdldE9yZ0lkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aD8udXNlcigpPy5hY3RpdmVPcmcgPz8gJyc7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,35 @@
1
+ import { InjectionToken, makeEnvironmentProviders } from '@angular/core';
2
+ /**
3
+ * Token de inyeccion para la configuracion del Chat.
4
+ */
5
+ export const VALTECH_CHAT_CONFIG = new InjectionToken('ValtechChatConfig');
6
+ /**
7
+ * Configuracion por defecto del Chat.
8
+ */
9
+ export const DEFAULT_CHAT_CONFIG = {
10
+ chatPrefix: '/v2/chat',
11
+ };
12
+ /**
13
+ * Provee el servicio de Chat a la aplicacion Angular.
14
+ *
15
+ * @example
16
+ * // main.ts
17
+ * import { provideValtechChat } from 'valtech-components';
18
+ *
19
+ * bootstrapApplication(AppComponent, {
20
+ * providers: [
21
+ * provideValtechChat({
22
+ * apiUrl: environment.apiUrl,
23
+ * appId: 'showcase',
24
+ * }),
25
+ * ],
26
+ * });
27
+ */
28
+ export function provideValtechChat(config) {
29
+ const mergedConfig = {
30
+ ...DEFAULT_CHAT_CONFIG,
31
+ ...config,
32
+ };
33
+ return makeEnvironmentProviders([{ provide: VALTECH_CHAT_CONFIG, useValue: mergedConfig }]);
34
+ }
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9jaGF0L2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXdCLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQWMvRjs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLElBQUksY0FBYyxDQUFvQixtQkFBbUIsQ0FBQyxDQUFDO0FBRTlGOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQStCO0lBQzdELFVBQVUsRUFBRSxVQUFVO0NBQ3ZCLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsTUFBeUI7SUFDMUQsTUFBTSxZQUFZLEdBQXNCO1FBQ3RDLEdBQUcsbUJBQW1CO1FBQ3RCLEdBQUcsTUFBTTtLQUNWLENBQUM7SUFFRixPQUFPLHdCQUF3QixDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztBQUM5RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRW52aXJvbm1lbnRQcm92aWRlcnMsIEluamVjdGlvblRva2VuLCBtYWtlRW52aXJvbm1lbnRQcm92aWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLyoqXG4gKiBDb25maWd1cmFjaW9uIGRlbCBzZXJ2aWNpbyBkZSBDaGF0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFZhbHRlY2hDaGF0Q29uZmlnIHtcbiAgLyoqIFVSTCBiYXNlIGRlIGxhIEFQSSBkZWwgYmFja2VuZCAoZWo6ICdodHRwczovL2FwaS5teXZhbHRlY2guY29tJykuICovXG4gIGFwaVVybDogc3RyaW5nO1xuICAvKiogSUQgZGUgbGEgYXBsaWNhY2lvbiAoZWo6ICdzaG93Y2FzZScpLiAqL1xuICBhcHBJZDogc3RyaW5nO1xuICAvKiogUHJlZmlqbyBkZWwgZW5kcG9pbnQgZGUgY2hhdCAoZGVmYXVsdDogJy92Mi9jaGF0JykuICovXG4gIGNoYXRQcmVmaXg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVG9rZW4gZGUgaW55ZWNjaW9uIHBhcmEgbGEgY29uZmlndXJhY2lvbiBkZWwgQ2hhdC5cbiAqL1xuZXhwb3J0IGNvbnN0IFZBTFRFQ0hfQ0hBVF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48VmFsdGVjaENoYXRDb25maWc+KCdWYWx0ZWNoQ2hhdENvbmZpZycpO1xuXG4vKipcbiAqIENvbmZpZ3VyYWNpb24gcG9yIGRlZmVjdG8gZGVsIENoYXQuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0NIQVRfQ09ORklHOiBQYXJ0aWFsPFZhbHRlY2hDaGF0Q29uZmlnPiA9IHtcbiAgY2hhdFByZWZpeDogJy92Mi9jaGF0Jyxcbn07XG5cbi8qKlxuICogUHJvdmVlIGVsIHNlcnZpY2lvIGRlIENoYXQgYSBsYSBhcGxpY2FjaW9uIEFuZ3VsYXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIG1haW4udHNcbiAqIGltcG9ydCB7IHByb3ZpZGVWYWx0ZWNoQ2hhdCB9IGZyb20gJ3ZhbHRlY2gtY29tcG9uZW50cyc7XG4gKlxuICogYm9vdHN0cmFwQXBwbGljYXRpb24oQXBwQ29tcG9uZW50LCB7XG4gKiAgIHByb3ZpZGVyczogW1xuICogICAgIHByb3ZpZGVWYWx0ZWNoQ2hhdCh7XG4gKiAgICAgICBhcGlVcmw6IGVudmlyb25tZW50LmFwaVVybCxcbiAqICAgICAgIGFwcElkOiAnc2hvd2Nhc2UnLFxuICogICAgIH0pLFxuICogICBdLFxuICogfSk7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlVmFsdGVjaENoYXQoY29uZmlnOiBWYWx0ZWNoQ2hhdENvbmZpZyk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAgY29uc3QgbWVyZ2VkQ29uZmlnOiBWYWx0ZWNoQ2hhdENvbmZpZyA9IHtcbiAgICAuLi5ERUZBVUxUX0NIQVRfQ09ORklHLFxuICAgIC4uLmNvbmZpZyxcbiAgfTtcblxuICByZXR1cm4gbWFrZUVudmlyb25tZW50UHJvdmlkZXJzKFt7IHByb3ZpZGU6IFZBTFRFQ0hfQ0hBVF9DT05GSUcsIHVzZVZhbHVlOiBtZXJnZWRDb25maWcgfV0pO1xufVxuIl19