kyd-shared-badge 0.3.5 → 0.3.7

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyd-shared-badge",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "private": false,
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -47,33 +47,11 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
47
47
  const [headerTop, setHeaderTop] = useState(0);
48
48
  const [showHint, setShowHint] = useState(false);
49
49
  const { messages, input, setInput, sending, sendMessage, cancel } = useChatStreaming({ api, badgeId });
50
- const containerRef = useRef<HTMLDivElement>(null);
51
- const [autoScroll, setAutoScroll] = useState(true);
50
+ const listRef = useRef<HTMLDivElement>(null);
52
51
 
53
- // Detect user scroll position to toggle auto-scroll
54
52
  useEffect(() => {
55
- if (!open) return;
56
- const root = containerRef.current;
57
- if (!root) return;
58
- const scrollEl = root.querySelector('.cs-message-list') as HTMLElement | null;
59
- if (!scrollEl) return;
60
- const onScroll = () => {
61
- const nearBottom = scrollEl.scrollTop + scrollEl.clientHeight >= scrollEl.scrollHeight - 8;
62
- setAutoScroll(nearBottom);
63
- };
64
- scrollEl.addEventListener('scroll', onScroll, { passive: true } as AddEventListenerOptions);
65
- return () => scrollEl.removeEventListener('scroll', onScroll);
66
- }, [open]);
67
-
68
- // Keep scrolled to bottom only when autoScroll is enabled
69
- useEffect(() => {
70
- if (!open) return;
71
- if (!autoScroll) return;
72
- const root = containerRef.current;
73
- if (!root) return;
74
- const scrollEl = root.querySelector('.cs-message-list') as HTMLElement | null;
75
- if (scrollEl) scrollEl.scrollTop = scrollEl.scrollHeight;
76
- }, [messages, open, autoScroll]);
53
+ if (listRef.current) listRef.current.scrollTop = listRef.current.scrollHeight;
54
+ }, [messages, open]);
77
55
 
78
56
  // Optional hint (only shows if user hasn't dismissed before and when collapsed)
79
57
  useEffect(() => {
@@ -230,7 +208,6 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
230
208
  aria-label={'Chat sidebar'}
231
209
  style={{ position: 'fixed', top: headerTop, right: 0, bottom: 0, width, maxWidth: '92vw' }}
232
210
  className={'shadow-xl border flex flex-col overflow-hidden'}
233
- ref={containerRef}
234
211
  >
235
212
  {/* Left-edge resizer */}
236
213
  <div
@@ -245,7 +222,7 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
245
222
  <div className={'flex-1'} style={{ minHeight: 0 }}>
246
223
  <MainContainer style={{ height: '100%', position: 'relative', background: 'var(--content-card-background)', border: 'none'}}>
247
224
  <ChatContainer style={{ height: '100%' }}>
248
- <MessageList typingIndicator={undefined} autoScrollToBottom={autoScroll}>
225
+ <MessageList typingIndicator={undefined} autoScrollToBottom>
249
226
  {messages.length === 0 && (
250
227
  <Message model={{ message: 'Start a conversation. I can answer questions about this developer’s report.', sender: 'KYD', direction: 'incoming', position: 'single' }} />
251
228
  )}
@@ -295,7 +272,7 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
295
272
  </ChatContainer>
296
273
  </MainContainer>
297
274
  </div>
298
- <form onSubmit={(e) => { e.preventDefault(); if (!sending && input.trim()) { setAutoScroll(true); sendMessage(); } }}>
275
+ <form onSubmit={(e) => { e.preventDefault(); if (!sending && input.trim()) sendMessage(); }}>
299
276
  <div className={'flex items-end gap-2 p-2 border-t'} style={{ borderColor: 'var(--icon-button-secondary)', background: 'var(--content-card-background)' }}>
300
277
  <input
301
278
  aria-label={'Type your message'}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { useEffect, useRef, useState } from 'react';
3
+ import { useEffect, useRef } from 'react';
4
4
  import './chat-overrides.css';
5
5
  import { FiSend } from 'react-icons/fi';
6
6
  import { useChatStreaming } from './useChatStreaming';
@@ -8,24 +8,14 @@ import { useChatStreaming } from './useChatStreaming';
8
8
  export default function ChatWindowStreaming({ api = '/api/chat', badgeId }: { api?: string, badgeId: string }) {
9
9
  const { messages, input, setInput, sending, sendMessage } = useChatStreaming({ api, badgeId });
10
10
  const listRef = useRef<HTMLDivElement>(null);
11
- const autoScrollRef = useRef<boolean>(true);
12
-
13
- const handleScroll = () => {
14
- const el = listRef.current;
15
- if (!el) return;
16
- const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 8;
17
- autoScrollRef.current = nearBottom;
18
- };
19
11
 
20
12
  useEffect(() => {
21
- if (listRef.current && autoScrollRef.current) {
22
- listRef.current.scrollTop = listRef.current.scrollHeight;
23
- }
13
+ if (listRef.current) listRef.current.scrollTop = listRef.current.scrollHeight;
24
14
  }, [messages]);
25
15
 
26
16
  return (
27
17
  <div className="flex flex-col border rounded-lg overflow-hidden" style={{ background: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)'}}>
28
- <div ref={listRef} className="p-4 space-y-3 h-72 overflow-auto" onScroll={handleScroll}>
18
+ <div ref={listRef} className="p-4 space-y-3 h-72 overflow-auto">
29
19
  {messages.map(m => (
30
20
  <div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
31
21
  <div
@@ -45,13 +35,13 @@ export default function ChatWindowStreaming({ api = '/api/chat', badgeId }: { ap
45
35
  <input
46
36
  value={input}
47
37
  onChange={e=>setInput(e.target.value)}
48
- onKeyDown={e=>{ if (e.key==='Enter') { autoScrollRef.current = true; sendMessage(); } }}
38
+ onKeyDown={e=>{ if (e.key==='Enter') sendMessage(); }}
49
39
  className="flex-1 px-3 py-2 rounded border kyd-chat-input"
50
40
  style={{ background: 'var(--input-background)', color: 'var(--text-main)', borderColor: 'var(--icon-button-secondary)' }}
51
41
  placeholder="Ask KYD…"
52
42
  />
53
43
  <button
54
- onClick={()=>{ autoScrollRef.current = true; sendMessage(); }}
44
+ onClick={()=>sendMessage()}
55
45
  disabled={sending}
56
46
  className="px-3 py-2 rounded disabled:opacity-60 kyd-chat-button"
57
47
  style={{ background: 'var(--gradient-start)', color: '#fff' }}