@bloonio/chat-angular 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/esm2022/bloonio-chat-angular.mjs +5 -0
- package/esm2022/index.mjs +25 -0
- package/esm2022/lib/bloonio-chat.service.mjs +311 -0
- package/esm2022/lib/bloonio-chat.token.mjs +46 -0
- package/esm2022/lib/components/input-bar.component.mjs +91 -0
- package/esm2022/lib/components/launcher.component.mjs +81 -0
- package/esm2022/lib/components/message-list.component.mjs +58 -0
- package/esm2022/lib/components/panel.component.mjs +211 -0
- package/esm2022/lib/components/quick-replies.component.mjs +58 -0
- package/esm2022/lib/components/thread.component.mjs +103 -0
- package/fesm2022/bloonio-chat-angular.mjs +958 -0
- package/fesm2022/bloonio-chat-angular.mjs.map +1 -0
- package/index.d.ts +27 -0
- package/lib/bloonio-chat.service.d.ts +79 -0
- package/lib/bloonio-chat.token.d.ts +67 -0
- package/lib/components/input-bar.component.d.ts +18 -0
- package/lib/components/launcher.component.d.ts +14 -0
- package/lib/components/message-list.component.d.ts +8 -0
- package/lib/components/panel.component.d.ts +31 -0
- package/lib/components/quick-replies.component.d.ts +10 -0
- package/lib/components/thread.component.d.ts +27 -0
- package/package.json +38 -0
- package/src/lib/styles/chat.css +268 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visitor input bar — multi-line textarea + send button. Enter sends,
|
|
3
|
+
* Shift+Enter inserts a newline. Emits `send` with the trimmed content
|
|
4
|
+
* once it's non-empty.
|
|
5
|
+
*/
|
|
6
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, signal, } from '@angular/core';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
export class InputBarComponent {
|
|
9
|
+
disabled = false;
|
|
10
|
+
send = new EventEmitter();
|
|
11
|
+
value = signal('');
|
|
12
|
+
canSend() {
|
|
13
|
+
return !this.disabled && this.value().trim().length > 0;
|
|
14
|
+
}
|
|
15
|
+
onInput(e) {
|
|
16
|
+
this.value.set(e.target.value);
|
|
17
|
+
}
|
|
18
|
+
onKey(e) {
|
|
19
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
20
|
+
e.preventDefault();
|
|
21
|
+
this.submit();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
submit() {
|
|
25
|
+
if (!this.canSend())
|
|
26
|
+
return;
|
|
27
|
+
const trimmed = this.value().trim();
|
|
28
|
+
this.send.emit(trimmed);
|
|
29
|
+
this.value.set('');
|
|
30
|
+
}
|
|
31
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
32
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: InputBarComponent, isStandalone: true, selector: "bloonio-chat-input-bar", inputs: { disabled: "disabled" }, outputs: { send: "send" }, ngImport: i0, template: `
|
|
33
|
+
<div class="bch-input">
|
|
34
|
+
<textarea
|
|
35
|
+
rows="1"
|
|
36
|
+
placeholder="Enter your message..."
|
|
37
|
+
[disabled]="disabled"
|
|
38
|
+
[value]="value()"
|
|
39
|
+
(input)="onInput($event)"
|
|
40
|
+
(keydown)="onKey($event)"
|
|
41
|
+
></textarea>
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
class="bch-input-send"
|
|
45
|
+
aria-label="Send"
|
|
46
|
+
[disabled]="!canSend()"
|
|
47
|
+
(click)="submit()"
|
|
48
|
+
>
|
|
49
|
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
50
|
+
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
|
|
51
|
+
</svg>
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
54
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
55
|
+
}
|
|
56
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputBarComponent, decorators: [{
|
|
57
|
+
type: Component,
|
|
58
|
+
args: [{
|
|
59
|
+
selector: 'bloonio-chat-input-bar',
|
|
60
|
+
standalone: true,
|
|
61
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
62
|
+
template: `
|
|
63
|
+
<div class="bch-input">
|
|
64
|
+
<textarea
|
|
65
|
+
rows="1"
|
|
66
|
+
placeholder="Enter your message..."
|
|
67
|
+
[disabled]="disabled"
|
|
68
|
+
[value]="value()"
|
|
69
|
+
(input)="onInput($event)"
|
|
70
|
+
(keydown)="onKey($event)"
|
|
71
|
+
></textarea>
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
class="bch-input-send"
|
|
75
|
+
aria-label="Send"
|
|
76
|
+
[disabled]="!canSend()"
|
|
77
|
+
(click)="submit()"
|
|
78
|
+
>
|
|
79
|
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
80
|
+
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
|
|
81
|
+
</svg>
|
|
82
|
+
</button>
|
|
83
|
+
</div>
|
|
84
|
+
`,
|
|
85
|
+
}]
|
|
86
|
+
}], propDecorators: { disabled: [{
|
|
87
|
+
type: Input
|
|
88
|
+
}], send: [{
|
|
89
|
+
type: Output
|
|
90
|
+
}] } });
|
|
91
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtYmFyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9pbnB1dC1iYXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7O0FBOEJ2QixNQUFNLE9BQU8saUJBQWlCO0lBQ25CLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDaEIsSUFBSSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7SUFFekIsS0FBSyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU1QixPQUFPO1FBQ2YsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELE9BQU8sQ0FBQyxDQUFRO1FBQ2QsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUUsQ0FBQyxDQUFDLE1BQThCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELEtBQUssQ0FBQyxDQUFnQjtRQUNwQixJQUFJLENBQUMsQ0FBQyxHQUFHLEtBQUssT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3JDLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNuQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDaEIsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNO1FBQ0osSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFBRSxPQUFPO1FBQzVCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNwQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyQixDQUFDO3dHQTFCVSxpQkFBaUI7NEZBQWpCLGlCQUFpQiwrSUF4QmxCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JUOzs0RkFFVSxpQkFBaUI7a0JBNUI3QixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSx3QkFBd0I7b0JBQ2xDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JUO2lCQUNGOzhCQUVVLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0ksSUFBSTtzQkFBYixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBWaXNpdG9yIGlucHV0IGJhciDigJQgbXVsdGktbGluZSB0ZXh0YXJlYSArIHNlbmQgYnV0dG9uLiBFbnRlciBzZW5kcyxcbiAqIFNoaWZ0K0VudGVyIGluc2VydHMgYSBuZXdsaW5lLiBFbWl0cyBgc2VuZGAgd2l0aCB0aGUgdHJpbW1lZCBjb250ZW50XG4gKiBvbmNlIGl0J3Mgbm9uLWVtcHR5LlxuICovXG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Jsb29uaW8tY2hhdC1pbnB1dC1iYXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwiYmNoLWlucHV0XCI+XG4gICAgICA8dGV4dGFyZWFcbiAgICAgICAgcm93cz1cIjFcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIkVudGVyIHlvdXIgbWVzc2FnZS4uLlwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgIFt2YWx1ZV09XCJ2YWx1ZSgpXCJcbiAgICAgICAgKGlucHV0KT1cIm9uSW5wdXQoJGV2ZW50KVwiXG4gICAgICAgIChrZXlkb3duKT1cIm9uS2V5KCRldmVudClcIlxuICAgICAgPjwvdGV4dGFyZWE+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImJjaC1pbnB1dC1zZW5kXCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIlNlbmRcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiIWNhblNlbmQoKVwiXG4gICAgICAgIChjbGljayk9XCJzdWJtaXQoKVwiXG4gICAgICA+XG4gICAgICAgIDxzdmcgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIj5cbiAgICAgICAgICA8cGF0aCBkPVwiTTIuMDEgMjFMMjMgMTIgMi4wMSAzIDIgMTBsMTUgMi0xNSAyelwiIC8+XG4gICAgICAgIDwvc3ZnPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIElucHV0QmFyQ29tcG9uZW50IHtcbiAgQElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcbiAgQE91dHB1dCgpIHNlbmQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgdmFsdWUgPSBzaWduYWwoJycpO1xuXG4gIHByb3RlY3RlZCBjYW5TZW5kKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5kaXNhYmxlZCAmJiB0aGlzLnZhbHVlKCkudHJpbSgpLmxlbmd0aCA+IDA7XG4gIH1cblxuICBvbklucHV0KGU6IEV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZS5zZXQoKGUudGFyZ2V0IGFzIEhUTUxUZXh0QXJlYUVsZW1lbnQpLnZhbHVlKTtcbiAgfVxuXG4gIG9uS2V5KGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoZS5rZXkgPT09ICdFbnRlcicgJiYgIWUuc2hpZnRLZXkpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHRoaXMuc3VibWl0KCk7XG4gICAgfVxuICB9XG5cbiAgc3VibWl0KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jYW5TZW5kKCkpIHJldHVybjtcbiAgICBjb25zdCB0cmltbWVkID0gdGhpcy52YWx1ZSgpLnRyaW0oKTtcbiAgICB0aGlzLnNlbmQuZW1pdCh0cmltbWVkKTtcbiAgICB0aGlzLnZhbHVlLnNldCgnJyk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating launcher — circular chat bubble with optional label.
|
|
3
|
+
* Wraps the `BloonioChatService` so consumers just drop
|
|
4
|
+
* `<bloonio-chat-launcher />` somewhere and the SDK handles state.
|
|
5
|
+
*/
|
|
6
|
+
import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
|
|
7
|
+
import { BloonioChatService } from '../bloonio-chat.service';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
export class BloonioChatLauncherComponent {
|
|
10
|
+
chat = inject(BloonioChatService);
|
|
11
|
+
position = computed(() => this.chat.bootstrap()?.widget_position ?? 'right');
|
|
12
|
+
/** Tint the bubble with the tenant's brand colour (falls back to the
|
|
13
|
+
* stylesheet default until bootstrap config loads). */
|
|
14
|
+
themeStyle = computed(() => {
|
|
15
|
+
const color = this.chat.bootstrap()?.branding_primary_color;
|
|
16
|
+
return color ? `--bch-primary: ${color}` : '';
|
|
17
|
+
});
|
|
18
|
+
label = computed(() => {
|
|
19
|
+
const b = this.chat.bootstrap();
|
|
20
|
+
return b?.button_label_enabled ? b.button_label_text : null;
|
|
21
|
+
});
|
|
22
|
+
ariaLabel = computed(() => {
|
|
23
|
+
const unread = this.chat.unreadCount();
|
|
24
|
+
return unread > 0
|
|
25
|
+
? `Open chat (${unread} unread)`
|
|
26
|
+
: 'Open chat';
|
|
27
|
+
});
|
|
28
|
+
onToggle() {
|
|
29
|
+
void this.chat.toggle();
|
|
30
|
+
}
|
|
31
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BloonioChatLauncherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
32
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: BloonioChatLauncherComponent, isStandalone: true, selector: "bloonio-chat-launcher", ngImport: i0, template: `
|
|
33
|
+
<div class="bch-root" [attr.data-position]="position()" [style]="themeStyle()">
|
|
34
|
+
<button
|
|
35
|
+
type="button"
|
|
36
|
+
class="bch-launcher"
|
|
37
|
+
[attr.aria-label]="ariaLabel()"
|
|
38
|
+
(click)="onToggle()"
|
|
39
|
+
>
|
|
40
|
+
@if (label()) {
|
|
41
|
+
<span class="bch-launcher-label">{{ label() }}</span>
|
|
42
|
+
}
|
|
43
|
+
<span class="bch-launcher-bubble">
|
|
44
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
45
|
+
stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
46
|
+
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
|
|
47
|
+
</svg>
|
|
48
|
+
</span>
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
52
|
+
}
|
|
53
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BloonioChatLauncherComponent, decorators: [{
|
|
54
|
+
type: Component,
|
|
55
|
+
args: [{
|
|
56
|
+
selector: 'bloonio-chat-launcher',
|
|
57
|
+
standalone: true,
|
|
58
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
59
|
+
template: `
|
|
60
|
+
<div class="bch-root" [attr.data-position]="position()" [style]="themeStyle()">
|
|
61
|
+
<button
|
|
62
|
+
type="button"
|
|
63
|
+
class="bch-launcher"
|
|
64
|
+
[attr.aria-label]="ariaLabel()"
|
|
65
|
+
(click)="onToggle()"
|
|
66
|
+
>
|
|
67
|
+
@if (label()) {
|
|
68
|
+
<span class="bch-launcher-label">{{ label() }}</span>
|
|
69
|
+
}
|
|
70
|
+
<span class="bch-launcher-bubble">
|
|
71
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
72
|
+
stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
73
|
+
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />
|
|
74
|
+
</svg>
|
|
75
|
+
</span>
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
`,
|
|
79
|
+
}]
|
|
80
|
+
}] });
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF1bmNoZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2xhdW5jaGVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXJGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDOztBQTJCN0QsTUFBTSxPQUFPLDRCQUE0QjtJQUNwQixJQUFJLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFFbEMsUUFBUSxHQUFHLFFBQVEsQ0FDcEMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxlQUFlLElBQUksT0FBTyxDQUN4RCxDQUFDO0lBRUY7NERBQ3dEO0lBQ3JDLFVBQVUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQzVDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsc0JBQXNCLENBQUM7UUFDNUQsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2hELENBQUMsQ0FBQyxDQUFDO0lBRWdCLEtBQUssR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQ3ZDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDaEMsT0FBTyxDQUFDLEVBQUUsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzlELENBQUMsQ0FBQyxDQUFDO0lBRWdCLFNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQzNDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDdkMsT0FBTyxNQUFNLEdBQUcsQ0FBQztZQUNmLENBQUMsQ0FBQyxjQUFjLE1BQU0sVUFBVTtZQUNoQyxDQUFDLENBQUMsV0FBVyxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUTtRQUNOLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUMxQixDQUFDO3dHQTVCVSw0QkFBNEI7NEZBQTVCLDRCQUE0QixpRkFyQjdCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJUOzs0RkFFVSw0QkFBNEI7a0JBekJ4QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSx1QkFBdUI7b0JBQ2pDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJUO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGbG9hdGluZyBsYXVuY2hlciDigJQgY2lyY3VsYXIgY2hhdCBidWJibGUgd2l0aCBvcHRpb25hbCBsYWJlbC5cbiAqIFdyYXBzIHRoZSBgQmxvb25pb0NoYXRTZXJ2aWNlYCBzbyBjb25zdW1lcnMganVzdCBkcm9wXG4gKiBgPGJsb29uaW8tY2hhdC1sYXVuY2hlciAvPmAgc29tZXdoZXJlIGFuZCB0aGUgU0RLIGhhbmRsZXMgc3RhdGUuXG4gKi9cbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgQmxvb25pb0NoYXRTZXJ2aWNlIH0gZnJvbSAnLi4vYmxvb25pby1jaGF0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdibG9vbmlvLWNoYXQtbGF1bmNoZXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwiYmNoLXJvb3RcIiBbYXR0ci5kYXRhLXBvc2l0aW9uXT1cInBvc2l0aW9uKClcIiBbc3R5bGVdPVwidGhlbWVTdHlsZSgpXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImJjaC1sYXVuY2hlclwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsKClcIlxuICAgICAgICAoY2xpY2spPVwib25Ub2dnbGUoKVwiXG4gICAgICA+XG4gICAgICAgIEBpZiAobGFiZWwoKSkge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYmNoLWxhdW5jaGVyLWxhYmVsXCI+e3sgbGFiZWwoKSB9fTwvc3Bhbj5cbiAgICAgICAgfVxuICAgICAgICA8c3BhbiBjbGFzcz1cImJjaC1sYXVuY2hlci1idWJibGVcIj5cbiAgICAgICAgICA8c3ZnIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG4gICAgICAgICAgICAgICBzdHJva2Utd2lkdGg9XCIyLjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIj5cbiAgICAgICAgICAgIDxwYXRoIGQ9XCJNMjEgMTEuNWE4LjM4IDguMzggMCAwIDEtLjkgMy44IDguNSA4LjUgMCAwIDEtNy42IDQuNyA4LjM4IDguMzggMCAwIDEtMy44LS45TDMgMjFsMS45LTUuN2E4LjM4IDguMzggMCAwIDEtLjktMy44IDguNSA4LjUgMCAwIDEgNC43LTcuNiA4LjM4IDguMzggMCAwIDEgMy44LS45aC41YTguNDggOC40OCAwIDAgMSA4IDh2LjV6XCIgLz5cbiAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEJsb29uaW9DaGF0TGF1bmNoZXJDb21wb25lbnQge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2hhdCA9IGluamVjdChCbG9vbmlvQ2hhdFNlcnZpY2UpO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBwb3NpdGlvbiA9IGNvbXB1dGVkKFxuICAgICgpID0+IHRoaXMuY2hhdC5ib290c3RyYXAoKT8ud2lkZ2V0X3Bvc2l0aW9uID8/ICdyaWdodCcsXG4gICk7XG5cbiAgLyoqIFRpbnQgdGhlIGJ1YmJsZSB3aXRoIHRoZSB0ZW5hbnQncyBicmFuZCBjb2xvdXIgKGZhbGxzIGJhY2sgdG8gdGhlXG4gICAqICBzdHlsZXNoZWV0IGRlZmF1bHQgdW50aWwgYm9vdHN0cmFwIGNvbmZpZyBsb2FkcykuICovXG4gIHByb3RlY3RlZCByZWFkb25seSB0aGVtZVN0eWxlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGNvbG9yID0gdGhpcy5jaGF0LmJvb3RzdHJhcCgpPy5icmFuZGluZ19wcmltYXJ5X2NvbG9yO1xuICAgIHJldHVybiBjb2xvciA/IGAtLWJjaC1wcmltYXJ5OiAke2NvbG9yfWAgOiAnJztcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxhYmVsID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGIgPSB0aGlzLmNoYXQuYm9vdHN0cmFwKCk7XG4gICAgcmV0dXJuIGI/LmJ1dHRvbl9sYWJlbF9lbmFibGVkID8gYi5idXR0b25fbGFiZWxfdGV4dCA6IG51bGw7XG4gIH0pO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBhcmlhTGFiZWwgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgdW5yZWFkID0gdGhpcy5jaGF0LnVucmVhZENvdW50KCk7XG4gICAgcmV0dXJuIHVucmVhZCA+IDBcbiAgICAgID8gYE9wZW4gY2hhdCAoJHt1bnJlYWR9IHVucmVhZClgXG4gICAgICA6ICdPcGVuIGNoYXQnO1xuICB9KTtcblxuICBvblRvZ2dsZSgpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuY2hhdC50b2dnbGUoKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the message log + typing indicator. Pure presentational —
|
|
3
|
+
* receives messages + typing flag as inputs so it can also be used
|
|
4
|
+
* outside the panel (custom layouts, debug screens).
|
|
5
|
+
*/
|
|
6
|
+
import { ChangeDetectionStrategy, Component, Input, } from '@angular/core';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
export class MessageListComponent {
|
|
9
|
+
messages = [];
|
|
10
|
+
botTyping = false;
|
|
11
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MessageListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: MessageListComponent, isStandalone: true, selector: "bloonio-chat-message-list", inputs: { messages: "messages", botTyping: "botTyping" }, ngImport: i0, template: `
|
|
13
|
+
@for (m of messages; track m.id) {
|
|
14
|
+
<div
|
|
15
|
+
class="bch-bubble"
|
|
16
|
+
[attr.data-from]="m.from"
|
|
17
|
+
[attr.data-pending]="m.pending ? 'true' : null"
|
|
18
|
+
>
|
|
19
|
+
{{ m.content }}
|
|
20
|
+
</div>
|
|
21
|
+
}
|
|
22
|
+
@if (botTyping) {
|
|
23
|
+
<div class="bch-typing" aria-label="Assistant is typing">
|
|
24
|
+
<span></span><span></span><span></span>
|
|
25
|
+
</div>
|
|
26
|
+
}
|
|
27
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
28
|
+
}
|
|
29
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
30
|
+
type: Component,
|
|
31
|
+
args: [{
|
|
32
|
+
selector: 'bloonio-chat-message-list',
|
|
33
|
+
standalone: true,
|
|
34
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
35
|
+
template: `
|
|
36
|
+
@for (m of messages; track m.id) {
|
|
37
|
+
<div
|
|
38
|
+
class="bch-bubble"
|
|
39
|
+
[attr.data-from]="m.from"
|
|
40
|
+
[attr.data-pending]="m.pending ? 'true' : null"
|
|
41
|
+
>
|
|
42
|
+
{{ m.content }}
|
|
43
|
+
</div>
|
|
44
|
+
}
|
|
45
|
+
@if (botTyping) {
|
|
46
|
+
<div class="bch-typing" aria-label="Assistant is typing">
|
|
47
|
+
<span></span><span></span><span></span>
|
|
48
|
+
</div>
|
|
49
|
+
}
|
|
50
|
+
`,
|
|
51
|
+
}]
|
|
52
|
+
}], propDecorators: { messages: [{
|
|
53
|
+
type: Input,
|
|
54
|
+
args: [{ required: true }]
|
|
55
|
+
}], botTyping: [{
|
|
56
|
+
type: Input
|
|
57
|
+
}] } });
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZS1saXN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9tZXNzYWdlLWxpc3QuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxLQUFLLEdBQ04sTUFBTSxlQUFlLENBQUM7O0FBeUJ2QixNQUFNLE9BQU8sb0JBQW9CO0lBQ0osUUFBUSxHQUFrQixFQUFFLENBQUM7SUFDL0MsU0FBUyxHQUFHLEtBQUssQ0FBQzt3R0FGaEIsb0JBQW9COzRGQUFwQixvQkFBb0IsK0lBakJyQjs7Ozs7Ozs7Ozs7Ozs7O0dBZVQ7OzRGQUVVLG9CQUFvQjtrQkFyQmhDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDJCQUEyQjtvQkFDckMsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7OztHQWVUO2lCQUNGOzhCQUU0QixRQUFRO3NCQUFsQyxLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFDaEIsU0FBUztzQkFBakIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUmVuZGVycyB0aGUgbWVzc2FnZSBsb2cgKyB0eXBpbmcgaW5kaWNhdG9yLiBQdXJlIHByZXNlbnRhdGlvbmFsIOKAlFxuICogcmVjZWl2ZXMgbWVzc2FnZXMgKyB0eXBpbmcgZmxhZyBhcyBpbnB1dHMgc28gaXQgY2FuIGFsc28gYmUgdXNlZFxuICogb3V0c2lkZSB0aGUgcGFuZWwgKGN1c3RvbSBsYXlvdXRzLCBkZWJ1ZyBzY3JlZW5zKS5cbiAqL1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgdHlwZSB7IENoYXRNZXNzYWdlIH0gZnJvbSAnLi4vYmxvb25pby1jaGF0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdibG9vbmlvLWNoYXQtbWVzc2FnZS1saXN0JyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgQGZvciAobSBvZiBtZXNzYWdlczsgdHJhY2sgbS5pZCkge1xuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cImJjaC1idWJibGVcIlxuICAgICAgICBbYXR0ci5kYXRhLWZyb21dPVwibS5mcm9tXCJcbiAgICAgICAgW2F0dHIuZGF0YS1wZW5kaW5nXT1cIm0ucGVuZGluZyA/ICd0cnVlJyA6IG51bGxcIlxuICAgICAgPlxuICAgICAgICB7eyBtLmNvbnRlbnQgfX1cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICBAaWYgKGJvdFR5cGluZykge1xuICAgICAgPGRpdiBjbGFzcz1cImJjaC10eXBpbmdcIiBhcmlhLWxhYmVsPVwiQXNzaXN0YW50IGlzIHR5cGluZ1wiPlxuICAgICAgICA8c3Bhbj48L3NwYW4+PHNwYW4+PC9zcGFuPjxzcGFuPjwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgTWVzc2FnZUxpc3RDb21wb25lbnQge1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSBtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSA9IFtdO1xuICBASW5wdXQoKSBib3RUeXBpbmcgPSBmYWxzZTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating or docked chat panel. Renders the header, message list, input,
|
|
3
|
+
* and footer. Sits inside `<bloonio-chat-launcher>` for the floating
|
|
4
|
+
* variant, or stand-alone for `mode="docked"`/`mode="inline"`.
|
|
5
|
+
*/
|
|
6
|
+
import { ChangeDetectionStrategy, Component, computed, inject, Input, signal, ViewChild, } from '@angular/core';
|
|
7
|
+
import { BloonioChatService } from '../bloonio-chat.service';
|
|
8
|
+
import { InputBarComponent } from './input-bar.component';
|
|
9
|
+
import { MessageListComponent } from './message-list.component';
|
|
10
|
+
import { QuickRepliesComponent } from './quick-replies.component';
|
|
11
|
+
import * as i0 from "@angular/core";
|
|
12
|
+
export class BloonioChatPanelComponent {
|
|
13
|
+
/** floating = paired with launcher (default). docked/inline = always-on
|
|
14
|
+
* inside the page flow (use for SSR landing pages or sidebar layouts). */
|
|
15
|
+
mode = 'floating';
|
|
16
|
+
chat = inject(BloonioChatService);
|
|
17
|
+
messagesRef;
|
|
18
|
+
lastScrollLen = signal(-1);
|
|
19
|
+
position = computed(() => this.chat.bootstrap()?.widget_position ?? 'right');
|
|
20
|
+
visible = computed(() => {
|
|
21
|
+
// Floating mode: only when service.open() is true.
|
|
22
|
+
// Docked/inline: always rendered if bootstrap is loaded.
|
|
23
|
+
if (this.mode === 'floating')
|
|
24
|
+
return this.chat.open();
|
|
25
|
+
return !!this.chat.bootstrap();
|
|
26
|
+
});
|
|
27
|
+
themeStyle = computed(() => {
|
|
28
|
+
const color = this.chat.bootstrap()?.branding_primary_color;
|
|
29
|
+
return color ? `--bch-primary: ${color}` : '';
|
|
30
|
+
});
|
|
31
|
+
displayName = computed(() => this.chat.bootstrap()?.branding_display_name
|
|
32
|
+
?? this.chat.bootstrap()?.tenant_name
|
|
33
|
+
?? 'Support');
|
|
34
|
+
logoUrl = computed(() => this.chat.bootstrap()?.branding_logo_url ?? null);
|
|
35
|
+
initials = computed(() => this.displayName()
|
|
36
|
+
.split(/\s+/)
|
|
37
|
+
.slice(0, 2)
|
|
38
|
+
.map((w) => w[0]?.toUpperCase() ?? '')
|
|
39
|
+
.join('') || '?');
|
|
40
|
+
statusText = computed(() => {
|
|
41
|
+
const b = this.chat.bootstrap();
|
|
42
|
+
if (!b)
|
|
43
|
+
return '';
|
|
44
|
+
return b.is_online ? b.online_status_text : b.offline_status_text;
|
|
45
|
+
});
|
|
46
|
+
isOnlineStr = computed(() => String(this.chat.bootstrap()?.is_online ?? false));
|
|
47
|
+
visibleMessages = computed(() => {
|
|
48
|
+
const b = this.chat.bootstrap();
|
|
49
|
+
const messages = this.chat.messages();
|
|
50
|
+
if (b && !b.is_online && messages.length === 0) {
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
id: 'sys_offline',
|
|
54
|
+
from: 'system',
|
|
55
|
+
content: b.offline_message,
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
return messages;
|
|
60
|
+
});
|
|
61
|
+
ngAfterViewChecked() {
|
|
62
|
+
// Scroll-to-bottom whenever message count changes. We compare against a
|
|
63
|
+
// stamped length so we don't churn when only typing/status updates fire.
|
|
64
|
+
const el = this.messagesRef?.nativeElement;
|
|
65
|
+
if (!el)
|
|
66
|
+
return;
|
|
67
|
+
const len = this.visibleMessages().length + (this.chat.botTyping() ? 1 : 0);
|
|
68
|
+
if (len !== this.lastScrollLen()) {
|
|
69
|
+
el.scrollTop = el.scrollHeight;
|
|
70
|
+
this.lastScrollLen.set(len);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
onClose() {
|
|
74
|
+
this.chat.closePanel();
|
|
75
|
+
}
|
|
76
|
+
onSend(content) {
|
|
77
|
+
this.chat.sendMessage(content);
|
|
78
|
+
}
|
|
79
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BloonioChatPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
80
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: BloonioChatPanelComponent, isStandalone: true, selector: "bloonio-chat-panel", inputs: { mode: "mode" }, viewQueries: [{ propertyName: "messagesRef", first: true, predicate: ["messages"], descendants: true }], ngImport: i0, template: `
|
|
81
|
+
<div
|
|
82
|
+
class="bch-root"
|
|
83
|
+
[class.bch-open]="visible()"
|
|
84
|
+
[attr.data-position]="position()"
|
|
85
|
+
[attr.data-mode]="mode"
|
|
86
|
+
>
|
|
87
|
+
<div class="bch-panel" [style]="themeStyle()">
|
|
88
|
+
<header class="bch-header">
|
|
89
|
+
<div class="bch-header-avatar">
|
|
90
|
+
@if (logoUrl()) {
|
|
91
|
+
<img [src]="logoUrl()" alt="" />
|
|
92
|
+
} @else {
|
|
93
|
+
<span style="font-weight:600;font-size:15px">{{ initials() }}</span>
|
|
94
|
+
}
|
|
95
|
+
</div>
|
|
96
|
+
<div class="bch-header-title">
|
|
97
|
+
<div class="bch-header-name">Chat with {{ displayName() }}</div>
|
|
98
|
+
<div class="bch-header-status">
|
|
99
|
+
<span class="bch-header-status-dot" [attr.data-online]="isOnlineStr()"></span>
|
|
100
|
+
{{ statusText() }}
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
<button
|
|
104
|
+
type="button"
|
|
105
|
+
class="bch-header-close"
|
|
106
|
+
aria-label="Close"
|
|
107
|
+
(click)="onClose()"
|
|
108
|
+
>
|
|
109
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
110
|
+
stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
|
|
111
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
112
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
113
|
+
</svg>
|
|
114
|
+
</button>
|
|
115
|
+
</header>
|
|
116
|
+
|
|
117
|
+
<div class="bch-messages" #messages>
|
|
118
|
+
<bloonio-chat-message-list
|
|
119
|
+
[messages]="visibleMessages()"
|
|
120
|
+
[botTyping]="chat.botTyping()"
|
|
121
|
+
/>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<bloonio-chat-quick-replies />
|
|
125
|
+
|
|
126
|
+
<bloonio-chat-input-bar
|
|
127
|
+
[disabled]="chat.connecting()"
|
|
128
|
+
(send)="onSend($event)"
|
|
129
|
+
/>
|
|
130
|
+
|
|
131
|
+
<div class="bch-footer">
|
|
132
|
+
Powered by
|
|
133
|
+
<a href="https://bloonio.com" target="_blank" rel="noopener noreferrer">Bloonio</a>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
`, isInline: true, dependencies: [{ kind: "component", type: InputBarComponent, selector: "bloonio-chat-input-bar", inputs: ["disabled"], outputs: ["send"] }, { kind: "component", type: MessageListComponent, selector: "bloonio-chat-message-list", inputs: ["messages", "botTyping"] }, { kind: "component", type: QuickRepliesComponent, selector: "bloonio-chat-quick-replies" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
138
|
+
}
|
|
139
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BloonioChatPanelComponent, decorators: [{
|
|
140
|
+
type: Component,
|
|
141
|
+
args: [{
|
|
142
|
+
selector: 'bloonio-chat-panel',
|
|
143
|
+
standalone: true,
|
|
144
|
+
imports: [InputBarComponent, MessageListComponent, QuickRepliesComponent],
|
|
145
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
146
|
+
template: `
|
|
147
|
+
<div
|
|
148
|
+
class="bch-root"
|
|
149
|
+
[class.bch-open]="visible()"
|
|
150
|
+
[attr.data-position]="position()"
|
|
151
|
+
[attr.data-mode]="mode"
|
|
152
|
+
>
|
|
153
|
+
<div class="bch-panel" [style]="themeStyle()">
|
|
154
|
+
<header class="bch-header">
|
|
155
|
+
<div class="bch-header-avatar">
|
|
156
|
+
@if (logoUrl()) {
|
|
157
|
+
<img [src]="logoUrl()" alt="" />
|
|
158
|
+
} @else {
|
|
159
|
+
<span style="font-weight:600;font-size:15px">{{ initials() }}</span>
|
|
160
|
+
}
|
|
161
|
+
</div>
|
|
162
|
+
<div class="bch-header-title">
|
|
163
|
+
<div class="bch-header-name">Chat with {{ displayName() }}</div>
|
|
164
|
+
<div class="bch-header-status">
|
|
165
|
+
<span class="bch-header-status-dot" [attr.data-online]="isOnlineStr()"></span>
|
|
166
|
+
{{ statusText() }}
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
<button
|
|
170
|
+
type="button"
|
|
171
|
+
class="bch-header-close"
|
|
172
|
+
aria-label="Close"
|
|
173
|
+
(click)="onClose()"
|
|
174
|
+
>
|
|
175
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
176
|
+
stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">
|
|
177
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
178
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
179
|
+
</svg>
|
|
180
|
+
</button>
|
|
181
|
+
</header>
|
|
182
|
+
|
|
183
|
+
<div class="bch-messages" #messages>
|
|
184
|
+
<bloonio-chat-message-list
|
|
185
|
+
[messages]="visibleMessages()"
|
|
186
|
+
[botTyping]="chat.botTyping()"
|
|
187
|
+
/>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
<bloonio-chat-quick-replies />
|
|
191
|
+
|
|
192
|
+
<bloonio-chat-input-bar
|
|
193
|
+
[disabled]="chat.connecting()"
|
|
194
|
+
(send)="onSend($event)"
|
|
195
|
+
/>
|
|
196
|
+
|
|
197
|
+
<div class="bch-footer">
|
|
198
|
+
Powered by
|
|
199
|
+
<a href="https://bloonio.com" target="_blank" rel="noopener noreferrer">Bloonio</a>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
`,
|
|
204
|
+
}]
|
|
205
|
+
}], propDecorators: { mode: [{
|
|
206
|
+
type: Input
|
|
207
|
+
}], messagesRef: [{
|
|
208
|
+
type: ViewChild,
|
|
209
|
+
args: ['messages']
|
|
210
|
+
}] } });
|
|
211
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFuZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3BhbmVsLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsUUFBUSxFQUNSLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUdOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7QUFvRWxFLE1BQU0sT0FBTyx5QkFBeUI7SUFDcEM7K0VBQzJFO0lBQ2xFLElBQUksR0FBa0IsVUFBVSxDQUFDO0lBRXZCLElBQUksR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUV0QixXQUFXLENBQThCO0lBQ2hFLGFBQWEsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVoQixRQUFRLEdBQUcsUUFBUSxDQUNwQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLGVBQWUsSUFBSSxPQUFPLENBQ3hELENBQUM7SUFFaUIsT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7UUFDekMsbURBQW1EO1FBQ25ELHlEQUF5RDtRQUN6RCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssVUFBVTtZQUFFLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN0RCxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNB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LEVBQUUsRUFBRSxDQUFDO1lBQ2pDLEVBQUUsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQztZQUMvQixJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QixDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFRCxNQUFNLENBQUMsT0FBZTtRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqQyxDQUFDO3dHQXZGVSx5QkFBeUI7NEZBQXpCLHlCQUF5QixpTkEzRDFCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5RFQsNERBM0RTLGlCQUFpQiw0R0FBRSxvQkFBb0IseUdBQUUscUJBQXFCOzs0RkE2RDdELHlCQUF5QjtrQkFoRXJDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLG9CQUFvQjtvQkFDOUIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLE9BQU8sRUFBRSxDQUFDLGlCQUFpQixFQUFFLG9CQUFvQixFQUFFLHFCQUFxQixDQUFDO29CQUN6RSxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5RFQ7aUJBQ0Y7OEJBSVUsSUFBSTtzQkFBWixLQUFLO2dCQUl5QixXQUFXO3NCQUF6QyxTQUFTO3VCQUFDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZsb2F0aW5nIG9yIGRvY2tlZCBjaGF0IHBhbmVsLiBSZW5kZXJzIHRoZSBoZWFkZXIsIG1lc3NhZ2UgbGlzdCwgaW5wdXQsXG4gKiBhbmQgZm9vdGVyLiBTaXRzIGluc2lkZSBgPGJsb29uaW8tY2hhdC1sYXVuY2hlcj5gIGZvciB0aGUgZmxvYXRpbmdcbiAqIHZhcmlhbnQsIG9yIHN0YW5kLWFsb25lIGZvciBgbW9kZT1cImRvY2tlZFwiYC9gbW9kZT1cImlubGluZVwiYC5cbiAqL1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgY29tcHV0ZWQsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIHNpZ25hbCxcbiAgdHlwZSBBZnRlclZpZXdDaGVja2VkLFxuICBFbGVtZW50UmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBCbG9vbmlvQ2hhdFNlcnZpY2UgfSBmcm9tICcuLi9ibG9vbmlvLWNoYXQuc2VydmljZSc7XG5pbXBvcnQgeyBJbnB1dEJhckNvbXBvbmVudCB9IGZyb20gJy4vaW5wdXQtYmFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBNZXNzYWdlTGlzdENvbXBvbmVudCB9IGZyb20gJy4vbWVzc2FnZS1saXN0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBRdWlja1JlcGxpZXNDb21wb25lbnQgfSBmcm9tICcuL3F1aWNrLXJlcGxpZXMuY29tcG9uZW50JztcblxuZXhwb3J0IHR5cGUgQ2hhdFBhbmVsTW9kZSA9ICdmbG9hdGluZycgfCAnZG9ja2VkJyB8ICdpbmxpbmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdibG9vbmlvLWNoYXQtcGFuZWwnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbSW5wdXRCYXJDb21wb25lbnQsIE1lc3NhZ2VMaXN0Q29tcG9uZW50LCBRdWlja1JlcGxpZXNDb21wb25lbnRdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cImJjaC1yb290XCJcbiAgICAgIFtjbGFzcy5iY2gtb3Blbl09XCJ2aXNpYmxlKClcIlxuICAgICAgW2F0dHIuZGF0YS1wb3NpdGlvbl09XCJwb3NpdGlvbigpXCJcbiAgICAgIFthdHRyLmRhdGEtbW9kZV09XCJtb2RlXCJcbiAgICA+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJiY2gtcGFuZWxcIiBbc3R5bGVdPVwidGhlbWVTdHlsZSgpXCI+XG4gICAgICAgICAgPGhlYWRlciBjbGFzcz1cImJjaC1oZWFkZXJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiY2gtaGVhZGVyLWF2YXRhclwiPlxuICAgICAgICAgICAgICBAaWYgKGxvZ29VcmwoKSkge1xuICAgICAgICAgICAgICAgIDxpbWcgW3NyY109XCJsb2dvVXJsKClcIiBhbHQ9XCJcIiAvPlxuICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICA8c3BhbiBzdHlsZT1cImZvbnQtd2VpZ2h0OjYwMDtmb250LXNpemU6MTVweFwiPnt7IGluaXRpYWxzKCkgfX08L3NwYW4+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJjaC1oZWFkZXItdGl0bGVcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJjaC1oZWFkZXItbmFtZVwiPkNoYXQgd2l0aCB7eyBkaXNwbGF5TmFtZSgpIH19PC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiY2gtaGVhZGVyLXN0YXR1c1wiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYmNoLWhlYWRlci1zdGF0dXMtZG90XCIgW2F0dHIuZGF0YS1vbmxpbmVdPVwiaXNPbmxpbmVTdHIoKVwiPjwvc3Bhbj5cbiAgICAgICAgICAgICAgICB7eyBzdGF0dXNUZXh0KCkgfX1cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiYmNoLWhlYWRlci1jbG9zZVwiXG4gICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJDbG9zZVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbkNsb3NlKClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8c3ZnIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG4gICAgICAgICAgICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMi40XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCI+XG4gICAgICAgICAgICAgICAgPGxpbmUgeDE9XCIxOFwiIHkxPVwiNlwiIHgyPVwiNlwiIHkyPVwiMThcIiAvPlxuICAgICAgICAgICAgICAgIDxsaW5lIHgxPVwiNlwiIHkxPVwiNlwiIHgyPVwiMThcIiB5Mj1cIjE4XCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2hlYWRlcj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJiY2gtbWVzc2FnZXNcIiAjbWVzc2FnZXM+XG4gICAgICAgICAgICA8Ymxvb25pby1jaGF0LW1lc3NhZ2UtbGlzdFxuICAgICAgICAgICAgICBbbWVzc2FnZXNdPVwidmlzaWJsZU1lc3NhZ2VzKClcIlxuICAgICAgICAgICAgICBbYm90VHlwaW5nXT1cImNoYXQuYm90VHlwaW5nKClcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxibG9vbmlvLWNoYXQtcXVpY2stcmVwbGllcyAvPlxuXG4gICAgICAgICAgPGJsb29uaW8tY2hhdC1pbnB1dC1iYXJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJjaGF0LmNvbm5lY3RpbmcoKVwiXG4gICAgICAgICAgICAoc2VuZCk9XCJvblNlbmQoJGV2ZW50KVwiXG4gICAgICAgICAgLz5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJiY2gtZm9vdGVyXCI+XG4gICAgICAgICAgICBQb3dlcmVkIGJ5XG4gICAgICAgICAgICA8YSBocmVmPVwiaHR0cHM6Ly9ibG9vbmlvLmNvbVwiIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyIG5vcmVmZXJyZXJcIj5CbG9vbmlvPC9hPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBCbG9vbmlvQ2hhdFBhbmVsQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3Q2hlY2tlZCB7XG4gIC8qKiBmbG9hdGluZyA9IHBhaXJlZCB3aXRoIGxhdW5jaGVyIChkZWZhdWx0KS4gZG9ja2VkL2lubGluZSA9IGFsd2F5cy1vblxuICAgKiAgaW5zaWRlIHRoZSBwYWdlIGZsb3cgKHVzZSBmb3IgU1NSIGxhbmRpbmcgcGFnZXMgb3Igc2lkZWJhciBsYXlvdXRzKS4gKi9cbiAgQElucHV0KCkgbW9kZTogQ2hhdFBhbmVsTW9kZSA9ICdmbG9hdGluZyc7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGNoYXQgPSBpbmplY3QoQmxvb25pb0NoYXRTZXJ2aWNlKTtcblxuICBAVmlld0NoaWxkKCdtZXNzYWdlcycpIHByaXZhdGUgbWVzc2FnZXNSZWY/OiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcbiAgcHJpdmF0ZSBsYXN0U2Nyb2xsTGVuID0gc2lnbmFsKC0xKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcG9zaXRpb24gPSBjb21wdXRlZChcbiAgICAoKSA9PiB0aGlzLmNoYXQuYm9vdHN0cmFwKCk/LndpZGdldF9wb3NpdGlvbiA/PyAncmlnaHQnLFxuICApO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSB2aXNpYmxlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIC8vIEZsb2F0aW5nIG1vZGU6IG9ubHkgd2hlbiBzZXJ2aWNlLm9wZW4oKSBpcyB0cnVlLlxuICAgIC8vIERvY2tlZC9pbmxpbmU6IGFsd2F5cyByZW5kZXJlZCBpZiBib290c3RyYXAgaXMgbG9hZGVkLlxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdmbG9hdGluZycpIHJldHVybiB0aGlzLmNoYXQub3BlbigpO1xuICAgIHJldHVybiAhIXRoaXMuY2hhdC5ib290c3RyYXAoKTtcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHRoZW1lU3R5bGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY29sb3IgPSB0aGlzLmNoYXQuYm9vdHN0cmFwKCk/LmJyYW5kaW5nX3ByaW1hcnlfY29sb3I7XG4gICAgcmV0dXJuIGNvbG9yID8gYC0tYmNoLXByaW1hcnk6ICR7Y29sb3J9YCA6ICcnO1xuICB9KTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGlzcGxheU5hbWUgPSBjb21wdXRlZChcbiAgICAoKSA9PiB0aGlzLmNoYXQuYm9vdHN0cmFwKCk/LmJyYW5kaW5nX2Rpc3BsYXlfbmFtZVxuICAgICAgPz8gdGhpcy5jaGF0LmJvb3RzdHJhcCgpPy50ZW5hbnRfbmFtZVxuICAgICAgPz8gJ1N1cHBvcnQnLFxuICApO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBsb2dvVXJsID0gY29tcHV0ZWQoXG4gICAgKCkgPT4gdGhpcy5jaGF0LmJvb3RzdHJhcCgpPy5icmFuZGluZ19sb2dvX3VybCA/PyBudWxsLFxuICApO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBpbml0aWFscyA9IGNvbXB1dGVkKCgpID0+XG4gICAgdGhpcy5kaXNwbGF5TmFtZSgpXG4gICAgICAuc3BsaXQoL1xccysvKVxuICAgICAgLnNsaWNlKDAsIDIpXG4gICAgICAubWFwKCh3KSA9PiB3WzBdPy50b1VwcGVyQ2FzZSgpID8/ICcnKVxuICAgICAgLmpvaW4oJycpIHx8ICc/JyxcbiAgKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3RhdHVzVGV4dCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBiID0gdGhpcy5jaGF0LmJvb3RzdHJhcCgpO1xuICAgIGlmICghYikgcmV0dXJuICcnO1xuICAgIHJldHVybiBiLmlzX29ubGluZSA/IGIub25saW5lX3N0YXR1c190ZXh0IDogYi5vZmZsaW5lX3N0YXR1c190ZXh0O1xuICB9KTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNPbmxpbmVTdHIgPSBjb21wdXRlZChcbiAgICAoKSA9PiBTdHJpbmcodGhpcy5jaGF0LmJvb3RzdHJhcCgpPy5pc19vbmxpbmUgPz8gZmFsc2UpLFxuICApO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSB2aXNpYmxlTWVzc2FnZXMgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgYiA9IHRoaXMuY2hhdC5ib290c3RyYXAoKTtcbiAgICBjb25zdCBtZXNzYWdlcyA9IHRoaXMuY2hhdC5tZXNzYWdlcygpO1xuICAgIGlmIChiICYmICFiLmlzX29ubGluZSAmJiBtZXNzYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJ3N5c19vZmZsaW5lJyxcbiAgICAgICAgICBmcm9tOiAnc3lzdGVtJyBhcyBjb25zdCxcbiAgICAgICAgICBjb250ZW50OiBiLm9mZmxpbmVfbWVzc2FnZSxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfVxuICAgIHJldHVybiBtZXNzYWdlcztcbiAgfSk7XG5cbiAgbmdBZnRlclZpZXdDaGVja2VkKCk6IHZvaWQge1xuICAgIC8vIFNjcm9sbC10by1ib3R0b20gd2hlbmV2ZXIgbWVzc2FnZSBjb3VudCBjaGFuZ2VzLiBXZSBjb21wYXJlIGFnYWluc3QgYVxuICAgIC8vIHN0YW1wZWQgbGVuZ3RoIHNvIHdlIGRvbid0IGNodXJuIHdoZW4gb25seSB0eXBpbmcvc3RhdHVzIHVwZGF0ZXMgZmlyZS5cbiAgICBjb25zdCBlbCA9IHRoaXMubWVzc2FnZXNSZWY/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuICAgIGNvbnN0IGxlbiA9IHRoaXMudmlzaWJsZU1lc3NhZ2VzKCkubGVuZ3RoICsgKHRoaXMuY2hhdC5ib3RUeXBpbmcoKSA/IDEgOiAwKTtcbiAgICBpZiAobGVuICE9PSB0aGlzLmxhc3RTY3JvbGxMZW4oKSkge1xuICAgICAgZWwuc2Nyb2xsVG9wID0gZWwuc2Nyb2xsSGVpZ2h0O1xuICAgICAgdGhpcy5sYXN0U2Nyb2xsTGVuLnNldChsZW4pO1xuICAgIH1cbiAgfVxuXG4gIG9uQ2xvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5jaGF0LmNsb3NlUGFuZWwoKTtcbiAgfVxuXG4gIG9uU2VuZChjb250ZW50OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmNoYXQuc2VuZE1lc3NhZ2UoY29udGVudCk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<bloonio-chat-quick-replies>` — tenant-configured opening prompt chips,
|
|
3
|
+
* shown under the welcome message until the visitor sends their first
|
|
4
|
+
* message. Tapping a chip sends its text as that first message.
|
|
5
|
+
*
|
|
6
|
+
* Driven by `BloonioChatService` (reads `bootstrap().quick_replies` +
|
|
7
|
+
* `messages()`), so it self-hides once the conversation starts. Used inside
|
|
8
|
+
* both the floating panel and the headless thread.
|
|
9
|
+
*/
|
|
10
|
+
import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core';
|
|
11
|
+
import { BloonioChatService } from '../bloonio-chat.service';
|
|
12
|
+
import * as i0 from "@angular/core";
|
|
13
|
+
export class QuickRepliesComponent {
|
|
14
|
+
chat = inject(BloonioChatService);
|
|
15
|
+
/** Show the configured chips only until the visitor's first message. */
|
|
16
|
+
replies = computed(() => {
|
|
17
|
+
const bootstrap = this.chat.bootstrap();
|
|
18
|
+
if (!bootstrap || bootstrap.quick_replies.length === 0)
|
|
19
|
+
return [];
|
|
20
|
+
const visitorSpoke = this.chat.messages().some((m) => m.from === 'visitor');
|
|
21
|
+
return visitorSpoke ? [] : bootstrap.quick_replies;
|
|
22
|
+
});
|
|
23
|
+
pick(text) {
|
|
24
|
+
this.chat.sendMessage(text);
|
|
25
|
+
}
|
|
26
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: QuickRepliesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
27
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: QuickRepliesComponent, isStandalone: true, selector: "bloonio-chat-quick-replies", ngImport: i0, template: `
|
|
28
|
+
@if (replies().length) {
|
|
29
|
+
<div class="bch-quick-replies" role="group" aria-label="Suggested replies">
|
|
30
|
+
@for (reply of replies(); track reply) {
|
|
31
|
+
<button type="button" class="bch-quick-reply" (click)="pick(reply)">
|
|
32
|
+
{{ reply }}
|
|
33
|
+
</button>
|
|
34
|
+
}
|
|
35
|
+
</div>
|
|
36
|
+
}
|
|
37
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
38
|
+
}
|
|
39
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: QuickRepliesComponent, decorators: [{
|
|
40
|
+
type: Component,
|
|
41
|
+
args: [{
|
|
42
|
+
selector: 'bloonio-chat-quick-replies',
|
|
43
|
+
standalone: true,
|
|
44
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
45
|
+
template: `
|
|
46
|
+
@if (replies().length) {
|
|
47
|
+
<div class="bch-quick-replies" role="group" aria-label="Suggested replies">
|
|
48
|
+
@for (reply of replies(); track reply) {
|
|
49
|
+
<button type="button" class="bch-quick-reply" (click)="pick(reply)">
|
|
50
|
+
{{ reply }}
|
|
51
|
+
</button>
|
|
52
|
+
}
|
|
53
|
+
</div>
|
|
54
|
+
}
|
|
55
|
+
`,
|
|
56
|
+
}]
|
|
57
|
+
}] });
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVpY2stcmVwbGllcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvcXVpY2stcmVwbGllcy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFDSCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFckYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7O0FBa0I3RCxNQUFNLE9BQU8scUJBQXFCO0lBQ2IsSUFBSSxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBRXJELHdFQUF3RTtJQUNyRCxPQUFPLEdBQUcsUUFBUSxDQUFXLEdBQUcsRUFBRTtRQUNuRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ2xFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxDQUFDO1FBQzVFLE9BQU8sWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUM7SUFDckQsQ0FBQyxDQUFDLENBQUM7SUFFTyxJQUFJLENBQUMsSUFBWTtRQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QixDQUFDO3dHQWJVLHFCQUFxQjs0RkFBckIscUJBQXFCLHNGQVp0Qjs7Ozs7Ozs7OztHQVVUOzs0RkFFVSxxQkFBcUI7a0JBaEJqQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSw0QkFBNEI7b0JBQ3RDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsUUFBUSxFQUFFOzs7Ozs7Ozs7O0dBVVQ7aUJBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGA8Ymxvb25pby1jaGF0LXF1aWNrLXJlcGxpZXM+YCDigJQgdGVuYW50LWNvbmZpZ3VyZWQgb3BlbmluZyBwcm9tcHQgY2hpcHMsXG4gKiBzaG93biB1bmRlciB0aGUgd2VsY29tZSBtZXNzYWdlIHVudGlsIHRoZSB2aXNpdG9yIHNlbmRzIHRoZWlyIGZpcnN0XG4gKiBtZXNzYWdlLiBUYXBwaW5nIGEgY2hpcCBzZW5kcyBpdHMgdGV4dCBhcyB0aGF0IGZpcnN0IG1lc3NhZ2UuXG4gKlxuICogRHJpdmVuIGJ5IGBCbG9vbmlvQ2hhdFNlcnZpY2VgIChyZWFkcyBgYm9vdHN0cmFwKCkucXVpY2tfcmVwbGllc2AgK1xuICogYG1lc3NhZ2VzKClgKSwgc28gaXQgc2VsZi1oaWRlcyBvbmNlIHRoZSBjb252ZXJzYXRpb24gc3RhcnRzLiBVc2VkIGluc2lkZVxuICogYm90aCB0aGUgZmxvYXRpbmcgcGFuZWwgYW5kIHRoZSBoZWFkbGVzcyB0aHJlYWQuXG4gKi9cbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgQmxvb25pb0NoYXRTZXJ2aWNlIH0gZnJvbSAnLi4vYmxvb25pby1jaGF0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdibG9vbmlvLWNoYXQtcXVpY2stcmVwbGllcycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAocmVwbGllcygpLmxlbmd0aCkge1xuICAgICAgPGRpdiBjbGFzcz1cImJjaC1xdWljay1yZXBsaWVzXCIgcm9sZT1cImdyb3VwXCIgYXJpYS1sYWJlbD1cIlN1Z2dlc3RlZCByZXBsaWVzXCI+XG4gICAgICAgIEBmb3IgKHJlcGx5IG9mIHJlcGxpZXMoKTsgdHJhY2sgcmVwbHkpIHtcbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJjaC1xdWljay1yZXBseVwiIChjbGljayk9XCJwaWNrKHJlcGx5KVwiPlxuICAgICAgICAgICAge3sgcmVwbHkgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgfVxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBRdWlja1JlcGxpZXNDb21wb25lbnQge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2hhdCA9IGluamVjdChCbG9vbmlvQ2hhdFNlcnZpY2UpO1xuXG4gIC8qKiBTaG93IHRoZSBjb25maWd1cmVkIGNoaXBzIG9ubHkgdW50aWwgdGhlIHZpc2l0b3IncyBmaXJzdCBtZXNzYWdlLiAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVwbGllcyA9IGNvbXB1dGVkPHN0cmluZ1tdPigoKSA9PiB7XG4gICAgY29uc3QgYm9vdHN0cmFwID0gdGhpcy5jaGF0LmJvb3RzdHJhcCgpO1xuICAgIGlmICghYm9vdHN0cmFwIHx8IGJvb3RzdHJhcC5xdWlja19yZXBsaWVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdO1xuICAgIGNvbnN0IHZpc2l0b3JTcG9rZSA9IHRoaXMuY2hhdC5tZXNzYWdlcygpLnNvbWUoKG0pID0+IG0uZnJvbSA9PT0gJ3Zpc2l0b3InKTtcbiAgICByZXR1cm4gdmlzaXRvclNwb2tlID8gW10gOiBib290c3RyYXAucXVpY2tfcmVwbGllcztcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIHBpY2sodGV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jaGF0LnNlbmRNZXNzYWdlKHRleHQpO1xuICB9XG59XG4iXX0=
|