@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.
- package/dist/components/bb-custom-avatar.d.ts +20 -0
- package/dist/components/bb-custom-avatar.js +145 -0
- package/dist/components/bb-letter-avatar.d.ts +14 -0
- package/dist/components/bb-letter-avatar.js +61 -0
- package/dist/components/bb-loading-overlay.d.ts +14 -0
- package/dist/components/bb-loading-overlay.js +89 -0
- package/dist/components/bb-message-bubble.d.ts +19 -0
- package/dist/components/bb-message-bubble.js +116 -0
- package/dist/components/bb-message.d.ts +27 -0
- package/dist/components/bb-message.js +174 -0
- package/dist/components/bb-msg-history.d.ts +111 -0
- package/dist/components/bb-msg-history.js +473 -0
- package/dist/components/bb-scroll-button.d.ts +16 -0
- package/dist/components/bb-scroll-button.js +161 -0
- package/dist/components/bb-timestamp.d.ts +15 -0
- package/dist/components/bb-timestamp.js +59 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.js +7 -0
- package/dist/const/styles.js +0 -33
- package/dist/contexts/author-context.d.ts +8 -0
- package/dist/contexts/author-context.js +6 -0
- package/dist/controllers/scroll-controller.d.ts +52 -0
- package/dist/controllers/scroll-controller.js +138 -0
- package/dist/core/renderer.js +1 -9
- package/dist/parsers/base.d.ts +21 -0
- package/dist/parsers/base.js +1 -0
- package/dist/parsers/default-parser.d.ts +10 -0
- package/dist/parsers/default-parser.js +40 -0
- package/dist/parsers/index.d.ts +2 -0
- package/dist/parsers/index.js +1 -0
- package/dist/utils/message-builder.d.ts +0 -4
- package/dist/utils/message-builder.js +0 -15
- package/dist/utils/tooltip.d.ts +11 -2
- package/dist/utils/tooltip.js +56 -13
- package/package.json +1 -1
- package/src/const/styles.ts +0 -33
- package/src/core/renderer.ts +1 -11
- package/src/utils/message-builder.ts +0 -15
- 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 };
|