@bbki.ng/bb-msg-history 0.13.1 → 0.14.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 +0 -3
- package/dist/component.js +2 -28
- package/package.json +14 -15
- package/src/component.ts +2 -33
package/dist/component.d.ts
CHANGED
|
@@ -5,9 +5,6 @@ export declare class BBMsgHistory extends HTMLElement {
|
|
|
5
5
|
private _lastAuthor;
|
|
6
6
|
private _lastGroupTimestamp;
|
|
7
7
|
private _scrollButtonVisible;
|
|
8
|
-
private _userHasScrolledManually;
|
|
9
|
-
private _isProgrammaticScroll;
|
|
10
|
-
private _lastScrollTop;
|
|
11
8
|
static get observedAttributes(): string[];
|
|
12
9
|
constructor();
|
|
13
10
|
attributeChangedCallback(name: string): void;
|
package/dist/component.js
CHANGED
|
@@ -13,9 +13,6 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
13
13
|
this._userAuthors = new Map();
|
|
14
14
|
this._lastAuthor = '';
|
|
15
15
|
this._scrollButtonVisible = false;
|
|
16
|
-
this._userHasScrolledManually = false;
|
|
17
|
-
this._isProgrammaticScroll = false;
|
|
18
|
-
this._lastScrollTop = 0;
|
|
19
16
|
this.attachShadow({ mode: 'open' });
|
|
20
17
|
}
|
|
21
18
|
attributeChangedCallback(name) {
|
|
@@ -138,16 +135,10 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
138
135
|
}
|
|
139
136
|
// Smooth scroll to bottom (skip in infinite mode)
|
|
140
137
|
if (!this.hasAttribute('infinite')) {
|
|
141
|
-
// Mark this as a programmatic scroll so the scroll handler ignores it
|
|
142
|
-
this._isProgrammaticScroll = true;
|
|
143
138
|
container.scrollTo({
|
|
144
139
|
top: container.scrollHeight,
|
|
145
140
|
behavior: 'smooth',
|
|
146
141
|
});
|
|
147
|
-
// Reset the flag after smooth scroll animation completes (~300ms)
|
|
148
|
-
setTimeout(() => {
|
|
149
|
-
this._isProgrammaticScroll = false;
|
|
150
|
-
}, 300);
|
|
151
142
|
// Hide scroll button since we're scrolling to bottom
|
|
152
143
|
if (this._scrollButtonVisible) {
|
|
153
144
|
this._scrollButtonVisible = false;
|
|
@@ -308,12 +299,7 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
308
299
|
const scrollButton = this.shadowRoot.querySelector('.scroll-to-bottom');
|
|
309
300
|
const isInfinite = this.hasAttribute('infinite');
|
|
310
301
|
if (container && !isInfinite) {
|
|
311
|
-
// Mark as programmatic scroll to prevent triggering user scroll detection
|
|
312
|
-
this._isProgrammaticScroll = true;
|
|
313
302
|
container.scrollTop = container.scrollHeight;
|
|
314
|
-
requestAnimationFrame(() => {
|
|
315
|
-
this._isProgrammaticScroll = false;
|
|
316
|
-
});
|
|
317
303
|
this._setupScrollTracking(container, scrollButton, { skipInitialCheck: true });
|
|
318
304
|
}
|
|
319
305
|
if (scrollButton && !isInfinite) {
|
|
@@ -349,21 +335,11 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
349
335
|
}
|
|
350
336
|
_setupScrollTracking(container, button, options) {
|
|
351
337
|
const checkScrollPosition = () => {
|
|
352
|
-
// Ignore programmatic scrolls - they don't indicate user intent
|
|
353
|
-
if (this._isProgrammaticScroll)
|
|
354
|
-
return;
|
|
355
|
-
// Mark that user has manually scrolled
|
|
356
|
-
if (!this._userHasScrolledManually) {
|
|
357
|
-
this._userHasScrolledManually = true;
|
|
358
|
-
}
|
|
359
|
-
const currentScrollTop = container.scrollTop;
|
|
360
|
-
const isScrollingUp = currentScrollTop < this._lastScrollTop;
|
|
361
|
-
this._lastScrollTop = currentScrollTop;
|
|
362
338
|
const threshold = 50; // pixels from bottom
|
|
363
339
|
const isAtBottom = container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
|
|
364
340
|
const hasOverflow = container.scrollHeight > container.clientHeight;
|
|
365
|
-
//
|
|
366
|
-
const shouldShow = !isAtBottom && hasOverflow
|
|
341
|
+
// Show button when not at bottom and content has overflow
|
|
342
|
+
const shouldShow = !isAtBottom && hasOverflow;
|
|
367
343
|
if (shouldShow !== this._scrollButtonVisible) {
|
|
368
344
|
this._scrollButtonVisible = shouldShow;
|
|
369
345
|
// Only toggle button visibility if button exists
|
|
@@ -378,8 +354,6 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
378
354
|
}));
|
|
379
355
|
}
|
|
380
356
|
};
|
|
381
|
-
// Initialize last scroll position
|
|
382
|
-
this._lastScrollTop = container.scrollTop;
|
|
383
357
|
// Check initial state unless skipped
|
|
384
358
|
if (!options?.skipInitialCheck) {
|
|
385
359
|
checkScrollPosition();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bbki.ng/bb-msg-history",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "A chat-style message history web component",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,19 +23,6 @@
|
|
|
23
23
|
"dist",
|
|
24
24
|
"src"
|
|
25
25
|
],
|
|
26
|
-
"scripts": {
|
|
27
|
-
"start": "tsc -w",
|
|
28
|
-
"preview": "python3 -m http.server 8000",
|
|
29
|
-
"prepare": "tsc && cp dist/index.js dist/index.dev.js && terser dist/index.js --compress --mangle --source-map -o dist/index.js",
|
|
30
|
-
"build": "tsc && cp dist/index.js dist/index.dev.js && terser dist/index.js --compress --mangle --source-map -o dist/index.js",
|
|
31
|
-
"lint": "eslint src/**/*.ts",
|
|
32
|
-
"lint:fix": "eslint src/**/*.ts --fix",
|
|
33
|
-
"format": "prettier --write \"src/**/*.ts\"",
|
|
34
|
-
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
35
|
-
"test": "vitest run",
|
|
36
|
-
"test:watch": "vitest",
|
|
37
|
-
"release": "release-it"
|
|
38
|
-
},
|
|
39
26
|
"lint-staged": {
|
|
40
27
|
"*.ts": [
|
|
41
28
|
"eslint --fix",
|
|
@@ -60,5 +47,17 @@
|
|
|
60
47
|
"terser": "^5.46.0",
|
|
61
48
|
"typescript": "^5.9.3",
|
|
62
49
|
"vitest": "^3.2.4"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"start": "tsc -w",
|
|
53
|
+
"preview": "python3 -m http.server 8000",
|
|
54
|
+
"build": "tsc && cp dist/index.js dist/index.dev.js && terser dist/index.js --compress --mangle --source-map -o dist/index.js",
|
|
55
|
+
"lint": "eslint src/**/*.ts",
|
|
56
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
57
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
58
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest",
|
|
61
|
+
"release": "release-it"
|
|
63
62
|
}
|
|
64
|
-
}
|
|
63
|
+
}
|
package/src/component.ts
CHANGED
|
@@ -12,9 +12,6 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
12
12
|
private _lastAuthor = '';
|
|
13
13
|
private _lastGroupTimestamp: string | undefined;
|
|
14
14
|
private _scrollButtonVisible = false;
|
|
15
|
-
private _userHasScrolledManually = false;
|
|
16
|
-
private _isProgrammaticScroll = false;
|
|
17
|
-
private _lastScrollTop = 0;
|
|
18
15
|
|
|
19
16
|
static get observedAttributes() {
|
|
20
17
|
return ['theme', 'loading', 'hide-scroll-bar', 'infinite', 'hide-scroll-button'];
|
|
@@ -176,19 +173,11 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
176
173
|
|
|
177
174
|
// Smooth scroll to bottom (skip in infinite mode)
|
|
178
175
|
if (!this.hasAttribute('infinite')) {
|
|
179
|
-
// Mark this as a programmatic scroll so the scroll handler ignores it
|
|
180
|
-
this._isProgrammaticScroll = true;
|
|
181
|
-
|
|
182
176
|
container.scrollTo({
|
|
183
177
|
top: container.scrollHeight,
|
|
184
178
|
behavior: 'smooth',
|
|
185
179
|
});
|
|
186
180
|
|
|
187
|
-
// Reset the flag after smooth scroll animation completes (~300ms)
|
|
188
|
-
setTimeout(() => {
|
|
189
|
-
this._isProgrammaticScroll = false;
|
|
190
|
-
}, 300);
|
|
191
|
-
|
|
192
181
|
// Hide scroll button since we're scrolling to bottom
|
|
193
182
|
if (this._scrollButtonVisible) {
|
|
194
183
|
this._scrollButtonVisible = false;
|
|
@@ -386,12 +375,7 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
386
375
|
const isInfinite = this.hasAttribute('infinite');
|
|
387
376
|
|
|
388
377
|
if (container && !isInfinite) {
|
|
389
|
-
// Mark as programmatic scroll to prevent triggering user scroll detection
|
|
390
|
-
this._isProgrammaticScroll = true;
|
|
391
378
|
container.scrollTop = container.scrollHeight;
|
|
392
|
-
requestAnimationFrame(() => {
|
|
393
|
-
this._isProgrammaticScroll = false;
|
|
394
|
-
});
|
|
395
379
|
this._setupScrollTracking(container, scrollButton, { skipInitialCheck: true });
|
|
396
380
|
}
|
|
397
381
|
|
|
@@ -435,24 +419,12 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
435
419
|
options?: { skipInitialCheck?: boolean }
|
|
436
420
|
): void {
|
|
437
421
|
const checkScrollPosition = () => {
|
|
438
|
-
// Ignore programmatic scrolls - they don't indicate user intent
|
|
439
|
-
if (this._isProgrammaticScroll) return;
|
|
440
|
-
|
|
441
|
-
// Mark that user has manually scrolled
|
|
442
|
-
if (!this._userHasScrolledManually) {
|
|
443
|
-
this._userHasScrolledManually = true;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
const currentScrollTop = container.scrollTop;
|
|
447
|
-
const isScrollingUp = currentScrollTop < this._lastScrollTop;
|
|
448
|
-
this._lastScrollTop = currentScrollTop;
|
|
449
|
-
|
|
450
422
|
const threshold = 50; // pixels from bottom
|
|
451
423
|
const isAtBottom =
|
|
452
424
|
container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
|
|
453
425
|
const hasOverflow = container.scrollHeight > container.clientHeight;
|
|
454
|
-
//
|
|
455
|
-
const shouldShow = !isAtBottom && hasOverflow
|
|
426
|
+
// Show button when not at bottom and content has overflow
|
|
427
|
+
const shouldShow = !isAtBottom && hasOverflow;
|
|
456
428
|
|
|
457
429
|
if (shouldShow !== this._scrollButtonVisible) {
|
|
458
430
|
this._scrollButtonVisible = shouldShow;
|
|
@@ -472,9 +444,6 @@ export class BBMsgHistory extends HTMLElement {
|
|
|
472
444
|
}
|
|
473
445
|
};
|
|
474
446
|
|
|
475
|
-
// Initialize last scroll position
|
|
476
|
-
this._lastScrollTop = container.scrollTop;
|
|
477
|
-
|
|
478
447
|
// Check initial state unless skipped
|
|
479
448
|
if (!options?.skipInitialCheck) {
|
|
480
449
|
checkScrollPosition();
|