goji-search 1.0.1 → 1.1.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.
@@ -3,10 +3,11 @@ interface ActionButtonsProps {
3
3
  isHovered: boolean;
4
4
  isStreaming: boolean;
5
5
  searchQuery: string;
6
+ isRecording?: boolean;
6
7
  onSubmit: () => void;
7
8
  onVoiceSearch: () => void;
8
9
  onClose: () => void;
9
10
  onCalendarClick: () => void;
10
11
  }
11
- export declare function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSubmit, onVoiceSearch, onClose, onCalendarClick, }: ActionButtonsProps): import("react/jsx-runtime").JSX.Element | null;
12
+ export declare function ActionButtons({ size, isHovered, isStreaming, searchQuery, isRecording, onSubmit, onVoiceSearch, onClose, onCalendarClick, }: ActionButtonsProps): import("react/jsx-runtime").JSX.Element | null;
12
13
  export {};
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Mic, Calendar, ArrowUp } from "lucide-react";
3
3
  import { useState, useId } from "react";
4
- export function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSubmit, onVoiceSearch, onClose, onCalendarClick, // Added calendar click handler
4
+ export function ActionButtons({ size, isHovered, isStreaming, searchQuery, isRecording = false, onSubmit, onVoiceSearch, onClose, onCalendarClick, // Added calendar click handler
5
5
  }) {
6
6
  if (size !== "m" && size !== "l" && size !== "xl")
7
7
  return null;
@@ -49,34 +49,68 @@ export function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSub
49
49
  pointerEvents: "none",
50
50
  transition: "opacity 120ms ease-in-out",
51
51
  zIndex: 30,
52
- }, children: "Send message" })] }), _jsxs("div", { style: { position: "relative", display: "inline-block", marginLeft: "0.25rem" }, onMouseEnter: () => setHoverVoice(true), onMouseLeave: () => setHoverVoice(false), children: [_jsx("button", { type: "button", onClick: onVoiceSearch, "aria-describedby": hoverVoice ? voiceTooltipId : undefined, onBlur: (e) => {
53
- setHoverVoice(false);
54
- e.currentTarget.style.boxShadow = "inset 0 1px 0 rgba(255, 255, 255, 0.3)";
55
- }, style: {
52
+ }, children: "Send message" })] }), _jsxs("div", { style: { position: "relative", display: "inline-block", marginLeft: "0.25rem" }, onMouseEnter: () => setHoverVoice(true), onMouseLeave: () => setHoverVoice(false), children: [_jsxs("button", { type: "button", onClick: onVoiceSearch, "aria-describedby": hoverVoice ? voiceTooltipId : undefined, onFocus: () => setHoverVoice(true), onBlur: () => setHoverVoice(false), style: {
56
53
  borderRadius: "1.3rem",
57
- border: "1px solid rgba(255, 255, 255, 0.3)",
58
- backgroundColor: "rgba(255, 255, 255, 0.2)",
54
+ border: isRecording ? "1px solid rgba(220, 38, 38, 0.5)" : "1px solid rgba(255, 255, 255, 0.3)",
55
+ backgroundColor: isRecording ? "rgba(220, 38, 38, 0.2)" : "rgba(255, 255, 255, 0.2)",
59
56
  padding: size === "l" || size === "xl" ? "0.5rem" : "0.3rem",
60
57
  display: "flex",
61
58
  alignItems: "center",
62
59
  justifyContent: "center",
63
- outlineColor: "none",
64
- color: "rgba(0, 0, 0, 0.75)",
60
+ color: isRecording ? "rgba(220, 38, 38, 0.9)" : "rgba(0, 0, 0, 0.75)",
65
61
  backdropFilter: "blur(20px)",
66
62
  WebkitBackdropFilter: "blur(20px)",
67
63
  transition: "all 0.2s",
68
64
  cursor: "pointer",
69
65
  outline: "none",
70
66
  opacity: size === "m" && !isHovered ? 0.7 : 1,
71
- boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.3)",
67
+ boxShadow: isRecording ? "inset 0 1px 0 rgba(220, 38, 38, 0.2)" : "inset 0 1px 0 rgba(255, 255, 255, 0.3)",
72
68
  }, onMouseEnter: (e) => {
73
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
69
+ if (!isRecording) {
70
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
71
+ }
74
72
  }, onMouseLeave: (e) => {
75
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
76
- }, children: _jsx(Mic, { style: {
77
- width: size === "l" || size === "xl" ? "1rem" : "0.875rem",
78
- height: size === "l" || size === "xl" ? "1rem" : "0.875rem",
79
- } }) }), _jsx("span", { id: voiceTooltipId, role: "tooltip", style: {
73
+ if (!isRecording) {
74
+ e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
75
+ }
76
+ }, children: [_jsx(Mic, { style: {
77
+ width: size === "l" || size === "xl" ? "1rem" : "0.875rem",
78
+ height: size === "l" || size === "xl" ? "1rem" : "0.875rem",
79
+ } }), isRecording && (_jsxs("span", { "aria-hidden": "true", style: {
80
+ display: "inline-flex",
81
+ alignItems: "flex-end",
82
+ gap: "2px",
83
+ marginLeft: size === "l" || size === "xl" ? "6px" : "4px",
84
+ height: size === "l" || size === "xl" ? "1rem" : "0.875rem",
85
+ }, children: [_jsx("span", { style: {
86
+ width: "2px",
87
+ height: "55%",
88
+ backgroundColor: "rgba(220, 38, 38, 0.95)",
89
+ borderRadius: "1px",
90
+ transformOrigin: "bottom",
91
+ animation: "eqPulse 900ms ease-in-out 0ms infinite",
92
+ } }), _jsx("span", { style: {
93
+ width: "2px",
94
+ height: "85%",
95
+ backgroundColor: "rgba(220, 38, 38, 0.95)",
96
+ borderRadius: "1px",
97
+ transformOrigin: "bottom",
98
+ animation: "eqPulse 900ms ease-in-out 100ms infinite",
99
+ } }), _jsx("span", { style: {
100
+ width: "2px",
101
+ height: "65%",
102
+ backgroundColor: "rgba(220, 38, 38, 0.95)",
103
+ borderRadius: "1px",
104
+ transformOrigin: "bottom",
105
+ animation: "eqPulse 900ms ease-in-out 200ms infinite",
106
+ } }), _jsx("span", { style: {
107
+ width: "2px",
108
+ height: "78%",
109
+ backgroundColor: "rgba(220, 38, 38, 0.95)",
110
+ borderRadius: "1px",
111
+ transformOrigin: "bottom",
112
+ animation: "eqPulse 900ms ease-in-out 300ms infinite",
113
+ } })] }))] }), _jsx("span", { id: voiceTooltipId, role: "tooltip", style: {
80
114
  position: "absolute",
81
115
  top: "calc(100% + 0.4rem)",
82
116
  left: "50%",
@@ -92,14 +126,13 @@ export function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSub
92
126
  pointerEvents: "none",
93
127
  transition: "opacity 120ms ease-in-out",
94
128
  zIndex: 30,
95
- }, children: "Voice input" })] }), _jsxs("div", { style: { position: "relative", display: "inline-block", marginRight: "0.25rem" }, onMouseEnter: () => setHoverCalendar(true), onMouseLeave: () => setHoverCalendar(false), children: [_jsxs("button", { type: "button", disabled: isStreaming, onClick: onCalendarClick, "aria-describedby": hoverCalendar ? calendarTooltipId : undefined, onFocus: () => setHoverCalendar(true), onBlur: () => setHoverCalendar(false), style: {
129
+ }, children: isRecording ? "Stop recording" : "Voice input" })] }), _jsxs("div", { style: { position: "relative", display: "inline-block", marginRight: "0.25rem" }, onMouseEnter: () => setHoverCalendar(true), onMouseLeave: () => setHoverCalendar(false), children: [_jsxs("button", { type: "button", disabled: isStreaming, onClick: onCalendarClick, "aria-describedby": hoverCalendar ? calendarTooltipId : undefined, onFocus: () => setHoverCalendar(true), onBlur: () => setHoverCalendar(false), style: {
96
130
  borderRadius: "1.3rem",
97
131
  border: "1px solid rgba(255, 255, 255, 0.3)",
98
132
  backgroundColor: "rgb(0, 0, 0)",
99
133
  padding: size === "l" || size === "xl" ? "0.5rem" : "0.4rem",
100
134
  display: size === "l" || size === "m" || size === "xl" ? "flex" : "none",
101
135
  alignItems: "center",
102
- outlineColor: "none",
103
136
  justifyContent: "center",
104
137
  color: "rgb(255, 255, 255)",
105
138
  transition: "all 0.2s",
@@ -113,7 +146,7 @@ export function ActionButtons({ size, isHovered, isStreaming, searchQuery, onSub
113
146
  marginLeft: "0.5rem",
114
147
  fontSize: "0.7rem",
115
148
  fontWeight: 400,
116
- display: size === "m" ? "none" : "block",
149
+ display: size === "m" || searchQuery.length > 0 ? "none" : "block",
117
150
  transition: "all 0.4s",
118
151
  }, children: "Book a call" })] }), _jsx("span", { id: calendarTooltipId, role: "tooltip", style: {
119
152
  position: "absolute",
@@ -0,0 +1,8 @@
1
+ import type React from "react";
2
+ interface AutoExpandingTextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
3
+ value: string;
4
+ onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
5
+ onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
6
+ }
7
+ declare const AutoExpandingTextarea: React.ForwardRefExoticComponent<AutoExpandingTextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
8
+ export default AutoExpandingTextarea;
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect, forwardRef } from "react";
3
+ const AutoExpandingTextarea = forwardRef(({ value, onChange, onKeyDown, className, style, ...props }, ref) => {
4
+ const textareaRef = useRef(null);
5
+ useEffect(() => {
6
+ const el = ref?.current || textareaRef.current;
7
+ if (el) {
8
+ el.style.height = "auto";
9
+ const scrollHeight = el.scrollHeight;
10
+ const minHeight = 24; // one line height
11
+ const maxHeight = 160; // max ~5 lines
12
+ el.style.height = `${Math.min(Math.max(scrollHeight, minHeight), maxHeight)}px`;
13
+ }
14
+ }, [value]);
15
+ return (_jsx("textarea", { ref: ref || textareaRef, value: value, onChange: onChange, onKeyDown: (e) => {
16
+ if (e.key === "Enter" && !e.shiftKey) {
17
+ e.preventDefault();
18
+ onKeyDown?.(e);
19
+ }
20
+ else {
21
+ onKeyDown?.(e);
22
+ }
23
+ }, placeholder: "Chat with me...", className: `w-full bg-white placeholder:text-gray-500 rounded-lg text-sm sm:text-base ${className}`, style: {
24
+ lineHeight: "1.5rem",
25
+ padding: "0.5rem 0.75rem",
26
+ minHeight: "1.5rem",
27
+ maxHeight: "160px",
28
+ outline: "none",
29
+ overflow: "hidden", // ← hide scrollbars
30
+ resize: "none", // ← remove corner handle
31
+ transition: "height 0.15s ease-out",
32
+ ...style,
33
+ }, rows: 1, ...props }));
34
+ });
35
+ AutoExpandingTextarea.displayName = "AutoExpandingTextarea";
36
+ export default AutoExpandingTextarea;
@@ -9,11 +9,14 @@ export function InspirationMenu({ questions, onQuestionClick, onClose }) {
9
9
  maxWidth: "20rem",
10
10
  borderRadius: "0.75rem",
11
11
  border: "1px solid rgba(85, 85, 85, 0.18)",
12
- backgroundColor: "rgb(248, 239, 255)",
13
- boxShadow: "0 8px 28px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.4)",
12
+ // Use opaque background to fully mask underlying text
13
+ backgroundColor: "#ffffff",
14
+ // Remove blur so underlying content does not bleed through visually
15
+ boxShadow: "0 8px 28px rgba(0, 0, 0, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.6)",
14
16
  padding: "0.625rem",
15
17
  animation: "slideUpMenu 0.25s cubic-bezier(0.4, 0, 0.2, 1)",
16
- zIndex: 100,
18
+ // Ensure the popover sits above chat bubbles and other content
19
+ zIndex: 1000,
17
20
  }, onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { style: {
18
21
  display: "flex",
19
22
  justifyContent: "space-between",
@@ -27,7 +30,7 @@ export function InspirationMenu({ questions, onQuestionClick, onClose }) {
27
30
  color: "rgba(0, 0, 0, 0.5)",
28
31
  letterSpacing: "0.05em",
29
32
  textTransform: "capitalize",
30
- }, children: "Inspiration" }), _jsx("button", { type: "button", onClick: onClose, style: {
33
+ }, children: "Suggested" }), _jsx("button", { type: "button", onClick: onClose, style: {
31
34
  padding: "0.25rem",
32
35
  borderRadius: "0.375rem",
33
36
  border: "1px solid rgba(255, 255, 255, 0.2)",
@@ -52,28 +55,25 @@ export function InspirationMenu({ questions, onQuestionClick, onClose }) {
52
55
  }, children: _jsx(X, { style: { width: "0.875rem", height: "0.875rem" } }) })] }), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: questions.map((question, index) => (_jsx("button", { type: "button", onClick: () => onQuestionClick(question), style: {
53
56
  padding: "0.5rem 0.75rem",
54
57
  borderRadius: "1.3rem",
55
- border: "1px solid rgba(255, 255, 255, 0.25)",
56
- backgroundColor: "rgba(255, 255, 255, 0.2)",
57
- color: "rgba(0, 0, 0, 0.75)",
58
+ border: "1px solid rgba(0, 0, 0, 0.06)",
59
+ backgroundColor: "#ffffff",
60
+ color: "rgba(0, 0, 0, 0.85)",
58
61
  fontSize: "0.75rem",
59
62
  textAlign: "left",
60
63
  cursor: "pointer",
61
64
  transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
62
- backdropFilter: "blur(20px) saturate(180%)",
63
- WebkitBackdropFilter: "blur(20px) saturate(180%)",
64
- boxShadow: "0 1px 2px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.3)",
65
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.06)",
65
66
  outline: "none",
66
67
  lineHeight: "1.3",
67
68
  }, onMouseEnter: (e) => {
68
- e.currentTarget.style.backgroundColor = "rgba(0, 122, 255, 0.15)";
69
- e.currentTarget.style.borderColor = "rgba(0, 122, 255, 0.3)";
69
+ e.currentTarget.style.backgroundColor = "rgba(0, 122, 255, 0.1)";
70
+ e.currentTarget.style.borderColor = "rgba(0, 122, 255, 0.25)";
70
71
  e.currentTarget.style.transform = "translateY(-1px)";
71
- e.currentTarget.style.boxShadow =
72
- "0 3px 8px rgba(0, 122, 255, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.4)";
72
+ e.currentTarget.style.boxShadow = "0 3px 8px rgba(0, 122, 255, 0.12)";
73
73
  }, onMouseLeave: (e) => {
74
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
75
- e.currentTarget.style.borderColor = "rgba(255, 255, 255, 0.25)";
74
+ e.currentTarget.style.backgroundColor = "#ffffff";
75
+ e.currentTarget.style.borderColor = "rgba(0, 0, 0, 0.06)";
76
76
  e.currentTarget.style.transform = "translateY(0)";
77
- e.currentTarget.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.3)";
77
+ e.currentTarget.style.boxShadow = "0 1px 2px rgba(0, 0, 0, 0.06)";
78
78
  }, children: question }, index))) })] }));
79
79
  }
@@ -16,9 +16,7 @@ interface MessageListProps {
16
16
  messages: Message[];
17
17
  isStreaming: boolean;
18
18
  aiAvatarSrc?: string;
19
- onClose?: () => void;
20
- onExpand?: () => void;
21
19
  size?: "m" | "l" | "xl" | "s" | "xs";
22
20
  }
23
- export declare function MessageList({ messages, isStreaming, aiAvatarSrc, onClose, onExpand, size, }: MessageListProps): import("react/jsx-runtime").JSX.Element;
21
+ export declare function MessageList({ messages, isStreaming, aiAvatarSrc, size, }: MessageListProps): import("react/jsx-runtime").JSX.Element;
24
22
  export {};
@@ -1,15 +1,31 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useEffect, useState, useId } from "react";
2
+ import { useRef, useEffect, useState } from "react";
3
3
  import ReactMarkdown from "react-markdown";
4
4
  import remarkGfm from "remark-gfm";
5
- import { ExternalLink, User, X, Maximize2, Minimize2 } from "lucide-react";
6
- export function MessageList({ messages, isStreaming, aiAvatarSrc = '', onClose, onExpand, size = 'l', }) {
5
+ import { ExternalLink } from "lucide-react";
6
+ export function MessageList({ messages, isStreaming, aiAvatarSrc = '', size = 'l', }) {
7
7
  const messagesEndRef = useRef(null);
8
- const [hoverTopExpand, setHoverTopExpand] = useState(false);
9
- const [hoverTopClose, setHoverTopClose] = useState(false);
10
- const idBase = useId();
11
- const xTooltipId = `${idBase}-x-tip`;
12
- const expandTooltipId = `${idBase}-expand-tip`;
8
+ const [expandedSourcesByMessageIndex, setExpandedSourcesByMessageIndex] = useState({});
9
+ const toggleSources = (messageIndex) => {
10
+ setExpandedSourcesByMessageIndex((prev) => ({
11
+ ...prev,
12
+ [messageIndex]: !prev[messageIndex],
13
+ }));
14
+ };
15
+ const convertCitationLinksToUrls = (markdown, sources) => {
16
+ if (!markdown || !sources || sources.length === 0)
17
+ return markdown;
18
+ // Replace [text](N) where N is a positive integer referencing sources[N-1]
19
+ return markdown.replace(/\[([^\]]+)\]\((\d+)\)/g, (match, text, numStr) => {
20
+ const num = parseInt(numStr, 10);
21
+ if (Number.isNaN(num) || num < 1 || num > sources.length)
22
+ return match;
23
+ const url = sources[num - 1]?.url;
24
+ if (!url)
25
+ return match;
26
+ return `[${text}](${url})`;
27
+ });
28
+ };
13
29
  useEffect(() => {
14
30
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
15
31
  }, [messages]);
@@ -19,101 +35,39 @@ export function MessageList({ messages, isStreaming, aiAvatarSrc = '', onClose,
19
35
  position: 'relative',
20
36
  flex: 1,
21
37
  overflowY: "auto",
22
- marginTop: "0",
38
+ marginTop: "1.3rem",
23
39
  display: "flex",
24
40
  flexDirection: "column",
25
- gap: "0.75rem",
41
+ gap: "0.5rem",
26
42
  padding: "0.5rem",
27
43
  borderRadius: "0.75rem",
28
44
  backgroundColor: "rgba(255, 255, 255, 0.08)",
29
45
  border: "1px solid rgba(255, 255, 255, 0.15)",
30
- }, className: "custom-scrollbar", children: [_jsxs("div", { style: { display: 'flex', gap: '0.5rem', zIndex: 20, justifyContent: 'flex-end', paddingTop: '0' }, children: [onExpand && (_jsxs("div", { style: { position: 'relative' }, children: [_jsx("button", { type: "button", onClick: onExpand, onMouseEnter: () => setHoverTopExpand(true), onMouseLeave: () => setHoverTopExpand(false), "aria-label": size === 'xl' ? 'Restore' : 'Expand', "aria-describedby": hoverTopExpand ? expandTooltipId : undefined, style: {
31
- borderRadius: '1.3rem',
32
- border: '1px solid rgba(255, 255, 255, 0.3)',
33
- backgroundColor: 'rgba(255, 255, 255, 0.12)',
34
- padding: '0.375rem',
35
- display: 'flex',
36
- alignItems: 'center',
37
- justifyContent: 'center',
38
- color: 'rgba(0, 0, 0, 0.75)',
39
- transition: 'all 0.15s',
40
- cursor: 'pointer',
41
- outline: 'none',
42
- boxShadow: 'inset 0 1px 0 rgba(255, 255, 255, 0.2)',
43
- }, children: size === 'xl' ? _jsx(Minimize2, { style: { width: '0.9rem', height: '0.9rem' } }) : _jsx(Maximize2, { style: { width: '0.9rem', height: '0.9rem' } }) }), _jsx("span", { id: expandTooltipId, role: "tooltip", style: {
44
- position: 'absolute',
45
- top: 'calc(100% + 0.4rem)',
46
- left: '50%',
47
- transform: 'translateX(-50%)',
48
- whiteSpace: 'nowrap',
49
- background: 'rgba(0,0,0,0.9)',
50
- color: '#fff',
51
- padding: '4px 6px',
52
- borderRadius: '1.3rem',
53
- fontSize: '0.55rem',
54
- boxShadow: '0 6px 18px rgba(0,0,0,0.35)',
55
- opacity: hoverTopExpand ? 1 : 0,
56
- pointerEvents: 'none',
57
- transition: 'opacity 120ms ease-in-out',
58
- zIndex: 30,
59
- }, children: size === 'xl' ? 'Restore' : 'Expand' })] })), onClose && (_jsxs("div", { style: { position: 'relative' }, children: [_jsx("button", { type: "button", onClick: onClose, onMouseEnter: () => setHoverTopClose(true), onMouseLeave: () => setHoverTopClose(false), "aria-label": "Close", "aria-describedby": hoverTopClose ? xTooltipId : undefined, style: {
60
- borderRadius: '1.3rem',
61
- border: '1px solid rgba(255, 255, 255, 0.3)',
62
- backgroundColor: 'rgba(255, 255, 255, 0.12)',
63
- padding: '0.375rem',
64
- display: 'flex',
65
- alignItems: 'center',
66
- justifyContent: 'center',
67
- color: 'rgba(0, 0, 0, 0.75)',
68
- transition: 'all 0.15s',
69
- cursor: 'pointer',
70
- outline: 'none',
71
- boxShadow: 'inset 0 1px 0 rgba(255, 255, 255, 0.2)',
72
- }, children: _jsx(X, { style: { width: '0.9rem', height: '0.9rem' } }) }), _jsx("span", { id: xTooltipId, role: "tooltip", style: {
73
- position: 'absolute',
74
- top: 'calc(100% + 0.4rem)',
75
- left: '50%',
76
- transform: 'translateX(-50%)',
77
- whiteSpace: 'nowrap',
78
- background: 'rgba(0,0,0,0.9)',
79
- color: '#fff',
80
- padding: '4px 6px',
81
- borderRadius: '1.3rem',
82
- fontSize: '0.55rem',
83
- boxShadow: '0 6px 18px rgba(0,0,0,0.35)',
84
- opacity: hoverTopClose ? 1 : 0,
85
- pointerEvents: 'none',
86
- transition: 'opacity 120ms ease-in-out',
87
- zIndex: 30,
88
- }, children: "Close" })] }))] }), messages.map((message, index) => (_jsxs("div", { style: {
46
+ }, className: "custom-scrollbar", children: [messages.map((message, index) => (_jsxs("div", { style: {
89
47
  display: "flex",
90
- flexDirection: "column",
91
- alignItems: message.role === "user" ? "flex-end" : "flex-start",
48
+ justifyContent: message.role === "user" ? "flex-end" : "flex-start",
92
49
  animation: "fadeIn 0.3s ease-in",
93
- gap: "0.375rem",
50
+ gap: "0.4rem",
94
51
  }, children: [_jsx("div", { style: {
95
52
  display: "flex",
96
- alignItems: "center",
97
- gap: "0.5rem",
98
- flexDirection: message.role === "user" ? "row-reverse" : "row"
53
+ gap: "0.4rem",
54
+ alignItems: message.role === "user" ? "flex-end" : "flex-start"
99
55
  }, children: _jsx("div", { style: {
100
- width: "1.75rem",
101
- height: "1.75rem",
102
- borderRadius: message.role === "user" ? "50%" : "0.75rem",
103
- backgroundColor: message.role === "user" ? "rgba(255, 255, 255, 0.15)" : "rgba(114, 126, 237, 0.15)",
56
+ width: message.role === "user" ? "0" : "1.4rem",
57
+ height: message.role === "user" ? "0" : "auto",
58
+ borderRadius: "none",
59
+ backgroundColor: "transparent",
104
60
  display: "flex",
105
61
  alignItems: "center",
106
62
  justifyContent: "center",
107
63
  fontSize: "0.75rem",
108
- color: "rgb(114, 126, 237)",
109
- border: message.role === "user"
110
- ? "1px solid rgba(114, 126, 237, 0.3)"
111
- : "1px dashed rgba(114, 126, 237, 0.3)",
112
- boxShadow: message.role === "user" ? "0 2px 4px rgba(0,0,0,0.05)" : "none",
113
- }, children: message.role === "user" ? (_jsx(User, { size: 16, color: "rgb(114, 126, 237)" })) : (aiAvatarSrc ? (_jsx("img", { src: aiAvatarSrc, alt: "AI Avatar", style: {
64
+ border: "none",
65
+ boxShadow: "none",
66
+ }, children: message.role === "user" ? (
67
+ // <User size={16} color="rgba(0, 0, 0, 1)" />
68
+ _jsx("div", {})) : (aiAvatarSrc ? (_jsx("img", { src: aiAvatarSrc, alt: "AI Avatar", style: {
114
69
  width: "100%",
115
70
  height: "100%",
116
- borderRadius: "inherit",
117
71
  objectFit: "cover"
118
72
  } })) : (_jsx("div", { style: {
119
73
  width: "100%",
@@ -122,34 +76,58 @@ export function MessageList({ messages, isStreaming, aiAvatarSrc = '', onClose,
122
76
  alignItems: "center",
123
77
  justifyContent: "center",
124
78
  fontSize: "0.75rem",
125
- color: "rgb(114, 126, 237)"
79
+ color: "rgba(217, 219, 234, 1)"
126
80
  }, children: "AI" }))) }) }), _jsxs("div", { style: {
127
81
  maxWidth: "85%",
128
- padding: message.role === "user" ? "0.275rem 0.75rem" : "0.5rem 0",
82
+ padding: message.role === "user" ? "0.275rem 0.5rem" : "0.5rem 0",
129
83
  borderRadius: message.role === "user" ? "1rem" : "0",
130
84
  fontSize: "0.875rem",
131
85
  marginLeft: message.role === "user" ? "0" : "1rem",
132
86
  marginRight: message.role === "user" ? "1rem" : "0",
133
- lineHeight: "1.6",
87
+ lineHeight: "1.4",
134
88
  backgroundColor: message.role === "user" ? "rgb(114, 126, 237)" : "transparent",
135
89
  color: message.role === "user" ? "white" : "rgba(0, 0, 0, 0.85)",
136
90
  border: message.role === "user" ? "1px solid rgba(255, 255, 255, 0.25)" : "none",
137
91
  }, children: [message.role === "user" ? (_jsx("p", { style: { margin: 0, whiteSpace: "pre-wrap" }, children: message.content })) : (_jsx("div", { className: "markdown-content", style: {
138
92
  fontSize: "0.875rem",
139
- lineHeight: "1.7",
93
+ lineHeight: "1.4",
140
94
  color: "rgba(0, 0, 0, 0.85)",
141
- }, children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.content }) })), message.role === "assistant" && message.sources && message.sources.length > 0 && (_jsxs("div", { style: {
142
- marginTop: "1rem",
143
- paddingTop: "0.75rem",
95
+ }, children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: {
96
+ a: ({ href, children, ...props }) => {
97
+ const hasSources = Array.isArray(message.sources) && message.sources.length > 0;
98
+ if (!hasSources) {
99
+ const anyProps = props;
100
+ return (_jsx("span", { className: anyProps?.className, style: anyProps?.style, children: children }));
101
+ }
102
+ return (_jsx("a", { href: href || '', target: "_blank", rel: "noopener noreferrer", ...props, children: children }));
103
+ },
104
+ }, children: convertCitationLinksToUrls(message.content, message.sources) }) })), message.role === "assistant" && message.sources && message.sources.length > 0 && (_jsxs("div", { style: {
105
+ marginTop: "0.25rem",
106
+ paddingTop: "0.25rem",
144
107
  borderTop: "1px solid rgba(0, 0, 0, 0.1)",
145
- }, children: [_jsx("p", { style: {
146
- fontSize: "0.65rem",
147
- fontWeight: 600,
148
- textTransform: "uppercase",
149
- letterSpacing: "0.05em",
150
- color: "rgba(0, 0, 0, 0.5)",
151
- marginBottom: "0.5rem",
152
- }, children: "Sources" }), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: message.sources.map((source) => (_jsxs("a", { href: source.url, target: "_blank", rel: "noopener noreferrer", style: {
108
+ }, children: [_jsxs("div", { style: {
109
+ display: "flex",
110
+ alignItems: "center",
111
+ justifyContent: "space-between",
112
+ gap: "0.5rem",
113
+ marginBottom: "0.25rem",
114
+ }, children: [_jsx("p", { style: {
115
+ fontSize: "0.65rem",
116
+ fontWeight: 600,
117
+ textTransform: "uppercase",
118
+ letterSpacing: "0.05em",
119
+ color: "rgba(0, 0, 0, 0.5)",
120
+ margin: 0,
121
+ }, children: "Sources" }), _jsx("button", { type: "button", onClick: () => toggleSources(index), style: {
122
+ borderRadius: "0.5rem",
123
+ border: "1px solid rgba(255, 255, 255, 0.3)",
124
+ backgroundColor: "rgba(255, 255, 255, 0.2)",
125
+ padding: "0.2rem 0.4rem",
126
+ fontSize: "0.7rem",
127
+ color: "rgba(0, 0, 0, 0.75)",
128
+ cursor: "pointer",
129
+ outline: "none",
130
+ }, children: expandedSourcesByMessageIndex[index] ? "Hide" : "Show" })] }), expandedSourcesByMessageIndex[index] && (_jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: message.sources.map((source) => (_jsxs("a", { href: source.url, target: "_blank", rel: "noopener noreferrer", style: {
153
131
  display: "flex",
154
132
  alignItems: "center",
155
133
  gap: "0.5rem",
@@ -167,8 +145,8 @@ export function MessageList({ messages, isStreaming, aiAvatarSrc = '', onClose,
167
145
  borderRadius: "0.375rem",
168
146
  fontSize: "0.65rem",
169
147
  fontWeight: 600,
170
- }, children: ["#", source.index] }), _jsx("span", { style: { flex: 1, wordBreak: "break-all" }, children: source.url }), _jsx(ExternalLink, { style: { width: "0.875rem", height: "0.875rem", opacity: 0.6 } })] }, source.index))) })] }))] })] }, index))), showThinkingDots && (_jsx("div", { style: { display: "flex", justifyContent: "flex-start" }, children: _jsxs("div", { style: {
171
- padding: "0.75rem 0.6rem",
148
+ }, children: ["#", source.index] }), _jsx("span", { style: { flex: 1, wordBreak: "break-all" }, children: source.url }), _jsx(ExternalLink, { style: { width: "0.875rem", height: "0.875rem", opacity: 0.6 } })] }, source.index))) }))] }))] })] }, index))), showThinkingDots && (_jsx("div", { style: { display: "flex", justifyContent: "flex-start" }, children: _jsxs("div", { style: {
149
+ padding: "0.25rem 0.6rem",
172
150
  borderRadius: "1rem",
173
151
  display: "flex",
174
152
  gap: "0.375rem",
@@ -1,12 +1,12 @@
1
1
  import type React from "react";
2
2
  interface SearchInputProps {
3
3
  value: string;
4
- onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
4
+ onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
5
5
  onFocus: () => void;
6
6
  onBlur: () => void;
7
7
  placeholder: string;
8
8
  size: "xs" | "s" | "m" | "l" | "xl";
9
- inputRef: React.RefObject<HTMLInputElement>;
9
+ inputRef: React.RefObject<HTMLTextAreaElement>;
10
10
  inspirationQuestions: string[];
11
11
  onInspirationClick: (question: string) => void;
12
12
  sparkleRef: React.RefObject<HTMLDivElement>;