kyd-shared-badge 0.3.5 → 0.3.6
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/package.json
CHANGED
package/src/chat/ChatWidget.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { FiMessageSquare, FiX, FiChevronRight } from 'react-icons/fi';
|
|
5
5
|
import { useChatStreaming } from './useChatStreaming';
|
|
6
6
|
import '@chatscope/chat-ui-kit-styles/dist/default/styles.min.css';
|
|
@@ -49,6 +49,7 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
|
|
|
49
49
|
const { messages, input, setInput, sending, sendMessage, cancel } = useChatStreaming({ api, badgeId });
|
|
50
50
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
51
51
|
const [autoScroll, setAutoScroll] = useState(true);
|
|
52
|
+
const prevScrollHeightRef = useRef<number>(0);
|
|
52
53
|
|
|
53
54
|
// Detect user scroll position to toggle auto-scroll
|
|
54
55
|
useEffect(() => {
|
|
@@ -65,14 +66,24 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
|
|
|
65
66
|
return () => scrollEl.removeEventListener('scroll', onScroll);
|
|
66
67
|
}, [open]);
|
|
67
68
|
|
|
68
|
-
//
|
|
69
|
-
|
|
69
|
+
// Preserve viewport when new content streams. If autoScroll is off, compensate for height growth.
|
|
70
|
+
useLayoutEffect(() => {
|
|
70
71
|
if (!open) return;
|
|
71
|
-
if (!autoScroll) return;
|
|
72
72
|
const root = containerRef.current;
|
|
73
73
|
if (!root) return;
|
|
74
74
|
const scrollEl = root.querySelector('.cs-message-list') as HTMLElement | null;
|
|
75
|
-
if (scrollEl)
|
|
75
|
+
if (!scrollEl) return;
|
|
76
|
+
const newHeight = scrollEl.scrollHeight;
|
|
77
|
+
const prevHeight = prevScrollHeightRef.current || newHeight;
|
|
78
|
+
if (autoScroll) {
|
|
79
|
+
scrollEl.scrollTop = newHeight;
|
|
80
|
+
} else {
|
|
81
|
+
const delta = newHeight - prevHeight;
|
|
82
|
+
if (delta !== 0) {
|
|
83
|
+
scrollEl.scrollTop = scrollEl.scrollTop + delta;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
prevScrollHeightRef.current = newHeight;
|
|
76
87
|
}, [messages, open, autoScroll]);
|
|
77
88
|
|
|
78
89
|
// Optional hint (only shows if user hasn't dismissed before and when collapsed)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { useEffect, useRef, useState, useLayoutEffect } from 'react';
|
|
4
4
|
import './chat-overrides.css';
|
|
5
5
|
import { FiSend } from 'react-icons/fi';
|
|
6
6
|
import { useChatStreaming } from './useChatStreaming';
|
|
@@ -9,6 +9,7 @@ export default function ChatWindowStreaming({ api = '/api/chat', badgeId }: { ap
|
|
|
9
9
|
const { messages, input, setInput, sending, sendMessage } = useChatStreaming({ api, badgeId });
|
|
10
10
|
const listRef = useRef<HTMLDivElement>(null);
|
|
11
11
|
const autoScrollRef = useRef<boolean>(true);
|
|
12
|
+
const prevScrollHeightRef = useRef<number>(0);
|
|
12
13
|
|
|
13
14
|
const handleScroll = () => {
|
|
14
15
|
const el = listRef.current;
|
|
@@ -17,10 +18,18 @@ export default function ChatWindowStreaming({ api = '/api/chat', badgeId }: { ap
|
|
|
17
18
|
autoScrollRef.current = nearBottom;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
const el = listRef.current;
|
|
23
|
+
if (!el) return;
|
|
24
|
+
const newHeight = el.scrollHeight;
|
|
25
|
+
const prevHeight = prevScrollHeightRef.current || newHeight;
|
|
26
|
+
if (autoScrollRef.current) {
|
|
27
|
+
el.scrollTop = newHeight;
|
|
28
|
+
} else {
|
|
29
|
+
const delta = newHeight - prevHeight;
|
|
30
|
+
if (delta !== 0) el.scrollTop = el.scrollTop + delta;
|
|
23
31
|
}
|
|
32
|
+
prevScrollHeightRef.current = newHeight;
|
|
24
33
|
}, [messages]);
|
|
25
34
|
|
|
26
35
|
return (
|