@bbki.ng/bb-msg-history 0.10.0 → 0.11.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/README.md CHANGED
@@ -130,6 +130,29 @@ You can also use the HTML attribute:
130
130
  </bb-msg-history>
131
131
  ```
132
132
 
133
+ ### `infinite` Attribute
134
+
135
+ Remove the height constraint and disable scrolling on the component. The container expands to fit all messages.
136
+
137
+ Use this when:
138
+ - The parent container handles scrolling
139
+ - You want to display an entire conversation without height limits
140
+ - You need the component to be part of a larger scrollable area
141
+
142
+ ```html
143
+ <bb-msg-history infinite>
144
+ alice: First message
145
+ bob: Second message
146
+ alice: Third message
147
+ <!-- Container keeps expanding to fit all messages -->
148
+ </bb-msg-history>
149
+ ```
150
+
151
+ In infinite mode:
152
+ - No `max-height` constraint is applied
153
+ - No scrollbar appears on the component
154
+ - The scroll-to-bottom button is hidden (not needed)
155
+
133
156
  ## Customization
134
157
 
135
158
  ### CSS Custom Properties
@@ -175,6 +198,7 @@ define('my-chat-history');
175
198
  - `prefers-reduced-motion` support
176
199
  - Reactive: automatically re-renders when content changes
177
200
  - Customizable max-height via `--bb-max-height` CSS custom property
201
+ - **`infinite` attribute** — remove height constraints for parent-controlled scrolling
178
202
  - Graceful degradation to `<pre>` when Custom Elements are unsupported
179
203
 
180
204
  ## Examples
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', 'hide-scroll-bar'];
9
+ return ['theme', 'loading', 'hide-scroll-bar', 'infinite'];
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' || name === 'hide-scroll-bar') {
19
+ if (name === 'theme' || name === 'loading' || name === 'hide-scroll-bar' || name === 'infinite') {
20
20
  this.render();
21
21
  }
22
22
  }
@@ -113,16 +113,18 @@ export class BBMsgHistory extends HTMLElement {
113
113
  if (newWrapper) {
114
114
  setupTooltipForElement(newWrapper);
115
115
  }
116
- // Smooth scroll to bottom
117
- container.scrollTo({
118
- top: container.scrollHeight,
119
- behavior: 'smooth',
120
- });
121
- // Hide scroll button since we're scrolling to bottom
122
- const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
123
- if (scrollButton && this._scrollButtonVisible) {
124
- this._scrollButtonVisible = false;
125
- scrollButton.classList.remove('visible');
116
+ // Smooth scroll to bottom (skip in infinite mode)
117
+ if (!this.hasAttribute('infinite')) {
118
+ container.scrollTo({
119
+ top: container.scrollHeight,
120
+ behavior: 'smooth',
121
+ });
122
+ // Hide scroll button since we're scrolling to bottom
123
+ const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
124
+ if (scrollButton && this._scrollButtonVisible) {
125
+ this._scrollButtonVisible = false;
126
+ scrollButton.classList.remove('visible');
127
+ }
126
128
  }
127
129
  }
128
130
  connectedCallback() {
@@ -266,11 +268,12 @@ export class BBMsgHistory extends HTMLElement {
266
268
  requestAnimationFrame(() => {
267
269
  const container = this.shadowRoot.querySelector('.history');
268
270
  const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
269
- if (container) {
271
+ const isInfinite = this.hasAttribute('infinite');
272
+ if (container && !isInfinite) {
270
273
  container.scrollTop = container.scrollHeight;
271
274
  this._setupScrollTracking(container, scrollButton);
272
275
  }
273
- if (scrollButton) {
276
+ if (scrollButton && !isInfinite) {
274
277
  scrollButton.addEventListener('click', () => {
275
278
  container?.scrollTo({
276
279
  top: container.scrollHeight,
@@ -60,6 +60,17 @@ export const MAIN_STYLES = `
60
60
  display: none; /* Chrome, Safari, Opera */
61
61
  }
62
62
 
63
+ /* Infinite mode - no max height, no scroll */
64
+ :host([infinite]) .history {
65
+ max-height: none;
66
+ overflow-y: visible;
67
+ }
68
+
69
+ /* Hide scroll button in infinite mode */
70
+ :host([infinite]) .scroll-to-bottom {
71
+ display: none;
72
+ }
73
+
63
74
  /* Scroll to bottom button */
64
75
  .scroll-to-bottom {
65
76
  position: absolute;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/bb-msg-history",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
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
@@ -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', 'hide-scroll-bar'];
17
+ return ['theme', 'loading', 'hide-scroll-bar', 'infinite'];
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' || name === 'hide-scroll-bar') {
26
+ if (name === 'theme' || name === 'loading' || name === 'hide-scroll-bar' || name === 'infinite') {
27
27
  this.render();
28
28
  }
29
29
  }
@@ -147,17 +147,19 @@ export class BBMsgHistory extends HTMLElement {
147
147
  setupTooltipForElement(newWrapper);
148
148
  }
149
149
 
150
- // Smooth scroll to bottom
151
- container.scrollTo({
152
- top: container.scrollHeight,
153
- behavior: 'smooth',
154
- });
150
+ // Smooth scroll to bottom (skip in infinite mode)
151
+ if (!this.hasAttribute('infinite')) {
152
+ container.scrollTo({
153
+ top: container.scrollHeight,
154
+ behavior: 'smooth',
155
+ });
155
156
 
156
- // Hide scroll button since we're scrolling to bottom
157
- const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement;
158
- if (scrollButton && this._scrollButtonVisible) {
159
- this._scrollButtonVisible = false;
160
- scrollButton.classList.remove('visible');
157
+ // Hide scroll button since we're scrolling to bottom
158
+ const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement;
159
+ if (scrollButton && this._scrollButtonVisible) {
160
+ this._scrollButtonVisible = false;
161
+ scrollButton.classList.remove('visible');
162
+ }
161
163
  }
162
164
  }
163
165
 
@@ -333,13 +335,14 @@ export class BBMsgHistory extends HTMLElement {
333
335
  requestAnimationFrame(() => {
334
336
  const container = this.shadowRoot!.querySelector('.history') as HTMLElement;
335
337
  const scrollButton = this.shadowRoot!.querySelector('.scroll-to-bottom') as HTMLButtonElement;
338
+ const isInfinite = this.hasAttribute('infinite');
336
339
 
337
- if (container) {
340
+ if (container && !isInfinite) {
338
341
  container.scrollTop = container.scrollHeight;
339
342
  this._setupScrollTracking(container, scrollButton);
340
343
  }
341
344
 
342
- if (scrollButton) {
345
+ if (scrollButton && !isInfinite) {
343
346
  scrollButton.addEventListener('click', () => {
344
347
  container?.scrollTo({
345
348
  top: container.scrollHeight,
@@ -61,6 +61,17 @@ export const MAIN_STYLES = `
61
61
  display: none; /* Chrome, Safari, Opera */
62
62
  }
63
63
 
64
+ /* Infinite mode - no max height, no scroll */
65
+ :host([infinite]) .history {
66
+ max-height: none;
67
+ overflow-y: visible;
68
+ }
69
+
70
+ /* Hide scroll button in infinite mode */
71
+ :host([infinite]) .scroll-to-bottom {
72
+ display: none;
73
+ }
74
+
64
75
  /* Scroll to bottom button */
65
76
  .scroll-to-bottom {
66
77
  position: absolute;