@bbki.ng/bb-msg-history 0.14.1 → 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/component.d.ts +6 -18
- package/dist/component.js +43 -275
- 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/authors.js +1 -1
- 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/message-processor.d.ts +56 -0
- package/dist/core/message-processor.js +85 -0
- package/dist/core/renderer.d.ts +87 -0
- package/dist/core/renderer.js +196 -0
- package/dist/core/scroll-manager.d.ts +54 -0
- package/dist/core/scroll-manager.js +119 -0
- 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/event-tracker.d.ts +23 -0
- package/dist/utils/event-tracker.js +33 -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/component.ts +56 -338
- package/src/const/authors.ts +3 -2
- package/src/const/styles.ts +0 -33
- package/src/core/message-processor.ts +120 -0
- package/src/core/renderer.ts +276 -0
- package/src/core/scroll-manager.ts +148 -0
- package/src/utils/event-tracker.ts +38 -0
- package/src/utils/message-builder.ts +0 -15
- package/src/utils/tooltip.ts +0 -16
|
@@ -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 };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { LitElement, type PropertyValues } from 'lit';
|
|
2
|
+
import type { AuthorOptions } from '../types/index.js';
|
|
3
|
+
import type { MessageParser, MessageInput } from '../parsers/base.js';
|
|
4
|
+
import './bb-message.js';
|
|
5
|
+
import './bb-scroll-button.js';
|
|
6
|
+
import './bb-loading-overlay.js';
|
|
7
|
+
/**
|
|
8
|
+
* BBMsgHistory - A chat-style message history web component
|
|
9
|
+
*
|
|
10
|
+
* Uses Lit for reactive rendering with a compositional architecture.
|
|
11
|
+
* Preserves backward compatibility with the lightweight textContent mode.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```html
|
|
15
|
+
* <!-- Lightweight mode -->
|
|
16
|
+
* <bb-msg-history>
|
|
17
|
+
* alice: Hello!
|
|
18
|
+
* bob: Hi there!
|
|
19
|
+
* </bb-msg-history>
|
|
20
|
+
*
|
|
21
|
+
* <!-- With custom authors -->
|
|
22
|
+
* <bb-msg-history id="chat"></bb-msg-history>
|
|
23
|
+
* <script>
|
|
24
|
+
* document.getElementById('chat')
|
|
25
|
+
* .setAuthor('alice', { avatar: '🐱', side: 'right' });
|
|
26
|
+
* </script>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare class BBMsgHistory extends LitElement {
|
|
30
|
+
static styles: import("lit").CSSResult;
|
|
31
|
+
loading: boolean;
|
|
32
|
+
hideScrollBar: boolean;
|
|
33
|
+
infinite: boolean;
|
|
34
|
+
hideScrollButton: boolean;
|
|
35
|
+
theme: 'light' | 'dark' | null;
|
|
36
|
+
private _messages;
|
|
37
|
+
private _processedMessages;
|
|
38
|
+
private _userAuthors;
|
|
39
|
+
private _mutationObserver?;
|
|
40
|
+
private _isParsing;
|
|
41
|
+
private _parser;
|
|
42
|
+
private _scrollController;
|
|
43
|
+
connectedCallback(): void;
|
|
44
|
+
disconnectedCallback(): void;
|
|
45
|
+
willUpdate(changedProps: PropertyValues<BBMsgHistory>): void;
|
|
46
|
+
updated(changedProps: PropertyValues<BBMsgHistory>): void;
|
|
47
|
+
/**
|
|
48
|
+
* Configure an author's avatar, side, and colors.
|
|
49
|
+
* Call before or after rendering — the component re-renders automatically.
|
|
50
|
+
*/
|
|
51
|
+
setAuthor(name: string, options: AuthorOptions): this;
|
|
52
|
+
/**
|
|
53
|
+
* Remove a previously set author config.
|
|
54
|
+
*/
|
|
55
|
+
removeAuthor(name: string): this;
|
|
56
|
+
/**
|
|
57
|
+
* Show or hide the loading overlay.
|
|
58
|
+
*/
|
|
59
|
+
setLoading(isLoading: boolean): this;
|
|
60
|
+
/**
|
|
61
|
+
* Append a message to the history.
|
|
62
|
+
* Automatically scrolls to the new message with smooth animation.
|
|
63
|
+
*/
|
|
64
|
+
appendMessage(input: MessageInput): this;
|
|
65
|
+
/**
|
|
66
|
+
* Scroll to the bottom of the message history.
|
|
67
|
+
*/
|
|
68
|
+
scrollToBottom(): this;
|
|
69
|
+
/**
|
|
70
|
+
* Set a custom parser for message parsing
|
|
71
|
+
*/
|
|
72
|
+
setParser(parser: MessageParser): this;
|
|
73
|
+
/**
|
|
74
|
+
* Initialize MutationObserver for Light DOM observation
|
|
75
|
+
*/
|
|
76
|
+
private _initLightDOMObserver;
|
|
77
|
+
/**
|
|
78
|
+
* Parse Light DOM textContent into messages
|
|
79
|
+
*/
|
|
80
|
+
private _parseLightDOM;
|
|
81
|
+
/**
|
|
82
|
+
* Check if messages have changed
|
|
83
|
+
*/
|
|
84
|
+
private _messagesChanged;
|
|
85
|
+
/**
|
|
86
|
+
* Hide light DOM content visually while keeping it for accessibility/parsing
|
|
87
|
+
*/
|
|
88
|
+
private _hideLightDOMContent;
|
|
89
|
+
/**
|
|
90
|
+
* Sync current messages back to light DOM
|
|
91
|
+
*/
|
|
92
|
+
private _syncToLightDOM;
|
|
93
|
+
/**
|
|
94
|
+
* Compute message groups for rendering
|
|
95
|
+
*/
|
|
96
|
+
private _computeGroups;
|
|
97
|
+
/**
|
|
98
|
+
* Check if two messages can be grouped together
|
|
99
|
+
*/
|
|
100
|
+
private _canGroup;
|
|
101
|
+
/**
|
|
102
|
+
* Handle scroll button click
|
|
103
|
+
*/
|
|
104
|
+
private _onScrollButtonClick;
|
|
105
|
+
render(): import("lit").TemplateResult<1>;
|
|
106
|
+
}
|
|
107
|
+
declare global {
|
|
108
|
+
interface HTMLElementTagNameMap {
|
|
109
|
+
'bb-msg-history': BBMsgHistory;
|
|
110
|
+
}
|
|
111
|
+
}
|