@bbki.ng/bb-msg-history 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/components/bb-custom-avatar.d.ts +20 -0
  2. package/dist/components/bb-custom-avatar.js +145 -0
  3. package/dist/components/bb-letter-avatar.d.ts +14 -0
  4. package/dist/components/bb-letter-avatar.js +61 -0
  5. package/dist/components/bb-loading-overlay.d.ts +14 -0
  6. package/dist/components/bb-loading-overlay.js +89 -0
  7. package/dist/components/bb-message-bubble.d.ts +19 -0
  8. package/dist/components/bb-message-bubble.js +116 -0
  9. package/dist/components/bb-message.d.ts +27 -0
  10. package/dist/components/bb-message.js +174 -0
  11. package/dist/components/bb-msg-history.d.ts +111 -0
  12. package/dist/components/bb-msg-history.js +473 -0
  13. package/dist/components/bb-scroll-button.d.ts +16 -0
  14. package/dist/components/bb-scroll-button.js +161 -0
  15. package/dist/components/bb-timestamp.d.ts +15 -0
  16. package/dist/components/bb-timestamp.js +59 -0
  17. package/dist/components/index.d.ts +7 -0
  18. package/dist/components/index.js +7 -0
  19. package/dist/const/styles.js +0 -33
  20. package/dist/contexts/author-context.d.ts +8 -0
  21. package/dist/contexts/author-context.js +6 -0
  22. package/dist/controllers/scroll-controller.d.ts +52 -0
  23. package/dist/controllers/scroll-controller.js +138 -0
  24. package/dist/core/renderer.js +1 -9
  25. package/dist/parsers/base.d.ts +21 -0
  26. package/dist/parsers/base.js +1 -0
  27. package/dist/parsers/default-parser.d.ts +10 -0
  28. package/dist/parsers/default-parser.js +40 -0
  29. package/dist/parsers/index.d.ts +2 -0
  30. package/dist/parsers/index.js +1 -0
  31. package/dist/utils/message-builder.d.ts +0 -4
  32. package/dist/utils/message-builder.js +0 -15
  33. package/dist/utils/tooltip.d.ts +11 -2
  34. package/dist/utils/tooltip.js +56 -13
  35. package/package.json +1 -1
  36. package/src/const/styles.ts +0 -33
  37. package/src/core/renderer.ts +1 -11
  38. package/src/utils/message-builder.ts +0 -15
  39. package/src/utils/tooltip.ts +0 -16
@@ -0,0 +1,20 @@
1
+ import { LitElement } from 'lit';
2
+ /**
3
+ * Custom avatar component - displays SVG, img, emoji, or HTML content
4
+ * Includes tooltip on hover
5
+ */
6
+ export declare class BBCustomAvatar extends LitElement {
7
+ static styles: import("lit").CSSResult;
8
+ tooltip: string;
9
+ private _tooltipRef;
10
+ private _showTooltip;
11
+ private _onMouseEnter;
12
+ private _onMouseLeave;
13
+ private _positionTooltip;
14
+ render(): import("lit").TemplateResult<1>;
15
+ }
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'bb-custom-avatar': BBCustomAvatar;
19
+ }
20
+ }
@@ -0,0 +1,145 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, html, css, unsafeCSS } from 'lit';
8
+ import { customElement, property } from 'lit/decorators.js';
9
+ import { THEME } from '../const/theme.js';
10
+ /**
11
+ * Custom avatar component - displays SVG, img, emoji, or HTML content
12
+ * Includes tooltip on hover
13
+ */
14
+ let BBCustomAvatar = class BBCustomAvatar extends LitElement {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.tooltip = '';
18
+ this._tooltipRef = null;
19
+ this._showTooltip = false;
20
+ }
21
+ static { this.styles = css `
22
+ :host {
23
+ display: block;
24
+ width: 1.75rem;
25
+ height: 1.75rem;
26
+ }
27
+
28
+ .avatar-wrapper {
29
+ position: relative;
30
+ width: 100%;
31
+ height: 100%;
32
+ background: #ffffff;
33
+ border-radius: 50%;
34
+ overflow: hidden;
35
+ cursor: help;
36
+ }
37
+
38
+ .avatar {
39
+ width: 100%;
40
+ height: 100%;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ border-radius: 50%;
45
+ overflow: hidden;
46
+ }
47
+
48
+ .avatar ::slotted(svg) {
49
+ width: 100%;
50
+ height: 100%;
51
+ }
52
+
53
+ .avatar ::slotted(img) {
54
+ width: 100%;
55
+ height: 100%;
56
+ object-fit: cover;
57
+ }
58
+
59
+ /* Tooltip styles */
60
+ .avatar-tooltip {
61
+ position: fixed;
62
+ padding: 0.25rem 0.5rem;
63
+ background: ${unsafeCSS(THEME.gray[800])};
64
+ color: ${unsafeCSS(THEME.gray[50])};
65
+ font-size: 0.75rem;
66
+ border-radius: 0.25rem;
67
+ white-space: nowrap;
68
+ opacity: 0;
69
+ visibility: hidden;
70
+ pointer-events: none;
71
+ z-index: 10000;
72
+ font-weight: 500;
73
+ letter-spacing: 0.02em;
74
+ transition:
75
+ opacity 0.2s ease,
76
+ visibility 0.2s ease;
77
+ }
78
+
79
+ .avatar-tooltip::after {
80
+ content: '';
81
+ position: absolute;
82
+ top: calc(100% - 1px);
83
+ left: 50%;
84
+ transform: translateX(-50%);
85
+ border: 4px solid transparent;
86
+ border-top-color: ${unsafeCSS(THEME.gray[800])};
87
+ }
88
+
89
+ .avatar-tooltip.visible {
90
+ opacity: 1;
91
+ visibility: visible;
92
+ }
93
+
94
+ @media (max-width: 480px) {
95
+ :host {
96
+ width: 1.5rem;
97
+ height: 1.5rem;
98
+ }
99
+ }
100
+ `; }
101
+ _onMouseEnter() {
102
+ this._showTooltip = true;
103
+ this._positionTooltip();
104
+ this.requestUpdate();
105
+ }
106
+ _onMouseLeave() {
107
+ this._showTooltip = false;
108
+ this.requestUpdate();
109
+ }
110
+ _positionTooltip() {
111
+ if (!this._tooltipRef || !this._showTooltip)
112
+ return;
113
+ const rect = this.getBoundingClientRect();
114
+ const tooltipRect = this._tooltipRef.getBoundingClientRect();
115
+ this._tooltipRef.style.left = `${rect.left + rect.width / 2 - tooltipRect.width / 2}px`;
116
+ this._tooltipRef.style.top = `${rect.top - tooltipRect.height - 8}px`;
117
+ }
118
+ render() {
119
+ return html `
120
+ <div
121
+ class="avatar-wrapper"
122
+ @mouseenter=${this._onMouseEnter}
123
+ @mouseleave=${this._onMouseLeave}
124
+ >
125
+ <div class="avatar"><slot></slot></div>
126
+ </div>
127
+ <div
128
+ class="avatar-tooltip ${this._showTooltip ? 'visible' : ''}"
129
+ ${(el) => {
130
+ if (el)
131
+ this._tooltipRef = el;
132
+ }}
133
+ >
134
+ ${this.tooltip}
135
+ </div>
136
+ `;
137
+ }
138
+ };
139
+ __decorate([
140
+ property()
141
+ ], BBCustomAvatar.prototype, "tooltip", void 0);
142
+ BBCustomAvatar = __decorate([
143
+ customElement('bb-custom-avatar')
144
+ ], BBCustomAvatar);
145
+ export { BBCustomAvatar };
@@ -0,0 +1,14 @@
1
+ import { LitElement } from 'lit';
2
+ /**
3
+ * Letter avatar component - displays a letter in a circular container
4
+ */
5
+ export declare class BBLetterAvatar extends LitElement {
6
+ static styles: import("lit").CSSResult;
7
+ letter: string;
8
+ render(): import("lit").TemplateResult<1>;
9
+ }
10
+ declare global {
11
+ interface HTMLElementTagNameMap {
12
+ 'bb-letter-avatar': BBLetterAvatar;
13
+ }
14
+ }
@@ -0,0 +1,61 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, html, css, unsafeCSS } from 'lit';
8
+ import { customElement, property } from 'lit/decorators.js';
9
+ import { THEME } from '../const/theme.js';
10
+ /**
11
+ * Letter avatar component - displays a letter in a circular container
12
+ */
13
+ let BBLetterAvatar = class BBLetterAvatar extends LitElement {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.letter = '';
17
+ }
18
+ static { this.styles = css `
19
+ :host {
20
+ display: block;
21
+ width: 1.75rem;
22
+ height: 1.75rem;
23
+ }
24
+
25
+ .avatar {
26
+ width: 100%;
27
+ height: 100%;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ background: var(--bb-avatar-bg, #ffffff);
32
+ color: var(--bb-avatar-color, ${unsafeCSS(THEME.gray[600])});
33
+ font-size: 14px;
34
+ font-weight: 600;
35
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
36
+ border-radius: 50%;
37
+ overflow: hidden;
38
+ }
39
+
40
+ @media (max-width: 480px) {
41
+ :host {
42
+ width: 1.5rem;
43
+ height: 1.5rem;
44
+ }
45
+
46
+ .avatar {
47
+ font-size: 12px;
48
+ }
49
+ }
50
+ `; }
51
+ render() {
52
+ return html `<div class="avatar">${this.letter}</div>`;
53
+ }
54
+ };
55
+ __decorate([
56
+ property()
57
+ ], BBLetterAvatar.prototype, "letter", void 0);
58
+ BBLetterAvatar = __decorate([
59
+ customElement('bb-letter-avatar')
60
+ ], BBLetterAvatar);
61
+ export { BBLetterAvatar };
@@ -0,0 +1,14 @@
1
+ import { LitElement } from 'lit';
2
+ /**
3
+ * Loading overlay component - displays spinner overlay
4
+ */
5
+ export declare class BBLoadingOverlay extends LitElement {
6
+ static styles: import("lit").CSSResult;
7
+ visible: boolean;
8
+ render(): import("lit").TemplateResult<1>;
9
+ }
10
+ declare global {
11
+ interface HTMLElementTagNameMap {
12
+ 'bb-loading-overlay': BBLoadingOverlay;
13
+ }
14
+ }
@@ -0,0 +1,89 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, html, css, unsafeCSS } from 'lit';
8
+ import { customElement, property } from 'lit/decorators.js';
9
+ import { THEME } from '../const/theme.js';
10
+ /**
11
+ * Loading overlay component - displays spinner overlay
12
+ */
13
+ let BBLoadingOverlay = class BBLoadingOverlay extends LitElement {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.visible = false;
17
+ }
18
+ static { this.styles = css `
19
+ :host {
20
+ display: block;
21
+ position: absolute;
22
+ inset: 0;
23
+ z-index: 20;
24
+ }
25
+
26
+ .overlay {
27
+ position: absolute;
28
+ inset: 0;
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ background: rgba(255, 255, 255, 0.6);
33
+ backdrop-filter: blur(1px);
34
+ border-radius: 0.5rem;
35
+ min-height: 120px;
36
+ }
37
+
38
+ .spinner {
39
+ width: 24px;
40
+ height: 24px;
41
+ border: 2px solid ${unsafeCSS(THEME.gray[200])};
42
+ border-top-color: ${unsafeCSS(THEME.gray[500])};
43
+ border-radius: 50%;
44
+ animation: spin 0.8s linear infinite;
45
+ }
46
+
47
+ @keyframes spin {
48
+ to {
49
+ transform: rotate(360deg);
50
+ }
51
+ }
52
+
53
+ @media (prefers-reduced-motion: reduce) {
54
+ .spinner {
55
+ animation-duration: 1.5s;
56
+ opacity: 0.8;
57
+ }
58
+ }
59
+
60
+ /* Dark mode */
61
+ @media (prefers-color-scheme: dark) {
62
+ .overlay {
63
+ background: rgba(17, 24, 39, 0.6);
64
+ }
65
+
66
+ .spinner {
67
+ border-color: ${unsafeCSS(THEME.gray[700])};
68
+ border-top-color: ${unsafeCSS(THEME.gray[400])};
69
+ }
70
+ }
71
+ `; }
72
+ render() {
73
+ if (!this.visible) {
74
+ return html ``;
75
+ }
76
+ return html `
77
+ <div class="overlay" role="status" aria-label="Loading messages">
78
+ <div class="spinner"></div>
79
+ </div>
80
+ `;
81
+ }
82
+ };
83
+ __decorate([
84
+ property({ type: Boolean, reflect: true })
85
+ ], BBLoadingOverlay.prototype, "visible", void 0);
86
+ BBLoadingOverlay = __decorate([
87
+ customElement('bb-loading-overlay')
88
+ ], BBLoadingOverlay);
89
+ export { BBLoadingOverlay };
@@ -0,0 +1,19 @@
1
+ import { LitElement } from 'lit';
2
+ /**
3
+ * Message bubble component - displays message text with theming
4
+ */
5
+ export declare class BBMessageBubble extends LitElement {
6
+ static styles: import("lit").CSSResult;
7
+ text: string;
8
+ side: 'left' | 'right';
9
+ subsequent: boolean;
10
+ customBg: string;
11
+ customColor: string;
12
+ private _getInlineStyles;
13
+ render(): import("lit").TemplateResult<1>;
14
+ }
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ 'bb-message-bubble': BBMessageBubble;
18
+ }
19
+ }
@@ -0,0 +1,116 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, html, css, unsafeCSS } from 'lit';
8
+ import { customElement, property } from 'lit/decorators.js';
9
+ import { THEME } from '../const/theme.js';
10
+ /**
11
+ * Message bubble component - displays message text with theming
12
+ */
13
+ let BBMessageBubble = class BBMessageBubble extends LitElement {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.text = '';
17
+ this.side = 'left';
18
+ this.subsequent = false;
19
+ this.customBg = '';
20
+ this.customColor = '';
21
+ }
22
+ static { this.styles = css `
23
+ :host {
24
+ display: block;
25
+ --bubble-bg: var(--bb-bubble-bg, ${unsafeCSS(THEME.gray[50])});
26
+ --bubble-color: var(--bb-bubble-color, ${unsafeCSS(THEME.gray[900])});
27
+ --bubble-radius: 1rem;
28
+ }
29
+
30
+ :host([side='right']) {
31
+ --bubble-bg: var(--bb-bubble-right-bg, ${unsafeCSS(THEME.gray[200])});
32
+ }
33
+
34
+ .bubble {
35
+ padding: 0.625rem 0.875rem;
36
+ font-size: 0.9375rem;
37
+ line-height: 1.5;
38
+ word-wrap: break-word;
39
+ overflow-wrap: anywhere;
40
+ word-break: break-word;
41
+ border-radius: var(--bubble-radius);
42
+ background-color: var(--bubble-bg);
43
+ color: var(--bubble-color);
44
+ }
45
+
46
+ /* Left side bubble - squared bottom left */
47
+ :host([side='left']:not([subsequent])) .bubble {
48
+ border-bottom-left-radius: 0.25rem;
49
+ }
50
+
51
+ /* Right side bubble - squared bottom right */
52
+ :host([side='right']:not([subsequent])) .bubble {
53
+ border-bottom-right-radius: 0.25rem;
54
+ }
55
+
56
+ @media (max-width: 480px) {
57
+ .bubble {
58
+ font-size: 0.9375rem;
59
+ padding: 0.5rem 0.75rem;
60
+ }
61
+ }
62
+
63
+ /* Dark mode support */
64
+ @media (prefers-color-scheme: dark) {
65
+ :host {
66
+ --bubble-bg: var(--bb-bubble-bg-dark, ${unsafeCSS(THEME.slate[800])});
67
+ --bubble-color: var(--bb-bubble-color-dark, ${unsafeCSS(THEME.slate[100])});
68
+ }
69
+
70
+ :host([side='right']) {
71
+ --bubble-bg: var(--bb-bubble-right-bg-dark, ${unsafeCSS(THEME.slate[700])});
72
+ }
73
+
74
+ .bubble {
75
+ border: 1px solid ${unsafeCSS(THEME.slate[700])};
76
+ }
77
+
78
+ :host([side='right']) .bubble {
79
+ border: none;
80
+ }
81
+ }
82
+ `; }
83
+ _getInlineStyles() {
84
+ const styles = [];
85
+ if (this.customBg) {
86
+ styles.push(`background-color: ${this.customBg}`);
87
+ }
88
+ if (this.customColor) {
89
+ styles.push(`color: ${this.customColor}`);
90
+ }
91
+ return styles.length > 0 ? styles.join('; ') : '';
92
+ }
93
+ render() {
94
+ const style = this._getInlineStyles();
95
+ return html `<div class="bubble" style="${style}">${this.text}</div>`;
96
+ }
97
+ };
98
+ __decorate([
99
+ property()
100
+ ], BBMessageBubble.prototype, "text", void 0);
101
+ __decorate([
102
+ property({ reflect: true })
103
+ ], BBMessageBubble.prototype, "side", void 0);
104
+ __decorate([
105
+ property({ type: Boolean, reflect: true })
106
+ ], BBMessageBubble.prototype, "subsequent", void 0);
107
+ __decorate([
108
+ property({ attribute: 'custom-bg' })
109
+ ], BBMessageBubble.prototype, "customBg", void 0);
110
+ __decorate([
111
+ property({ attribute: 'custom-color' })
112
+ ], BBMessageBubble.prototype, "customColor", void 0);
113
+ BBMessageBubble = __decorate([
114
+ customElement('bb-message-bubble')
115
+ ], BBMessageBubble);
116
+ export { BBMessageBubble };
@@ -0,0 +1,27 @@
1
+ import { LitElement, type PropertyValues } from 'lit';
2
+ import './bb-letter-avatar.js';
3
+ import './bb-custom-avatar.js';
4
+ import './bb-message-bubble.js';
5
+ import './bb-timestamp.js';
6
+ /**
7
+ * Message row component - composes avatar, bubble, and timestamp
8
+ */
9
+ export declare class BBMessage extends LitElement {
10
+ static styles: import("lit").CSSResult;
11
+ author: string;
12
+ text: string;
13
+ timestamp: string;
14
+ subsequent: boolean;
15
+ lastInGroup: boolean;
16
+ side: 'left' | 'right';
17
+ private _authors?;
18
+ private _getConfig;
19
+ willUpdate(changedProps: PropertyValues<this>): void;
20
+ private _renderAvatar;
21
+ render(): import("lit").TemplateResult<1>;
22
+ }
23
+ declare global {
24
+ interface HTMLElementTagNameMap {
25
+ 'bb-message': BBMessage;
26
+ }
27
+ }
@@ -0,0 +1,174 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, html, css, nothing } from 'lit';
8
+ import { customElement, property, state } from 'lit/decorators.js';
9
+ import { consume } from '@lit/context';
10
+ import { authorContext } from '../contexts/author-context.js';
11
+ import { resolveAuthorConfig } from '../utils/author-resolver.js';
12
+ import { FIRST_CHAR_AVATAR_AUTHORS } from '../const/authors.js';
13
+ import './bb-letter-avatar.js';
14
+ import './bb-custom-avatar.js';
15
+ import './bb-message-bubble.js';
16
+ import './bb-timestamp.js';
17
+ /**
18
+ * Message row component - composes avatar, bubble, and timestamp
19
+ */
20
+ let BBMessage = class BBMessage extends LitElement {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.author = '';
24
+ this.text = '';
25
+ this.timestamp = '';
26
+ this.subsequent = false;
27
+ this.lastInGroup = false;
28
+ }
29
+ static { this.styles = css `
30
+ :host {
31
+ display: flex;
32
+ align-items: flex-end;
33
+ gap: 0.5rem;
34
+ max-width: 80%;
35
+ }
36
+
37
+ :host([side='left']) {
38
+ align-self: flex-start;
39
+ margin-right: auto;
40
+ }
41
+
42
+ :host([side='right']) {
43
+ align-self: flex-end;
44
+ margin-left: auto;
45
+ flex-direction: row-reverse;
46
+ }
47
+
48
+ :host([subsequent]) {
49
+ margin-top: 0.375rem;
50
+ }
51
+
52
+ :host(:not([subsequent])) {
53
+ margin-top: 0.75rem;
54
+ }
55
+
56
+ :host(:first-of-type:not([subsequent])) {
57
+ margin-top: 0;
58
+ }
59
+
60
+ .content {
61
+ display: flex;
62
+ flex-direction: column;
63
+ position: relative;
64
+ padding-bottom: 12px;
65
+ }
66
+
67
+ .avatar-container {
68
+ flex-shrink: 0;
69
+ width: 1.75rem;
70
+ height: 1.75rem;
71
+ }
72
+
73
+ :host([subsequent]) .avatar-container {
74
+ opacity: 0;
75
+ pointer-events: none;
76
+ }
77
+
78
+ @media (max-width: 480px) {
79
+ :host {
80
+ max-width: 85%;
81
+ }
82
+
83
+ .avatar-container {
84
+ width: 1.5rem;
85
+ height: 1.5rem;
86
+ }
87
+ }
88
+ `; }
89
+ _getConfig() {
90
+ return resolveAuthorConfig(this.author, this._authors ?? new Map());
91
+ }
92
+ _renderAvatar(config) {
93
+ const isLetterAvatar = !config.isCustomAvatar || FIRST_CHAR_AVATAR_AUTHORS.has(this.author);
94
+ if (isLetterAvatar) {
95
+ return html `
96
+ <bb-letter-avatar
97
+ class="avatar-container"
98
+ .letter=${this.author.charAt(0).toUpperCase()}
99
+ ></bb-letter-avatar>
100
+ `;
101
+ }
102
+ // Custom avatar - need to parse the avatar HTML
103
+ const avatarContent = config.avatar;
104
+ const isPlainText = !avatarContent.includes('<');
105
+ if (isPlainText) {
106
+ // Single emoji or text - wrap in styled div
107
+ return html `
108
+ <bb-custom-avatar class="avatar-container" .tooltip=${this.author}>
109
+ <div
110
+ style="
111
+ width: 100%;
112
+ height: 100%;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ font-size: 18px;
117
+ line-height: 1;
118
+ "
119
+ >
120
+ ${avatarContent}
121
+ </div>
122
+ </bb-custom-avatar>
123
+ `;
124
+ }
125
+ // HTML content (SVG, img, etc.)
126
+ return html `
127
+ <bb-custom-avatar class="avatar-container" .tooltip=${this.author}>
128
+ <div .innerHTML=${avatarContent}></div>
129
+ </bb-custom-avatar>
130
+ `;
131
+ }
132
+ render() {
133
+ const config = this._getConfig();
134
+ const side = config.side;
135
+ return html `
136
+ ${this._renderAvatar(config)}
137
+ <div class="content">
138
+ <bb-message-bubble
139
+ .text=${this.text}
140
+ side=${side}
141
+ ?subsequent=${this.subsequent}
142
+ custom-bg=${config.bubbleColor}
143
+ custom-color=${config.textColor}
144
+ ></bb-message-bubble>
145
+ ${this.lastInGroup && this.timestamp
146
+ ? html `<bb-timestamp .value=${this.timestamp} side=${side}></bb-timestamp>`
147
+ : nothing}
148
+ </div>
149
+ `;
150
+ }
151
+ };
152
+ __decorate([
153
+ property()
154
+ ], BBMessage.prototype, "author", void 0);
155
+ __decorate([
156
+ property()
157
+ ], BBMessage.prototype, "text", void 0);
158
+ __decorate([
159
+ property()
160
+ ], BBMessage.prototype, "timestamp", void 0);
161
+ __decorate([
162
+ property({ type: Boolean, reflect: true })
163
+ ], BBMessage.prototype, "subsequent", void 0);
164
+ __decorate([
165
+ property({ type: Boolean, reflect: true })
166
+ ], BBMessage.prototype, "lastInGroup", void 0);
167
+ __decorate([
168
+ consume({ context: authorContext, subscribe: true }),
169
+ state()
170
+ ], BBMessage.prototype, "_authors", void 0);
171
+ BBMessage = __decorate([
172
+ customElement('bb-message')
173
+ ], BBMessage);
174
+ export { BBMessage };