@bbki.ng/bb-msg-history 0.8.0 → 0.9.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 +4 -0
- package/dist/component.js +48 -2
- package/dist/const/authors.js +6 -0
- package/dist/const/styles.js +10 -0
- package/package.json +1 -1
- package/src/component.ts +57 -2
- package/src/const/authors.ts +6 -0
- package/src/const/styles.ts +10 -0
package/dist/component.d.ts
CHANGED
|
@@ -43,6 +43,10 @@ export declare class BBMsgHistory extends HTMLElement {
|
|
|
43
43
|
disconnectedCallback(): void;
|
|
44
44
|
private _setupMutationObserver;
|
|
45
45
|
private render;
|
|
46
|
+
private _renderFullStructure;
|
|
47
|
+
private _updateContent;
|
|
48
|
+
private _updateLoadingOverlay;
|
|
49
|
+
private _setupAfterRender;
|
|
46
50
|
private _renderEmpty;
|
|
47
51
|
private _setupScrollTracking;
|
|
48
52
|
}
|
package/dist/component.js
CHANGED
|
@@ -6,7 +6,7 @@ import { buildMessageRowHtml, setupTooltipForElement } from './utils/message-bui
|
|
|
6
6
|
import { buildScrollButtonHtml } from './utils/scroll-button.js';
|
|
7
7
|
export class BBMsgHistory extends HTMLElement {
|
|
8
8
|
static get observedAttributes() {
|
|
9
|
-
return ['theme', 'loading'];
|
|
9
|
+
return ['theme', 'loading', 'hide-scroll-bar'];
|
|
10
10
|
}
|
|
11
11
|
constructor() {
|
|
12
12
|
super();
|
|
@@ -16,7 +16,7 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
16
16
|
this.attachShadow({ mode: 'open' });
|
|
17
17
|
}
|
|
18
18
|
attributeChangedCallback(name) {
|
|
19
|
-
if (name === 'theme' || name === 'loading') {
|
|
19
|
+
if (name === 'theme' || name === 'loading' || name === 'hide-scroll-bar') {
|
|
20
20
|
this.render();
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -204,6 +204,19 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
204
204
|
})
|
|
205
205
|
.join('');
|
|
206
206
|
this._lastAuthor = lastAuthor;
|
|
207
|
+
// Check if we need to create or update the structure
|
|
208
|
+
const historyContainer = this.shadowRoot.querySelector('.history');
|
|
209
|
+
const needsFullSetup = !historyContainer;
|
|
210
|
+
if (needsFullSetup) {
|
|
211
|
+
// First render - create full structure
|
|
212
|
+
this._renderFullStructure(messagesHtml);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// Update only - preserve DOM structure, just update content
|
|
216
|
+
this._updateContent(historyContainer, messagesHtml);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
_renderFullStructure(messagesHtml) {
|
|
207
220
|
const loadingOverlay = this.hasAttribute('loading')
|
|
208
221
|
? `<div class="loading-overlay" role="status" aria-label="Loading messages">
|
|
209
222
|
<div class="loading-spinner"></div>
|
|
@@ -217,6 +230,39 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
217
230
|
${buildScrollButtonHtml()}
|
|
218
231
|
${loadingOverlay}
|
|
219
232
|
`;
|
|
233
|
+
this._setupAfterRender();
|
|
234
|
+
}
|
|
235
|
+
_updateContent(historyContainer, messagesHtml) {
|
|
236
|
+
// Preserve scroll position before update
|
|
237
|
+
const scrollContainer = historyContainer;
|
|
238
|
+
const wasAtBottom = scrollContainer.scrollHeight - scrollContainer.scrollTop - scrollContainer.clientHeight < 50;
|
|
239
|
+
// Update messages content only
|
|
240
|
+
historyContainer.innerHTML = messagesHtml;
|
|
241
|
+
// Update loading overlay
|
|
242
|
+
this._updateLoadingOverlay();
|
|
243
|
+
// Restore scroll position or scroll to bottom if we were there
|
|
244
|
+
if (wasAtBottom) {
|
|
245
|
+
scrollContainer.scrollTop = scrollContainer.scrollHeight;
|
|
246
|
+
}
|
|
247
|
+
// Re-setup tooltips for new content
|
|
248
|
+
setupTooltips(this.shadowRoot);
|
|
249
|
+
}
|
|
250
|
+
_updateLoadingOverlay() {
|
|
251
|
+
const existingOverlay = this.shadowRoot.querySelector('.loading-overlay');
|
|
252
|
+
const shouldShow = this.hasAttribute('loading');
|
|
253
|
+
if (shouldShow && !existingOverlay) {
|
|
254
|
+
const overlay = document.createElement('div');
|
|
255
|
+
overlay.className = 'loading-overlay';
|
|
256
|
+
overlay.setAttribute('role', 'status');
|
|
257
|
+
overlay.setAttribute('aria-label', 'Loading messages');
|
|
258
|
+
overlay.innerHTML = '<div class="loading-spinner"></div>';
|
|
259
|
+
this.shadowRoot.appendChild(overlay);
|
|
260
|
+
}
|
|
261
|
+
else if (!shouldShow && existingOverlay) {
|
|
262
|
+
existingOverlay.remove();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
_setupAfterRender() {
|
|
220
266
|
requestAnimationFrame(() => {
|
|
221
267
|
const container = this.shadowRoot.querySelector('.history');
|
|
222
268
|
const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
|
package/dist/const/authors.js
CHANGED
|
@@ -22,6 +22,12 @@ export const AUTHOR_CONFIG = {
|
|
|
22
22
|
textColor: THEME.gray[900],
|
|
23
23
|
side: 'left',
|
|
24
24
|
},
|
|
25
|
+
'GitHub': {
|
|
26
|
+
avatar: '<div style="width: 60%; height: 60%; margin: auto"><svg data-testid="geist-icon" height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16" style="color: currentcolor;"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.46252C4.40875 1.46252 1.5 4.37029 1.5 7.96032C1.5 10.8356 3.36062 13.2642 5.94438 14.1251C6.26937 14.182 6.39125 13.987 6.39125 13.8165C6.39125 13.6621 6.38313 13.1504 6.38313 12.6063C4.75 12.9068 4.3275 12.2083 4.1975 11.8428C4.12437 11.6559 3.8075 11.0793 3.53125 10.9249C3.30375 10.8031 2.97875 10.5026 3.52312 10.4945C4.035 10.4863 4.40062 10.9656 4.5225 11.1605C5.1075 12.1433 6.04188 11.8671 6.41563 11.6966C6.4725 11.2742 6.64313 10.9899 6.83 10.8275C5.38375 10.665 3.8725 10.1046 3.8725 7.61919C3.8725 6.91255 4.12438 6.32775 4.53875 5.87291C4.47375 5.71046 4.24625 5.04444 4.60375 4.15099C4.60375 4.15099 5.14812 3.98042 6.39125 4.81701C6.91125 4.67081 7.46375 4.59771 8.01625 4.59771C8.56875 4.59771 9.12125 4.67081 9.64125 4.81701C10.8844 3.9723 11.4288 4.15099 11.4288 4.15099C11.7863 5.04444 11.5588 5.71046 11.4938 5.87291C11.9081 6.32775 12.16 6.90443 12.16 7.61919C12.16 10.1127 10.6406 10.665 9.19438 10.8275C9.43 11.0305 9.63313 11.4204 9.63313 12.0296C9.63313 12.8987 9.625 13.5972 9.625 13.8165C9.625 13.987 9.74687 14.1901 10.0719 14.1251C11.3622 13.6896 12.4835 12.8606 13.2779 11.7547C14.0722 10.6488 14.4997 9.32178 14.5 7.96032C14.5 4.37029 11.5913 1.46252 8 1.46252Z" fill="currentColor"></path></svg></div>',
|
|
27
|
+
side: 'left',
|
|
28
|
+
bubbleColor: '#ecf4ec',
|
|
29
|
+
textColor: THEME.gray[900],
|
|
30
|
+
},
|
|
25
31
|
};
|
|
26
32
|
/**
|
|
27
33
|
* Authors that should use first-character avatar instead of SVG
|
package/dist/const/styles.js
CHANGED
|
@@ -50,6 +50,16 @@ export const MAIN_STYLES = `
|
|
|
50
50
|
background: ${THEME.gray[500]};
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/* Hide scrollbar styles */
|
|
54
|
+
:host([hide-scroll-bar]) .history {
|
|
55
|
+
scrollbar-width: none; /* Firefox */
|
|
56
|
+
-ms-overflow-style: none; /* IE/Edge */
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:host([hide-scroll-bar]) .history::-webkit-scrollbar {
|
|
60
|
+
display: none; /* Chrome, Safari, Opera */
|
|
61
|
+
}
|
|
62
|
+
|
|
53
63
|
/* Scroll to bottom button */
|
|
54
64
|
.scroll-to-bottom {
|
|
55
65
|
position: absolute;
|
package/package.json
CHANGED
package/src/component.ts
CHANGED
|
@@ -14,7 +14,7 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
14
14
|
private _scrollButtonVisible = false;
|
|
15
15
|
|
|
16
16
|
static get observedAttributes() {
|
|
17
|
-
return ['theme', 'loading'];
|
|
17
|
+
return ['theme', 'loading', 'hide-scroll-bar'];
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
constructor() {
|
|
@@ -23,7 +23,7 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
attributeChangedCallback(name: string) {
|
|
26
|
-
if (name === 'theme' || name === 'loading') {
|
|
26
|
+
if (name === 'theme' || name === 'loading' || name === 'hide-scroll-bar') {
|
|
27
27
|
this.render();
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -260,6 +260,20 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
260
260
|
|
|
261
261
|
this._lastAuthor = lastAuthor;
|
|
262
262
|
|
|
263
|
+
// Check if we need to create or update the structure
|
|
264
|
+
const historyContainer = this.shadowRoot!.querySelector('.history') as HTMLElement;
|
|
265
|
+
const needsFullSetup = !historyContainer;
|
|
266
|
+
|
|
267
|
+
if (needsFullSetup) {
|
|
268
|
+
// First render - create full structure
|
|
269
|
+
this._renderFullStructure(messagesHtml);
|
|
270
|
+
} else {
|
|
271
|
+
// Update only - preserve DOM structure, just update content
|
|
272
|
+
this._updateContent(historyContainer, messagesHtml);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private _renderFullStructure(messagesHtml: string): void {
|
|
263
277
|
const loadingOverlay = this.hasAttribute('loading')
|
|
264
278
|
? `<div class="loading-overlay" role="status" aria-label="Loading messages">
|
|
265
279
|
<div class="loading-spinner"></div>
|
|
@@ -275,6 +289,47 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
275
289
|
${loadingOverlay}
|
|
276
290
|
`;
|
|
277
291
|
|
|
292
|
+
this._setupAfterRender();
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private _updateContent(historyContainer: HTMLElement, messagesHtml: string): void {
|
|
296
|
+
// Preserve scroll position before update
|
|
297
|
+
const scrollContainer = historyContainer;
|
|
298
|
+
const wasAtBottom =
|
|
299
|
+
scrollContainer.scrollHeight - scrollContainer.scrollTop - scrollContainer.clientHeight < 50;
|
|
300
|
+
|
|
301
|
+
// Update messages content only
|
|
302
|
+
historyContainer.innerHTML = messagesHtml;
|
|
303
|
+
|
|
304
|
+
// Update loading overlay
|
|
305
|
+
this._updateLoadingOverlay();
|
|
306
|
+
|
|
307
|
+
// Restore scroll position or scroll to bottom if we were there
|
|
308
|
+
if (wasAtBottom) {
|
|
309
|
+
scrollContainer.scrollTop = scrollContainer.scrollHeight;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Re-setup tooltips for new content
|
|
313
|
+
setupTooltips(this.shadowRoot!);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private _updateLoadingOverlay(): void {
|
|
317
|
+
const existingOverlay = this.shadowRoot!.querySelector('.loading-overlay');
|
|
318
|
+
const shouldShow = this.hasAttribute('loading');
|
|
319
|
+
|
|
320
|
+
if (shouldShow && !existingOverlay) {
|
|
321
|
+
const overlay = document.createElement('div');
|
|
322
|
+
overlay.className = 'loading-overlay';
|
|
323
|
+
overlay.setAttribute('role', 'status');
|
|
324
|
+
overlay.setAttribute('aria-label', 'Loading messages');
|
|
325
|
+
overlay.innerHTML = '<div class="loading-spinner"></div>';
|
|
326
|
+
this.shadowRoot!.appendChild(overlay);
|
|
327
|
+
} else if (!shouldShow && existingOverlay) {
|
|
328
|
+
existingOverlay.remove();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private _setupAfterRender(): void {
|
|
278
333
|
requestAnimationFrame(() => {
|
|
279
334
|
const container = this.shadowRoot!.querySelector('.history') as HTMLElement;
|
|
280
335
|
const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement;
|
package/src/const/authors.ts
CHANGED
|
@@ -24,6 +24,12 @@ export const AUTHOR_CONFIG: Record<string, Omit<AuthorConfig, 'isCustomAvatar'>>
|
|
|
24
24
|
textColor: THEME.gray[900],
|
|
25
25
|
side: 'left',
|
|
26
26
|
},
|
|
27
|
+
'GitHub': {
|
|
28
|
+
avatar: '<div style="width: 60%; height: 60%; margin: auto"><svg data-testid="geist-icon" height="16" stroke-linejoin="round" viewBox="0 0 16 16" width="16" style="color: currentcolor;"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.46252C4.40875 1.46252 1.5 4.37029 1.5 7.96032C1.5 10.8356 3.36062 13.2642 5.94438 14.1251C6.26937 14.182 6.39125 13.987 6.39125 13.8165C6.39125 13.6621 6.38313 13.1504 6.38313 12.6063C4.75 12.9068 4.3275 12.2083 4.1975 11.8428C4.12437 11.6559 3.8075 11.0793 3.53125 10.9249C3.30375 10.8031 2.97875 10.5026 3.52312 10.4945C4.035 10.4863 4.40062 10.9656 4.5225 11.1605C5.1075 12.1433 6.04188 11.8671 6.41563 11.6966C6.4725 11.2742 6.64313 10.9899 6.83 10.8275C5.38375 10.665 3.8725 10.1046 3.8725 7.61919C3.8725 6.91255 4.12438 6.32775 4.53875 5.87291C4.47375 5.71046 4.24625 5.04444 4.60375 4.15099C4.60375 4.15099 5.14812 3.98042 6.39125 4.81701C6.91125 4.67081 7.46375 4.59771 8.01625 4.59771C8.56875 4.59771 9.12125 4.67081 9.64125 4.81701C10.8844 3.9723 11.4288 4.15099 11.4288 4.15099C11.7863 5.04444 11.5588 5.71046 11.4938 5.87291C11.9081 6.32775 12.16 6.90443 12.16 7.61919C12.16 10.1127 10.6406 10.665 9.19438 10.8275C9.43 11.0305 9.63313 11.4204 9.63313 12.0296C9.63313 12.8987 9.625 13.5972 9.625 13.8165C9.625 13.987 9.74687 14.1901 10.0719 14.1251C11.3622 13.6896 12.4835 12.8606 13.2779 11.7547C14.0722 10.6488 14.4997 9.32178 14.5 7.96032C14.5 4.37029 11.5913 1.46252 8 1.46252Z" fill="currentColor"></path></svg></div>',
|
|
29
|
+
side: 'left',
|
|
30
|
+
bubbleColor: '#ecf4ec',
|
|
31
|
+
textColor: THEME.gray[900],
|
|
32
|
+
},
|
|
27
33
|
};
|
|
28
34
|
|
|
29
35
|
/**
|
package/src/const/styles.ts
CHANGED
|
@@ -51,6 +51,16 @@ export const MAIN_STYLES = `
|
|
|
51
51
|
background: ${THEME.gray[500]};
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/* Hide scrollbar styles */
|
|
55
|
+
:host([hide-scroll-bar]) .history {
|
|
56
|
+
scrollbar-width: none; /* Firefox */
|
|
57
|
+
-ms-overflow-style: none; /* IE/Edge */
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:host([hide-scroll-bar]) .history::-webkit-scrollbar {
|
|
61
|
+
display: none; /* Chrome, Safari, Opera */
|
|
62
|
+
}
|
|
63
|
+
|
|
54
64
|
/* Scroll to bottom button */
|
|
55
65
|
.scroll-to-bottom {
|
|
56
66
|
position: absolute;
|