@px-ui/ai 4.1.0 → 4.2.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/index.d.ts +0 -38
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ interface Message {
|
|
|
10
10
|
type?: MessageType;
|
|
11
11
|
debugTrace?: unknown;
|
|
12
12
|
}
|
|
13
|
-
/** API response structure from the backend */
|
|
14
13
|
interface XandiApiResponse {
|
|
15
14
|
success: boolean;
|
|
16
15
|
message: string;
|
|
@@ -27,20 +26,17 @@ interface XandiApiResponse {
|
|
|
27
26
|
debug_trace: unknown;
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
|
-
/** Transformed response for internal use */
|
|
31
29
|
interface XandiResponse {
|
|
32
30
|
content: string;
|
|
33
31
|
type?: MessageType;
|
|
34
32
|
debugTrace?: unknown;
|
|
35
33
|
conversationId?: string;
|
|
36
34
|
}
|
|
37
|
-
/** Conversation summary for history list */
|
|
38
35
|
interface ConversationSummary {
|
|
39
36
|
id: string;
|
|
40
37
|
title: string;
|
|
41
38
|
timestamp: Date;
|
|
42
39
|
}
|
|
43
|
-
/** Full conversation with messages */
|
|
44
40
|
interface Conversation {
|
|
45
41
|
id: string | null;
|
|
46
42
|
title: string;
|
|
@@ -50,11 +46,8 @@ interface Conversation {
|
|
|
50
46
|
}
|
|
51
47
|
type XandiUIMode = "full" | "sidebar" | "floating";
|
|
52
48
|
interface XandiConfig {
|
|
53
|
-
/** URL for the assistant's avatar image */
|
|
54
49
|
avatarUrl?: string;
|
|
55
|
-
/** Name of the assistant (default: "Xandi") */
|
|
56
50
|
assistantName?: string;
|
|
57
|
-
/** UI mode: full (no close button), sidebar, or floating (with close button) */
|
|
58
51
|
uiMode?: XandiUIMode;
|
|
59
52
|
}
|
|
60
53
|
interface FetchRespOptions {
|
|
@@ -62,51 +55,31 @@ interface FetchRespOptions {
|
|
|
62
55
|
signal?: AbortSignal;
|
|
63
56
|
}
|
|
64
57
|
interface GetConvOptions {
|
|
65
|
-
/** Page number (default: 1) */
|
|
66
58
|
page?: number;
|
|
67
|
-
/** Items per page (default: 20) */
|
|
68
59
|
perPage?: number;
|
|
69
60
|
}
|
|
70
61
|
interface XandiHandlers {
|
|
71
|
-
/** Fetch AI response for a message */
|
|
72
62
|
fetchResp: (message: string, options?: FetchRespOptions) => Promise<XandiResponse>;
|
|
73
|
-
/** Get a conversation by ID with pagination; consumer transforms API response to Conversation */
|
|
74
63
|
getConv?: (conversationId: string, options?: GetConvOptions) => Promise<Conversation>;
|
|
75
|
-
/** Get conversation history list */
|
|
76
64
|
getConvHistory?: () => Promise<ConversationSummary[]>;
|
|
77
|
-
/** Called when user provides feedback on a message */
|
|
78
65
|
onFeedback?: (messageId: string, conversationId: string, feedback: FeedbackType) => void;
|
|
79
|
-
/** Called when user stops the current request */
|
|
80
66
|
onStop?: (conversationId: string) => void;
|
|
81
67
|
}
|
|
82
68
|
interface XandiContextValue {
|
|
83
|
-
/** Current conversation with messages */
|
|
84
69
|
conversation: Conversation;
|
|
85
|
-
/** Whether a request is in progress */
|
|
86
70
|
isLoading: boolean;
|
|
87
|
-
/** Send a message to the assistant */
|
|
88
71
|
sendMessage: (text: string) => void;
|
|
89
|
-
/** Stop the current request */
|
|
90
72
|
stopRequest: () => void;
|
|
91
|
-
/** Load an existing conversation by ID (with optional page/perPage) */
|
|
92
73
|
loadConversation: (conversationId: string, options?: GetConvOptions) => Promise<void>;
|
|
93
|
-
/** Start a new empty conversation */
|
|
94
74
|
startNewConversation: () => void;
|
|
95
|
-
/** Submit feedback for a message */
|
|
96
75
|
submitFeedback: (messageId: string, feedback: FeedbackType) => void;
|
|
97
|
-
/** Get conversation history list (from handlers) */
|
|
98
76
|
getConvHistory?: () => Promise<ConversationSummary[]>;
|
|
99
|
-
/** Configuration for the assistant */
|
|
100
77
|
config: Required<XandiConfig>;
|
|
101
|
-
/** Set UI mode override from Xandi component (internal use) */
|
|
102
78
|
setUiModeOverride: (mode: XandiUIMode | null) => void;
|
|
103
79
|
}
|
|
104
80
|
interface XandiProviderProps {
|
|
105
|
-
/** All handler functions for API communication */
|
|
106
81
|
handlers: XandiHandlers;
|
|
107
|
-
/** Initial conversation ID to restore */
|
|
108
82
|
conversationId?: string;
|
|
109
|
-
/** Configuration for the assistant appearance */
|
|
110
83
|
config?: XandiConfig;
|
|
111
84
|
children: React.ReactNode;
|
|
112
85
|
}
|
|
@@ -129,10 +102,6 @@ interface Suggestion {
|
|
|
129
102
|
interface XandiProps {
|
|
130
103
|
welcomeMessage?: string;
|
|
131
104
|
suggestions?: Suggestion[];
|
|
132
|
-
/**
|
|
133
|
-
* UI mode: "full" (default) = no close button; "sidebar" | "floating" = show close button in header.
|
|
134
|
-
* Overrides provider config when set.
|
|
135
|
-
*/
|
|
136
105
|
uiMode?: XandiUIMode;
|
|
137
106
|
}
|
|
138
107
|
declare function Xandi({
|
|
@@ -169,7 +138,6 @@ interface ChatHistoryItem {
|
|
|
169
138
|
}
|
|
170
139
|
interface XChatHistoryProps {
|
|
171
140
|
items?: ChatHistoryItem[];
|
|
172
|
-
/** Whether conversation history is being fetched */
|
|
173
141
|
isLoading?: boolean;
|
|
174
142
|
activeChatId?: string;
|
|
175
143
|
onSelectChat?: (chatId: string) => void;
|
|
@@ -183,12 +151,6 @@ declare function XChatHistory({
|
|
|
183
151
|
declare namespace x_message_actions_d_exports {
|
|
184
152
|
export { Copy, CopyProps, Debug, DebugProps, Feedback, FeedbackProps, FeedbackType, Root };
|
|
185
153
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Container for message actions. Use with composable children:
|
|
188
|
-
* - XMessageActions.Feedback
|
|
189
|
-
* - XMessageActions.Copy
|
|
190
|
-
* - XMessageActions.Debug
|
|
191
|
-
*/
|
|
192
154
|
declare function Root({
|
|
193
155
|
children
|
|
194
156
|
}: {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/context/xandi-context.tsx","../src/components/x-main-intake.tsx","../src/components/xandi.tsx","../src/components/x-header.tsx","../src/components/x-sidebar.tsx","../src/components/x-chat-history.tsx","../src/components/x-message-actions.tsx"],"sourcesContent":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/context/xandi-context.tsx","../src/components/x-main-intake.tsx","../src/components/xandi.tsx","../src/components/x-header.tsx","../src/components/x-sidebar.tsx","../src/components/x-chat-history.tsx","../src/components/x-message-actions.tsx"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,6 @@ const XANDI_AVATAR_URL = getXandiAvatarUrl();
|
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
18
18
|
//#region src/context/xandi-context.tsx
|
|
19
|
-
/** Creates a new empty conversation */
|
|
20
19
|
function createEmptyConversation() {
|
|
21
20
|
return {
|
|
22
21
|
id: null,
|
|
@@ -444,12 +443,6 @@ var x_message_actions_exports = /* @__PURE__ */ __export({
|
|
|
444
443
|
Feedback: () => Feedback,
|
|
445
444
|
Root: () => Root
|
|
446
445
|
});
|
|
447
|
-
/**
|
|
448
|
-
* Container for message actions. Use with composable children:
|
|
449
|
-
* - XMessageActions.Feedback
|
|
450
|
-
* - XMessageActions.Copy
|
|
451
|
-
* - XMessageActions.Debug
|
|
452
|
-
*/
|
|
453
446
|
function Root({ children }) {
|
|
454
447
|
return /* @__PURE__ */ jsx("div", {
|
|
455
448
|
className: "flex items-center gap-1",
|
|
@@ -612,10 +605,6 @@ function TextRenderer({ message }) {
|
|
|
612
605
|
|
|
613
606
|
//#endregion
|
|
614
607
|
//#region src/components/x-message-item.tsx
|
|
615
|
-
/**
|
|
616
|
-
* Router component that renders messages based on their type.
|
|
617
|
-
* Defaults to markdown rendering if no type is specified.
|
|
618
|
-
*/
|
|
619
608
|
function XMessageItem({ message }) {
|
|
620
609
|
const isUser = message.role === "user";
|
|
621
610
|
const messageType = message.type ?? "markdown";
|
|
@@ -636,9 +625,6 @@ function XMessageItem({ message }) {
|
|
|
636
625
|
})
|
|
637
626
|
});
|
|
638
627
|
}
|
|
639
|
-
/**
|
|
640
|
-
* Switch component that selects the appropriate renderer based on message type.
|
|
641
|
-
*/
|
|
642
628
|
function MessageRenderer({ type, message }) {
|
|
643
629
|
switch (type) {
|
|
644
630
|
case "text": return /* @__PURE__ */ jsx(TextRenderer, { message });
|
|
@@ -693,9 +679,11 @@ function XMessageContainer({ height = 400, onLoadMore }) {
|
|
|
693
679
|
if (!el) return;
|
|
694
680
|
const prevCount = prevMessageCountRef.current;
|
|
695
681
|
const prevLastId = prevLastMessageIdRef.current;
|
|
696
|
-
if (prevCount > 0 && messageCount > prevCount && lastMessageId != null && lastMessageId
|
|
682
|
+
if (prevCount > 0 && messageCount > prevCount && lastMessageId != null && lastMessageId === prevLastId) {
|
|
697
683
|
const prevScrollHeight = prevScrollHeightRef.current;
|
|
698
|
-
|
|
684
|
+
const prevScrollTop = prevScrollTopRef.current;
|
|
685
|
+
const newScrollHeight = el.scrollHeight;
|
|
686
|
+
el.scrollTop = Math.max(0, prevScrollTop + (newScrollHeight - prevScrollHeight));
|
|
699
687
|
skipScrollToBottomRef.current = true;
|
|
700
688
|
}
|
|
701
689
|
prevScrollHeightRef.current = el.scrollHeight;
|
|
@@ -714,7 +702,7 @@ function XMessageContainer({ height = 400, onLoadMore }) {
|
|
|
714
702
|
skipScrollToBottomRef.current = false;
|
|
715
703
|
return;
|
|
716
704
|
}
|
|
717
|
-
el.scrollTop =
|
|
705
|
+
el.scrollTop = el.scrollHeight - el.clientHeight;
|
|
718
706
|
}, [conversation.messages, isLoading]);
|
|
719
707
|
useEffect(() => {
|
|
720
708
|
if (!onLoadMore) return;
|
|
@@ -739,13 +727,13 @@ function XMessageContainer({ height = 400, onLoadMore }) {
|
|
|
739
727
|
children: /* @__PURE__ */ jsxs("div", {
|
|
740
728
|
className: "flex flex-col-reverse gap-5 p-4",
|
|
741
729
|
children: [
|
|
730
|
+
isLoading && /* @__PURE__ */ jsx(XTypingIndicator, {}),
|
|
731
|
+
[...messages].reverse().map((message) => /* @__PURE__ */ jsx(XMessageItem, { message }, message.id)),
|
|
742
732
|
/* @__PURE__ */ jsx("div", {
|
|
743
733
|
ref: topSentinelRef,
|
|
744
734
|
className: "h-1 shrink-0",
|
|
745
735
|
"aria-hidden": "true"
|
|
746
|
-
})
|
|
747
|
-
messages.map((message) => /* @__PURE__ */ jsx(XMessageItem, { message }, message.id)),
|
|
748
|
-
isLoading && /* @__PURE__ */ jsx(XTypingIndicator, {})
|
|
736
|
+
})
|
|
749
737
|
]
|
|
750
738
|
})
|
|
751
739
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["defaultConfig: Required<XandiConfig>","defaultGetConvOptions: Required<GetConvOptions>","config: Required<XandiConfig>","userMessage: Message","assistantMessage: Message","value: XandiContextValue","XMessageActions.Root","XMessageActions.Feedback","XMessageActions.Copy","XMessageActions.Debug","XMessageActions.Root","XMessageActions.Feedback","XMessageActions.Copy","XMessageActions.Debug","messageType: MessageType"],"sources":["../src/constants.ts","../src/context/xandi-context.tsx","../src/components/x-main-intake.tsx","../src/assets/icons/chat-icon.tsx","../src/assets/icons/check-icon.tsx","../src/assets/icons/close-icon.tsx","../src/assets/icons/copy-icon.tsx","../src/assets/icons/debug-icon.tsx","../src/assets/icons/menu-icon.tsx","../src/assets/icons/new-chat-icon.tsx","../src/assets/icons/sparkles-icon.tsx","../src/assets/icons/thumbs-down-icon.tsx","../src/assets/icons/thumbs-up-icon.tsx","../src/components/x-message-actions.tsx","../src/components/renderers/markdown-renderer.tsx","../src/components/renderers/text-renderer.tsx","../src/components/x-message-item.tsx","../src/components/x-typing-indicator.tsx","../src/components/x-message-container.tsx","../src/components/x-welcome.tsx","../src/components/xandi.tsx","../src/components/x-header.tsx","../src/components/x-chat-history.tsx","../src/components/x-sidebar.tsx"],"sourcesContent":["// Xandi avatar asset path\n// Wrapped in try-catch for SSR compatibility (import.meta.url may not work in all environments)\nfunction getXandiAvatarUrl(): string {\n try {\n return new URL(\"./assets/images/xandi-avatar.png\", import.meta.url).href;\n } catch {\n // Fallback for SSR environments where import.meta.url is not a valid URL\n return \"\";\n }\n}\n\nexport const XANDI_AVATAR_URL = getXandiAvatarUrl();\n","import { createContext, useContext, useEffect, useRef, useState } from \"react\";\n\nimport { XANDI_AVATAR_URL } from \"../constants\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type MessageType = \"text\" | \"markdown\";\nexport type FeedbackType = \"up\" | \"down\" | null;\n\nexport interface Message {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n type?: MessageType;\n debugTrace?: unknown;\n}\n\n/** API response structure from the backend */\nexport interface XandiApiResponse {\n success: boolean;\n message: string;\n data: {\n intent: string;\n data: unknown;\n conversation_id: string;\n };\n trace?: {\n trace_id: string;\n execution_mode: string;\n intent: string;\n tool_id: string;\n debug_trace: unknown;\n };\n}\n\n/** Transformed response for internal use */\nexport interface XandiResponse {\n content: string;\n type?: MessageType;\n debugTrace?: unknown;\n conversationId?: string;\n}\n\n/** Conversation summary for history list */\nexport interface ConversationSummary {\n id: string;\n title: string;\n timestamp: Date;\n}\n\n/** Full conversation with messages */\nexport interface Conversation {\n id: string | null;\n title: string;\n messages: Message[];\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Creates a new empty conversation */\nfunction createEmptyConversation(): Conversation {\n return {\n id: null,\n title: \"New Chat\",\n messages: [],\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n}\n\n// ============================================================================\n// Config\n// ============================================================================\n\nexport type XandiUIMode = \"full\" | \"sidebar\" | \"floating\";\n\nexport interface XandiConfig {\n /** URL for the assistant's avatar image */\n avatarUrl?: string;\n /** Name of the assistant (default: \"Xandi\") */\n assistantName?: string;\n /** UI mode: full (no close button), sidebar, or floating (with close button) */\n uiMode?: XandiUIMode;\n}\n\nconst defaultConfig: Required<XandiConfig> = {\n avatarUrl: XANDI_AVATAR_URL,\n assistantName: \"Xandi\",\n uiMode: \"full\",\n};\n\n// ============================================================================\n// Handlers\n// ============================================================================\n\nexport interface FetchRespOptions {\n conversationId?: string;\n signal?: AbortSignal;\n}\n\nexport interface GetConvOptions {\n /** Page number (default: 1) */\n page?: number;\n /** Items per page (default: 20) */\n perPage?: number;\n}\n\nconst defaultGetConvOptions: Required<GetConvOptions> = {\n page: 1,\n perPage: 20,\n};\n\nexport interface XandiHandlers {\n /** Fetch AI response for a message */\n fetchResp: (message: string, options?: FetchRespOptions) => Promise<XandiResponse>;\n /** Get a conversation by ID with pagination; consumer transforms API response to Conversation */\n getConv?: (conversationId: string, options?: GetConvOptions) => Promise<Conversation>;\n /** Get conversation history list */\n getConvHistory?: () => Promise<ConversationSummary[]>;\n /** Called when user provides feedback on a message */\n onFeedback?: (messageId: string, conversationId: string, feedback: FeedbackType) => void;\n /** Called when user stops the current request */\n onStop?: (conversationId: string) => void;\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nexport interface XandiContextValue {\n /** Current conversation with messages */\n conversation: Conversation;\n /** Whether a request is in progress */\n isLoading: boolean;\n /** Send a message to the assistant */\n sendMessage: (text: string) => void;\n /** Stop the current request */\n stopRequest: () => void;\n /** Load an existing conversation by ID (with optional page/perPage) */\n loadConversation: (conversationId: string, options?: GetConvOptions) => Promise<void>;\n /** Start a new empty conversation */\n startNewConversation: () => void;\n /** Submit feedback for a message */\n submitFeedback: (messageId: string, feedback: FeedbackType) => void;\n /** Get conversation history list (from handlers) */\n getConvHistory?: () => Promise<ConversationSummary[]>;\n /** Configuration for the assistant */\n config: Required<XandiConfig>;\n /** Set UI mode override from Xandi component (internal use) */\n setUiModeOverride: (mode: XandiUIMode | null) => void;\n}\n\nconst XandiContext = createContext<XandiContextValue | null>(null);\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface XandiProviderProps {\n /** All handler functions for API communication */\n handlers: XandiHandlers;\n /** Initial conversation ID to restore */\n conversationId?: string;\n /** Configuration for the assistant appearance */\n config?: XandiConfig;\n children: React.ReactNode;\n}\n\nexport function XandiProvider({\n handlers,\n conversationId: initialConversationId,\n config: userConfig,\n children,\n}: XandiProviderProps) {\n const [conversation, setConversation] = useState<Conversation>(createEmptyConversation);\n const [isLoading, setIsLoading] = useState(false);\n const [uiModeOverride, setUiModeOverride] = useState<XandiUIMode | null>(null);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n // Merge user config with defaults; Xandi's uiMode prop overrides config.uiMode when set\n const config: Required<XandiConfig> = {\n ...defaultConfig,\n ...userConfig,\n uiMode: uiModeOverride ?? userConfig?.uiMode ?? defaultConfig.uiMode,\n };\n\n // Load initial conversation if ID is provided\n useEffect(() => {\n if (initialConversationId && handlers.getConv) {\n loadConversation(initialConversationId);\n }\n }, [initialConversationId]);\n\n const loadConversation = async (convId: string, options?: GetConvOptions) => {\n if (!handlers.getConv) return;\n\n const opts = { ...defaultGetConvOptions, ...options };\n\n try {\n setIsLoading(true);\n const loadedConversation = await handlers.getConv(convId, opts);\n setConversation(loadedConversation);\n } catch (error) {\n console.error(\"Failed to load conversation:\", error);\n } finally {\n setIsLoading(false);\n }\n };\n\n const startNewConversation = () => {\n setConversation(createEmptyConversation());\n };\n\n const sendMessage = async (text: string) => {\n if (!text.trim() || isLoading) return;\n\n // Add user message\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: \"user\",\n content: text,\n };\n setConversation((prev) => ({\n ...prev,\n messages: [...prev.messages, userMessage],\n updatedAt: new Date(),\n }));\n setIsLoading(true);\n\n // Create abort controller for this request\n abortControllerRef.current = new AbortController();\n\n try {\n const response = await handlers.fetchResp(text, {\n conversationId: conversation.id ?? undefined,\n signal: abortControllerRef.current.signal,\n });\n\n const assistantMessage: Message = {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: response.content,\n type: response.type,\n debugTrace: response.debugTrace,\n };\n\n setConversation((prev) => ({\n ...prev,\n id: response.conversationId ?? prev.id,\n messages: [...prev.messages, assistantMessage],\n updatedAt: new Date(),\n }));\n } catch (error) {\n if ((error as Error).name !== \"AbortError\") {\n console.error(\"Failed to send message:\", error);\n }\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n };\n\n const stopRequest = () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n if (conversation.id && handlers.onStop) {\n handlers.onStop(conversation.id);\n }\n setIsLoading(false);\n };\n\n const submitFeedback = (messageId: string, feedback: FeedbackType) => {\n if (handlers.onFeedback && conversation.id) {\n handlers.onFeedback(messageId, conversation.id, feedback);\n }\n };\n\n const value: XandiContextValue = {\n conversation,\n isLoading,\n sendMessage,\n stopRequest,\n loadConversation,\n startNewConversation,\n submitFeedback,\n getConvHistory: handlers.getConvHistory,\n config,\n setUiModeOverride,\n };\n\n return <XandiContext.Provider value={value}>{children}</XandiContext.Provider>;\n}\n\nexport function useXandi(): XandiContextValue {\n const context = useContext(XandiContext);\n if (!context) {\n throw new Error(\"useXandi must be used within XandiProvider\");\n }\n return context;\n}\n","import { useState } from \"react\";\n\nimport { Button, FileIcon, SendIcon, StopIcon } from \"@px-ui/core\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface Suggestion {\n id: string;\n label: string;\n prompt: string;\n}\n\nexport interface XMainIntakeProps {\n placeholder?: string;\n suggestions?: Suggestion[];\n}\n\nexport function XMainIntake({ \n placeholder = \"Ask about jobs, candidates, timesheets, or anything workforce...\",\n suggestions = [],\n}: XMainIntakeProps) {\n const { isLoading, sendMessage, stopRequest } = useXandi();\n const [input, setInput] = useState(\"\");\n\n const handleSubmit = (e?: React.FormEvent) => {\n e?.preventDefault();\n if (input.trim() && !isLoading) {\n sendMessage(input);\n setInput(\"\");\n }\n };\n\n const handleSuggestionClick = (prompt: string) => {\n setInput(prompt);\n };\n\n const handleStopOrSend = () => {\n if (isLoading) {\n stopRequest();\n }\n };\n\n return (\n <div className=\"flex flex-col gap-3\">\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-2 rounded-2xl border border-ppx-neutral-5 bg-ppx-neutral-1 p-3\">\n <div className=\"uploads-section\"></div>\n\n <XIntakeTextarea\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n placeholder={placeholder}\n disabled={isLoading}\n />\n\n <div className=\"actions-section flex flex-row items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n disabled={isLoading}\n >\n <FileIcon width={20} />\n </Button>\n <span className=\"ml-auto text-ppx-xs text-ppx-neutral-10\">\n Enter to send · Shift+Enter for new line\n </span>\n {isLoading ? (\n <Button\n type=\"button\"\n size=\"icon-sm\"\n onClick={handleStopOrSend}\n className=\"flex h-8 w-8 items-center justify-center rounded-full bg-ppx-red-5 text-white transition-all hover:bg-ppx-red-4 hover:shadow-[0_0_12px_rgba(220,38,38,0.6)]\"\n >\n <StopIcon width={14} />\n </Button>\n ) : (\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n disabled={!input.trim()}\n className=\"flex h-8 w-8 items-center justify-center rounded-full bg-ppx-green-5 text-white transition-all hover:bg-ppx-green-4 hover:shadow-[0_0_12px_rgba(40,182,116,0.6)] disabled:bg-ppx-neutral-5 disabled:text-ppx-neutral-10 disabled:shadow-none\"\n >\n <SendIcon width={16} />\n </Button>\n )}\n </div>\n </form>\n\n {suggestions.length > 0 && (\n <div className=\"flex flex-wrap justify-center gap-2\">\n {suggestions.map((suggestion, index) => (\n <Button\n key={suggestion.id}\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleSuggestionClick(suggestion.prompt)}\n className=\"animate-[popUp_0.3s_ease-out_forwards] rounded-full opacity-0\"\n style={{ animationDelay: `${index * 0.1}s` }}\n >\n {suggestion.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n\n/////////////////////////////////////////////////////////////////////////////////////////////////\n//////////////////////////////////////Supporting Components//////////////////////////////////////\n/////////////////////////////////////////////////////////////////////////////////////////////////\n\ninterface XIntakeTextareaProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit: () => void;\n placeholder?: string;\n disabled?: boolean;\n}\n\nfunction XIntakeTextarea({ value, onChange, onSubmit, placeholder, disabled }: XIntakeTextareaProps) {\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n onSubmit();\n }\n // Shift+Enter allows default behavior (newline)\n };\n\n return (\n <textarea\n className=\"w-full resize-none border-none bg-transparent outline-none\"\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n />\n );\n}\n","export function ChatIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n\n","export function CheckIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\n","export function CloseIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n","export function CopyIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n","export function DebugIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" />\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />\n </svg>\n );\n}\n\n","export function MenuIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\n <line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\" />\n <line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n","export function NewChatIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </svg>\n );\n}\n\n","export function SparklesIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n <path d=\"M20 3v4\" />\n <path d=\"M22 5h-4\" />\n <path d=\"M4 17v2\" />\n <path d=\"M5 18H3\" />\n </svg>\n );\n}\n\n","export function ThumbsDownIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M17 14V2\" />\n <path d=\"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\" />\n </svg>\n );\n}\n\n","export function ThumbsUpIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M7 10v12\" />\n <path d=\"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\" />\n </svg>\n );\n}\n\n","import { useState } from \"react\";\nimport { Button, Dialog, toast, Tooltip } from \"@px-ui/core\";\n\nimport {\n CheckIcon,\n CopyIcon,\n DebugIcon,\n ThumbsDownIcon,\n ThumbsUpIcon,\n} from \"../assets/icons\";\nimport { useXandi, type FeedbackType } from \"../context/xandi-context\";\n\nexport type { FeedbackType } from \"../context/xandi-context\";\n\n// ============================================================================\n// Root\n// ============================================================================\n\n/**\n * Container for message actions. Use with composable children:\n * - XMessageActions.Feedback\n * - XMessageActions.Copy\n * - XMessageActions.Debug\n */\nexport function Root({ children }: { children: React.ReactNode }) {\n return <div className=\"flex items-center gap-1\">{children}</div>;\n}\n\n// ============================================================================\n// Feedback\n// ============================================================================\n\nexport interface FeedbackProps {\n messageId: string;\n}\n\nexport function Feedback({ messageId }: FeedbackProps) {\n const { submitFeedback } = useXandi();\n const [feedback, setFeedback] = useState<FeedbackType>(null);\n\n const handleFeedback = (type: FeedbackType) => {\n const newFeedback = feedback === type ? null : type;\n setFeedback(newFeedback);\n submitFeedback(messageId, newFeedback);\n };\n\n return (\n <>\n {/* Thumbs Up */}\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleFeedback(\"up\")}\n className={`h-7 w-7 ${\n feedback === \"up\"\n ? \"bg-ppx-green-2 text-ppx-green-5\"\n : \"text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n }`}\n >\n <ThumbsUpIcon className={feedback === \"up\" ? \"fill-current\" : \"\"} />\n </Button>\n }\n />\n <Tooltip.Content>\n {feedback === \"up\" ? \"You found this helpful\" : \"Good response\"}\n </Tooltip.Content>\n </Tooltip.Root>\n\n {/* Thumbs Down */}\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleFeedback(\"down\")}\n className={`h-7 w-7 ${\n feedback === \"down\"\n ? \"bg-ppx-red-2 text-ppx-red-5\"\n : \"text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n }`}\n >\n <ThumbsDownIcon className={feedback === \"down\" ? \"fill-current\" : \"\"} />\n </Button>\n }\n />\n <Tooltip.Content>\n {feedback === \"down\" ? \"You found this unhelpful\" : \"Bad response\"}\n </Tooltip.Content>\n </Tooltip.Root>\n </>\n );\n}\n\n// ============================================================================\n// Copy\n// ============================================================================\n\nexport interface CopyProps {\n content: string;\n}\n\nexport function Copy({ content }: CopyProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(content);\n setCopied(true);\n toast.add({\n title: \"Copied!\",\n description: \"Message copied to clipboard\",\n type: \"success\",\n });\n setTimeout(() => setCopied(false), 2000);\n } catch {\n toast.add({\n title: \"Failed to copy\",\n description: \"Could not copy message to clipboard\",\n type: \"error\",\n });\n }\n };\n\n return (\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={handleCopy}\n className=\"h-7 w-7 text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n >\n {copied ? (\n <CheckIcon className=\"text-ppx-green-5\" />\n ) : (\n <CopyIcon />\n )}\n </Button>\n }\n />\n <Tooltip.Content>\n {copied ? \"Copied!\" : \"Copy message\"}\n </Tooltip.Content>\n </Tooltip.Root>\n );\n}\n\n// ============================================================================\n// Debug\n// ============================================================================\n\nexport interface DebugProps {\n messageId: string;\n debugTrace: unknown;\n}\n\nexport function Debug({ messageId, debugTrace }: DebugProps) {\n const [debugOpen, setDebugOpen] = useState(false);\n\n return (\n <Dialog.Root open={debugOpen} onOpenChange={setDebugOpen}>\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Dialog.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"h-7 w-7 text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n >\n <DebugIcon />\n </Button>\n }\n />\n }\n />\n <Tooltip.Content>\n View debug trace\n </Tooltip.Content>\n </Tooltip.Root>\n\n <Dialog.Portal>\n <Dialog.Overlay />\n <Dialog.Content className=\"max-w-2xl\">\n <Dialog.Header>\n <Dialog.Title>Debug Trace</Dialog.Title>\n <Dialog.Description>\n Response debug information for message {messageId}\n </Dialog.Description>\n </Dialog.Header>\n <div className=\"max-h-96 overflow-auto rounded bg-ppx-neutral-2 p-4\">\n <pre className=\"whitespace-pre-wrap font-mono text-ppx-xs text-ppx-neutral-12\">\n {JSON.stringify(debugTrace, null, 2)}\n </pre>\n </div>\n <Dialog.Footer>\n <Dialog.Close render={<Button variant=\"outline\">Close</Button>} />\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import ReactMarkdown from \"react-markdown\";\n\nimport type { Message } from \"../../context/xandi-context\";\nimport * as XMessageActions from \"../x-message-actions\";\n\nexport interface MarkdownRendererProps {\n message: Message;\n}\n\nexport function MarkdownRenderer({ message }: MarkdownRendererProps) {\n const isUser = message.role === \"user\";\n const baseClass = `text-ppx-sm leading-relaxed ${isUser ? \"text-white\" : \"text-ppx-neutral-13\"}`;\n const showActions = !isUser;\n\n return (\n <div>\n <div className={baseClass}>\n <ReactMarkdown\n components={{\n p: ({ children }) => <p className=\"mb-2 last:mb-0\">{children}</p>,\n ul: ({ children }) => <ul className=\"mb-2 list-disc pl-4\">{children}</ul>,\n ol: ({ children }) => <ol className=\"mb-2 list-decimal pl-4\">{children}</ol>,\n li: ({ children }) => <li className=\"mb-1\">{children}</li>,\n a: ({ href, children }) => (\n <a href={href} className=\"underline\" target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n ),\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n }}\n >\n {message.content}\n </ReactMarkdown>\n </div>\n {showActions && (\n <div className=\"mt-2\">\n <XMessageActions.Root>\n <XMessageActions.Feedback messageId={message.id} />\n <XMessageActions.Copy content={message.content} />\n {message.debugTrace != null && (\n <XMessageActions.Debug messageId={message.id} debugTrace={message.debugTrace} />\n )}\n </XMessageActions.Root>\n </div>\n )}\n </div>\n );\n}\n","import type { Message } from \"../../context/xandi-context\";\nimport * as XMessageActions from \"../x-message-actions\";\n\nexport interface TextRendererProps {\n message: Message;\n}\n\nexport function TextRenderer({ message }: TextRendererProps) {\n const isUser = message.role === \"user\";\n const showActions = !isUser;\n\n return (\n <div>\n <p className={`text-ppx-sm leading-relaxed ${isUser ? \"text-white\" : \"text-ppx-neutral-13\"}`}>\n {message.content}\n </p>\n {showActions && (\n <div className=\"mt-2\">\n <XMessageActions.Root>\n <XMessageActions.Feedback messageId={message.id} />\n <XMessageActions.Copy content={message.content} />\n {message.debugTrace != null && (\n <XMessageActions.Debug messageId={message.id} debugTrace={message.debugTrace} />\n )}\n </XMessageActions.Root>\n </div>\n )}\n </div>\n );\n}\n","import type { Message, MessageType } from \"../context/xandi-context\";\nimport { MarkdownRenderer } from \"./renderers/markdown-renderer\";\nimport { TextRenderer } from \"./renderers/text-renderer\";\n\nexport interface XMessageItemProps {\n message: Message;\n}\n\n/**\n * Router component that renders messages based on their type.\n * Defaults to markdown rendering if no type is specified.\n */\nexport function XMessageItem({ message }: XMessageItemProps) {\n const isUser = message.role === \"user\";\n const messageType: MessageType = message.type ?? \"markdown\";\n\n return (\n <div className={`flex ${isUser ? \"justify-end\" : \"justify-start\"}`}>\n {isUser ? (\n <div className=\"max-w-[90%] rounded-2xl rounded-br-sm bg-ppx-green-5 px-4 py-2.5\">\n <MessageRenderer type={messageType} message={message} />\n </div>\n ) : (\n <div className=\"max-w-[90%]\">\n <MessageRenderer type={messageType} message={message} />\n </div>\n )}\n </div>\n );\n}\n\ninterface MessageRendererProps {\n type: MessageType;\n message: Message;\n}\n\n/**\n * Switch component that selects the appropriate renderer based on message type.\n */\nfunction MessageRenderer({ type, message }: MessageRendererProps) {\n switch (type) {\n case \"text\":\n return <TextRenderer message={message} />;\n case \"markdown\":\n default:\n return <MarkdownRenderer message={message} />;\n }\n}\n","import { Avatar } from \"@px-ui/core\";\n\nimport { useXandi } from \"../context/xandi-context\";\n\nexport function XTypingIndicator() {\n const { config } = useXandi();\n\n return (\n <div className=\"flex items-center gap-4\">\n <div className=\"animate-[popUp_0.3s_ease-out_forwards]\">\n <Avatar\n imgSrc={config.avatarUrl}\n name={config.assistantName}\n variant=\"rounded\"\n size=\"48px\"\n hideTooltip\n className=\"border-2 border-ppx-neutral-4\"\n />\n </div>\n <div className=\"flex animate-[slideIn_0.3s_ease-out_0.2s_forwards] items-center gap-2 rounded-xl bg-ppx-neutral-2 px-[10px] pb-[5px] pt-[10px] opacity-0 shadow-sm\">\n <span className=\"h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-9 [animation-delay:-0.3s]\" />\n <span className=\"h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-6 [animation-delay:-0.15s]\" />\n <span className=\"h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-9\" />\n </div>\n </div>\n );\n}\n","import { useEffect, useLayoutEffect, useRef } from \"react\";\n\nimport { XMessageItem } from \"./x-message-item\";\nimport { XTypingIndicator } from \"./x-typing-indicator\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface XMessageContainerProps {\n height?: string | number;\n /** Called when user scrolls to top (load more / older messages) */\n onLoadMore?: () => void;\n}\n\nexport function XMessageContainer({ height = 400, onLoadMore }: XMessageContainerProps) {\n const { conversation, isLoading } = useXandi();\n const containerRef = useRef<HTMLDivElement>(null);\n const topSentinelRef = useRef<HTMLDivElement>(null);\n const prevScrollHeightRef = useRef(0);\n const prevScrollTopRef = useRef(0);\n const prevLastMessageIdRef = useRef<string | null>(null);\n const prevMessageCountRef = useRef(0);\n const skipScrollToBottomRef = useRef(false);\n\n const messages = conversation.messages;\n const messageCount = messages.length;\n const lastMessageId = messageCount > 0 ? messages[messageCount - 1].id : null;\n\n // Restore scroll when older messages are appended (content added at top in column-reverse)\n useLayoutEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const prevCount = prevMessageCountRef.current;\n const prevLastId = prevLastMessageIdRef.current;\n const isAppendOlder =\n prevCount > 0 &&\n messageCount > prevCount &&\n lastMessageId != null &&\n lastMessageId !== prevLastId;\n\n if (isAppendOlder) {\n const prevScrollHeight = prevScrollHeightRef.current;\n const prevScrollTop = prevScrollTopRef.current;\n const newScrollHeight = el.scrollHeight;\n el.scrollTop = prevScrollTop + (newScrollHeight - prevScrollHeight);\n skipScrollToBottomRef.current = true;\n }\n\n prevScrollHeightRef.current = el.scrollHeight;\n prevScrollTopRef.current = el.scrollTop;\n prevMessageCountRef.current = messageCount;\n prevLastMessageIdRef.current = lastMessageId;\n }, [messageCount, lastMessageId, messages]);\n\n // Scroll to bottom (newest) when new messages arrive or typing starts (column-reverse: bottom = 0)\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n if (skipScrollToBottomRef.current) {\n skipScrollToBottomRef.current = false;\n return;\n }\n el.scrollTop = 0;\n }, [conversation.messages, isLoading]);\n\n // IntersectionObserver: when top sentinel is visible, trigger load more\n useEffect(() => {\n if (!onLoadMore) return;\n const sentinel = topSentinelRef.current;\n const container = containerRef.current;\n if (!sentinel || !container) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n const [entry] = entries;\n if (entry?.isIntersecting) {\n onLoadMore();\n }\n },\n {\n root: container,\n rootMargin: \"0px\",\n threshold: 0,\n }\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [onLoadMore]);\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col overflow-y-auto py-[10px]\"\n style={{ height: typeof height === \"number\" ? `${height}px` : height }}\n >\n {/* column-reverse: messages [newest…oldest] show as oldest at top, newest at bottom; sentinel at top for load more */}\n <div className=\"flex flex-col-reverse gap-5 p-4\">\n <div ref={topSentinelRef} className=\"h-1 shrink-0\" aria-hidden=\"true\" />\n {messages.map((message) => (\n <XMessageItem key={message.id} message={message} />\n ))}\n {isLoading && <XTypingIndicator />}\n </div>\n </div>\n );\n}\n","import { Avatar } from \"@px-ui/core\";\n\nimport { SparklesIcon } from \"../assets/icons\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface XWelcomeProps {\n message: string;\n}\n\nexport function XWelcome({ message }: XWelcomeProps) {\n const { config } = useXandi();\n\n return (\n <div className=\"flex flex-col items-center justify-center gap-4 py-12\">\n <div className=\"relative\">\n {/* Gradient border ring */}\n <div className=\"absolute -inset-1 rounded-full bg-gradient-to-b from-ppx-green-4 via-ppx-green-5/50 to-transparent\" />\n \n {/* Avatar container */}\n <div className=\"relative rounded-full bg-ppx-neutral-18 p-1\">\n <Avatar\n imgSrc={config.avatarUrl}\n name={config.assistantName}\n variant=\"rounded\"\n size=\"120px\"\n hideTooltip\n />\n </div>\n\n {/* Sparkles icon with pulse-zoom animation */}\n <div className=\"absolute -bottom-2 left-1/2\">\n <div className=\"flex h-6 w-6 animate-[pulse-zoom_2s_ease-in-out_infinite] items-center justify-center rounded-full bg-ppx-green-5\">\n <SparklesIcon className=\"text-white\" />\n </div>\n </div>\n </div>\n\n <h2 className=\"text-ppx-xl font-semibold text-ppx-foreground\">\n {message}\n </h2>\n </div>\n );\n}\n","import { useEffect } from \"react\";\nimport { XMainIntake, type Suggestion } from \"./x-main-intake\";\nimport { XMessageContainer } from \"./x-message-container\";\nimport { XWelcome } from \"./x-welcome\";\nimport { useXandi } from \"../context/xandi-context\";\nimport type { XandiUIMode } from \"../context/xandi-context\";\n\nexport interface XandiProps {\n welcomeMessage?: string;\n suggestions?: Suggestion[];\n /**\n * UI mode: \"full\" (default) = no close button; \"sidebar\" | \"floating\" = show close button in header.\n * Overrides provider config when set.\n */\n uiMode?: XandiUIMode;\n}\n\nexport function Xandi({\n welcomeMessage = \"How can I help you today?\",\n suggestions = [],\n uiMode,\n}: XandiProps) {\n const { conversation, setUiModeOverride } = useXandi();\n\n // Push uiMode into provider so XHeader and others see it\n useEffect(() => {\n setUiModeOverride(uiMode ?? null);\n return () => setUiModeOverride(null);\n }, [uiMode, setUiModeOverride]);\n const isEmpty = conversation.messages.length === 0;\n\n return (\n <div className=\"flex flex-col\">\n {isEmpty ? (\n <XWelcome message={welcomeMessage} />\n ) : (\n <XMessageContainer />\n )}\n <XMainIntake suggestions={isEmpty ? suggestions : []} />\n </div>\n );\n}\n","import { Avatar, Button } from \"@px-ui/core\";\n\nimport { CloseIcon, MenuIcon, NewChatIcon } from \"../assets/icons\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface XHeaderProps {\n onClose?: () => void;\n onToggleHistory?: () => void;\n}\n\nexport function XHeader({\n onClose,\n onToggleHistory,\n}: XHeaderProps) {\n const { startNewConversation, config } = useXandi();\n\n return (\n <header className=\"flex items-center justify-between border-b border-ppx-neutral-5 bg-transparent px-3 py-2\">\n {/* Left section - Menu & Title */}\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onToggleHistory}\n aria-label=\"Toggle chat history\"\n >\n <MenuIcon />\n </Button>\n\n <div className=\"flex items-center gap-2\">\n <Avatar\n imgSrc={config.avatarUrl}\n name={config.assistantName}\n variant=\"rounded\"\n size=\"24px\"\n hideTooltip\n />\n <span className=\"font-medium text-ppx-foreground\">{config.assistantName}</span>\n </div>\n </div>\n\n {/* Right section - Actions */}\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={startNewConversation}\n aria-label=\"New chat\"\n >\n <NewChatIcon />\n </Button>\n\n {config.uiMode !== \"full\" && (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClose}\n aria-label=\"Close\"\n >\n <CloseIcon />\n </Button>\n )}\n </div>\n </header>\n );\n}\n","import { Button, Spinner } from \"@px-ui/core\";\n\nimport { ChatIcon } from \"../assets/icons\";\n\nexport interface ChatHistoryItem {\n id: string;\n title: string;\n timestamp: Date;\n}\n\nexport interface XChatHistoryProps {\n items?: ChatHistoryItem[];\n /** Whether conversation history is being fetched */\n isLoading?: boolean;\n activeChatId?: string;\n onSelectChat?: (chatId: string) => void;\n}\n\nexport function XChatHistory({\n items = [],\n isLoading = false,\n activeChatId,\n onSelectChat,\n}: XChatHistoryProps) {\n return (\n <div className=\"flex-1 overflow-y-auto\">\n {/* Header */}\n <div className=\"px-3 py-2\">\n <div className=\"flex items-center gap-2 text-ppx-sm font-medium text-ppx-foreground\">\n <ChatIcon />\n Chats\n </div>\n </div>\n\n {/* Chat List - show loader only when loading and list is empty (first time) */}\n {isLoading && items.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-2 px-6 py-8\">\n <Spinner size=\"medium\" className=\"text-ppx-neutral-10\" />\n <span className=\"text-ppx-sm text-ppx-neutral-10\">Loading conversations...</span>\n </div>\n ) : items.length === 0 ? (\n <div className=\"px-6 py-4 text-ppx-sm text-ppx-neutral-10\">\n No chat history yet\n </div>\n ) : (\n <div className=\"space-y-0.5\">\n {items.map((item) => (\n <Button\n key={item.id}\n variant=\"ghost\"\n onClick={() => onSelectChat?.(item.id)}\n className={`w-full justify-start truncate rounded-none px-6 ${\n activeChatId === item.id\n ? \"bg-ppx-neutral-4 text-ppx-foreground\"\n : \"text-ppx-neutral-12\"\n }`}\n >\n {item.title}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport { Button } from \"@px-ui/core\";\n\nimport { CloseIcon, NewChatIcon } from \"../assets/icons\";\nimport { useXandi } from \"../context/xandi-context\";\nimport { XChatHistory, type ChatHistoryItem } from \"./x-chat-history\";\n\nexport interface XSidebarProps {\n isOpen?: boolean;\n onClose?: () => void;\n}\n\nexport function XSidebar({\n isOpen = true,\n onClose,\n}: XSidebarProps) {\n const { startNewConversation, getConvHistory, loadConversation, conversation } = useXandi();\n const [chatHistoryItems, setChatHistoryItems] = useState<ChatHistoryItem[]>([]);\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\n const fetchInProgressRef = useRef(false);\n\n // Fetch conversation history when sidebar opens (skip if a request is already pending)\n useEffect(() => {\n if (!isOpen || !getConvHistory || fetchInProgressRef.current) return;\n\n fetchInProgressRef.current = true;\n setIsLoadingHistory(true);\n\n getConvHistory()\n .then((history) => {\n setChatHistoryItems(\n (history ?? []).map((item) => ({\n id: item.id,\n title: item.title,\n timestamp: item.timestamp,\n }))\n );\n })\n .catch((error) => {\n console.error(\"Failed to fetch conversation history:\", error);\n })\n .finally(() => {\n fetchInProgressRef.current = false;\n setIsLoadingHistory(false);\n });\n }, [isOpen, getConvHistory]);\n\n const handleSelectChat = (chatId: string) => {\n loadConversation(chatId);\n };\n\n if (!isOpen) return null;\n\n return (\n <aside className=\"flex h-full w-64 flex-col border-r border-ppx-neutral-5 bg-ppx-neutral-2\">\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-ppx-neutral-5 p-3\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClose}\n aria-label=\"Close sidebar\"\n >\n <CloseIcon />\n </Button>\n </div>\n\n {/* New Chat Button */}\n <div className=\"p-3\">\n <Button\n variant=\"ghost\"\n onClick={startNewConversation}\n className=\"w-full justify-start gap-3\"\n >\n <NewChatIcon className=\"h-5 w-5\" />\n New chat\n </Button>\n </div>\n\n {/* Chat History */}\n <XChatHistory\n items={chatHistoryItems}\n isLoading={isLoadingHistory}\n activeChatId={conversation.id ?? undefined}\n onSelectChat={handleSelectChat}\n />\n </aside>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["defaultConfig: Required<XandiConfig>","defaultGetConvOptions: Required<GetConvOptions>","config: Required<XandiConfig>","userMessage: Message","assistantMessage: Message","value: XandiContextValue","XMessageActions.Root","XMessageActions.Feedback","XMessageActions.Copy","XMessageActions.Debug","XMessageActions.Root","XMessageActions.Feedback","XMessageActions.Copy","XMessageActions.Debug","messageType: MessageType"],"sources":["../src/constants.ts","../src/context/xandi-context.tsx","../src/components/x-main-intake.tsx","../src/assets/icons/chat-icon.tsx","../src/assets/icons/check-icon.tsx","../src/assets/icons/close-icon.tsx","../src/assets/icons/copy-icon.tsx","../src/assets/icons/debug-icon.tsx","../src/assets/icons/menu-icon.tsx","../src/assets/icons/new-chat-icon.tsx","../src/assets/icons/sparkles-icon.tsx","../src/assets/icons/thumbs-down-icon.tsx","../src/assets/icons/thumbs-up-icon.tsx","../src/components/x-message-actions.tsx","../src/components/renderers/markdown-renderer.tsx","../src/components/renderers/text-renderer.tsx","../src/components/x-message-item.tsx","../src/components/x-typing-indicator.tsx","../src/components/x-message-container.tsx","../src/components/x-welcome.tsx","../src/components/xandi.tsx","../src/components/x-header.tsx","../src/components/x-chat-history.tsx","../src/components/x-sidebar.tsx"],"sourcesContent":["function getXandiAvatarUrl(): string {\n try {\n return new URL(\"./assets/images/xandi-avatar.png\", import.meta.url).href;\n } catch {\n return \"\";\n }\n}\n\nexport const XANDI_AVATAR_URL = getXandiAvatarUrl();\n","import { createContext, useContext, useEffect, useRef, useState } from \"react\";\n\nimport { XANDI_AVATAR_URL } from \"../constants\";\n\nexport type MessageType = \"text\" | \"markdown\";\nexport type FeedbackType = \"up\" | \"down\" | null;\n\nexport interface Message {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n type?: MessageType;\n debugTrace?: unknown;\n}\n\nexport interface XandiApiResponse {\n success: boolean;\n message: string;\n data: {\n intent: string;\n data: unknown;\n conversation_id: string;\n };\n trace?: {\n trace_id: string;\n execution_mode: string;\n intent: string;\n tool_id: string;\n debug_trace: unknown;\n };\n}\n\nexport interface XandiResponse {\n content: string;\n type?: MessageType;\n debugTrace?: unknown;\n conversationId?: string;\n}\n\nexport interface ConversationSummary {\n id: string;\n title: string;\n timestamp: Date;\n}\n\nexport interface Conversation {\n id: string | null;\n title: string;\n messages: Message[];\n createdAt: Date;\n updatedAt: Date;\n}\n\nfunction createEmptyConversation(): Conversation {\n return {\n id: null,\n title: \"New Chat\",\n messages: [],\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n}\n\nexport type XandiUIMode = \"full\" | \"sidebar\" | \"floating\";\n\nexport interface XandiConfig {\n avatarUrl?: string;\n assistantName?: string;\n uiMode?: XandiUIMode;\n}\n\nconst defaultConfig: Required<XandiConfig> = {\n avatarUrl: XANDI_AVATAR_URL,\n assistantName: \"Xandi\",\n uiMode: \"full\",\n};\n\nexport interface FetchRespOptions {\n conversationId?: string;\n signal?: AbortSignal;\n}\n\nexport interface GetConvOptions {\n page?: number;\n perPage?: number;\n}\n\nconst defaultGetConvOptions: Required<GetConvOptions> = {\n page: 1,\n perPage: 20,\n};\n\nexport interface XandiHandlers {\n fetchResp: (message: string, options?: FetchRespOptions) => Promise<XandiResponse>;\n getConv?: (conversationId: string, options?: GetConvOptions) => Promise<Conversation>;\n getConvHistory?: () => Promise<ConversationSummary[]>;\n onFeedback?: (messageId: string, conversationId: string, feedback: FeedbackType) => void;\n onStop?: (conversationId: string) => void;\n}\n\nexport interface XandiContextValue {\n conversation: Conversation;\n isLoading: boolean;\n sendMessage: (text: string) => void;\n stopRequest: () => void;\n loadConversation: (conversationId: string, options?: GetConvOptions) => Promise<void>;\n startNewConversation: () => void;\n submitFeedback: (messageId: string, feedback: FeedbackType) => void;\n getConvHistory?: () => Promise<ConversationSummary[]>;\n config: Required<XandiConfig>;\n setUiModeOverride: (mode: XandiUIMode | null) => void;\n}\n\nconst XandiContext = createContext<XandiContextValue | null>(null);\n\nexport interface XandiProviderProps {\n handlers: XandiHandlers;\n conversationId?: string;\n config?: XandiConfig;\n children: React.ReactNode;\n}\n\nexport function XandiProvider({\n handlers,\n conversationId: initialConversationId,\n config: userConfig,\n children,\n}: XandiProviderProps) {\n const [conversation, setConversation] = useState<Conversation>(createEmptyConversation);\n const [isLoading, setIsLoading] = useState(false);\n const [uiModeOverride, setUiModeOverride] = useState<XandiUIMode | null>(null);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const config: Required<XandiConfig> = {\n ...defaultConfig,\n ...userConfig,\n uiMode: uiModeOverride ?? userConfig?.uiMode ?? defaultConfig.uiMode,\n };\n\n useEffect(() => {\n if (initialConversationId && handlers.getConv) {\n loadConversation(initialConversationId);\n }\n }, [initialConversationId]);\n\n const loadConversation = async (convId: string, options?: GetConvOptions) => {\n if (!handlers.getConv) return;\n\n const opts = { ...defaultGetConvOptions, ...options };\n\n try {\n setIsLoading(true);\n const loadedConversation = await handlers.getConv(convId, opts);\n setConversation(loadedConversation);\n } catch (error) {\n console.error(\"Failed to load conversation:\", error);\n } finally {\n setIsLoading(false);\n }\n };\n\n const startNewConversation = () => {\n setConversation(createEmptyConversation());\n };\n\n const sendMessage = async (text: string) => {\n if (!text.trim() || isLoading) return;\n\n const userMessage: Message = {\n id: crypto.randomUUID(),\n role: \"user\",\n content: text,\n };\n setConversation((prev) => ({\n ...prev,\n messages: [...prev.messages, userMessage],\n updatedAt: new Date(),\n }));\n setIsLoading(true);\n\n abortControllerRef.current = new AbortController();\n\n try {\n const response = await handlers.fetchResp(text, {\n conversationId: conversation.id ?? undefined,\n signal: abortControllerRef.current.signal,\n });\n\n const assistantMessage: Message = {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: response.content,\n type: response.type,\n debugTrace: response.debugTrace,\n };\n\n setConversation((prev) => ({\n ...prev,\n id: response.conversationId ?? prev.id,\n messages: [...prev.messages, assistantMessage],\n updatedAt: new Date(),\n }));\n } catch (error) {\n if ((error as Error).name !== \"AbortError\") {\n console.error(\"Failed to send message:\", error);\n }\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n };\n\n const stopRequest = () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n if (conversation.id && handlers.onStop) {\n handlers.onStop(conversation.id);\n }\n setIsLoading(false);\n };\n\n const submitFeedback = (messageId: string, feedback: FeedbackType) => {\n if (handlers.onFeedback && conversation.id) {\n handlers.onFeedback(messageId, conversation.id, feedback);\n }\n };\n\n const value: XandiContextValue = {\n conversation,\n isLoading,\n sendMessage,\n stopRequest,\n loadConversation,\n startNewConversation,\n submitFeedback,\n getConvHistory: handlers.getConvHistory,\n config,\n setUiModeOverride,\n };\n\n return <XandiContext.Provider value={value}>{children}</XandiContext.Provider>;\n}\n\nexport function useXandi(): XandiContextValue {\n const context = useContext(XandiContext);\n if (!context) {\n throw new Error(\"useXandi must be used within XandiProvider\");\n }\n return context;\n}\n","import { useState } from \"react\";\n\nimport { Button, FileIcon, SendIcon, StopIcon } from \"@px-ui/core\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface Suggestion {\n id: string;\n label: string;\n prompt: string;\n}\n\nexport interface XMainIntakeProps {\n placeholder?: string;\n suggestions?: Suggestion[];\n}\n\nexport function XMainIntake({ \n placeholder = \"Ask about jobs, candidates, timesheets, or anything workforce...\",\n suggestions = [],\n}: XMainIntakeProps) {\n const { isLoading, sendMessage, stopRequest } = useXandi();\n const [input, setInput] = useState(\"\");\n\n const handleSubmit = (e?: React.FormEvent) => {\n e?.preventDefault();\n if (input.trim() && !isLoading) {\n sendMessage(input);\n setInput(\"\");\n }\n };\n\n const handleSuggestionClick = (prompt: string) => {\n setInput(prompt);\n };\n\n const handleStopOrSend = () => {\n if (isLoading) {\n stopRequest();\n }\n };\n\n return (\n <div className=\"flex flex-col gap-3\">\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-2 rounded-2xl border border-ppx-neutral-5 bg-ppx-neutral-1 p-3\">\n <div className=\"uploads-section\"></div>\n\n <XIntakeTextarea\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n placeholder={placeholder}\n disabled={isLoading}\n />\n\n <div className=\"actions-section flex flex-row items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n disabled={isLoading}\n >\n <FileIcon width={20} />\n </Button>\n <span className=\"ml-auto text-ppx-xs text-ppx-neutral-10\">\n Enter to send · Shift+Enter for new line\n </span>\n {isLoading ? (\n <Button\n type=\"button\"\n size=\"icon-sm\"\n onClick={handleStopOrSend}\n className=\"flex h-8 w-8 items-center justify-center rounded-full bg-ppx-red-5 text-white transition-all hover:bg-ppx-red-4 hover:shadow-[0_0_12px_rgba(220,38,38,0.6)]\"\n >\n <StopIcon width={14} />\n </Button>\n ) : (\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n disabled={!input.trim()}\n className=\"flex h-8 w-8 items-center justify-center rounded-full bg-ppx-green-5 text-white transition-all hover:bg-ppx-green-4 hover:shadow-[0_0_12px_rgba(40,182,116,0.6)] disabled:bg-ppx-neutral-5 disabled:text-ppx-neutral-10 disabled:shadow-none\"\n >\n <SendIcon width={16} />\n </Button>\n )}\n </div>\n </form>\n\n {suggestions.length > 0 && (\n <div className=\"flex flex-wrap justify-center gap-2\">\n {suggestions.map((suggestion, index) => (\n <Button\n key={suggestion.id}\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => handleSuggestionClick(suggestion.prompt)}\n className=\"animate-[popUp_0.3s_ease-out_forwards] rounded-full opacity-0\"\n style={{ animationDelay: `${index * 0.1}s` }}\n >\n {suggestion.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\ninterface XIntakeTextareaProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit: () => void;\n placeholder?: string;\n disabled?: boolean;\n}\n\nfunction XIntakeTextarea({ value, onChange, onSubmit, placeholder, disabled }: XIntakeTextareaProps) {\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n onSubmit();\n }\n };\n\n return (\n <textarea\n className=\"w-full resize-none border-none bg-transparent outline-none\"\n placeholder={placeholder}\n disabled={disabled}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n />\n );\n}\n","export function ChatIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n\n","export function CheckIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\n","export function CloseIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n","export function CopyIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n","export function DebugIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" />\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />\n </svg>\n );\n}\n\n","export function MenuIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\n <line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\" />\n <line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\" />\n </svg>\n );\n}\n\n","export function NewChatIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </svg>\n );\n}\n\n","export function SparklesIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n <path d=\"M20 3v4\" />\n <path d=\"M22 5h-4\" />\n <path d=\"M4 17v2\" />\n <path d=\"M5 18H3\" />\n </svg>\n );\n}\n\n","export function ThumbsDownIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M17 14V2\" />\n <path d=\"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\" />\n </svg>\n );\n}\n\n","export function ThumbsUpIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M7 10v12\" />\n <path d=\"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\" />\n </svg>\n );\n}\n\n","import { useState } from \"react\";\nimport { Button, Dialog, toast, Tooltip } from \"@px-ui/core\";\n\nimport {\n CheckIcon,\n CopyIcon,\n DebugIcon,\n ThumbsDownIcon,\n ThumbsUpIcon,\n} from \"../assets/icons\";\nimport { useXandi, type FeedbackType } from \"../context/xandi-context\";\n\nexport type { FeedbackType } from \"../context/xandi-context\";\n\nexport function Root({ children }: { children: React.ReactNode }) {\n return <div className=\"flex items-center gap-1\">{children}</div>;\n}\n\nexport interface FeedbackProps {\n messageId: string;\n}\n\nexport function Feedback({ messageId }: FeedbackProps) {\n const { submitFeedback } = useXandi();\n const [feedback, setFeedback] = useState<FeedbackType>(null);\n\n const handleFeedback = (type: FeedbackType) => {\n const newFeedback = feedback === type ? null : type;\n setFeedback(newFeedback);\n submitFeedback(messageId, newFeedback);\n };\n\n return (\n <>\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleFeedback(\"up\")}\n className={`h-7 w-7 ${\n feedback === \"up\"\n ? \"bg-ppx-green-2 text-ppx-green-5\"\n : \"text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n }`}\n >\n <ThumbsUpIcon className={feedback === \"up\" ? \"fill-current\" : \"\"} />\n </Button>\n }\n />\n <Tooltip.Content>\n {feedback === \"up\" ? \"You found this helpful\" : \"Good response\"}\n </Tooltip.Content>\n </Tooltip.Root>\n\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleFeedback(\"down\")}\n className={`h-7 w-7 ${\n feedback === \"down\"\n ? \"bg-ppx-red-2 text-ppx-red-5\"\n : \"text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n }`}\n >\n <ThumbsDownIcon className={feedback === \"down\" ? \"fill-current\" : \"\"} />\n </Button>\n }\n />\n <Tooltip.Content>\n {feedback === \"down\" ? \"You found this unhelpful\" : \"Bad response\"}\n </Tooltip.Content>\n </Tooltip.Root>\n </>\n );\n}\n\nexport interface CopyProps {\n content: string;\n}\n\nexport function Copy({ content }: CopyProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(content);\n setCopied(true);\n toast.add({\n title: \"Copied!\",\n description: \"Message copied to clipboard\",\n type: \"success\",\n });\n setTimeout(() => setCopied(false), 2000);\n } catch {\n toast.add({\n title: \"Failed to copy\",\n description: \"Could not copy message to clipboard\",\n type: \"error\",\n });\n }\n };\n\n return (\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={handleCopy}\n className=\"h-7 w-7 text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n >\n {copied ? (\n <CheckIcon className=\"text-ppx-green-5\" />\n ) : (\n <CopyIcon />\n )}\n </Button>\n }\n />\n <Tooltip.Content>\n {copied ? \"Copied!\" : \"Copy message\"}\n </Tooltip.Content>\n </Tooltip.Root>\n );\n}\n\nexport interface DebugProps {\n messageId: string;\n debugTrace: unknown;\n}\n\nexport function Debug({ messageId, debugTrace }: DebugProps) {\n const [debugOpen, setDebugOpen] = useState(false);\n\n return (\n <Dialog.Root open={debugOpen} onOpenChange={setDebugOpen}>\n <Tooltip.Root>\n <Tooltip.Trigger\n render={\n <Dialog.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n className=\"h-7 w-7 text-ppx-neutral-10 hover:text-ppx-neutral-12\"\n >\n <DebugIcon />\n </Button>\n }\n />\n }\n />\n <Tooltip.Content>\n View debug trace\n </Tooltip.Content>\n </Tooltip.Root>\n\n <Dialog.Portal>\n <Dialog.Overlay />\n <Dialog.Content className=\"max-w-2xl\">\n <Dialog.Header>\n <Dialog.Title>Debug Trace</Dialog.Title>\n <Dialog.Description>\n Response debug information for message {messageId}\n </Dialog.Description>\n </Dialog.Header>\n <div className=\"max-h-96 overflow-auto rounded bg-ppx-neutral-2 p-4\">\n <pre className=\"whitespace-pre-wrap font-mono text-ppx-xs text-ppx-neutral-12\">\n {JSON.stringify(debugTrace, null, 2)}\n </pre>\n </div>\n <Dialog.Footer>\n <Dialog.Close render={<Button variant=\"outline\">Close</Button>} />\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n","import ReactMarkdown from \"react-markdown\";\n\nimport type { Message } from \"../../context/xandi-context\";\nimport * as XMessageActions from \"../x-message-actions\";\n\nexport interface MarkdownRendererProps {\n message: Message;\n}\n\nexport function MarkdownRenderer({ message }: MarkdownRendererProps) {\n const isUser = message.role === \"user\";\n const baseClass = `text-ppx-sm leading-relaxed ${isUser ? \"text-white\" : \"text-ppx-neutral-13\"}`;\n const showActions = !isUser;\n\n return (\n <div>\n <div className={baseClass}>\n <ReactMarkdown\n components={{\n p: ({ children }) => <p className=\"mb-2 last:mb-0\">{children}</p>,\n ul: ({ children }) => <ul className=\"mb-2 list-disc pl-4\">{children}</ul>,\n ol: ({ children }) => <ol className=\"mb-2 list-decimal pl-4\">{children}</ol>,\n li: ({ children }) => <li className=\"mb-1\">{children}</li>,\n a: ({ href, children }) => (\n <a href={href} className=\"underline\" target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n ),\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n }}\n >\n {message.content}\n </ReactMarkdown>\n </div>\n {showActions && (\n <div className=\"mt-2\">\n <XMessageActions.Root>\n <XMessageActions.Feedback messageId={message.id} />\n <XMessageActions.Copy content={message.content} />\n {message.debugTrace != null && (\n <XMessageActions.Debug messageId={message.id} debugTrace={message.debugTrace} />\n )}\n </XMessageActions.Root>\n </div>\n )}\n </div>\n );\n}\n","import type { Message } from \"../../context/xandi-context\";\nimport * as XMessageActions from \"../x-message-actions\";\n\nexport interface TextRendererProps {\n message: Message;\n}\n\nexport function TextRenderer({ message }: TextRendererProps) {\n const isUser = message.role === \"user\";\n const showActions = !isUser;\n\n return (\n <div>\n <p className={`text-ppx-sm leading-relaxed ${isUser ? \"text-white\" : \"text-ppx-neutral-13\"}`}>\n {message.content}\n </p>\n {showActions && (\n <div className=\"mt-2\">\n <XMessageActions.Root>\n <XMessageActions.Feedback messageId={message.id} />\n <XMessageActions.Copy content={message.content} />\n {message.debugTrace != null && (\n <XMessageActions.Debug messageId={message.id} debugTrace={message.debugTrace} />\n )}\n </XMessageActions.Root>\n </div>\n )}\n </div>\n );\n}\n","import type { Message, MessageType } from \"../context/xandi-context\";\nimport { MarkdownRenderer } from \"./renderers/markdown-renderer\";\nimport { TextRenderer } from \"./renderers/text-renderer\";\n\nexport interface XMessageItemProps {\n message: Message;\n}\n\nexport function XMessageItem({ message }: XMessageItemProps) {\n const isUser = message.role === \"user\";\n const messageType: MessageType = message.type ?? \"markdown\";\n\n return (\n <div className={`flex ${isUser ? \"justify-end\" : \"justify-start\"}`}>\n {isUser ? (\n <div className=\"max-w-[90%] rounded-2xl rounded-br-sm bg-ppx-green-5 px-4 py-2.5\">\n <MessageRenderer type={messageType} message={message} />\n </div>\n ) : (\n <div className=\"max-w-[90%]\">\n <MessageRenderer type={messageType} message={message} />\n </div>\n )}\n </div>\n );\n}\n\ninterface MessageRendererProps {\n type: MessageType;\n message: Message;\n}\n\nfunction MessageRenderer({ type, message }: MessageRendererProps) {\n switch (type) {\n case \"text\":\n return <TextRenderer message={message} />;\n case \"markdown\":\n default:\n return <MarkdownRenderer message={message} />;\n }\n}\n","import { Avatar } from \"@px-ui/core\";\n\nimport { useXandi } from \"../context/xandi-context\";\n\nexport function XTypingIndicator() {\n const { config } = useXandi();\n\n return (\n <div className=\"flex items-center gap-4\">\n <div className=\"animate-[popUp_0.3s_ease-out_forwards]\">\n <Avatar\n imgSrc={config.avatarUrl}\n name={config.assistantName}\n variant=\"rounded\"\n size=\"48px\"\n hideTooltip\n className=\"border-2 border-ppx-neutral-4\"\n />\n </div>\n <div className=\"flex animate-[slideIn_0.3s_ease-out_0.2s_forwards] items-center gap-2 rounded-xl bg-ppx-neutral-2 px-[10px] pb-[5px] pt-[10px] opacity-0 shadow-sm\">\n <span className=\"h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-9 [animation-delay:-0.3s]\" />\n <span className=\"h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-6 [animation-delay:-0.15s]\" />\n <span className=\"h-[12px] w-[12px] animate-bounce rounded-full bg-ppx-neutral-9\" />\n </div>\n </div>\n );\n}\n","import { useEffect, useLayoutEffect, useRef } from \"react\";\n\nimport { XMessageItem } from \"./x-message-item\";\nimport { XTypingIndicator } from \"./x-typing-indicator\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface XMessageContainerProps {\n height?: string | number;\n onLoadMore?: () => void;\n}\n\nexport function XMessageContainer({ height = 400, onLoadMore }: XMessageContainerProps) {\n const { conversation, isLoading } = useXandi();\n const containerRef = useRef<HTMLDivElement>(null);\n const topSentinelRef = useRef<HTMLDivElement>(null);\n const prevScrollHeightRef = useRef(0);\n const prevScrollTopRef = useRef(0);\n const prevLastMessageIdRef = useRef<string | null>(null);\n const prevMessageCountRef = useRef(0);\n const skipScrollToBottomRef = useRef(false);\n\n const messages = conversation.messages;\n const messageCount = messages.length;\n const lastMessageId = messageCount > 0 ? messages[messageCount - 1].id : null;\n\n useLayoutEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const prevCount = prevMessageCountRef.current;\n const prevLastId = prevLastMessageIdRef.current;\n const isPrependOlder =\n prevCount > 0 &&\n messageCount > prevCount &&\n lastMessageId != null &&\n lastMessageId === prevLastId;\n\n if (isPrependOlder) {\n const prevScrollHeight = prevScrollHeightRef.current;\n const prevScrollTop = prevScrollTopRef.current;\n const newScrollHeight = el.scrollHeight;\n el.scrollTop = Math.max(0, prevScrollTop + (newScrollHeight - prevScrollHeight));\n skipScrollToBottomRef.current = true;\n }\n\n prevScrollHeightRef.current = el.scrollHeight;\n prevScrollTopRef.current = el.scrollTop;\n prevMessageCountRef.current = messageCount;\n prevLastMessageIdRef.current = lastMessageId;\n }, [messageCount, lastMessageId, messages]);\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n if (skipScrollToBottomRef.current) {\n skipScrollToBottomRef.current = false;\n return;\n }\n el.scrollTop = el.scrollHeight - el.clientHeight;\n }, [conversation.messages, isLoading]);\n\n useEffect(() => {\n if (!onLoadMore) return;\n const sentinel = topSentinelRef.current;\n const container = containerRef.current;\n if (!sentinel || !container) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n const [entry] = entries;\n if (entry?.isIntersecting) {\n onLoadMore();\n }\n },\n {\n root: container,\n rootMargin: \"0px\",\n threshold: 0,\n }\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [onLoadMore]);\n\n return (\n <div\n ref={containerRef}\n className=\"flex flex-col overflow-y-auto py-[10px]\"\n style={{ height: typeof height === \"number\" ? `${height}px` : height }}\n >\n <div className=\"flex flex-col-reverse gap-5 p-4\">\n {isLoading && <XTypingIndicator />}\n {[...messages].reverse().map((message) => (\n <XMessageItem key={message.id} message={message} />\n ))}\n <div ref={topSentinelRef} className=\"h-1 shrink-0\" aria-hidden=\"true\" />\n </div>\n </div>\n );\n}\n","import { Avatar } from \"@px-ui/core\";\n\nimport { SparklesIcon } from \"../assets/icons\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface XWelcomeProps {\n message: string;\n}\n\nexport function XWelcome({ message }: XWelcomeProps) {\n const { config } = useXandi();\n\n return (\n <div className=\"flex flex-col items-center justify-center gap-4 py-12\">\n <div className=\"relative\">\n <div className=\"absolute -inset-1 rounded-full bg-gradient-to-b from-ppx-green-4 via-ppx-green-5/50 to-transparent\" />\n <div className=\"relative rounded-full bg-ppx-neutral-18 p-1\">\n <Avatar\n imgSrc={config.avatarUrl}\n name={config.assistantName}\n variant=\"rounded\"\n size=\"120px\"\n hideTooltip\n />\n </div>\n\n <div className=\"absolute -bottom-2 left-1/2\">\n <div className=\"flex h-6 w-6 animate-[pulse-zoom_2s_ease-in-out_infinite] items-center justify-center rounded-full bg-ppx-green-5\">\n <SparklesIcon className=\"text-white\" />\n </div>\n </div>\n </div>\n\n <h2 className=\"text-ppx-xl font-semibold text-ppx-foreground\">\n {message}\n </h2>\n </div>\n );\n}\n","import { useEffect } from \"react\";\nimport { XMainIntake, type Suggestion } from \"./x-main-intake\";\nimport { XMessageContainer } from \"./x-message-container\";\nimport { XWelcome } from \"./x-welcome\";\nimport { useXandi } from \"../context/xandi-context\";\nimport type { XandiUIMode } from \"../context/xandi-context\";\n\nexport interface XandiProps {\n welcomeMessage?: string;\n suggestions?: Suggestion[];\n uiMode?: XandiUIMode;\n}\n\nexport function Xandi({\n welcomeMessage = \"How can I help you today?\",\n suggestions = [],\n uiMode,\n}: XandiProps) {\n const { conversation, setUiModeOverride } = useXandi();\n\n useEffect(() => {\n setUiModeOverride(uiMode ?? null);\n return () => setUiModeOverride(null);\n }, [uiMode, setUiModeOverride]);\n const isEmpty = conversation.messages.length === 0;\n\n return (\n <div className=\"flex flex-col\">\n {isEmpty ? (\n <XWelcome message={welcomeMessage} />\n ) : (\n <XMessageContainer />\n )}\n <XMainIntake suggestions={isEmpty ? suggestions : []} />\n </div>\n );\n}\n","import { Avatar, Button } from \"@px-ui/core\";\n\nimport { CloseIcon, MenuIcon, NewChatIcon } from \"../assets/icons\";\nimport { useXandi } from \"../context/xandi-context\";\n\nexport interface XHeaderProps {\n onClose?: () => void;\n onToggleHistory?: () => void;\n}\n\nexport function XHeader({\n onClose,\n onToggleHistory,\n}: XHeaderProps) {\n const { startNewConversation, config } = useXandi();\n\n return (\n <header className=\"flex items-center justify-between border-b border-ppx-neutral-5 bg-transparent px-3 py-2\">\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onToggleHistory}\n aria-label=\"Toggle chat history\"\n >\n <MenuIcon />\n </Button>\n\n <div className=\"flex items-center gap-2\">\n <Avatar\n imgSrc={config.avatarUrl}\n name={config.assistantName}\n variant=\"rounded\"\n size=\"24px\"\n hideTooltip\n />\n <span className=\"font-medium text-ppx-foreground\">{config.assistantName}</span>\n </div>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={startNewConversation}\n aria-label=\"New chat\"\n >\n <NewChatIcon />\n </Button>\n\n {config.uiMode !== \"full\" && (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClose}\n aria-label=\"Close\"\n >\n <CloseIcon />\n </Button>\n )}\n </div>\n </header>\n );\n}\n","import { Button, Spinner } from \"@px-ui/core\";\n\nimport { ChatIcon } from \"../assets/icons\";\n\nexport interface ChatHistoryItem {\n id: string;\n title: string;\n timestamp: Date;\n}\n\nexport interface XChatHistoryProps {\n items?: ChatHistoryItem[];\n isLoading?: boolean;\n activeChatId?: string;\n onSelectChat?: (chatId: string) => void;\n}\n\nexport function XChatHistory({\n items = [],\n isLoading = false,\n activeChatId,\n onSelectChat,\n}: XChatHistoryProps) {\n return (\n <div className=\"flex-1 overflow-y-auto\">\n <div className=\"px-3 py-2\">\n <div className=\"flex items-center gap-2 text-ppx-sm font-medium text-ppx-foreground\">\n <ChatIcon />\n Chats\n </div>\n </div>\n\n {isLoading && items.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-2 px-6 py-8\">\n <Spinner size=\"medium\" className=\"text-ppx-neutral-10\" />\n <span className=\"text-ppx-sm text-ppx-neutral-10\">Loading conversations...</span>\n </div>\n ) : items.length === 0 ? (\n <div className=\"px-6 py-4 text-ppx-sm text-ppx-neutral-10\">\n No chat history yet\n </div>\n ) : (\n <div className=\"space-y-0.5\">\n {items.map((item) => (\n <Button\n key={item.id}\n variant=\"ghost\"\n onClick={() => onSelectChat?.(item.id)}\n className={`w-full justify-start truncate rounded-none px-6 ${\n activeChatId === item.id\n ? \"bg-ppx-neutral-4 text-ppx-foreground\"\n : \"text-ppx-neutral-12\"\n }`}\n >\n {item.title}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n","import { useEffect, useRef, useState } from \"react\";\nimport { Button } from \"@px-ui/core\";\n\nimport { CloseIcon, NewChatIcon } from \"../assets/icons\";\nimport { useXandi } from \"../context/xandi-context\";\nimport { XChatHistory, type ChatHistoryItem } from \"./x-chat-history\";\n\nexport interface XSidebarProps {\n isOpen?: boolean;\n onClose?: () => void;\n}\n\nexport function XSidebar({\n isOpen = true,\n onClose,\n}: XSidebarProps) {\n const { startNewConversation, getConvHistory, loadConversation, conversation } = useXandi();\n const [chatHistoryItems, setChatHistoryItems] = useState<ChatHistoryItem[]>([]);\n const [isLoadingHistory, setIsLoadingHistory] = useState(false);\n const fetchInProgressRef = useRef(false);\n\n useEffect(() => {\n if (!isOpen || !getConvHistory || fetchInProgressRef.current) return;\n\n fetchInProgressRef.current = true;\n setIsLoadingHistory(true);\n\n getConvHistory()\n .then((history) => {\n setChatHistoryItems(\n (history ?? []).map((item) => ({\n id: item.id,\n title: item.title,\n timestamp: item.timestamp,\n }))\n );\n })\n .catch((error) => {\n console.error(\"Failed to fetch conversation history:\", error);\n })\n .finally(() => {\n fetchInProgressRef.current = false;\n setIsLoadingHistory(false);\n });\n }, [isOpen, getConvHistory]);\n\n const handleSelectChat = (chatId: string) => {\n loadConversation(chatId);\n };\n\n if (!isOpen) return null;\n\n return (\n <aside className=\"flex h-full w-64 flex-col border-r border-ppx-neutral-5 bg-ppx-neutral-2\">\n <div className=\"flex items-center justify-between border-b border-ppx-neutral-5 p-3\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClose}\n aria-label=\"Close sidebar\"\n >\n <CloseIcon />\n </Button>\n </div>\n\n <div className=\"p-3\">\n <Button\n variant=\"ghost\"\n onClick={startNewConversation}\n className=\"w-full justify-start gap-3\"\n >\n <NewChatIcon className=\"h-5 w-5\" />\n New chat\n </Button>\n </div>\n\n <XChatHistory\n items={chatHistoryItems}\n isLoading={isLoadingHistory}\n activeChatId={conversation.id ?? undefined}\n onSelectChat={handleSelectChat}\n />\n </aside>\n );\n}\n"],"mappings":"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"}
|