@bbki.ng/bb-msg-history 0.12.0 → 0.13.1

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.
@@ -41,6 +41,13 @@ export declare class BBMsgHistory extends HTMLElement {
41
41
  * el.appendMessage({ author: 'bob', text: 'How are you?' });
42
42
  */
43
43
  appendMessage(message: Message): this;
44
+ /**
45
+ * Scroll to the bottom of the message history.
46
+ *
47
+ * @example
48
+ * el.scrollToBottom(); // Scroll with smooth animation
49
+ */
50
+ scrollToBottom(): this;
44
51
  private _appendSingleMessage;
45
52
  connectedCallback(): void;
46
53
  disconnectedCallback(): void;
package/dist/component.js CHANGED
@@ -76,6 +76,26 @@ export class BBMsgHistory extends HTMLElement {
76
76
  this._setupMutationObserver();
77
77
  return this;
78
78
  }
79
+ /**
80
+ * Scroll to the bottom of the message history.
81
+ *
82
+ * @example
83
+ * el.scrollToBottom(); // Scroll with smooth animation
84
+ */
85
+ scrollToBottom() {
86
+ if (this.hasAttribute('infinite')) {
87
+ return this;
88
+ }
89
+ const container = this.shadowRoot?.querySelector('.history');
90
+ if (!container) {
91
+ return this;
92
+ }
93
+ container.scrollTo({
94
+ top: container.scrollHeight,
95
+ behavior: 'smooth',
96
+ });
97
+ return this;
98
+ }
79
99
  _appendSingleMessage(message) {
80
100
  const container = this.shadowRoot.querySelector('.history');
81
101
  // If empty state or no container, do full render first
@@ -129,11 +149,13 @@ export class BBMsgHistory extends HTMLElement {
129
149
  this._isProgrammaticScroll = false;
130
150
  }, 300);
131
151
  // Hide scroll button since we're scrolling to bottom
132
- const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
133
- if (scrollButton && this._scrollButtonVisible) {
152
+ if (this._scrollButtonVisible) {
134
153
  this._scrollButtonVisible = false;
135
- scrollButton.classList.remove('visible');
136
- // Dispatch hide event
154
+ const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
155
+ if (scrollButton) {
156
+ scrollButton.classList.remove('visible');
157
+ }
158
+ // Dispatch hide event (always, regardless of button visibility)
137
159
  this.dispatchEvent(new CustomEvent('bb-scrollbuttonhide', {
138
160
  bubbles: true,
139
161
  composed: true,
@@ -283,12 +305,9 @@ export class BBMsgHistory extends HTMLElement {
283
305
  _setupAfterRender() {
284
306
  requestAnimationFrame(() => {
285
307
  const container = this.shadowRoot.querySelector('.history');
286
- const hideScrollButton = this.hasAttribute('hide-scroll-button');
287
- const scrollButton = hideScrollButton
288
- ? null
289
- : this.shadowRoot.querySelector('.scroll-to-bottom');
308
+ const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
290
309
  const isInfinite = this.hasAttribute('infinite');
291
- if (container && !isInfinite && !hideScrollButton) {
310
+ if (container && !isInfinite) {
292
311
  // Mark as programmatic scroll to prevent triggering user scroll detection
293
312
  this._isProgrammaticScroll = true;
294
313
  container.scrollTop = container.scrollHeight;
@@ -347,8 +366,11 @@ export class BBMsgHistory extends HTMLElement {
347
366
  const shouldShow = !isAtBottom && hasOverflow && this._userHasScrolledManually && isScrollingUp;
348
367
  if (shouldShow !== this._scrollButtonVisible) {
349
368
  this._scrollButtonVisible = shouldShow;
350
- button.classList.toggle('visible', shouldShow);
351
- // Dispatch custom event
369
+ // Only toggle button visibility if button exists
370
+ if (button) {
371
+ button.classList.toggle('visible', shouldShow);
372
+ }
373
+ // Dispatch custom event (always, regardless of button visibility)
352
374
  this.dispatchEvent(new CustomEvent(shouldShow ? 'bb-scrollbuttonshow' : 'bb-scrollbuttonhide', {
353
375
  bubbles: true,
354
376
  composed: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/bb-msg-history",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "description": "A chat-style message history web component",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
package/src/component.ts CHANGED
@@ -92,6 +92,30 @@ export class BBMsgHistory extends HTMLElement {
92
92
  return this;
93
93
  }
94
94
 
95
+ /**
96
+ * Scroll to the bottom of the message history.
97
+ *
98
+ * @example
99
+ * el.scrollToBottom(); // Scroll with smooth animation
100
+ */
101
+ scrollToBottom(): this {
102
+ if (this.hasAttribute('infinite')) {
103
+ return this;
104
+ }
105
+
106
+ const container = this.shadowRoot?.querySelector('.history') as HTMLElement | null;
107
+ if (!container) {
108
+ return this;
109
+ }
110
+
111
+ container.scrollTo({
112
+ top: container.scrollHeight,
113
+ behavior: 'smooth',
114
+ });
115
+
116
+ return this;
117
+ }
118
+
95
119
  private _appendSingleMessage(message: Message): void {
96
120
  const container = this.shadowRoot!.querySelector('.history') as HTMLElement;
97
121
 
@@ -166,12 +190,14 @@ export class BBMsgHistory extends HTMLElement {
166
190
  }, 300);
167
191
 
168
192
  // Hide scroll button since we're scrolling to bottom
169
- const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement;
170
- if (scrollButton && this._scrollButtonVisible) {
193
+ if (this._scrollButtonVisible) {
171
194
  this._scrollButtonVisible = false;
172
- scrollButton.classList.remove('visible');
195
+ const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement | null;
196
+ if (scrollButton) {
197
+ scrollButton.classList.remove('visible');
198
+ }
173
199
 
174
- // Dispatch hide event
200
+ // Dispatch hide event (always, regardless of button visibility)
175
201
  this.dispatchEvent(
176
202
  new CustomEvent('bb-scrollbuttonhide', {
177
203
  bubbles: true,
@@ -356,20 +382,17 @@ export class BBMsgHistory extends HTMLElement {
356
382
  private _setupAfterRender(): void {
357
383
  requestAnimationFrame(() => {
358
384
  const container = this.shadowRoot!.querySelector('.history') as HTMLElement;
359
- const hideScrollButton = this.hasAttribute('hide-scroll-button');
360
- const scrollButton = hideScrollButton
361
- ? null
362
- : (this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement);
385
+ const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement | null;
363
386
  const isInfinite = this.hasAttribute('infinite');
364
387
 
365
- if (container && !isInfinite && !hideScrollButton) {
388
+ if (container && !isInfinite) {
366
389
  // Mark as programmatic scroll to prevent triggering user scroll detection
367
390
  this._isProgrammaticScroll = true;
368
391
  container.scrollTop = container.scrollHeight;
369
392
  requestAnimationFrame(() => {
370
393
  this._isProgrammaticScroll = false;
371
394
  });
372
- this._setupScrollTracking(container, scrollButton!, { skipInitialCheck: true });
395
+ this._setupScrollTracking(container, scrollButton, { skipInitialCheck: true });
373
396
  }
374
397
 
375
398
  if (scrollButton && !isInfinite) {
@@ -408,7 +431,7 @@ export class BBMsgHistory extends HTMLElement {
408
431
 
409
432
  private _setupScrollTracking(
410
433
  container: HTMLElement,
411
- button: HTMLButtonElement,
434
+ button: HTMLButtonElement | null,
412
435
  options?: { skipInitialCheck?: boolean }
413
436
  ): void {
414
437
  const checkScrollPosition = () => {
@@ -433,9 +456,12 @@ export class BBMsgHistory extends HTMLElement {
433
456
 
434
457
  if (shouldShow !== this._scrollButtonVisible) {
435
458
  this._scrollButtonVisible = shouldShow;
436
- button.classList.toggle('visible', shouldShow);
459
+ // Only toggle button visibility if button exists
460
+ if (button) {
461
+ button.classList.toggle('visible', shouldShow);
462
+ }
437
463
 
438
- // Dispatch custom event
464
+ // Dispatch custom event (always, regardless of button visibility)
439
465
  this.dispatchEvent(
440
466
  new CustomEvent(shouldShow ? 'bb-scrollbuttonshow' : 'bb-scrollbuttonhide', {
441
467
  bubbles: true,