@bbki.ng/bb-msg-history 0.7.0 → 0.7.2
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 +46 -0
- package/package.json +1 -1
- package/src/component.ts +55 -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
|
@@ -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/package.json
CHANGED
package/src/component.ts
CHANGED
|
@@ -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;
|