@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 +24 -0
- package/dist/component.js +17 -14
- package/dist/const/styles.js +11 -0
- package/package.json +1 -1
- package/src/component.ts +17 -14
- package/src/const/styles.ts +11 -0
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this._scrollButtonVisible
|
|
125
|
-
|
|
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
|
-
|
|
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,
|
package/dist/const/styles.js
CHANGED
|
@@ -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
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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,
|
package/src/const/styles.ts
CHANGED
|
@@ -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;
|