goji-search 1.0.0 → 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.
@@ -1,15 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import "./goji-search.css";
3
3
  import { ArrowLeft, X, Maximize2, Minimize2 } from "lucide-react";
4
- import { useState, useEffect, useRef, useId } from "react";
4
+ import { useState, useEffect, useRef, useId, useMemo } from "react";
5
5
  import { SuggestedQuestions } from "./elements/suggested-questions";
6
6
  import { MessageList } from "./elements/message-list";
7
+ import chatLogo from "../assets/chat-logo.png";
7
8
  import { SearchInput } from "./elements/search-input";
8
9
  import { ActionButtons } from "./elements/action-buttons";
9
10
  import CalendarIntegration from "./elements/calendar-integration";
10
- import { gojiClient } from "../lib/goji-client";
11
+ import { createGojiClient } from "../lib/goji-client";
11
12
  import { companyConfig } from "../config/company";
12
- export function GojiSearchComponent() {
13
+ export function GojiSearchComponent({ apiUrl } = {}) {
14
+ // Create client instance based on provided API URL
15
+ const client = useMemo(() => createGojiClient(apiUrl), [apiUrl]);
13
16
  const [searchQuery, setSearchQuery] = useState("");
14
17
  const [size, setSize] = useState("xs");
15
18
  const [isHovered, setIsHovered] = useState(false);
@@ -22,13 +25,20 @@ export function GojiSearchComponent() {
22
25
  const inputRef = useRef(null);
23
26
  const sparkleRef = useRef(null);
24
27
  const streamingCancelRef = useRef(null);
28
+ const mediaRecorderRef = useRef(null);
29
+ const audioChunksRef = useRef([]);
25
30
  const [isInputHovered, setIsInputHovered] = useState(false);
26
31
  const [hoverTopExpand, setHoverTopExpand] = useState(false);
27
32
  const [hoverTopClose, setHoverTopClose] = useState(false);
28
- const currentLanguage = companyConfig.defaultLanguage;
33
+ const [isRecording, setIsRecording] = useState(false);
34
+ const [backendSuggestedQuestions, setBackendSuggestedQuestions] = useState(null);
35
+ // Language selection state - will be set from backend default
36
+ const [selectedLanguage, setSelectedLanguage] = useState('en');
37
+ const [showLanguageMenu, setShowLanguageMenu] = useState(false);
38
+ const currentLanguage = selectedLanguage;
29
39
  const languageConfig = companyConfig.languages[currentLanguage];
30
- const suggestedQuestions = languageConfig.suggestedPrompts;
31
- const inspirationQuestions = languageConfig.suggestedPrompts;
40
+ // Use backend-provided questions only (no hardcoded prompts)
41
+ const inspirationQuestions = backendSuggestedQuestions || [];
32
42
  const idBase = useId();
33
43
  const xTooltipId = `${idBase}-x-tip`;
34
44
  const expandTooltipId = `${idBase}-expand-tip`;
@@ -38,22 +48,83 @@ export function GojiSearchComponent() {
38
48
  }, 4000);
39
49
  return () => clearTimeout(timer);
40
50
  }, []);
51
+ // Close language menu when clicking outside
41
52
  useEffect(() => {
42
- const timer = setTimeout(() => {
43
- if (!hasInteracted && size !== "xs") {
44
- setSize("xs");
53
+ if (!showLanguageMenu)
54
+ return;
55
+ const handleClickOutside = (e) => {
56
+ const target = e.target;
57
+ if (!target.closest('[data-language-menu]')) {
58
+ setShowLanguageMenu(false);
45
59
  }
46
- }, 12000);
47
- return () => clearTimeout(timer);
48
- }, [hasInteracted, size]);
60
+ };
61
+ document.addEventListener('mousedown', handleClickOutside);
62
+ return () => document.removeEventListener('mousedown', handleClickOutside);
63
+ }, [showLanguageMenu]);
64
+ // Language change handler with persistence
65
+ const handleLanguageChange = (lang) => {
66
+ setSelectedLanguage(lang);
67
+ setShowLanguageMenu(false);
68
+ // Persist to localStorage
69
+ if (typeof window !== 'undefined') {
70
+ localStorage.setItem('goji-language', lang);
71
+ }
72
+ // Reload suggestions for new language
73
+ client.getSuggestions({ language: lang })
74
+ .then(res => {
75
+ if (Array.isArray(res?.suggestions) && res.suggestions.length > 0) {
76
+ setBackendSuggestedQuestions(res.suggestions);
77
+ }
78
+ })
79
+ .catch(e => console.error("Failed to fetch suggestions", e));
80
+ };
49
81
  useEffect(() => {
82
+ // Load initial suggestions and default language from backend on mount (ONLY ONCE)
83
+ (async () => {
84
+ try {
85
+ // Fetch suggestions with initial language (en)
86
+ const res = await client.getSuggestions({ language: 'en' });
87
+ // Check if backend provides a different default language
88
+ if (res?.default_language && typeof res.default_language === 'string') {
89
+ const backendDefaultLang = res.default_language.toLowerCase().trim();
90
+ // Validate it's a supported language
91
+ if (companyConfig.languages[backendDefaultLang]) {
92
+ // Set the language FIRST
93
+ setSelectedLanguage(backendDefaultLang);
94
+ // Then fetch suggestions for the correct language
95
+ if (backendDefaultLang !== 'en') {
96
+ const langRes = await client.getSuggestions({ language: backendDefaultLang });
97
+ if (Array.isArray(langRes?.suggestions) && langRes.suggestions.length > 0) {
98
+ setBackendSuggestedQuestions(langRes.suggestions);
99
+ }
100
+ }
101
+ else {
102
+ // Use English suggestions
103
+ if (Array.isArray(res?.suggestions) && res.suggestions.length > 0) {
104
+ setBackendSuggestedQuestions(res.suggestions);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ else {
110
+ // No default language override, use English suggestions
111
+ if (Array.isArray(res?.suggestions) && res.suggestions.length > 0) {
112
+ setBackendSuggestedQuestions(res.suggestions);
113
+ }
114
+ }
115
+ }
116
+ catch (e) {
117
+ // Silent fail; UI will simply show empty inspiration until chat flows populate
118
+ console.error("Failed to fetch suggestions", e);
119
+ }
120
+ })();
50
121
  return () => {
51
122
  if (streamingCancelRef.current) {
52
123
  streamingCancelRef.current();
53
124
  }
54
- gojiClient.closeWebSocket();
125
+ client.closeWebSocket();
55
126
  };
56
- }, []);
127
+ }, [client]);
57
128
  const handleSearch = async (e) => {
58
129
  e.preventDefault();
59
130
  if (!searchQuery.trim() || isStreaming)
@@ -73,11 +144,11 @@ export function GojiSearchComponent() {
73
144
  setMessages((prev) => [...prev, { role: "assistant", content: "", timestamp: Date.now() }]);
74
145
  let accumulatedContent = "";
75
146
  try {
76
- const cancelFn = await gojiClient.streamChat({
147
+ const cancelFn = await client.streamChat({
77
148
  message: userMessage.content,
78
149
  sessionId,
79
150
  limit: 5,
80
- language: "en",
151
+ language: currentLanguage,
81
152
  onDelta: (delta) => {
82
153
  accumulatedContent += delta;
83
154
  setMessages((prev) => {
@@ -95,10 +166,15 @@ export function GojiSearchComponent() {
95
166
  const updated = [...prev];
96
167
  updated[assistantMessageIndex] = {
97
168
  ...updated[assistantMessageIndex],
169
+ content: response.answer,
98
170
  sources: response.sources,
99
171
  };
100
172
  return updated;
101
173
  });
174
+ // Update suggested questions from backend
175
+ if (response.suggested_questions && response.suggested_questions.length > 0) {
176
+ setBackendSuggestedQuestions(response.suggested_questions);
177
+ }
102
178
  setIsStreaming(false);
103
179
  streamingCancelRef.current = null;
104
180
  },
@@ -138,11 +214,11 @@ export function GojiSearchComponent() {
138
214
  setMessages((prev) => [...prev, { role: "assistant", content: "", timestamp: Date.now() }]);
139
215
  let accumulatedContent = "";
140
216
  try {
141
- const cancelFn = await gojiClient.streamChat({
217
+ const cancelFn = await client.streamChat({
142
218
  message: question,
143
219
  sessionId,
144
220
  limit: 5,
145
- language: "en",
221
+ language: currentLanguage,
146
222
  onDelta: (delta) => {
147
223
  accumulatedContent += delta;
148
224
  setMessages((prev) => {
@@ -160,10 +236,15 @@ export function GojiSearchComponent() {
160
236
  const updated = [...prev];
161
237
  updated[assistantMessageIndex] = {
162
238
  ...updated[assistantMessageIndex],
239
+ content: response.answer,
163
240
  sources: response.sources,
164
241
  };
165
242
  return updated;
166
243
  });
244
+ // Update suggested questions from backend
245
+ if (response.suggested_questions && response.suggested_questions.length > 0) {
246
+ setBackendSuggestedQuestions(response.suggested_questions);
247
+ }
167
248
  setIsStreaming(false);
168
249
  streamingCancelRef.current = null;
169
250
  },
@@ -193,8 +274,130 @@ export function GojiSearchComponent() {
193
274
  setSize("xs");
194
275
  setShowCalendar(false);
195
276
  };
196
- const handleVoiceSearch = () => {
197
- console.log("Voice search activated");
277
+ const handleVoiceSearch = async () => {
278
+ try {
279
+ if (typeof window === "undefined")
280
+ return;
281
+ if (isRecording) {
282
+ try {
283
+ mediaRecorderRef.current?.stop();
284
+ }
285
+ catch (_) { }
286
+ setIsRecording(false);
287
+ return;
288
+ }
289
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
290
+ const recorder = new MediaRecorder(stream);
291
+ mediaRecorderRef.current = recorder;
292
+ audioChunksRef.current = [];
293
+ recorder.ondataavailable = (e) => {
294
+ if (e.data && e.data.size > 0) {
295
+ audioChunksRef.current.push(e.data);
296
+ }
297
+ };
298
+ recorder.onstop = async () => {
299
+ try {
300
+ const blob = new Blob(audioChunksRef.current, { type: "audio/webm" });
301
+ // Send to backend for transcription
302
+ const language = companyConfig.defaultLanguage || "en";
303
+ const result = await client.transcribeAudio({
304
+ file: blob,
305
+ filename: "recording.webm",
306
+ model: "gpt-4o-transcribe",
307
+ language,
308
+ });
309
+ const text = (result?.text || "").trim();
310
+ if (!text)
311
+ return;
312
+ // Auto-submit the transcribed text
313
+ const userMessage = {
314
+ role: "user",
315
+ content: text,
316
+ timestamp: Date.now(),
317
+ };
318
+ setMessages((prev) => [...prev, userMessage]);
319
+ setSearchQuery("");
320
+ setSize((prev) => (prev === "xl" ? "xl" : "l"));
321
+ setIsStreaming(true);
322
+ const assistantMessageIndex = messages.length + 1;
323
+ setMessages((prev) => [...prev, { role: "assistant", content: "", timestamp: Date.now() }]);
324
+ let accumulatedContent = "";
325
+ try {
326
+ const cancelFn = await client.streamChat({
327
+ message: userMessage.content,
328
+ sessionId,
329
+ limit: 5,
330
+ language: currentLanguage,
331
+ onDelta: (delta) => {
332
+ accumulatedContent += delta;
333
+ setMessages((prev) => {
334
+ const updated = [...prev];
335
+ updated[assistantMessageIndex] = {
336
+ ...updated[assistantMessageIndex],
337
+ content: accumulatedContent,
338
+ };
339
+ return updated;
340
+ });
341
+ },
342
+ onDone: (response) => {
343
+ setSessionId(response.session_id);
344
+ setMessages((prev) => {
345
+ const updated = [...prev];
346
+ updated[assistantMessageIndex] = {
347
+ ...updated[assistantMessageIndex],
348
+ content: response.answer,
349
+ sources: response.sources,
350
+ };
351
+ return updated;
352
+ });
353
+ // Update suggested questions from backend
354
+ if (response.suggested_questions && response.suggested_questions.length > 0) {
355
+ setBackendSuggestedQuestions(response.suggested_questions);
356
+ }
357
+ setIsStreaming(false);
358
+ streamingCancelRef.current = null;
359
+ },
360
+ onError: (error) => {
361
+ console.error(" Streaming error:", error);
362
+ setMessages((prev) => {
363
+ const updated = [...prev];
364
+ updated[assistantMessageIndex] = {
365
+ ...updated[assistantMessageIndex],
366
+ content: "I'm sorry, I encountered an error. Please try again.",
367
+ };
368
+ return updated;
369
+ });
370
+ setIsStreaming(false);
371
+ streamingCancelRef.current = null;
372
+ },
373
+ });
374
+ streamingCancelRef.current = cancelFn;
375
+ }
376
+ catch (error) {
377
+ console.error(" Failed to start streaming:", error);
378
+ setIsStreaming(false);
379
+ }
380
+ }
381
+ catch (err) {
382
+ console.error("Transcription failed:", err);
383
+ }
384
+ finally {
385
+ // Cleanup audio tracks
386
+ try {
387
+ mediaRecorderRef.current?.stream?.getTracks?.().forEach((t) => t.stop());
388
+ }
389
+ catch (_) { }
390
+ mediaRecorderRef.current = null;
391
+ audioChunksRef.current = [];
392
+ }
393
+ };
394
+ recorder.start(250);
395
+ setIsRecording(true);
396
+ }
397
+ catch (err) {
398
+ console.error("Voice search failed:", err);
399
+ setIsRecording(false);
400
+ }
198
401
  };
199
402
  const handleToggle = () => {
200
403
  setHasInteracted(true);
@@ -268,7 +471,7 @@ export function GojiSearchComponent() {
268
471
  };
269
472
  const handleCalendarClick = () => {
270
473
  setShowCalendar(true);
271
- setSize("l");
474
+ setSize("xl");
272
475
  };
273
476
  const handleBackToChat = () => {
274
477
  setShowCalendar(false);
@@ -277,8 +480,8 @@ export function GojiSearchComponent() {
277
480
  xs: { maxWidth: "5.5rem", bottom: "0.5rem", padding: "0" },
278
481
  s: { maxWidth: "25.5rem", bottom: "0.5rem", padding: "0" },
279
482
  m: { maxWidth: "30rem", bottom: "0.75rem", padding: "0.25rem" },
280
- l: { maxWidth: "45vw", bottom: "1.25rem", padding: "1rem" },
281
- xl: { maxWidth: "70vw", bottom: "1.5rem", padding: "1.25rem" },
483
+ l: { maxWidth: "45vw", bottom: "1.25rem", padding: "0.5rem" },
484
+ xl: { maxWidth: "70vw", bottom: "1.5rem", padding: "0.75rem" },
282
485
  };
283
486
  const currentConfig = sizeConfig[size];
284
487
  return (_jsx("div", { style: {
@@ -298,6 +501,8 @@ export function GojiSearchComponent() {
298
501
  border: size === "xs" || size === "s" ? "none" : "1px solid rgba(85, 85, 85, 0.18)",
299
502
  backgroundColor: size === "xs" || size === "s" ? "transparent" : "rgba(233, 210, 251, 0.15)",
300
503
  padding: size === "s" ? "0" : currentConfig.padding,
504
+ // remove top padding so inner message list / calendar sit flush with the component border
505
+ paddingTop: 0,
301
506
  height: size === "l" ? "55vh" : size === "xl" ? "70vh" : "auto",
302
507
  display: "flex",
303
508
  flexDirection: "column",
@@ -310,77 +515,76 @@ export function GojiSearchComponent() {
310
515
  backdropFilter: size === "xs" || size === "s" ? "none" : "blur(40px) saturate(180%) brightness(110%)",
311
516
  WebkitBackdropFilter: size === "xs" || size === "s" ? "none" : "blur(40px) saturate(180%) brightness(110%)",
312
517
  transition: "all 0.4s cubic-bezier(0.4, 0, 0.2, 1)",
313
- }, children: [(size === "m" || size === "l" || size === "xl") && (_jsx("div", { style: {
518
+ }, children: [["m", "l", "xl"].includes(size) && (_jsx("div", { style: {
314
519
  position: "absolute",
315
- top: size === "m" ? "0.5rem" : "0.75rem",
316
- right: size === "m" ? "0.5rem" : "0.75rem",
520
+ top: 0,
521
+ right: "0.5rem",
317
522
  zIndex: 50,
523
+ paddingBottom: "0.5rem",
318
524
  }, children: _jsx("div", { style: {
319
525
  position: "relative",
320
- // show the top-right controls when we have no messages OR when in compact (m) mode OR when calendar is open
321
- // but hide them when only suggested questions are shown (messages.length === 0 && showSuggestions)
322
- display: (size === 'm' || messages.length === 0 || showCalendar) && !(messages.length === 0 && showSuggestions) ? 'inline-flex' : 'none',
526
+ display: 'flex',
323
527
  gap: '0.5rem',
324
528
  alignItems: 'center',
325
- }, children: _jsxs("div", { style: { display: 'inline-flex', gap: '0.375rem', alignItems: 'center' }, children: [_jsxs("div", { style: { position: 'relative' }, children: [_jsx("button", { type: "button", onClick: handleExpandToggle, onMouseEnter: () => setHoverTopExpand(true), onMouseLeave: () => setHoverTopExpand(false), "aria-label": size === 'xl' ? 'Restore' : 'Expand', "aria-describedby": hoverTopExpand ? expandTooltipId : undefined, style: {
326
- borderRadius: '1.3rem',
327
- border: '1px solid rgba(255, 255, 255, 0.3)',
328
- backgroundColor: 'rgba(255, 255, 255, 0.2)',
329
- padding: '0.375rem',
330
- display: 'flex',
331
- alignItems: 'center',
332
- justifyContent: 'center',
333
- color: 'rgba(0, 0, 0, 0.75)',
334
- transition: 'all 0.2s',
335
- cursor: 'pointer',
336
- outline: 'none',
337
- boxShadow: 'inset 0 1px 0 rgba(255, 255, 255, 0.3)',
338
- }, 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: {
339
- position: 'absolute',
340
- top: 'calc(100% + 0.4rem)',
341
- left: '50%',
342
- transform: 'translateX(-50%)',
343
- whiteSpace: 'nowrap',
344
- background: 'rgba(0,0,0,0.9)',
345
- color: '#fff',
346
- padding: '4px 6px',
347
- borderRadius: '1.3rem',
348
- fontSize: '0.55rem',
349
- boxShadow: '0 6px 18px rgba(0,0,0,0.35)',
529
+ justifyContent: 'flex-end',
530
+ zIndex: 20,
531
+ paddingRight: "0.3rem",
532
+ backgroundColor: "transparent",
533
+ borderRadius: "0.75rem",
534
+ }, children: _jsxs("div", { style: {
535
+ display: "flex",
536
+ gap: "0.375rem",
537
+ alignItems: "center",
538
+ padding: "0.3rem 0 0.5rem 0",
539
+ }, children: [_jsxs("div", { style: { position: "relative" }, children: [_jsx("button", { type: "button", onClick: handleExpandToggle, onMouseEnter: () => setHoverTopExpand(true), onMouseLeave: () => setHoverTopExpand(false), "aria-label": size === "xl" ? "Restore" : "Expand", "aria-describedby": hoverTopExpand ? expandTooltipId : undefined, style: {
540
+ padding: "0.375rem",
541
+ display: "flex",
542
+ alignItems: "center",
543
+ justifyContent: "center",
544
+ color: "rgba(0, 0, 0, 0.75)",
545
+ transition: "all 0.15s",
546
+ cursor: "pointer",
547
+ outline: "none",
548
+ }, 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: {
549
+ position: "absolute",
550
+ top: "calc(100% + 0.4rem)",
551
+ left: "50%",
552
+ transform: "translateX(-50%)",
553
+ whiteSpace: "nowrap",
554
+ background: "rgba(0,0,0,0.9)",
555
+ color: "#fff",
556
+ padding: "4px 6px",
557
+ borderRadius: "1.3rem",
558
+ fontSize: "0.55rem",
559
+ boxShadow: "0 6px 18px rgba(0,0,0,0.35)",
350
560
  opacity: hoverTopExpand ? 1 : 0,
351
- pointerEvents: 'none',
352
- transition: 'opacity 120ms ease-in-out',
561
+ pointerEvents: "none",
562
+ transition: "opacity 120ms ease-in-out",
353
563
  zIndex: 30,
354
- }, children: size === 'xl' ? 'Restore' : 'Expand' })] }), _jsxs("div", { style: { position: 'relative' }, children: [_jsx("button", { type: "button", onClick: handleClose, onMouseEnter: () => setHoverTopClose(true), onMouseLeave: () => setHoverTopClose(false), "aria-label": "Close", "aria-describedby": hoverTopClose ? xTooltipId : undefined, style: {
355
- borderRadius: "1.3rem",
356
- border: "1px solid rgba(255, 255, 255, 0.3)",
357
- backgroundColor: "rgba(255, 255, 255, 0.2)",
358
- padding: "0.4rem",
564
+ }, children: size === "xl" ? "Restore" : "Expand" })] }), _jsxs("div", { style: { position: "relative" }, children: [_jsx("button", { type: "button", onClick: handleClose, onMouseEnter: () => setHoverTopClose(true), onMouseLeave: () => setHoverTopClose(false), "aria-label": "Close", "aria-describedby": hoverTopClose ? xTooltipId : undefined, style: {
565
+ padding: "0.375rem",
359
566
  display: "flex",
360
567
  alignItems: "center",
361
568
  justifyContent: "center",
362
569
  color: "rgba(0, 0, 0, 0.75)",
363
- backdropFilter: "blur(20px)",
364
- WebkitBackdropFilter: "blur(20px)",
365
- transition: "all 0.2s",
570
+ transition: "all 0.15s",
366
571
  cursor: "pointer",
367
572
  outline: "none",
368
- boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.3)",
369
- }, children: _jsx(X, { style: { width: "0.875rem", height: "0.875rem" } }) }), _jsx("span", { id: xTooltipId, role: "tooltip", style: {
370
- position: 'absolute',
371
- top: 'calc(100% + 0.4rem)',
372
- left: '50%',
373
- transform: 'translateX(-50%)',
374
- whiteSpace: 'nowrap',
375
- background: 'rgba(0,0,0,0.9)',
376
- color: '#fff',
377
- padding: '4px 6px',
378
- borderRadius: '1.3rem',
379
- fontSize: '0.55rem',
380
- boxShadow: '0 6px 18px rgba(0,0,0,0.35)',
573
+ }, children: _jsx(X, { style: { width: "0.9rem", height: "0.9rem" } }) }), _jsx("span", { id: xTooltipId, role: "tooltip", style: {
574
+ position: "absolute",
575
+ top: "calc(100% + 0.4rem)",
576
+ left: "50%",
577
+ transform: "translateX(-50%)",
578
+ whiteSpace: "nowrap",
579
+ background: "rgba(0,0,0,0.9)",
580
+ color: "#fff",
581
+ padding: "4px 6px",
582
+ borderRadius: "1.3rem",
583
+ fontSize: "0.55rem",
584
+ boxShadow: "0 6px 18px rgba(0,0,0,0.35)",
381
585
  opacity: hoverTopClose ? 1 : 0,
382
- pointerEvents: 'none',
383
- transition: 'opacity 120ms ease-in-out',
586
+ pointerEvents: "none",
587
+ transition: "opacity 120ms ease-in-out",
384
588
  zIndex: 30,
385
589
  }, children: "Close" })] })] }) }) })), size === "xs" ? (_jsx("button", { type: "button", onClick: handleToggle, style: {
386
590
  background: "transparent",
@@ -401,29 +605,21 @@ export function GojiSearchComponent() {
401
605
  display: "flex",
402
606
  alignItems: "center",
403
607
  justifyContent: "center",
404
- padding: "0.5rem",
405
- borderRadius: "0.5rem",
406
- border: "1px solid rgba(255, 255, 255, 0.3)",
407
- backgroundColor: "rgba(255, 255, 255, 0.2)",
608
+ padding: "0.3rem 0 0.5rem 0.3rem",
408
609
  color: "rgba(0, 0, 0, 0.75)",
409
610
  cursor: "pointer",
410
611
  transition: "all 0.2s",
411
612
  alignSelf: "flex-start",
412
- width: "2.5rem",
413
- height: "2.5rem",
414
- }, onMouseEnter: (e) => {
415
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.3)";
416
- }, onMouseLeave: (e) => {
417
- e.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
418
- }, children: _jsx(ArrowLeft, { style: { width: "1.125rem", height: "1.125rem" } }) }), _jsx("div", { style: {
613
+ outline: "none",
614
+ }, children: _jsx(ArrowLeft, { style: { width: "0.875rem", height: "0.875rem" } }) }), _jsx("div", { style: {
419
615
  flex: 1,
420
616
  borderRadius: "0.75rem",
421
617
  overflow: "hidden",
422
- backgroundColor: "rgba(255, 255, 255, 0.5)",
618
+ backgroundColor: "transparent",
423
619
  minHeight: 0,
424
620
  display: "flex",
425
621
  flexDirection: "column",
426
- }, children: _jsx(CalendarIntegration, { onBooked: handleBackToChat }) })] })) : (_jsxs(_Fragment, { children: [(size === "l" || size === "xl") && messages.length > 0 && (_jsx(MessageList, { messages: messages, isStreaming: isStreaming, aiAvatarSrc: undefined, onClose: handleClose, onExpand: handleExpandToggle, size: size })), size === "s" ? (_jsxs("div", { style: {
622
+ }, children: _jsx(CalendarIntegration, { onBooked: handleBackToChat }) })] })) : (_jsxs(_Fragment, { children: [(size === "l" || size === "xl") && messages.length > 0 && (_jsx(MessageList, { messages: messages, isStreaming: isStreaming, aiAvatarSrc: chatLogo, size: size })), size === "s" ? (_jsxs("div", { style: {
427
623
  display: "flex",
428
624
  alignItems: "center",
429
625
  gap: "0.35rem",
@@ -443,7 +639,7 @@ export function GojiSearchComponent() {
443
639
  flexDirection: "column",
444
640
  gap: "0.35rem",
445
641
  flex: 1,
446
- backgroundColor: "rgba(233, 210, 251, 0.15)",
642
+ backgroundColor: "transparent",
447
643
  borderRadius: "1.5rem",
448
644
  border: "1px solid rgba(85, 85, 85, 0.18)",
449
645
  boxShadow: "0 4px 24px 0 rgba(0, 0, 0, 0.08), inset 0 1px 0 0 rgba(255, 255, 255, 0.3)",
@@ -456,16 +652,13 @@ export function GojiSearchComponent() {
456
652
  gap: "0.375rem",
457
653
  transition: "gap 0.3s ease",
458
654
  flexShrink: 0,
459
- }, children: [_jsx("div", { style: { flex: 1 }, children: _jsx(SearchInput, { value: searchQuery, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: "Search...", size: size, inputRef: inputRef, inspirationQuestions: inspirationQuestions, onInspirationClick: handleSuggestionClick, sparkleRef: sparkleRef }) }), _jsx(ActionButtons, { size: size, isHovered: isHovered, isStreaming: isStreaming, searchQuery: searchQuery, onSubmit: () => { }, onVoiceSearch: handleVoiceSearch, onClose: handleClose, onCalendarClick: handleCalendarClick })] }) })] })) : (_jsxs("div", { onMouseEnter: handleInputAreaMouseEnter, onMouseLeave: handleInputAreaMouseLeave, style: {
655
+ }, children: [_jsx("div", { style: { flex: 1 }, children: _jsx(SearchInput, { value: searchQuery, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: "Search...", size: size, inputRef: inputRef, inspirationQuestions: inspirationQuestions, onInspirationClick: handleSuggestionClick, sparkleRef: sparkleRef }) }), _jsx(ActionButtons, { size: size, isHovered: isHovered, isStreaming: isStreaming, searchQuery: searchQuery, isRecording: isRecording, onSubmit: () => { }, onVoiceSearch: handleVoiceSearch, onClose: handleClose, onCalendarClick: handleCalendarClick })] }) })] })) : (_jsxs("div", { onMouseEnter: handleInputAreaMouseEnter, onMouseLeave: handleInputAreaMouseLeave, style: {
460
656
  display: "flex",
461
657
  flexDirection: "column",
462
658
  gap: "0.5rem",
463
- paddingTop: size === "m" ? "0.5rem" : "0.75rem",
659
+ paddingTop: 0,
464
660
  }, children: [_jsx("button", { type: "button", onClick: handleClose, style: {
465
- borderRadius: "1.3rem",
466
- border: "1px solid rgba(255, 255, 255, 0.3)",
467
- backgroundColor: "rgba(255, 255, 255, 0.2)",
468
- padding: "0.4rem",
661
+ padding: " 0 0.4rem",
469
662
  // rendered only when size !== 'xs' so show the button
470
663
  display: size === 'm' ? "flex" : "none",
471
664
  alignItems: "center",
@@ -473,12 +666,9 @@ export function GojiSearchComponent() {
473
666
  alignSelf: "flex-end",
474
667
  width: "fit-content",
475
668
  color: "rgba(0, 0, 0, 0.75)",
476
- backdropFilter: "blur(20px)",
477
- WebkitBackdropFilter: "blur(20px)",
478
669
  transition: "all 0.2s",
479
670
  cursor: "pointer",
480
- outline: "none",
481
- boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.3)",
671
+ outline: "none"
482
672
  }, children: _jsx(X, { style: { width: "0.875rem", height: "0.875rem" } }) }), _jsx("span", { role: "tooltip", style: {
483
673
  position: "absolute",
484
674
  top: "calc(100% + 0.4rem)",
@@ -495,11 +685,11 @@ export function GojiSearchComponent() {
495
685
  pointerEvents: "none",
496
686
  transition: "opacity 120ms ease-in-out",
497
687
  zIndex: 30,
498
- }, children: "Close" }), showSuggestions && messages.length === 0 && !searchQuery && (_jsx(SuggestedQuestions, { questions: suggestedQuestions, onQuestionClick: handleSuggestionClick })), _jsxs("form", { onSubmit: handleSearch, style: {
688
+ }, children: "Close" }), showSuggestions && messages.length === 0 && !searchQuery && (_jsx(SuggestedQuestions, { questions: inspirationQuestions, onQuestionClick: handleSuggestionClick })), _jsxs("form", { onSubmit: handleSearch, style: {
499
689
  display: "flex",
500
690
  alignItems: "center",
501
691
  gap: "0.375rem",
502
692
  transition: "gap 0.3s ease",
503
693
  flexShrink: 0,
504
- }, children: [_jsx("div", { style: { flex: 1 }, children: _jsx(SearchInput, { value: searchQuery, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: "Ask me anything...", size: size, inputRef: inputRef, inspirationQuestions: inspirationQuestions, onInspirationClick: handleSuggestionClick, sparkleRef: sparkleRef }) }), _jsx(ActionButtons, { size: size, isHovered: isHovered, isStreaming: isStreaming, searchQuery: searchQuery, onSubmit: () => { }, onVoiceSearch: handleVoiceSearch, onClose: handleClose, onCalendarClick: handleCalendarClick })] })] }))] })) }))] }) }) }));
694
+ }, children: [_jsx("div", { style: { flex: 1 }, children: _jsx(SearchInput, { value: searchQuery, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: "Ask me anything...", size: size, inputRef: inputRef, inspirationQuestions: inspirationQuestions, onInspirationClick: handleSuggestionClick, sparkleRef: sparkleRef }) }), _jsx(ActionButtons, { size: size, isHovered: isHovered, isStreaming: isStreaming, searchQuery: searchQuery, isRecording: isRecording, onSubmit: () => { }, onVoiceSearch: handleVoiceSearch, onClose: handleClose, onCalendarClick: handleCalendarClick })] })] }))] })) }))] }) }) }));
505
695
  }
@@ -8,7 +8,6 @@ interface LanguageConfig {
8
8
  title: string;
9
9
  description: string;
10
10
  };
11
- suggestedPrompts: string[];
12
11
  headerSubtitleExpanded: string;
13
12
  headerSubtitleCollapsed: string;
14
13
  sourcesLabel: string;