valtech-components 4.0.228 → 4.0.230

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 (28) hide show
  1. package/esm2022/lib/components/molecules/chat-composer/chat-composer.component.mjs +431 -0
  2. package/esm2022/lib/components/molecules/chat-input/chat-input.component.mjs +1 -9
  3. package/esm2022/lib/components/molecules/conversation-list-item/conversation-list-item.component.mjs +108 -0
  4. package/esm2022/lib/components/molecules/message-bubble/message-bubble.component.mjs +274 -191
  5. package/esm2022/lib/components/molecules/typing-indicator/typing-indicator.component.mjs +11 -12
  6. package/esm2022/lib/components/organisms/chat-window/chat-window.component.mjs +213 -203
  7. package/esm2022/lib/components/organisms/thread-panel/thread-panel.component.mjs +13 -11
  8. package/esm2022/lib/services/chat/conversation.service.mjs +37 -14
  9. package/esm2022/lib/services/chat/types.mjs +1 -1
  10. package/esm2022/lib/services/i18n/default-content.mjs +5 -1
  11. package/esm2022/lib/shared/utils/datetime.mjs +54 -1
  12. package/esm2022/lib/version.mjs +2 -2
  13. package/esm2022/public-api.mjs +4 -2
  14. package/fesm2022/valtech-components.mjs +1120 -429
  15. package/fesm2022/valtech-components.mjs.map +1 -1
  16. package/lib/components/molecules/chat-composer/chat-composer.component.d.ts +75 -0
  17. package/lib/components/molecules/conversation-list-item/conversation-list-item.component.d.ts +30 -0
  18. package/lib/components/molecules/message-bubble/message-bubble.component.d.ts +34 -32
  19. package/lib/components/molecules/typing-indicator/typing-indicator.component.d.ts +5 -4
  20. package/lib/components/organisms/chat-window/chat-window.component.d.ts +52 -56
  21. package/lib/components/organisms/thread-panel/thread-panel.component.d.ts +4 -1
  22. package/lib/services/chat/conversation.service.d.ts +12 -5
  23. package/lib/services/chat/types.d.ts +86 -52
  24. package/lib/shared/utils/datetime.d.ts +19 -0
  25. package/lib/version.d.ts +1 -1
  26. package/package.json +1 -1
  27. package/public-api.d.ts +3 -1
  28. package/src/lib/services/firebase/firebase-messaging-sw.js +70 -125
@@ -0,0 +1,108 @@
1
+ import { Component, computed, inject, input, output } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { I18nService } from '../../../services/i18n';
4
+ import { formatRelativeTime } from '../../../shared/utils/datetime';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * val-conversation-list-item — fila de lista de conversaciones estilo
8
+ * Telegram/WhatsApp: avatar (imagen o iniciales), nombre + hora relativa,
9
+ * preview del último mensaje + badge de no-leídos. Signal inputs, dark-safe.
10
+ *
11
+ * @example
12
+ * <val-conversation-list-item
13
+ * [name]="conv.name"
14
+ * [lastMessage]="conv.lastMsgPreview"
15
+ * [timestamp]="conv.lastMsgAt"
16
+ * [unreadCount]="conv.unread"
17
+ * (select)="open(conv.convId)" />
18
+ */
19
+ export class ConversationListItemComponent {
20
+ constructor() {
21
+ this.i18n = inject(I18nService);
22
+ this.name = input('');
23
+ this.avatarUrl = input(undefined);
24
+ this.lastMessage = input('');
25
+ this.timestamp = input(undefined);
26
+ this.unreadCount = input(0);
27
+ this.locale = input('es-CL');
28
+ this.select = output();
29
+ this.initials = computed(() => {
30
+ const name = this.name().trim();
31
+ if (!name)
32
+ return '?';
33
+ const parts = name.split(/\s+/);
34
+ return (parts[0][0] + (parts[1]?.[0] ?? '')).toUpperCase();
35
+ });
36
+ this.timeLabel = computed(() => formatRelativeTime(this.timestamp(), this.locale(), {
37
+ today: '',
38
+ yesterday: this.i18n.t('yesterday', '_global'),
39
+ }));
40
+ this.i18n.registerDefaults('ConversationListItem', {
41
+ es: { empty: 'Sin mensajes' },
42
+ en: { empty: 'No messages' },
43
+ });
44
+ }
45
+ emptyText() {
46
+ this.i18n.lang();
47
+ return this.i18n.t('empty', 'ConversationListItem');
48
+ }
49
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConversationListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
50
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ConversationListItemComponent, isStandalone: true, selector: "val-conversation-list-item", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, avatarUrl: { classPropertyName: "avatarUrl", publicName: "avatarUrl", isSignal: true, isRequired: false, transformFunction: null }, lastMessage: { classPropertyName: "lastMessage", publicName: "lastMessage", isSignal: true, isRequired: false, transformFunction: null }, timestamp: { classPropertyName: "timestamp", publicName: "timestamp", isSignal: true, isRequired: false, transformFunction: null }, unreadCount: { classPropertyName: "unreadCount", publicName: "unreadCount", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { select: "select" }, ngImport: i0, template: `
51
+ <button class="item" (click)="select.emit()">
52
+ <div class="avatar">
53
+ @if (avatarUrl()) {
54
+ <img [src]="avatarUrl()" [alt]="name()" />
55
+ } @else {
56
+ <span>{{ initials() }}</span>
57
+ }
58
+ </div>
59
+ <div class="content">
60
+ <div class="top">
61
+ <span class="name">{{ name() }}</span>
62
+ @if (timeLabel()) {
63
+ <span class="time" [class.unread]="unreadCount() > 0">{{ timeLabel() }}</span>
64
+ }
65
+ </div>
66
+ <div class="bottom">
67
+ <span class="preview" [class.muted]="!lastMessage()">
68
+ {{ lastMessage() || emptyText() }}
69
+ </span>
70
+ @if (unreadCount() > 0) {
71
+ <span class="badge">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</span>
72
+ }
73
+ </div>
74
+ </div>
75
+ </button>
76
+ `, isInline: true, styles: [":host{display:block}.item{display:flex;align-items:center;gap:12px;width:100%;padding:10px 12px;border:none;background:transparent;cursor:pointer;text-align:left;border-radius:12px;transition:background .12s ease}.item:hover{background:var(--ion-color-step-50, rgba(127, 127, 127, .06))}.avatar{width:48px;height:48px;flex-shrink:0;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:var(--ion-color-primary);color:#fff;font-weight:700;font-size:1rem}.avatar img{width:100%;height:100%;object-fit:cover}.content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.top,.bottom{display:flex;align-items:center;gap:8px}.name{flex:1;min-width:0;font-weight:600;font-size:.9375rem;color:var(--ion-text-color, #000);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.time{flex-shrink:0;font-size:.75rem;color:var(--ion-color-medium, #92949c)}.time.unread{color:var(--ion-color-primary);font-weight:600}.preview{flex:1;min-width:0;font-size:.875rem;color:var(--ion-color-medium, #92949c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preview.muted{font-style:italic;opacity:.7}.badge{flex-shrink:0;min-width:20px;height:20px;padding:0 6px;border-radius:10px;background:var(--ion-color-primary);color:var(--ion-color-primary-contrast, #fff);font-size:.6875rem;font-weight:700;display:inline-flex;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
77
+ }
78
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ConversationListItemComponent, decorators: [{
79
+ type: Component,
80
+ args: [{ selector: 'val-conversation-list-item', standalone: true, imports: [CommonModule], template: `
81
+ <button class="item" (click)="select.emit()">
82
+ <div class="avatar">
83
+ @if (avatarUrl()) {
84
+ <img [src]="avatarUrl()" [alt]="name()" />
85
+ } @else {
86
+ <span>{{ initials() }}</span>
87
+ }
88
+ </div>
89
+ <div class="content">
90
+ <div class="top">
91
+ <span class="name">{{ name() }}</span>
92
+ @if (timeLabel()) {
93
+ <span class="time" [class.unread]="unreadCount() > 0">{{ timeLabel() }}</span>
94
+ }
95
+ </div>
96
+ <div class="bottom">
97
+ <span class="preview" [class.muted]="!lastMessage()">
98
+ {{ lastMessage() || emptyText() }}
99
+ </span>
100
+ @if (unreadCount() > 0) {
101
+ <span class="badge">{{ unreadCount() > 99 ? '99+' : unreadCount() }}</span>
102
+ }
103
+ </div>
104
+ </div>
105
+ </button>
106
+ `, styles: [":host{display:block}.item{display:flex;align-items:center;gap:12px;width:100%;padding:10px 12px;border:none;background:transparent;cursor:pointer;text-align:left;border-radius:12px;transition:background .12s ease}.item:hover{background:var(--ion-color-step-50, rgba(127, 127, 127, .06))}.avatar{width:48px;height:48px;flex-shrink:0;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:var(--ion-color-primary);color:#fff;font-weight:700;font-size:1rem}.avatar img{width:100%;height:100%;object-fit:cover}.content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.top,.bottom{display:flex;align-items:center;gap:8px}.name{flex:1;min-width:0;font-weight:600;font-size:.9375rem;color:var(--ion-text-color, #000);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.time{flex-shrink:0;font-size:.75rem;color:var(--ion-color-medium, #92949c)}.time.unread{color:var(--ion-color-primary);font-weight:600}.preview{flex:1;min-width:0;font-size:.875rem;color:var(--ion-color-medium, #92949c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.preview.muted{font-style:italic;opacity:.7}.badge{flex-shrink:0;min-width:20px;height:20px;padding:0 6px;border-radius:10px;background:var(--ion-color-primary);color:var(--ion-color-primary-contrast, #fff);font-size:.6875rem;font-weight:700;display:inline-flex;align-items:center;justify-content:center}\n"] }]
107
+ }], ctorParameters: () => [] });
108
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVyc2F0aW9uLWxpc3QtaXRlbS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvbW9sZWN1bGVzL2NvbnZlcnNhdGlvbi1saXN0LWl0ZW0vY29udmVyc2F0aW9uLWxpc3QtaXRlbS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0UsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRS9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7QUFFcEU7Ozs7Ozs7Ozs7OztHQVlHO0FBc0lILE1BQU0sT0FBTyw2QkFBNkI7SUFZeEM7UUFYUSxTQUFJLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRTFCLFNBQUksR0FBRyxLQUFLLENBQVMsRUFBRSxDQUFDLENBQUM7UUFDekIsY0FBUyxHQUFHLEtBQUssQ0FBcUIsU0FBUyxDQUFDLENBQUM7UUFDakQsZ0JBQVcsR0FBRyxLQUFLLENBQVMsRUFBRSxDQUFDLENBQUM7UUFDaEMsY0FBUyxHQUFHLEtBQUssQ0FBNEIsU0FBUyxDQUFDLENBQUM7UUFDeEQsZ0JBQVcsR0FBRyxLQUFLLENBQVMsQ0FBQyxDQUFDLENBQUM7UUFDL0IsV0FBTSxHQUFHLEtBQUssQ0FBUyxPQUFPLENBQUMsQ0FBQztRQUVoQyxXQUFNLEdBQUcsTUFBTSxFQUFRLENBQUM7UUFTZCxhQUFRLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLElBQUk7Z0JBQUUsT0FBTyxHQUFHLENBQUM7WUFDdEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNoQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUM3RCxDQUFDLENBQUMsQ0FBQztRQUVnQixjQUFTLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUMzQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ2xELEtBQUssRUFBRSxFQUFFO1lBQ1QsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUM7U0FDL0MsQ0FBQyxDQUNILENBQUM7UUFsQkEsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxzQkFBc0IsRUFBRTtZQUNqRCxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFO1lBQzdCLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUU7U0FDN0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQWdCUyxTQUFTO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDakIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsc0JBQXNCLENBQUMsQ0FBQztJQUN0RCxDQUFDOytHQXBDVSw2QkFBNkI7bUdBQTdCLDZCQUE2Qiw2NEJBakk5Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQlQsNjhDQTNCUyxZQUFZOzs0RkFrSVgsNkJBQTZCO2tCQXJJekMsU0FBUzsrQkFDRSw0QkFBNEIsY0FDMUIsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDLFlBQ2I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMEJUIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBjb21wdXRlZCwgaW5qZWN0LCBpbnB1dCwgb3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5pbXBvcnQgeyBJMThuU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2kxOG4nO1xuaW1wb3J0IHsgZm9ybWF0UmVsYXRpdmVUaW1lIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL3V0aWxzL2RhdGV0aW1lJztcblxuLyoqXG4gKiB2YWwtY29udmVyc2F0aW9uLWxpc3QtaXRlbSDigJQgZmlsYSBkZSBsaXN0YSBkZSBjb252ZXJzYWNpb25lcyBlc3RpbG9cbiAqIFRlbGVncmFtL1doYXRzQXBwOiBhdmF0YXIgKGltYWdlbiBvIGluaWNpYWxlcyksIG5vbWJyZSArIGhvcmEgcmVsYXRpdmEsXG4gKiBwcmV2aWV3IGRlbCDDumx0aW1vIG1lbnNhamUgKyBiYWRnZSBkZSBuby1sZcOtZG9zLiBTaWduYWwgaW5wdXRzLCBkYXJrLXNhZmUuXG4gKlxuICogQGV4YW1wbGVcbiAqIDx2YWwtY29udmVyc2F0aW9uLWxpc3QtaXRlbVxuICogICBbbmFtZV09XCJjb252Lm5hbWVcIlxuICogICBbbGFzdE1lc3NhZ2VdPVwiY29udi5sYXN0TXNnUHJldmlld1wiXG4gKiAgIFt0aW1lc3RhbXBdPVwiY29udi5sYXN0TXNnQXRcIlxuICogICBbdW5yZWFkQ291bnRdPVwiY29udi51bnJlYWRcIlxuICogICAoc2VsZWN0KT1cIm9wZW4oY29udi5jb252SWQpXCIgLz5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndmFsLWNvbnZlcnNhdGlvbi1saXN0LWl0ZW0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8YnV0dG9uIGNsYXNzPVwiaXRlbVwiIChjbGljayk9XCJzZWxlY3QuZW1pdCgpXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiYXZhdGFyXCI+XG4gICAgICAgIEBpZiAoYXZhdGFyVXJsKCkpIHtcbiAgICAgICAgICA8aW1nIFtzcmNdPVwiYXZhdGFyVXJsKClcIiBbYWx0XT1cIm5hbWUoKVwiIC8+XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDxzcGFuPnt7IGluaXRpYWxzKCkgfX08L3NwYW4+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNvbnRlbnRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRvcFwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibmFtZVwiPnt7IG5hbWUoKSB9fTwvc3Bhbj5cbiAgICAgICAgICBAaWYgKHRpbWVMYWJlbCgpKSB7XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRpbWVcIiBbY2xhc3MudW5yZWFkXT1cInVucmVhZENvdW50KCkgPiAwXCI+e3sgdGltZUxhYmVsKCkgfX08L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImJvdHRvbVwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwicHJldmlld1wiIFtjbGFzcy5tdXRlZF09XCIhbGFzdE1lc3NhZ2UoKVwiPlxuICAgICAgICAgICAge3sgbGFzdE1lc3NhZ2UoKSB8fCBlbXB0eVRleHQoKSB9fVxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICBAaWYgKHVucmVhZENvdW50KCkgPiAwKSB7XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlXCI+e3sgdW5yZWFkQ291bnQoKSA+IDk5ID8gJzk5KycgOiB1bnJlYWRDb3VudCgpIH19PC9zcGFuPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2J1dHRvbj5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgOmhvc3Qge1xuICAgICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgIH1cbiAgICAgIC5pdGVtIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAgZ2FwOiAxMnB4O1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgcGFkZGluZzogMTBweCAxMnB4O1xuICAgICAgICBib3JkZXI6IG5vbmU7XG4gICAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICAgIHRleHQtYWxpZ246IGxlZnQ7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDEycHg7XG4gICAgICAgIHRyYW5zaXRpb246IGJhY2tncm91bmQgMC4xMnMgZWFzZTtcbiAgICAgIH1cbiAgICAgIC5pdGVtOmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZDogdmFyKC0taW9uLWNvbG9yLXN0ZXAtNTAsIHJnYmEoMTI3LCAxMjcsIDEyNywgMC4wNikpO1xuICAgICAgfVxuICAgICAgLmF2YXRhciB7XG4gICAgICAgIHdpZHRoOiA0OHB4O1xuICAgICAgICBoZWlnaHQ6IDQ4cHg7XG4gICAgICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgICAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1pb24tY29sb3ItcHJpbWFyeSk7XG4gICAgICAgIGNvbG9yOiAjZmZmO1xuICAgICAgICBmb250LXdlaWdodDogNzAwO1xuICAgICAgICBmb250LXNpemU6IDFyZW07XG4gICAgICB9XG4gICAgICAuYXZhdGFyIGltZyB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICAgIG9iamVjdC1maXQ6IGNvdmVyO1xuICAgICAgfVxuICAgICAgLmNvbnRlbnQge1xuICAgICAgICBmbGV4OiAxO1xuICAgICAgICBtaW4td2lkdGg6IDA7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGdhcDogMnB4O1xuICAgICAgfVxuICAgICAgLnRvcCxcbiAgICAgIC5ib3R0b20ge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBnYXA6IDhweDtcbiAgICAgIH1cbiAgICAgIC5uYW1lIHtcbiAgICAgICAgZmxleDogMTtcbiAgICAgICAgbWluLXdpZHRoOiAwO1xuICAgICAgICBmb250LXdlaWdodDogNjAwO1xuICAgICAgICBmb250LXNpemU6IDAuOTM3NXJlbTtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi10ZXh0LWNvbG9yLCAjMDAwKTtcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gICAgICB9XG4gICAgICAudGltZSB7XG4gICAgICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgICAgICBmb250LXNpemU6IDAuNzVyZW07XG4gICAgICAgIGNvbG9yOiB2YXIoLS1pb24tY29sb3ItbWVkaXVtLCAjOTI5NDljKTtcbiAgICAgIH1cbiAgICAgIC50aW1lLnVucmVhZCB7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1pb24tY29sb3ItcHJpbWFyeSk7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XG4gICAgICB9XG4gICAgICAucHJldmlldyB7XG4gICAgICAgIGZsZXg6IDE7XG4gICAgICAgIG1pbi13aWR0aDogMDtcbiAgICAgICAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi1jb2xvci1tZWRpdW0sICM5Mjk0OWMpO1xuICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgICAgIH1cbiAgICAgIC5wcmV2aWV3Lm11dGVkIHtcbiAgICAgICAgZm9udC1zdHlsZTogaXRhbGljO1xuICAgICAgICBvcGFjaXR5OiAwLjc7XG4gICAgICB9XG4gICAgICAuYmFkZ2Uge1xuICAgICAgICBmbGV4LXNocmluazogMDtcbiAgICAgICAgbWluLXdpZHRoOiAyMHB4O1xuICAgICAgICBoZWlnaHQ6IDIwcHg7XG4gICAgICAgIHBhZGRpbmc6IDAgNnB4O1xuICAgICAgICBib3JkZXItcmFkaXVzOiAxMHB4O1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1pb24tY29sb3ItcHJpbWFyeSk7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1pb24tY29sb3ItcHJpbWFyeS1jb250cmFzdCwgI2ZmZik7XG4gICAgICAgIGZvbnQtc2l6ZTogMC42ODc1cmVtO1xuICAgICAgICBmb250LXdlaWdodDogNzAwO1xuICAgICAgICBkaXNwbGF5OiBpbmxpbmUtZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQ29udmVyc2F0aW9uTGlzdEl0ZW1Db21wb25lbnQge1xuICBwcml2YXRlIGkxOG4gPSBpbmplY3QoSTE4blNlcnZpY2UpO1xuXG4gIHJlYWRvbmx5IG5hbWUgPSBpbnB1dDxzdHJpbmc+KCcnKTtcbiAgcmVhZG9ubHkgYXZhdGFyVXJsID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICByZWFkb25seSBsYXN0TWVzc2FnZSA9IGlucHV0PHN0cmluZz4oJycpO1xuICByZWFkb25seSB0aW1lc3RhbXAgPSBpbnB1dDxzdHJpbmcgfCBEYXRlIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICByZWFkb25seSB1bnJlYWRDb3VudCA9IGlucHV0PG51bWJlcj4oMCk7XG4gIHJlYWRvbmx5IGxvY2FsZSA9IGlucHV0PHN0cmluZz4oJ2VzLUNMJyk7XG5cbiAgcmVhZG9ubHkgc2VsZWN0ID0gb3V0cHV0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5pMThuLnJlZ2lzdGVyRGVmYXVsdHMoJ0NvbnZlcnNhdGlvbkxpc3RJdGVtJywge1xuICAgICAgZXM6IHsgZW1wdHk6ICdTaW4gbWVuc2FqZXMnIH0sXG4gICAgICBlbjogeyBlbXB0eTogJ05vIG1lc3NhZ2VzJyB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGluaXRpYWxzID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IG5hbWUgPSB0aGlzLm5hbWUoKS50cmltKCk7XG4gICAgaWYgKCFuYW1lKSByZXR1cm4gJz8nO1xuICAgIGNvbnN0IHBhcnRzID0gbmFtZS5zcGxpdCgvXFxzKy8pO1xuICAgIHJldHVybiAocGFydHNbMF1bMF0gKyAocGFydHNbMV0/LlswXSA/PyAnJykpLnRvVXBwZXJDYXNlKCk7XG4gIH0pO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSB0aW1lTGFiZWwgPSBjb21wdXRlZCgoKSA9PlxuICAgIGZvcm1hdFJlbGF0aXZlVGltZSh0aGlzLnRpbWVzdGFtcCgpLCB0aGlzLmxvY2FsZSgpLCB7XG4gICAgICB0b2RheTogJycsXG4gICAgICB5ZXN0ZXJkYXk6IHRoaXMuaTE4bi50KCd5ZXN0ZXJkYXknLCAnX2dsb2JhbCcpLFxuICAgIH0pXG4gICk7XG5cbiAgcHJvdGVjdGVkIGVtcHR5VGV4dCgpOiBzdHJpbmcge1xuICAgIHRoaXMuaTE4bi5sYW5nKCk7XG4gICAgcmV0dXJuIHRoaXMuaTE4bi50KCdlbXB0eScsICdDb252ZXJzYXRpb25MaXN0SXRlbScpO1xuICB9XG59XG4iXX0=