orchid-ai 1.3.6 → 1.3.8

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.
@@ -60,6 +60,12 @@ interface ChatPanelProps {
60
60
  * (e.g. MUI AppBar ~1100, custom sidebars ~999). Default Tailwind z-50 is too low for many shells.
61
61
  */
62
62
  overlayZIndex?: number;
63
+ /**
64
+ * When true (default) and `showHistory` is on, only the chat history column is a narrow strip
65
+ * until hover (or tap) expands it; the main conversation area stays full width.
66
+ * Set to false to keep the history sidebar always fully expanded (~150px).
67
+ */
68
+ expandOnHover?: boolean;
63
69
  }
64
70
  /**
65
71
  * ChatPanel component
@@ -98,7 +104,7 @@ showHistory, // Default to hidden
98
104
  showProfileBubbles, // Default to hidden
99
105
  modalPosition, // Default to left position
100
106
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features, showFloatingButton, floatingButtonIcon, floatingButtonPosition, floatingButtonSize, floatingButtonClassName, chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon, // Default to bot icon
101
- headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
107
+ headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, expandOnHover, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
102
108
  /**
103
109
  * ChatInput component
104
110
  * @param query - The current query
@@ -61,6 +61,10 @@ interface ConversationProps {
61
61
  showClearChat?: boolean;
62
62
  onClearChat?: () => void;
63
63
  additionalContext?: string | Record<string, unknown>;
64
+ /** Optional ref to the main chat textarea (for parent focus control). */
65
+ chatInputRef?: React.RefObject<HTMLTextAreaElement | null>;
66
+ /** Increment to move focus to the main input (panel open, chat switch, new chat). */
67
+ focusChatNonce?: number;
64
68
  }
65
69
  /**
66
70
  * Conversation component - displays a single chat conversation
@@ -72,5 +76,5 @@ interface ConversationProps {
72
76
  * @param autoScroll - Whether to auto-scroll to bottom on new messages
73
77
  * @param maxHeight - Maximum height of the conversation container
74
78
  */
75
- export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
79
+ export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, chatInputRef: externalChatInputRef, focusChatNonce, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
76
80
  export {};
@@ -60,6 +60,12 @@ interface ChatPanelProps {
60
60
  * (e.g. MUI AppBar ~1100, custom sidebars ~999). Default Tailwind z-50 is too low for many shells.
61
61
  */
62
62
  overlayZIndex?: number;
63
+ /**
64
+ * When true (default) and `showHistory` is on, only the chat history column is a narrow strip
65
+ * until hover (or tap) expands it; the main conversation area stays full width.
66
+ * Set to false to keep the history sidebar always fully expanded (~150px).
67
+ */
68
+ expandOnHover?: boolean;
63
69
  }
64
70
  /**
65
71
  * ChatPanel component
@@ -98,7 +104,7 @@ showHistory, // Default to hidden
98
104
  showProfileBubbles, // Default to hidden
99
105
  modalPosition, // Default to left position
100
106
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features, showFloatingButton, floatingButtonIcon, floatingButtonPosition, floatingButtonSize, floatingButtonClassName, chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon, // Default to bot icon
101
- headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
107
+ headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, expandOnHover, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
102
108
  /**
103
109
  * ChatInput component
104
110
  * @param query - The current query
@@ -61,6 +61,10 @@ interface ConversationProps {
61
61
  showClearChat?: boolean;
62
62
  onClearChat?: () => void;
63
63
  additionalContext?: string | Record<string, unknown>;
64
+ /** Optional ref to the main chat textarea (for parent focus control). */
65
+ chatInputRef?: React.RefObject<HTMLTextAreaElement | null>;
66
+ /** Increment to move focus to the main input (panel open, chat switch, new chat). */
67
+ focusChatNonce?: number;
64
68
  }
65
69
  /**
66
70
  * Conversation component - displays a single chat conversation
@@ -72,5 +76,5 @@ interface ConversationProps {
72
76
  * @param autoScroll - Whether to auto-scroll to bottom on new messages
73
77
  * @param maxHeight - Maximum height of the conversation container
74
78
  */
75
- export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
79
+ export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, chatInputRef: externalChatInputRef, focusChatNonce, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
76
80
  export {};
package/dist/index.esm.js CHANGED
@@ -2807,8 +2807,10 @@ initialQuery, setInitialQuery,
2807
2807
  // Clear chat functionality
2808
2808
  showClearChat = false, onClearChat,
2809
2809
  // Additional context for AI requests
2810
- additionalContext, }) {
2810
+ additionalContext, chatInputRef: externalChatInputRef, focusChatNonce, }) {
2811
2811
  const chatRef = useRef(null);
2812
+ const fallbackInputRef = useRef(null);
2813
+ const inputRef = externalChatInputRef ?? fallbackInputRef;
2812
2814
  // Internal state for AI functionality
2813
2815
  const [query, setQuery] = useState(externalQuery);
2814
2816
  const [attachedFiles, setAttachedFiles] = useState(externalAttachedFiles);
@@ -2994,6 +2996,15 @@ additionalContext, }) {
2994
2996
  initialQuerySentRef.current = false;
2995
2997
  }
2996
2998
  }, [initialQuery]);
2999
+ // Focus main input when parent signals (open panel, new chat, switch chat)
3000
+ useEffect(() => {
3001
+ if (focusChatNonce === undefined || focusChatNonce < 1)
3002
+ return;
3003
+ const id = window.setTimeout(() => {
3004
+ inputRef.current?.focus({ preventScroll: true });
3005
+ }, 0);
3006
+ return () => clearTimeout(id);
3007
+ }, [focusChatNonce, inputRef]);
2997
3008
  // Scrollbar styles - dynamically themed
2998
3009
  const scrollbarStyles = `
2999
3010
  .custom-scrollbar::-webkit-scrollbar {
@@ -3035,7 +3046,7 @@ additionalContext, }) {
3035
3046
  e.currentTarget.style.color = theme.colors.text.secondary;
3036
3047
  e.currentTarget.style.backgroundColor = theme.colors.surface.primary;
3037
3048
  e.currentTarget.style.borderColor = theme.colors.border.primary;
3038
- }, title: "Clear chat history", "aria-label": "Clear chat", children: [jsx(Icon, { name: "trash", size: "sm" }), "Clear Chat History"] }) })), showInput && (jsx("div", { style: { flexShrink: 0 }, children: jsx(ChatInput, { query: finalQuery, setQuery: finalSetQuery, onSend: finalOnSend, isLoading: isLoading, inputRef: useRef(null), attachedFiles: finalAttachedFiles, setAttachedFiles: finalSetAttachedFiles, models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features, currentModelSelection: currentModelSelection, onModelSelectionChange: handleModelSelectionChange, theme: theme, isOpen: true }) }))] })] }));
3049
+ }, title: "Clear chat history", "aria-label": "Clear chat", children: [jsx(Icon, { name: "trash", size: "sm" }), "Clear Chat History"] }) })), showInput && (jsx("div", { style: { flexShrink: 0 }, children: jsx(ChatInput, { query: finalQuery, setQuery: finalSetQuery, onSend: finalOnSend, isLoading: isLoading, inputRef: inputRef, attachedFiles: finalAttachedFiles, setAttachedFiles: finalSetAttachedFiles, models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features, currentModelSelection: currentModelSelection, onModelSelectionChange: handleModelSelectionChange, theme: theme, isOpen: true }) }))] })] }));
3039
3050
  }
3040
3051
  /**
3041
3052
  * ErrorDisplay component - used to display error messages
@@ -3365,6 +3376,14 @@ theme, isOpen, }) {
3365
3376
  onModelSelectionChange(modelInfo);
3366
3377
  }
3367
3378
  }, [onModelSelectionChange]);
3379
+ /** Ghost icon buttons — explicit reset so host app (e.g. MUI) button styles don’t add light fills. */
3380
+ const ghostIconBtnClass = 'inline-flex items-center justify-center w-9 h-9 shrink-0 rounded-md p-0 border-0 shadow-none !bg-transparent appearance-none transition-colors';
3381
+ const ghostIconBtnStyle = {
3382
+ backgroundColor: 'transparent',
3383
+ border: 'none',
3384
+ boxShadow: 'none',
3385
+ color: theme.colors.text.secondary,
3386
+ };
3368
3387
  return (jsxs("div", { className: `px-3 py-2 border-t flex flex-col gap-2 transition-all duration-500 delay-500 ${isOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`, style: { borderColor: theme.colors.border.primary }, children: [attachedFiles.length > 0 && (jsx("div", { className: "flex flex-wrap gap-2 mb-2", children: attachedFiles.map((file, index) => (jsxs("div", { className: "relative group", children: [jsx("div", { className: "w-16 h-16 rounded-lg border border-gray-200 bg-gray-50 flex items-center justify-center overflow-hidden", children: file.type.startsWith('image/') ? (jsx("img", { src: URL.createObjectURL(file), alt: `Attached ${index + 1}`, className: "w-full h-full object-cover" })) : (jsx("div", { className: "flex items-center justify-center", children: FileHandler.getFileIcon(file) })) }), jsx("button", { onClick: () => removeFile(index), className: "absolute -top-2 -right-2 w-5 h-5 bg-red-500 text-white rounded-full flex items-center justify-center text-xs hover:bg-red-600 transition-colors", title: "Remove file", children: "\u00D7" }), jsx("div", { className: "absolute bottom-0 left-1/2 transform -translate-x-1/2 translate-y-full opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-10 mt-2", children: jsxs("div", { className: "bg-gray-900 text-white text-xs rounded-lg px-2 py-1 whitespace-nowrap shadow-lg", children: [jsx("div", { className: "font-medium truncate max-w-32", title: file.name, children: file.name }), jsxs("div", { className: "text-gray-300", children: [FileHandler.getFileTypeDescription(file), " \u2022", ' ', FileHandler.formatFileSize(file.size)] }), jsx("div", { className: "absolute -top-1 left-1/2 transform -translate-x-1/2 w-2 h-2 bg-gray-900 rotate-45" })] }) })] }, index))) })), incompatibleFiles.length > 0 && (jsxs("div", { className: "relative flex flex-col gap-1 text-sm text-orange-700 bg-orange-50 border border-orange-200 rounded px-3 py-2 mb-2", children: [jsx("button", { onClick: () => setIncompatibleFiles([]), className: "absolute top-1 right-1 w-5 h-5 flex items-center justify-center text-orange-500 hover:text-orange-700 hover:bg-orange-200 rounded-full transition-colors", title: "Dismiss", type: "button", children: "\u00D7" }), jsxs("div", { className: "flex items-center gap-2 pr-6", children: [jsx("span", { children: "\u26A0\uFE0F" }), jsx("span", { className: "font-medium", children: incompatibleFiles.length === 1
3369
3388
  ? 'File not supported'
3370
3389
  : 'Some files not supported' })] }), jsxs("div", { className: "text-xs", children: [jsx("div", { className: "mb-1", children: "These files were skipped:" }), jsxs("ul", { className: "list-disc list-inside ml-2 space-y-0.5", children: [incompatibleFiles.slice(0, 3).map((fileName, index) => (jsx("li", { className: "truncate", children: fileName }, index))), incompatibleFiles.length > 3 && (jsxs("li", { children: ["... and ", incompatibleFiles.length - 3, " more"] }))] }), jsxs("div", { className: "mt-1 text-orange-600", children: ["\uD83D\uDCA1 Only ", FileHandler.getAcceptedTypesDescription(), " are supported", incompatibleFiles.some((name) => name.includes('images not supported by current model')) && (jsx("div", { className: "mt-1", children: "\uD83D\uDD04 Switch to a model showing the image icon in the model switcher to enable image uploads" }))] })] })] })), jsxs("div", { className: `relative flex flex-col gap-1 rounded border px-2 pt-1 pb-1 cursor-text transition-all duration-200 border-2 focus-within:shadow-sm ${isDragOver ? 'border-dashed bg-opacity-20' : 'border-transparent'}`, style: {
@@ -3381,21 +3400,30 @@ theme, isOpen, }) {
3381
3400
  }
3382
3401
  }, onClick: handleContainerClick, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [isDragOver && (jsx("div", { className: "absolute top-2 left-2 right-2 bottom-2 flex items-center justify-center py-1 bg-blue-100 rounded text-blue-600 text-sm font-medium z-10 pointer-events-none", children: "\uD83D\uDCC2 Drop files here" })), jsx("textarea", { ref: inputRef, value: query, onChange: (e) => setQuery(e.target.value), onFocus: () => setFocused(true), onBlur: () => setFocused(false), onKeyDown: (e) => e.key === 'Enter' && !e.shiftKey && (e.preventDefault(), onSend()), onPaste: handlePaste, placeholder: "Describe what you need... (Try: 'I want to know how much time has been updated')", className: "w-full outline-none resize-none min-h-[3.5rem] max-h-32 border-none px-0 bg-transparent", style: {
3383
3402
  color: theme.colors.text.primary,
3384
- }, rows: 3 }), jsxs("div", { className: "flex gap-2 items-center justify-between", children: [jsxs("div", { className: "flex gap-1", children: [features.fileUploads !== false && (jsx("button", { className: "p-1 cursor-pointer disabled:opacity-50 disabled:cursor-default transition-colors", style: { color: theme.colors.text.tertiary }, onMouseEnter: (e) => {
3385
- e.currentTarget.style.color = theme.colors.primary[500];
3403
+ }, rows: 3 }), jsxs("div", { className: "flex gap-2 items-center justify-between", children: [jsxs("div", { className: "flex gap-1", children: [features.fileUploads !== false && (jsx("button", { type: "button", className: `${ghostIconBtnClass} cursor-pointer disabled:cursor-not-allowed disabled:opacity-50`, style: ghostIconBtnStyle, onMouseEnter: (e) => {
3404
+ e.currentTarget.style.color = theme.colors.primary[400];
3405
+ e.currentTarget.style.backgroundColor = theme.colors.surface.secondary;
3386
3406
  }, onMouseLeave: (e) => {
3387
- e.currentTarget.style.color = theme.colors.text.tertiary;
3388
- }, title: `Attach files - Supports: ${FileHandler.getAcceptedTypesDescription()}`, tabIndex: -1, type: "button", onClick: () => fileInputRef.current?.click(), children: jsx(Icon, { name: "paperclip", size: "sm" }) })), features.enableImageUploads !== false &&
3389
- features.imageAnalysis !== false && (jsx("button", { className: `p-1 cursor-pointer disabled:opacity-50 disabled:cursor-default transition-colors ${!imageSupported ? 'opacity-50 cursor-not-allowed' : ''}`, style: { color: theme.colors.text.tertiary }, onMouseEnter: (e) => {
3407
+ e.currentTarget.style.color = theme.colors.text.secondary;
3408
+ e.currentTarget.style.backgroundColor = 'transparent';
3409
+ }, title: `Attach files - Supports: ${FileHandler.getAcceptedTypesDescription()}`, tabIndex: -1, onClick: () => fileInputRef.current?.click(), children: jsx(Icon, { name: "paperclip", size: "sm" }) })), features.enableImageUploads !== false &&
3410
+ features.imageAnalysis !== false && (jsx("button", { type: "button", className: `${ghostIconBtnClass} cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 ${!imageSupported ? 'opacity-50' : ''}`, style: ghostIconBtnStyle, onMouseEnter: (e) => {
3390
3411
  if (imageSupported) {
3391
- e.currentTarget.style.color = theme.colors.primary[500];
3412
+ e.currentTarget.style.color = theme.colors.primary[400];
3413
+ e.currentTarget.style.backgroundColor =
3414
+ theme.colors.surface.secondary;
3392
3415
  }
3393
3416
  }, onMouseLeave: (e) => {
3394
- e.currentTarget.style.color = theme.colors.text.tertiary;
3417
+ e.currentTarget.style.color = theme.colors.text.secondary;
3418
+ e.currentTarget.style.backgroundColor = 'transparent';
3395
3419
  }, title: imageSupported
3396
3420
  ? 'Attach images - AI can analyze image content'
3397
- : "Current model doesn't support images. Switch to GPT-4O, Claude, or Gemini to use image attachments.", tabIndex: -1, type: "button", onClick: () => imageSupported && imageInputRef.current?.click(), disabled: !imageSupported, children: jsx(Icon, { name: "image", size: "sm" }) })), jsx("button", { className: "p-1 cursor-pointer disabled:opacity-50 disabled:cursor-default transition-colors", style: { color: theme.colors.text.tertiary }, title: "Record audio (coming soon)", tabIndex: -1, type: "button", onClick: handleAudioRecord, disabled: true, children: jsx(Icon, { name: "microphone", size: "sm" }) })] }), jsx("button", { onClick: () => onSend(), disabled: (!query.trim() && attachedFiles.length === 0) || isLoading, className: "rounded-full transition disabled:opacity-50 p-2", style: {
3421
+ : "Current model doesn't support images. Switch to GPT-4O, Claude, or Gemini to use image attachments.", tabIndex: -1, onClick: () => imageSupported && imageInputRef.current?.click(), disabled: !imageSupported, children: jsx(Icon, { name: "image", size: "sm" }) })), jsx("button", { type: "button", className: `${ghostIconBtnClass} cursor-not-allowed opacity-50`, style: {
3422
+ ...ghostIconBtnStyle,
3423
+ color: theme.colors.text.tertiary,
3424
+ }, title: "Record audio (coming soon)", tabIndex: -1, onClick: handleAudioRecord, disabled: true, children: jsx(Icon, { name: "microphone", size: "sm" }) })] }), jsx("button", { type: "button", onClick: () => onSend(), disabled: (!query.trim() && attachedFiles.length === 0) || isLoading, className: "inline-flex shrink-0 items-center justify-center rounded-full border-0 p-2 shadow-none !bg-transparent transition-colors disabled:cursor-not-allowed disabled:opacity-50", style: {
3398
3425
  color: theme.colors.text.primary,
3426
+ backgroundColor: 'transparent',
3399
3427
  }, onMouseEnter: (e) => {
3400
3428
  if (!e.currentTarget.disabled) {
3401
3429
  e.currentTarget.style.backgroundColor =
@@ -3405,7 +3433,7 @@ theme, isOpen, }) {
3405
3433
  if (!e.currentTarget.disabled) {
3406
3434
  e.currentTarget.style.backgroundColor = 'transparent';
3407
3435
  }
3408
- }, title: "Send", tabIndex: -1, type: "button", children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("g", { clipPath: "url(#clip0_892_5571)", children: jsx("path", { d: "M13.3334 10.0001L10.0001 6.66675M10.0001 6.66675L6.66675 10.0001M10.0001 6.66675V13.3334M18.3334 10.0001C18.3334 14.6025 14.6025 18.3334 10.0001 18.3334C5.39771 18.3334 1.66675 14.6025 1.66675 10.0001C1.66675 5.39771 5.39771 1.66675 10.0001 1.66675C14.6025 1.66675 18.3334 5.39771 18.3334 10.0001Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }), jsx("defs", { children: jsx("clipPath", { id: "clip0_892_5571", children: jsx("rect", { width: "20", height: "20", fill: "white" }) }) })] }) })] })] }), jsx("input", { ref: fileInputRef, type: "file", accept: FileHandler.getInputAcceptAttribute(), multiple: true, onChange: handleAllFileUpload, className: "hidden", "aria-label": "Upload any file" }), jsx("input", { ref: imageInputRef, type: "file", accept: "image/*", multiple: true, onChange: handleImageUpload, className: "hidden", "aria-label": "Upload images" }), features.modelSwitching !== false &&
3436
+ }, title: "Send", tabIndex: -1, children: jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("g", { clipPath: "url(#clip0_892_5571)", children: jsx("path", { d: "M13.3334 10.0001L10.0001 6.66675M10.0001 6.66675L6.66675 10.0001M10.0001 6.66675V13.3334M18.3334 10.0001C18.3334 14.6025 14.6025 18.3334 10.0001 18.3334C5.39771 18.3334 1.66675 14.6025 1.66675 10.0001C1.66675 5.39771 5.39771 1.66675 10.0001 1.66675C14.6025 1.66675 18.3334 5.39771 18.3334 10.0001Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }), jsx("defs", { children: jsx("clipPath", { id: "clip0_892_5571", children: jsx("rect", { width: "20", height: "20", fill: "white" }) }) })] }) })] })] }), jsx("input", { ref: fileInputRef, type: "file", accept: FileHandler.getInputAcceptAttribute(), multiple: true, onChange: handleAllFileUpload, className: "hidden", "aria-label": "Upload any file" }), jsx("input", { ref: imageInputRef, type: "file", accept: "image/*", multiple: true, onChange: handleImageUpload, className: "hidden", "aria-label": "Upload images" }), features.modelSwitching !== false &&
3409
3437
  features.imageAnalysis !== false &&
3410
3438
  features.enableImageUploads !== false &&
3411
3439
  !imageSupported &&
@@ -3508,7 +3536,37 @@ showHistory = false, // Default to hidden
3508
3536
  showProfileBubbles = false, // Default to hidden
3509
3537
  modalPosition = 'left', // Default to left position
3510
3538
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features = {}, showFloatingButton = false, floatingButtonIcon, floatingButtonPosition = 'bottom-right', floatingButtonSize = 'md', floatingButtonClassName = '', chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon = 'command', // Default to bot icon
3511
- headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist you with your queries', onSuggestionSelect, overlayZIndex, }) {
3539
+ headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist you with your queries', onSuggestionSelect, overlayZIndex, expandOnHover = true, }) {
3540
+ const chatInputRef = useRef(null);
3541
+ const [focusChatNonce, setFocusChatNonce] = useState(0);
3542
+ /** Match original slide-out sizing (not the temporary wider caps). */
3543
+ const expandedWidthClass = showHistory
3544
+ ? 'w-[min(90vw,700px)] max-w-[700px]'
3545
+ : 'w-[min(80vw,550px)] max-w-[550px]';
3546
+ const panelRoundedClass = modalPosition === 'right' ? 'rounded-l-lg' : 'rounded-r-lg';
3547
+ // Focus the main input when the panel opens, chat switches, or new chat is selected
3548
+ useEffect(() => {
3549
+ if (!isOpen)
3550
+ return;
3551
+ setFocusChatNonce((n) => n + 1);
3552
+ }, [isOpen, currentChatId]);
3553
+ const handleCloseChat = useCallback((chatId) => {
3554
+ setChats?.((prev) => {
3555
+ const next = { ...prev };
3556
+ delete next[chatId];
3557
+ setCurrentChatId?.((cur) => {
3558
+ if (cur !== chatId)
3559
+ return cur;
3560
+ const keys = Object.keys(next).sort((a, b) => Number(b) - Number(a));
3561
+ if (keys.length)
3562
+ return keys[0];
3563
+ const nid = Date.now().toString();
3564
+ setChats?.((p) => ({ ...p, [nid]: [] }));
3565
+ return nid;
3566
+ });
3567
+ return next;
3568
+ });
3569
+ }, [setChats, setCurrentChatId]);
3512
3570
  const handleSuggestionClick = (s) => {
3513
3571
  if (onSuggestionSelect) {
3514
3572
  onSuggestionSelect(s);
@@ -3544,6 +3602,16 @@ headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist
3544
3602
  });
3545
3603
  }
3546
3604
  }, [isOpen, isVisible]);
3605
+ // If parent sets isOpen false without calling our handleClose, isVisible can stay true and
3606
+ // shouldRenderPanel keeps the fixed overlay mounted (e.g. stray strip during app loading).
3607
+ useEffect(() => {
3608
+ if (!isOpen && isVisible) {
3609
+ const id = window.setTimeout(() => {
3610
+ setIsVisible(false);
3611
+ }, 300);
3612
+ return () => window.clearTimeout(id);
3613
+ }
3614
+ }, [isOpen, isVisible]);
3547
3615
  // Handle closing animation
3548
3616
  const handleClose = useCallback(() => {
3549
3617
  if (!isAnimating) {
@@ -3678,105 +3746,143 @@ headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist
3678
3746
  transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
3679
3747
  }
3680
3748
  `;
3681
- return (jsxs(Fragment, { children: [jsx("style", { children: scrollbarStyles }), jsxs(ErrorBoundary, { children: [!isOpen && showFloatingButton && (jsx(FloatingChatButton, { onClick: handleOpen, theme: theme, icon: floatingButtonIcon, position: floatingButtonPosition, size: floatingButtonSize, className: floatingButtonClassName, zIndex: overlayZIndex })), shouldRenderPanel && (jsxs("div", { className: "fixed inset-0 z-50", style: overlayZIndex !== undefined ? { zIndex: overlayZIndex } : undefined, children: [jsx("div", { className: `absolute inset-0 bg-black/20 transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0'}`, onClick: handleClose }), jsx("div", { className: `fixed z-[60] top-6 transition-all duration-300 ${isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-75'}`, style: { ...(modalPosition === 'left'
3682
- ? { left: showHistory ? 'min(90vw, 700px)' : 'min(80vw, 550px)', marginLeft: '16px' }
3683
- : { right: showHistory ? 'min(90vw, 700px)' : 'min(80vw, 550px)', marginRight: '16px' }) }, children: jsx("button", { onClick: handleClose, className: "w-10 h-10 rounded-full shadow-lg transition-all duration-200 flex items-center justify-center text-xl font-bold hover:scale-110", style: {
3684
- backgroundColor: finalTheme.colors.surface.elevated,
3685
- color: finalTheme.colors.text.secondary,
3686
- border: `2px solid ${finalTheme.colors.border.primary}`,
3687
- boxShadow: finalTheme.shadows.lg,
3688
- }, onMouseEnter: (e) => {
3689
- e.currentTarget.style.backgroundColor =
3690
- finalTheme.colors.surface.secondary;
3691
- e.currentTarget.style.color = finalTheme.colors.text.primary;
3692
- e.currentTarget.style.borderColor =
3693
- finalTheme.colors.border.secondary;
3694
- e.currentTarget.style.transform = 'scale(1.05)';
3695
- }, onMouseLeave: (e) => {
3696
- e.currentTarget.style.backgroundColor =
3697
- finalTheme.colors.surface.elevated;
3698
- e.currentTarget.style.color =
3699
- finalTheme.colors.text.secondary;
3700
- e.currentTarget.style.borderColor =
3701
- finalTheme.colors.border.primary;
3702
- e.currentTarget.style.transform = 'scale(1)';
3703
- }, title: "Close", children: "\u00D7" }) }), jsxs("div", { className: `fixed top-0 h-full w-full z-50 flex flex-col relative
3704
- ${modalPosition === 'left' ? 'left-0 rounded-r-lg' : 'right-0 rounded-l-lg'}
3705
- ${showHistory ? 'sm:w-[90vw] md:w-[700px]' : 'sm:w-[80vw] md:w-[550px]'}
3749
+ return (jsxs(Fragment, { children: [jsx("style", { children: scrollbarStyles }), jsxs(ErrorBoundary, { children: [!isOpen && showFloatingButton && (jsx(FloatingChatButton, { onClick: handleOpen, theme: theme, icon: floatingButtonIcon, position: floatingButtonPosition, size: floatingButtonSize, className: floatingButtonClassName, zIndex: overlayZIndex })), shouldRenderPanel && (jsxs("div", { className: "fixed inset-0 z-50", style: overlayZIndex !== undefined ? { zIndex: overlayZIndex } : undefined, children: [jsx("div", { className: `absolute inset-0 bg-black/20 transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0'}`, onClick: handleClose }), jsx("div", { className: `fixed top-0 z-50 flex h-full min-h-0 flex-col overflow-hidden ${panelRoundedClass}
3750
+ ${expandedWidthClass}
3706
3751
  transition-all duration-300 ease-out
3707
3752
  ${getAnimationClasses()}
3753
+ ${modalPosition === 'left' ? 'left-0' : 'right-0'}
3708
3754
  `, style: {
3709
- backgroundColor: finalTheme.colors.background.primary,
3755
+ /* Chrome shell matches header + history; main chat column uses primary below */
3756
+ backgroundColor: finalTheme.colors.background.secondary,
3710
3757
  color: finalTheme.colors.text.primary,
3711
3758
  boxShadow: modalPosition === 'left'
3712
3759
  ? '8px 0 32px rgba(0, 0, 0, 0.3), 4px 0 16px rgba(0, 0, 0, 0.2)'
3713
3760
  : '-8px 0 32px rgba(0, 0, 0, 0.3), -4px 0 16px rgba(0, 0, 0, 0.2)',
3714
- }, ref: containerRef, onClick: (e) => e.stopPropagation(), children: [jsx("div", { className: `flex items-center justify-between px-6 py-4 border-b min-h-[72px] transition-all duration-500 delay-100 ${isOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-2'}`, style: {
3715
- borderColor: finalTheme.colors.border.primary,
3716
- backgroundColor: finalTheme.colors.background.primary,
3717
- }, children: jsxs("div", { className: "flex items-center gap-3", children: [jsx("span", { className: `inline-flex items-center justify-center rounded-full w-8 h-8 transition-all duration-500 delay-200 ${isOpen ? 'opacity-100 scale-100 rotate-0' : 'opacity-0 scale-75 rotate-12'}`, style: { backgroundColor: finalTheme.colors.primary[600] }, children: typeof headerIcon === 'string' ? (jsx(Icon, { name: headerIcon, size: "sm", style: { color: finalTheme.colors.text.primary } })) : (headerIcon || (jsx(Icon, { name: "command", size: "sm", style: { color: finalTheme.colors.text.primary } }))) }), jsxs("div", { className: `transition-all duration-500 delay-300 ${isOpen ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-2'}`, children: [jsx("div", { className: "font-bold text-lg leading-tight", style: { color: finalTheme.colors.text.primary }, children: headerTitle }), jsx("div", { className: "text-xs", style: { color: finalTheme.colors.text.tertiary }, children: headerSubtitle })] })] }) }), jsxs("div", { className: `flex flex-1 min-h-0 h-full transition-all duration-500 delay-200 ${isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-95'}`, children: [showHistory && (jsx(ChatHistorySidebar, { chats: chats || {}, currentChatId: currentChatId || 'default', switchChat: handleHistorySwitchChat, newChat: handleHistoryNewChat, theme: finalTheme, isOpen: isOpen })), jsx("div", { className: "flex-1 flex flex-col min-h-0 h-full", children: jsx("div", { className: `flex-1 px-6 py-4 min-h-0 transition-all duration-500 delay-300 ${isOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`, style: {
3761
+ }, ref: containerRef, onClick: (e) => e.stopPropagation(), children: jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col overflow-hidden", children: [jsxs("div", { className: `flex min-h-[72px] items-center justify-between border-b px-6 py-4 transition-all duration-500 delay-100 ${isOpen ? 'translate-y-0 opacity-100' : 'translate-y-2 opacity-0'}`, style: {
3762
+ borderColor: finalTheme.colors.border.primary,
3763
+ backgroundColor: finalTheme.colors.background.secondary,
3764
+ }, children: [jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [jsx("span", { className: `inline-flex h-8 w-8 items-center justify-center rounded-full transition-all duration-500 delay-200 ${isOpen ? 'rotate-0 scale-100 opacity-100' : 'rotate-12 scale-75 opacity-0'}`, style: {
3765
+ backgroundColor: finalTheme.colors.surface.tertiary,
3766
+ border: `1px solid ${finalTheme.colors.border.secondary}`,
3767
+ }, children: typeof headerIcon === 'string' ? (jsx(Icon, { name: headerIcon, size: "sm", style: { color: finalTheme.colors.primary[400] } })) : (headerIcon || (jsx(Icon, { name: "command", size: "sm", style: { color: finalTheme.colors.primary[400] } }))) }), jsxs("div", { className: `min-w-0 transition-all duration-500 delay-300 ${isOpen ? 'translate-x-0 opacity-100' : 'translate-x-2 opacity-0'}`, children: [jsx("div", { className: "text-lg font-bold leading-tight", style: { color: finalTheme.colors.text.primary }, children: headerTitle }), jsx("div", { className: "text-xs", style: { color: finalTheme.colors.text.tertiary }, children: headerSubtitle })] })] }), jsx("button", { type: "button", onClick: handleClose, className: "ml-2 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full text-xl font-bold transition-transform hover:scale-105", style: {
3768
+ backgroundColor: finalTheme.colors.surface.elevated,
3769
+ color: finalTheme.colors.text.secondary,
3770
+ border: `2px solid ${finalTheme.colors.border.primary}`,
3771
+ boxShadow: finalTheme.shadows?.lg,
3772
+ }, title: "Close", "aria-label": "Close chat panel", children: "\u00D7" })] }), jsxs("div", { className: `flex min-h-0 flex-1 flex-row transition-all duration-500 delay-200 ${isOpen ? 'scale-100 opacity-100' : 'scale-95 opacity-0'}`, children: [showHistory && (jsx(ChatHistorySidebar, { chats: chats || {}, currentChatId: currentChatId || 'default', switchChat: handleHistorySwitchChat, newChat: handleHistoryNewChat, onCloseChat: handleCloseChat, expandOnHover: expandOnHover, theme: finalTheme, isOpen: isOpen })), jsx("div", { className: `flex min-h-0 min-w-0 flex-1 flex-col ${showHistory ? 'border-l' : ''}`, style: {
3773
+ borderColor: showHistory
3774
+ ? finalTheme.colors.border.primary
3775
+ : undefined,
3718
3776
  backgroundColor: finalTheme.colors.background.primary,
3719
- }, children: jsx(Conversation, { onSuggestionClick: handleSuggestionClick, theme: finalTheme, showProfileBubbles: showProfileBubbles, autoScroll: true, showInput: true,
3720
- // AI functionality props
3721
- userId: userId, serverConfig: serverConfig, formData: formData, setFormState: setFormState, onNavigate: onNavigate, chatLevel: chatLevel,
3722
- // External chat management
3723
- chats: chats, setChats: setChats, currentChatId: currentChatId, setCurrentChatId: setCurrentChatId,
3724
- // Model configuration
3725
- models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features,
3726
- // Initial query handling
3727
- initialQuery: initialQuery, setInitialQuery: setInitialQuery }) }) })] })] })] }))] })] }));
3777
+ }, children: jsx("div", { className: `min-h-0 flex-1 px-6 py-4 transition-all duration-500 delay-300 ${isOpen ? 'translate-y-0 opacity-100' : 'translate-y-4 opacity-0'}`, children: jsx(Conversation, { onSuggestionClick: handleSuggestionClick, theme: finalTheme, showProfileBubbles: showProfileBubbles, autoScroll: true, showInput: true, userId: userId, serverConfig: serverConfig, formData: formData, setFormState: setFormState, onNavigate: onNavigate, chatLevel: chatLevel, chats: chats, setChats: setChats, currentChatId: currentChatId, setCurrentChatId: setCurrentChatId, models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features, initialQuery: initialQuery, setInitialQuery: setInitialQuery, chatInputRef: chatInputRef, focusChatNonce: focusChatNonce }) }) })] })] }) })] }))] })] }));
3728
3778
  }
3729
3779
  /**
3730
- * ChatHistorySidebar component with animation support
3780
+ * ChatHistorySidebar optional collapsed strip; expands on hover (or tap) for more room for the main chat.
3731
3781
  */
3732
- function ChatHistorySidebar({ chats, currentChatId, switchChat, newChat, theme, isOpen, }) {
3733
- return (jsx("div", { className: `flex-shrink-0 flex-grow-0 border-r flex flex-col h-full p-2 w-[150px] transition-all duration-500 delay-400 ${isOpen ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-4'}`, style: {
3782
+ function ChatHistorySidebar({ chats, currentChatId, switchChat, newChat, onCloseChat, expandOnHover = true, theme, isOpen, }) {
3783
+ const [historyExpanded, setHistoryExpanded] = useState(false);
3784
+ const leaveTimerRef = useRef(null);
3785
+ useEffect(() => {
3786
+ if (!isOpen)
3787
+ setHistoryExpanded(false);
3788
+ }, [isOpen]);
3789
+ const clearLeaveTimer = useCallback(() => {
3790
+ if (leaveTimerRef.current != null) {
3791
+ clearTimeout(leaveTimerRef.current);
3792
+ leaveTimerRef.current = null;
3793
+ }
3794
+ }, []);
3795
+ useEffect(() => () => clearLeaveTimer(), [clearLeaveTimer]);
3796
+ const handleSidebarEnter = useCallback(() => {
3797
+ clearLeaveTimer();
3798
+ if (expandOnHover)
3799
+ setHistoryExpanded(true);
3800
+ }, [expandOnHover, clearLeaveTimer]);
3801
+ const handleSidebarLeave = useCallback(() => {
3802
+ if (!expandOnHover)
3803
+ return;
3804
+ clearLeaveTimer();
3805
+ leaveTimerRef.current = setTimeout(() => {
3806
+ setHistoryExpanded(false);
3807
+ leaveTimerRef.current = null;
3808
+ }, 220);
3809
+ }, [expandOnHover, clearLeaveTimer]);
3810
+ const listExpanded = !expandOnHover || historyExpanded;
3811
+ const widthClass = expandOnHover
3812
+ ? listExpanded
3813
+ ? 'w-[min(52vw,220px)] max-w-[220px]'
3814
+ : 'w-14'
3815
+ : 'w-[150px]';
3816
+ const chatRows = Object.keys(chats)
3817
+ .sort((a, b) => Number(b) - Number(a))
3818
+ .map((chatId) => (jsxs("div", { className: "flex w-full cursor-pointer items-center gap-1 rounded-full px-2 py-2 transition-colors", style: {
3819
+ backgroundColor: chatId === currentChatId
3820
+ ? theme.colors.primary[900]
3821
+ : 'transparent',
3822
+ color: chatId === currentChatId
3823
+ ? theme.colors.primary[100]
3824
+ : theme.colors.text.secondary,
3825
+ fontWeight: chatId === currentChatId ? 'bold' : 'normal',
3826
+ }, onMouseEnter: (e) => {
3827
+ if (chatId !== currentChatId) {
3828
+ e.currentTarget.style.backgroundColor = theme.colors.surface.secondary;
3829
+ }
3830
+ }, onMouseLeave: (e) => {
3831
+ if (chatId !== currentChatId) {
3832
+ e.currentTarget.style.backgroundColor = 'transparent';
3833
+ }
3834
+ }, onClick: () => switchChat(chatId), title: (chats[chatId]?.[0]
3835
+ ? getTextFromMessage(chats[chatId][0])
3836
+ : '')?.slice(0, 30) ||
3837
+ `Chat started at ${new Date(Number(chatId)).toLocaleString()}`, children: [jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full", style: {
3838
+ backgroundColor: theme.colors.surface.secondary,
3839
+ color: theme.colors.primary[400],
3840
+ }, children: jsx("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) }), jsxs("div", { className: "min-w-0 flex-1", children: [jsx("div", { className: "truncate font-semibold", children: (chats[chatId]?.[0]
3841
+ ? getTextFromMessage(chats[chatId][0])
3842
+ : '')?.slice(0, 18) || 'New chat' }), jsx("div", { className: "text-xs", style: { color: theme.colors.text.tertiary }, children: (() => {
3843
+ const now = Date.now();
3844
+ const diff = Math.floor((now - Number(chatId)) / 1000);
3845
+ if (diff < 60)
3846
+ return 'Just now';
3847
+ if (diff < 3600)
3848
+ return `${Math.floor(diff / 60)}m ago`;
3849
+ if (diff < 86400)
3850
+ return `${Math.floor(diff / 3600)}h ago`;
3851
+ return `${Math.floor(diff / 86400)}d ago`;
3852
+ })() })] }), onCloseChat && (jsx("button", { type: "button", className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-md text-base font-semibold leading-none transition-colors", style: {
3853
+ color: theme.colors.text.primary,
3854
+ backgroundColor: theme.colors.surface.secondary,
3855
+ border: `1px solid ${theme.colors.border.secondary}`,
3856
+ }, title: "Close chat", "aria-label": "Close chat", onClick: (e) => {
3857
+ e.stopPropagation();
3858
+ onCloseChat(chatId);
3859
+ }, onMouseEnter: (e) => {
3860
+ e.currentTarget.style.backgroundColor = theme.colors.surface.tertiary;
3861
+ }, onMouseLeave: (e) => {
3862
+ e.currentTarget.style.backgroundColor = theme.colors.surface.secondary;
3863
+ }, children: "\u00D7" }))] }, chatId)));
3864
+ return (jsx("div", { className: `flex h-full flex-shrink-0 flex-grow-0 flex-col overflow-hidden border-r transition-[width] duration-300 ease-out ${isOpen ? 'translate-x-0 opacity-100' : 'translate-x-4 opacity-0'} ${widthClass}`, style: {
3734
3865
  backgroundColor: theme.colors.background.secondary,
3735
3866
  borderColor: theme.colors.border.primary,
3736
- }, children: jsxs("div", { className: "flex-1 overflow-y-auto flex flex-col items-center gap-2 p-2 custom-scrollbar", children: [jsx("button", { className: "rounded-lg w-full py-2 font-bold text-xl mb-2 shadow transition-colors", style: {
3737
- backgroundColor: theme.colors.primary[600],
3738
- color: theme.colors.text.inverse,
3739
- borderColor: theme.colors.primary[700],
3740
- }, onMouseEnter: (e) => {
3741
- e.currentTarget.style.backgroundColor = theme.colors.primary[700];
3742
- }, onMouseLeave: (e) => {
3743
- e.currentTarget.style.backgroundColor = theme.colors.primary[600];
3744
- }, onClick: newChat, children: "+" }), Object.keys(chats)
3745
- .sort((a, b) => Number(b) - Number(a))
3746
- .map((chatId) => (jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-lg cursor-pointer transition-colors w-full", style: {
3747
- backgroundColor: chatId === currentChatId
3748
- ? theme.colors.primary[900]
3749
- : theme.colors.surface.primary,
3750
- color: chatId === currentChatId
3751
- ? theme.colors.primary[100]
3752
- : theme.colors.text.secondary,
3753
- fontWeight: chatId === currentChatId ? 'bold' : 'normal',
3754
- }, onMouseEnter: (e) => {
3755
- if (chatId !== currentChatId) {
3756
- e.currentTarget.style.backgroundColor =
3757
- theme.colors.surface.secondary;
3758
- }
3759
- }, onMouseLeave: (e) => {
3760
- if (chatId !== currentChatId) {
3761
- e.currentTarget.style.backgroundColor =
3762
- theme.colors.surface.primary;
3763
- }
3764
- }, onClick: () => switchChat(chatId), title: (chats[chatId]?.[0]
3765
- ? getTextFromMessage(chats[chatId][0])
3766
- : '')?.slice(0, 30) ||
3767
- `Chat started at ${new Date(Number(chatId)).toLocaleString()}`, children: [jsx("span", { className: "flex items-center justify-center w-7 h-7 rounded-full bg-blue-50", children: jsx("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) }), jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "truncate font-semibold", children: (chats[chatId]?.[0]
3768
- ? getTextFromMessage(chats[chatId][0])
3769
- : '')?.slice(0, 18) || 'New chat' }), jsx("div", { className: "text-xs text-gray-400", children: (() => {
3770
- const now = Date.now();
3771
- const diff = Math.floor((now - Number(chatId)) / 1000);
3772
- if (diff < 60)
3773
- return 'Just now';
3774
- if (diff < 3600)
3775
- return `${Math.floor(diff / 60)}m ago`;
3776
- if (diff < 86400)
3777
- return `${Math.floor(diff / 3600)}h ago`;
3778
- return `${Math.floor(diff / 86400)}d ago`;
3779
- })() })] })] }, chatId)))] }) }));
3867
+ }, onMouseEnter: handleSidebarEnter, onMouseLeave: handleSidebarLeave, children: expandOnHover && !listExpanded ? (jsxs("div", { className: "flex flex-1 flex-col items-center gap-2 px-1 py-3", children: [jsx("button", { type: "button", className: "inline-flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full text-xl font-bold transition-colors", style: {
3868
+ backgroundColor: theme.colors.surface.tertiary,
3869
+ color: theme.colors.primary[400],
3870
+ border: `1px solid ${theme.colors.border.secondary}`,
3871
+ }, title: "New chat", "aria-label": "New chat", onClick: () => {
3872
+ newChat();
3873
+ setHistoryExpanded(true);
3874
+ }, children: "+" }), jsx("button", { type: "button", className: "inline-flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full transition-transform hover:scale-105", style: {
3875
+ backgroundColor: theme.colors.surface.tertiary,
3876
+ border: `1px solid ${theme.colors.border.secondary}`,
3877
+ }, title: "Open chat history", "aria-label": "Open chat history", onClick: () => setHistoryExpanded(true), children: jsx("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", style: { color: theme.colors.primary[400] }, children: jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) })] })) : (jsx("div", { className: "flex min-h-0 flex-1 flex-col p-2", children: jsxs("div", { className: "custom-scrollbar flex flex-1 flex-col items-center gap-2 overflow-y-auto p-2", children: [jsx("button", { className: "mb-2 w-full rounded-full py-2 text-xl font-bold shadow transition-colors", style: {
3878
+ backgroundColor: theme.colors.primary[600],
3879
+ color: theme.colors.text.inverse,
3880
+ borderColor: theme.colors.primary[700],
3881
+ }, onMouseEnter: (e) => {
3882
+ e.currentTarget.style.backgroundColor = theme.colors.primary[700];
3883
+ }, onMouseLeave: (e) => {
3884
+ e.currentTarget.style.backgroundColor = theme.colors.primary[600];
3885
+ }, onClick: newChat, children: "+" }), chatRows] }) })) }));
3780
3886
  }
3781
3887
  /**
3782
3888
  * FloatingChatButton component
package/dist/index.js CHANGED
@@ -2809,8 +2809,10 @@ initialQuery, setInitialQuery,
2809
2809
  // Clear chat functionality
2810
2810
  showClearChat = false, onClearChat,
2811
2811
  // Additional context for AI requests
2812
- additionalContext, }) {
2812
+ additionalContext, chatInputRef: externalChatInputRef, focusChatNonce, }) {
2813
2813
  const chatRef = React.useRef(null);
2814
+ const fallbackInputRef = React.useRef(null);
2815
+ const inputRef = externalChatInputRef ?? fallbackInputRef;
2814
2816
  // Internal state for AI functionality
2815
2817
  const [query, setQuery] = React.useState(externalQuery);
2816
2818
  const [attachedFiles, setAttachedFiles] = React.useState(externalAttachedFiles);
@@ -2996,6 +2998,15 @@ additionalContext, }) {
2996
2998
  initialQuerySentRef.current = false;
2997
2999
  }
2998
3000
  }, [initialQuery]);
3001
+ // Focus main input when parent signals (open panel, new chat, switch chat)
3002
+ React.useEffect(() => {
3003
+ if (focusChatNonce === undefined || focusChatNonce < 1)
3004
+ return;
3005
+ const id = window.setTimeout(() => {
3006
+ inputRef.current?.focus({ preventScroll: true });
3007
+ }, 0);
3008
+ return () => clearTimeout(id);
3009
+ }, [focusChatNonce, inputRef]);
2999
3010
  // Scrollbar styles - dynamically themed
3000
3011
  const scrollbarStyles = `
3001
3012
  .custom-scrollbar::-webkit-scrollbar {
@@ -3037,7 +3048,7 @@ additionalContext, }) {
3037
3048
  e.currentTarget.style.color = theme.colors.text.secondary;
3038
3049
  e.currentTarget.style.backgroundColor = theme.colors.surface.primary;
3039
3050
  e.currentTarget.style.borderColor = theme.colors.border.primary;
3040
- }, title: "Clear chat history", "aria-label": "Clear chat", children: [jsxRuntime.jsx(Icon, { name: "trash", size: "sm" }), "Clear Chat History"] }) })), showInput && (jsxRuntime.jsx("div", { style: { flexShrink: 0 }, children: jsxRuntime.jsx(ChatInput, { query: finalQuery, setQuery: finalSetQuery, onSend: finalOnSend, isLoading: isLoading, inputRef: React.useRef(null), attachedFiles: finalAttachedFiles, setAttachedFiles: finalSetAttachedFiles, models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features, currentModelSelection: currentModelSelection, onModelSelectionChange: handleModelSelectionChange, theme: theme, isOpen: true }) }))] })] }));
3051
+ }, title: "Clear chat history", "aria-label": "Clear chat", children: [jsxRuntime.jsx(Icon, { name: "trash", size: "sm" }), "Clear Chat History"] }) })), showInput && (jsxRuntime.jsx("div", { style: { flexShrink: 0 }, children: jsxRuntime.jsx(ChatInput, { query: finalQuery, setQuery: finalSetQuery, onSend: finalOnSend, isLoading: isLoading, inputRef: inputRef, attachedFiles: finalAttachedFiles, setAttachedFiles: finalSetAttachedFiles, models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features, currentModelSelection: currentModelSelection, onModelSelectionChange: handleModelSelectionChange, theme: theme, isOpen: true }) }))] })] }));
3041
3052
  }
3042
3053
  /**
3043
3054
  * ErrorDisplay component - used to display error messages
@@ -3367,6 +3378,14 @@ theme, isOpen, }) {
3367
3378
  onModelSelectionChange(modelInfo);
3368
3379
  }
3369
3380
  }, [onModelSelectionChange]);
3381
+ /** Ghost icon buttons — explicit reset so host app (e.g. MUI) button styles don’t add light fills. */
3382
+ const ghostIconBtnClass = 'inline-flex items-center justify-center w-9 h-9 shrink-0 rounded-md p-0 border-0 shadow-none !bg-transparent appearance-none transition-colors';
3383
+ const ghostIconBtnStyle = {
3384
+ backgroundColor: 'transparent',
3385
+ border: 'none',
3386
+ boxShadow: 'none',
3387
+ color: theme.colors.text.secondary,
3388
+ };
3370
3389
  return (jsxRuntime.jsxs("div", { className: `px-3 py-2 border-t flex flex-col gap-2 transition-all duration-500 delay-500 ${isOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`, style: { borderColor: theme.colors.border.primary }, children: [attachedFiles.length > 0 && (jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mb-2", children: attachedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: "relative group", children: [jsxRuntime.jsx("div", { className: "w-16 h-16 rounded-lg border border-gray-200 bg-gray-50 flex items-center justify-center overflow-hidden", children: file.type.startsWith('image/') ? (jsxRuntime.jsx("img", { src: URL.createObjectURL(file), alt: `Attached ${index + 1}`, className: "w-full h-full object-cover" })) : (jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: FileHandler.getFileIcon(file) })) }), jsxRuntime.jsx("button", { onClick: () => removeFile(index), className: "absolute -top-2 -right-2 w-5 h-5 bg-red-500 text-white rounded-full flex items-center justify-center text-xs hover:bg-red-600 transition-colors", title: "Remove file", children: "\u00D7" }), jsxRuntime.jsx("div", { className: "absolute bottom-0 left-1/2 transform -translate-x-1/2 translate-y-full opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none z-10 mt-2", children: jsxRuntime.jsxs("div", { className: "bg-gray-900 text-white text-xs rounded-lg px-2 py-1 whitespace-nowrap shadow-lg", children: [jsxRuntime.jsx("div", { className: "font-medium truncate max-w-32", title: file.name, children: file.name }), jsxRuntime.jsxs("div", { className: "text-gray-300", children: [FileHandler.getFileTypeDescription(file), " \u2022", ' ', FileHandler.formatFileSize(file.size)] }), jsxRuntime.jsx("div", { className: "absolute -top-1 left-1/2 transform -translate-x-1/2 w-2 h-2 bg-gray-900 rotate-45" })] }) })] }, index))) })), incompatibleFiles.length > 0 && (jsxRuntime.jsxs("div", { className: "relative flex flex-col gap-1 text-sm text-orange-700 bg-orange-50 border border-orange-200 rounded px-3 py-2 mb-2", children: [jsxRuntime.jsx("button", { onClick: () => setIncompatibleFiles([]), className: "absolute top-1 right-1 w-5 h-5 flex items-center justify-center text-orange-500 hover:text-orange-700 hover:bg-orange-200 rounded-full transition-colors", title: "Dismiss", type: "button", children: "\u00D7" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2 pr-6", children: [jsxRuntime.jsx("span", { children: "\u26A0\uFE0F" }), jsxRuntime.jsx("span", { className: "font-medium", children: incompatibleFiles.length === 1
3371
3390
  ? 'File not supported'
3372
3391
  : 'Some files not supported' })] }), jsxRuntime.jsxs("div", { className: "text-xs", children: [jsxRuntime.jsx("div", { className: "mb-1", children: "These files were skipped:" }), jsxRuntime.jsxs("ul", { className: "list-disc list-inside ml-2 space-y-0.5", children: [incompatibleFiles.slice(0, 3).map((fileName, index) => (jsxRuntime.jsx("li", { className: "truncate", children: fileName }, index))), incompatibleFiles.length > 3 && (jsxRuntime.jsxs("li", { children: ["... and ", incompatibleFiles.length - 3, " more"] }))] }), jsxRuntime.jsxs("div", { className: "mt-1 text-orange-600", children: ["\uD83D\uDCA1 Only ", FileHandler.getAcceptedTypesDescription(), " are supported", incompatibleFiles.some((name) => name.includes('images not supported by current model')) && (jsxRuntime.jsx("div", { className: "mt-1", children: "\uD83D\uDD04 Switch to a model showing the image icon in the model switcher to enable image uploads" }))] })] })] })), jsxRuntime.jsxs("div", { className: `relative flex flex-col gap-1 rounded border px-2 pt-1 pb-1 cursor-text transition-all duration-200 border-2 focus-within:shadow-sm ${isDragOver ? 'border-dashed bg-opacity-20' : 'border-transparent'}`, style: {
@@ -3383,21 +3402,30 @@ theme, isOpen, }) {
3383
3402
  }
3384
3403
  }, onClick: handleContainerClick, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [isDragOver && (jsxRuntime.jsx("div", { className: "absolute top-2 left-2 right-2 bottom-2 flex items-center justify-center py-1 bg-blue-100 rounded text-blue-600 text-sm font-medium z-10 pointer-events-none", children: "\uD83D\uDCC2 Drop files here" })), jsxRuntime.jsx("textarea", { ref: inputRef, value: query, onChange: (e) => setQuery(e.target.value), onFocus: () => setFocused(true), onBlur: () => setFocused(false), onKeyDown: (e) => e.key === 'Enter' && !e.shiftKey && (e.preventDefault(), onSend()), onPaste: handlePaste, placeholder: "Describe what you need... (Try: 'I want to know how much time has been updated')", className: "w-full outline-none resize-none min-h-[3.5rem] max-h-32 border-none px-0 bg-transparent", style: {
3385
3404
  color: theme.colors.text.primary,
3386
- }, rows: 3 }), jsxRuntime.jsxs("div", { className: "flex gap-2 items-center justify-between", children: [jsxRuntime.jsxs("div", { className: "flex gap-1", children: [features.fileUploads !== false && (jsxRuntime.jsx("button", { className: "p-1 cursor-pointer disabled:opacity-50 disabled:cursor-default transition-colors", style: { color: theme.colors.text.tertiary }, onMouseEnter: (e) => {
3387
- e.currentTarget.style.color = theme.colors.primary[500];
3405
+ }, rows: 3 }), jsxRuntime.jsxs("div", { className: "flex gap-2 items-center justify-between", children: [jsxRuntime.jsxs("div", { className: "flex gap-1", children: [features.fileUploads !== false && (jsxRuntime.jsx("button", { type: "button", className: `${ghostIconBtnClass} cursor-pointer disabled:cursor-not-allowed disabled:opacity-50`, style: ghostIconBtnStyle, onMouseEnter: (e) => {
3406
+ e.currentTarget.style.color = theme.colors.primary[400];
3407
+ e.currentTarget.style.backgroundColor = theme.colors.surface.secondary;
3388
3408
  }, onMouseLeave: (e) => {
3389
- e.currentTarget.style.color = theme.colors.text.tertiary;
3390
- }, title: `Attach files - Supports: ${FileHandler.getAcceptedTypesDescription()}`, tabIndex: -1, type: "button", onClick: () => fileInputRef.current?.click(), children: jsxRuntime.jsx(Icon, { name: "paperclip", size: "sm" }) })), features.enableImageUploads !== false &&
3391
- features.imageAnalysis !== false && (jsxRuntime.jsx("button", { className: `p-1 cursor-pointer disabled:opacity-50 disabled:cursor-default transition-colors ${!imageSupported ? 'opacity-50 cursor-not-allowed' : ''}`, style: { color: theme.colors.text.tertiary }, onMouseEnter: (e) => {
3409
+ e.currentTarget.style.color = theme.colors.text.secondary;
3410
+ e.currentTarget.style.backgroundColor = 'transparent';
3411
+ }, title: `Attach files - Supports: ${FileHandler.getAcceptedTypesDescription()}`, tabIndex: -1, onClick: () => fileInputRef.current?.click(), children: jsxRuntime.jsx(Icon, { name: "paperclip", size: "sm" }) })), features.enableImageUploads !== false &&
3412
+ features.imageAnalysis !== false && (jsxRuntime.jsx("button", { type: "button", className: `${ghostIconBtnClass} cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 ${!imageSupported ? 'opacity-50' : ''}`, style: ghostIconBtnStyle, onMouseEnter: (e) => {
3392
3413
  if (imageSupported) {
3393
- e.currentTarget.style.color = theme.colors.primary[500];
3414
+ e.currentTarget.style.color = theme.colors.primary[400];
3415
+ e.currentTarget.style.backgroundColor =
3416
+ theme.colors.surface.secondary;
3394
3417
  }
3395
3418
  }, onMouseLeave: (e) => {
3396
- e.currentTarget.style.color = theme.colors.text.tertiary;
3419
+ e.currentTarget.style.color = theme.colors.text.secondary;
3420
+ e.currentTarget.style.backgroundColor = 'transparent';
3397
3421
  }, title: imageSupported
3398
3422
  ? 'Attach images - AI can analyze image content'
3399
- : "Current model doesn't support images. Switch to GPT-4O, Claude, or Gemini to use image attachments.", tabIndex: -1, type: "button", onClick: () => imageSupported && imageInputRef.current?.click(), disabled: !imageSupported, children: jsxRuntime.jsx(Icon, { name: "image", size: "sm" }) })), jsxRuntime.jsx("button", { className: "p-1 cursor-pointer disabled:opacity-50 disabled:cursor-default transition-colors", style: { color: theme.colors.text.tertiary }, title: "Record audio (coming soon)", tabIndex: -1, type: "button", onClick: handleAudioRecord, disabled: true, children: jsxRuntime.jsx(Icon, { name: "microphone", size: "sm" }) })] }), jsxRuntime.jsx("button", { onClick: () => onSend(), disabled: (!query.trim() && attachedFiles.length === 0) || isLoading, className: "rounded-full transition disabled:opacity-50 p-2", style: {
3423
+ : "Current model doesn't support images. Switch to GPT-4O, Claude, or Gemini to use image attachments.", tabIndex: -1, onClick: () => imageSupported && imageInputRef.current?.click(), disabled: !imageSupported, children: jsxRuntime.jsx(Icon, { name: "image", size: "sm" }) })), jsxRuntime.jsx("button", { type: "button", className: `${ghostIconBtnClass} cursor-not-allowed opacity-50`, style: {
3424
+ ...ghostIconBtnStyle,
3425
+ color: theme.colors.text.tertiary,
3426
+ }, title: "Record audio (coming soon)", tabIndex: -1, onClick: handleAudioRecord, disabled: true, children: jsxRuntime.jsx(Icon, { name: "microphone", size: "sm" }) })] }), jsxRuntime.jsx("button", { type: "button", onClick: () => onSend(), disabled: (!query.trim() && attachedFiles.length === 0) || isLoading, className: "inline-flex shrink-0 items-center justify-center rounded-full border-0 p-2 shadow-none !bg-transparent transition-colors disabled:cursor-not-allowed disabled:opacity-50", style: {
3400
3427
  color: theme.colors.text.primary,
3428
+ backgroundColor: 'transparent',
3401
3429
  }, onMouseEnter: (e) => {
3402
3430
  if (!e.currentTarget.disabled) {
3403
3431
  e.currentTarget.style.backgroundColor =
@@ -3407,7 +3435,7 @@ theme, isOpen, }) {
3407
3435
  if (!e.currentTarget.disabled) {
3408
3436
  e.currentTarget.style.backgroundColor = 'transparent';
3409
3437
  }
3410
- }, title: "Send", tabIndex: -1, type: "button", children: jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("g", { clipPath: "url(#clip0_892_5571)", children: jsxRuntime.jsx("path", { d: "M13.3334 10.0001L10.0001 6.66675M10.0001 6.66675L6.66675 10.0001M10.0001 6.66675V13.3334M18.3334 10.0001C18.3334 14.6025 14.6025 18.3334 10.0001 18.3334C5.39771 18.3334 1.66675 14.6025 1.66675 10.0001C1.66675 5.39771 5.39771 1.66675 10.0001 1.66675C14.6025 1.66675 18.3334 5.39771 18.3334 10.0001Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }), jsxRuntime.jsx("defs", { children: jsxRuntime.jsx("clipPath", { id: "clip0_892_5571", children: jsxRuntime.jsx("rect", { width: "20", height: "20", fill: "white" }) }) })] }) })] })] }), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: FileHandler.getInputAcceptAttribute(), multiple: true, onChange: handleAllFileUpload, className: "hidden", "aria-label": "Upload any file" }), jsxRuntime.jsx("input", { ref: imageInputRef, type: "file", accept: "image/*", multiple: true, onChange: handleImageUpload, className: "hidden", "aria-label": "Upload images" }), features.modelSwitching !== false &&
3438
+ }, title: "Send", tabIndex: -1, children: jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("g", { clipPath: "url(#clip0_892_5571)", children: jsxRuntime.jsx("path", { d: "M13.3334 10.0001L10.0001 6.66675M10.0001 6.66675L6.66675 10.0001M10.0001 6.66675V13.3334M18.3334 10.0001C18.3334 14.6025 14.6025 18.3334 10.0001 18.3334C5.39771 18.3334 1.66675 14.6025 1.66675 10.0001C1.66675 5.39771 5.39771 1.66675 10.0001 1.66675C14.6025 1.66675 18.3334 5.39771 18.3334 10.0001Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }), jsxRuntime.jsx("defs", { children: jsxRuntime.jsx("clipPath", { id: "clip0_892_5571", children: jsxRuntime.jsx("rect", { width: "20", height: "20", fill: "white" }) }) })] }) })] })] }), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: FileHandler.getInputAcceptAttribute(), multiple: true, onChange: handleAllFileUpload, className: "hidden", "aria-label": "Upload any file" }), jsxRuntime.jsx("input", { ref: imageInputRef, type: "file", accept: "image/*", multiple: true, onChange: handleImageUpload, className: "hidden", "aria-label": "Upload images" }), features.modelSwitching !== false &&
3411
3439
  features.imageAnalysis !== false &&
3412
3440
  features.enableImageUploads !== false &&
3413
3441
  !imageSupported &&
@@ -3510,7 +3538,37 @@ showHistory = false, // Default to hidden
3510
3538
  showProfileBubbles = false, // Default to hidden
3511
3539
  modalPosition = 'left', // Default to left position
3512
3540
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features = {}, showFloatingButton = false, floatingButtonIcon, floatingButtonPosition = 'bottom-right', floatingButtonSize = 'md', floatingButtonClassName = '', chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon = 'command', // Default to bot icon
3513
- headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist you with your queries', onSuggestionSelect, overlayZIndex, }) {
3541
+ headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist you with your queries', onSuggestionSelect, overlayZIndex, expandOnHover = true, }) {
3542
+ const chatInputRef = React.useRef(null);
3543
+ const [focusChatNonce, setFocusChatNonce] = React.useState(0);
3544
+ /** Match original slide-out sizing (not the temporary wider caps). */
3545
+ const expandedWidthClass = showHistory
3546
+ ? 'w-[min(90vw,700px)] max-w-[700px]'
3547
+ : 'w-[min(80vw,550px)] max-w-[550px]';
3548
+ const panelRoundedClass = modalPosition === 'right' ? 'rounded-l-lg' : 'rounded-r-lg';
3549
+ // Focus the main input when the panel opens, chat switches, or new chat is selected
3550
+ React.useEffect(() => {
3551
+ if (!isOpen)
3552
+ return;
3553
+ setFocusChatNonce((n) => n + 1);
3554
+ }, [isOpen, currentChatId]);
3555
+ const handleCloseChat = React.useCallback((chatId) => {
3556
+ setChats?.((prev) => {
3557
+ const next = { ...prev };
3558
+ delete next[chatId];
3559
+ setCurrentChatId?.((cur) => {
3560
+ if (cur !== chatId)
3561
+ return cur;
3562
+ const keys = Object.keys(next).sort((a, b) => Number(b) - Number(a));
3563
+ if (keys.length)
3564
+ return keys[0];
3565
+ const nid = Date.now().toString();
3566
+ setChats?.((p) => ({ ...p, [nid]: [] }));
3567
+ return nid;
3568
+ });
3569
+ return next;
3570
+ });
3571
+ }, [setChats, setCurrentChatId]);
3514
3572
  const handleSuggestionClick = (s) => {
3515
3573
  if (onSuggestionSelect) {
3516
3574
  onSuggestionSelect(s);
@@ -3546,6 +3604,16 @@ headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist
3546
3604
  });
3547
3605
  }
3548
3606
  }, [isOpen, isVisible]);
3607
+ // If parent sets isOpen false without calling our handleClose, isVisible can stay true and
3608
+ // shouldRenderPanel keeps the fixed overlay mounted (e.g. stray strip during app loading).
3609
+ React.useEffect(() => {
3610
+ if (!isOpen && isVisible) {
3611
+ const id = window.setTimeout(() => {
3612
+ setIsVisible(false);
3613
+ }, 300);
3614
+ return () => window.clearTimeout(id);
3615
+ }
3616
+ }, [isOpen, isVisible]);
3549
3617
  // Handle closing animation
3550
3618
  const handleClose = React.useCallback(() => {
3551
3619
  if (!isAnimating) {
@@ -3680,105 +3748,143 @@ headerTitle = 'AI Logistics & Customs Expert', headerSubtitle = 'Ready to assist
3680
3748
  transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1);
3681
3749
  }
3682
3750
  `;
3683
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("style", { children: scrollbarStyles }), jsxRuntime.jsxs(ErrorBoundary, { children: [!isOpen && showFloatingButton && (jsxRuntime.jsx(FloatingChatButton, { onClick: handleOpen, theme: theme, icon: floatingButtonIcon, position: floatingButtonPosition, size: floatingButtonSize, className: floatingButtonClassName, zIndex: overlayZIndex })), shouldRenderPanel && (jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50", style: overlayZIndex !== undefined ? { zIndex: overlayZIndex } : undefined, children: [jsxRuntime.jsx("div", { className: `absolute inset-0 bg-black/20 transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0'}`, onClick: handleClose }), jsxRuntime.jsx("div", { className: `fixed z-[60] top-6 transition-all duration-300 ${isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-75'}`, style: { ...(modalPosition === 'left'
3684
- ? { left: showHistory ? 'min(90vw, 700px)' : 'min(80vw, 550px)', marginLeft: '16px' }
3685
- : { right: showHistory ? 'min(90vw, 700px)' : 'min(80vw, 550px)', marginRight: '16px' }) }, children: jsxRuntime.jsx("button", { onClick: handleClose, className: "w-10 h-10 rounded-full shadow-lg transition-all duration-200 flex items-center justify-center text-xl font-bold hover:scale-110", style: {
3686
- backgroundColor: finalTheme.colors.surface.elevated,
3687
- color: finalTheme.colors.text.secondary,
3688
- border: `2px solid ${finalTheme.colors.border.primary}`,
3689
- boxShadow: finalTheme.shadows.lg,
3690
- }, onMouseEnter: (e) => {
3691
- e.currentTarget.style.backgroundColor =
3692
- finalTheme.colors.surface.secondary;
3693
- e.currentTarget.style.color = finalTheme.colors.text.primary;
3694
- e.currentTarget.style.borderColor =
3695
- finalTheme.colors.border.secondary;
3696
- e.currentTarget.style.transform = 'scale(1.05)';
3697
- }, onMouseLeave: (e) => {
3698
- e.currentTarget.style.backgroundColor =
3699
- finalTheme.colors.surface.elevated;
3700
- e.currentTarget.style.color =
3701
- finalTheme.colors.text.secondary;
3702
- e.currentTarget.style.borderColor =
3703
- finalTheme.colors.border.primary;
3704
- e.currentTarget.style.transform = 'scale(1)';
3705
- }, title: "Close", children: "\u00D7" }) }), jsxRuntime.jsxs("div", { className: `fixed top-0 h-full w-full z-50 flex flex-col relative
3706
- ${modalPosition === 'left' ? 'left-0 rounded-r-lg' : 'right-0 rounded-l-lg'}
3707
- ${showHistory ? 'sm:w-[90vw] md:w-[700px]' : 'sm:w-[80vw] md:w-[550px]'}
3751
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("style", { children: scrollbarStyles }), jsxRuntime.jsxs(ErrorBoundary, { children: [!isOpen && showFloatingButton && (jsxRuntime.jsx(FloatingChatButton, { onClick: handleOpen, theme: theme, icon: floatingButtonIcon, position: floatingButtonPosition, size: floatingButtonSize, className: floatingButtonClassName, zIndex: overlayZIndex })), shouldRenderPanel && (jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50", style: overlayZIndex !== undefined ? { zIndex: overlayZIndex } : undefined, children: [jsxRuntime.jsx("div", { className: `absolute inset-0 bg-black/20 transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0'}`, onClick: handleClose }), jsxRuntime.jsx("div", { className: `fixed top-0 z-50 flex h-full min-h-0 flex-col overflow-hidden ${panelRoundedClass}
3752
+ ${expandedWidthClass}
3708
3753
  transition-all duration-300 ease-out
3709
3754
  ${getAnimationClasses()}
3755
+ ${modalPosition === 'left' ? 'left-0' : 'right-0'}
3710
3756
  `, style: {
3711
- backgroundColor: finalTheme.colors.background.primary,
3757
+ /* Chrome shell matches header + history; main chat column uses primary below */
3758
+ backgroundColor: finalTheme.colors.background.secondary,
3712
3759
  color: finalTheme.colors.text.primary,
3713
3760
  boxShadow: modalPosition === 'left'
3714
3761
  ? '8px 0 32px rgba(0, 0, 0, 0.3), 4px 0 16px rgba(0, 0, 0, 0.2)'
3715
3762
  : '-8px 0 32px rgba(0, 0, 0, 0.3), -4px 0 16px rgba(0, 0, 0, 0.2)',
3716
- }, ref: containerRef, onClick: (e) => e.stopPropagation(), children: [jsxRuntime.jsx("div", { className: `flex items-center justify-between px-6 py-4 border-b min-h-[72px] transition-all duration-500 delay-100 ${isOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-2'}`, style: {
3717
- borderColor: finalTheme.colors.border.primary,
3718
- backgroundColor: finalTheme.colors.background.primary,
3719
- }, children: jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [jsxRuntime.jsx("span", { className: `inline-flex items-center justify-center rounded-full w-8 h-8 transition-all duration-500 delay-200 ${isOpen ? 'opacity-100 scale-100 rotate-0' : 'opacity-0 scale-75 rotate-12'}`, style: { backgroundColor: finalTheme.colors.primary[600] }, children: typeof headerIcon === 'string' ? (jsxRuntime.jsx(Icon, { name: headerIcon, size: "sm", style: { color: finalTheme.colors.text.primary } })) : (headerIcon || (jsxRuntime.jsx(Icon, { name: "command", size: "sm", style: { color: finalTheme.colors.text.primary } }))) }), jsxRuntime.jsxs("div", { className: `transition-all duration-500 delay-300 ${isOpen ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-2'}`, children: [jsxRuntime.jsx("div", { className: "font-bold text-lg leading-tight", style: { color: finalTheme.colors.text.primary }, children: headerTitle }), jsxRuntime.jsx("div", { className: "text-xs", style: { color: finalTheme.colors.text.tertiary }, children: headerSubtitle })] })] }) }), jsxRuntime.jsxs("div", { className: `flex flex-1 min-h-0 h-full transition-all duration-500 delay-200 ${isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-95'}`, children: [showHistory && (jsxRuntime.jsx(ChatHistorySidebar, { chats: chats || {}, currentChatId: currentChatId || 'default', switchChat: handleHistorySwitchChat, newChat: handleHistoryNewChat, theme: finalTheme, isOpen: isOpen })), jsxRuntime.jsx("div", { className: "flex-1 flex flex-col min-h-0 h-full", children: jsxRuntime.jsx("div", { className: `flex-1 px-6 py-4 min-h-0 transition-all duration-500 delay-300 ${isOpen ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'}`, style: {
3763
+ }, ref: containerRef, onClick: (e) => e.stopPropagation(), children: jsxRuntime.jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col overflow-hidden", children: [jsxRuntime.jsxs("div", { className: `flex min-h-[72px] items-center justify-between border-b px-6 py-4 transition-all duration-500 delay-100 ${isOpen ? 'translate-y-0 opacity-100' : 'translate-y-2 opacity-0'}`, style: {
3764
+ borderColor: finalTheme.colors.border.primary,
3765
+ backgroundColor: finalTheme.colors.background.secondary,
3766
+ }, children: [jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [jsxRuntime.jsx("span", { className: `inline-flex h-8 w-8 items-center justify-center rounded-full transition-all duration-500 delay-200 ${isOpen ? 'rotate-0 scale-100 opacity-100' : 'rotate-12 scale-75 opacity-0'}`, style: {
3767
+ backgroundColor: finalTheme.colors.surface.tertiary,
3768
+ border: `1px solid ${finalTheme.colors.border.secondary}`,
3769
+ }, children: typeof headerIcon === 'string' ? (jsxRuntime.jsx(Icon, { name: headerIcon, size: "sm", style: { color: finalTheme.colors.primary[400] } })) : (headerIcon || (jsxRuntime.jsx(Icon, { name: "command", size: "sm", style: { color: finalTheme.colors.primary[400] } }))) }), jsxRuntime.jsxs("div", { className: `min-w-0 transition-all duration-500 delay-300 ${isOpen ? 'translate-x-0 opacity-100' : 'translate-x-2 opacity-0'}`, children: [jsxRuntime.jsx("div", { className: "text-lg font-bold leading-tight", style: { color: finalTheme.colors.text.primary }, children: headerTitle }), jsxRuntime.jsx("div", { className: "text-xs", style: { color: finalTheme.colors.text.tertiary }, children: headerSubtitle })] })] }), jsxRuntime.jsx("button", { type: "button", onClick: handleClose, className: "ml-2 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full text-xl font-bold transition-transform hover:scale-105", style: {
3770
+ backgroundColor: finalTheme.colors.surface.elevated,
3771
+ color: finalTheme.colors.text.secondary,
3772
+ border: `2px solid ${finalTheme.colors.border.primary}`,
3773
+ boxShadow: finalTheme.shadows?.lg,
3774
+ }, title: "Close", "aria-label": "Close chat panel", children: "\u00D7" })] }), jsxRuntime.jsxs("div", { className: `flex min-h-0 flex-1 flex-row transition-all duration-500 delay-200 ${isOpen ? 'scale-100 opacity-100' : 'scale-95 opacity-0'}`, children: [showHistory && (jsxRuntime.jsx(ChatHistorySidebar, { chats: chats || {}, currentChatId: currentChatId || 'default', switchChat: handleHistorySwitchChat, newChat: handleHistoryNewChat, onCloseChat: handleCloseChat, expandOnHover: expandOnHover, theme: finalTheme, isOpen: isOpen })), jsxRuntime.jsx("div", { className: `flex min-h-0 min-w-0 flex-1 flex-col ${showHistory ? 'border-l' : ''}`, style: {
3775
+ borderColor: showHistory
3776
+ ? finalTheme.colors.border.primary
3777
+ : undefined,
3720
3778
  backgroundColor: finalTheme.colors.background.primary,
3721
- }, children: jsxRuntime.jsx(Conversation, { onSuggestionClick: handleSuggestionClick, theme: finalTheme, showProfileBubbles: showProfileBubbles, autoScroll: true, showInput: true,
3722
- // AI functionality props
3723
- userId: userId, serverConfig: serverConfig, formData: formData, setFormState: setFormState, onNavigate: onNavigate, chatLevel: chatLevel,
3724
- // External chat management
3725
- chats: chats, setChats: setChats, currentChatId: currentChatId, setCurrentChatId: setCurrentChatId,
3726
- // Model configuration
3727
- models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features,
3728
- // Initial query handling
3729
- initialQuery: initialQuery, setInitialQuery: setInitialQuery }) }) })] })] })] }))] })] }));
3779
+ }, children: jsxRuntime.jsx("div", { className: `min-h-0 flex-1 px-6 py-4 transition-all duration-500 delay-300 ${isOpen ? 'translate-y-0 opacity-100' : 'translate-y-4 opacity-0'}`, children: jsxRuntime.jsx(Conversation, { onSuggestionClick: handleSuggestionClick, theme: finalTheme, showProfileBubbles: showProfileBubbles, autoScroll: true, showInput: true, userId: userId, serverConfig: serverConfig, formData: formData, setFormState: setFormState, onNavigate: onNavigate, chatLevel: chatLevel, chats: chats, setChats: setChats, currentChatId: currentChatId, setCurrentChatId: setCurrentChatId, models: models, defaultModel: defaultModel, showUsageStats: showUsageStats, maxFileSize: maxFileSize, features: features, initialQuery: initialQuery, setInitialQuery: setInitialQuery, chatInputRef: chatInputRef, focusChatNonce: focusChatNonce }) }) })] })] }) })] }))] })] }));
3730
3780
  }
3731
3781
  /**
3732
- * ChatHistorySidebar component with animation support
3782
+ * ChatHistorySidebar optional collapsed strip; expands on hover (or tap) for more room for the main chat.
3733
3783
  */
3734
- function ChatHistorySidebar({ chats, currentChatId, switchChat, newChat, theme, isOpen, }) {
3735
- return (jsxRuntime.jsx("div", { className: `flex-shrink-0 flex-grow-0 border-r flex flex-col h-full p-2 w-[150px] transition-all duration-500 delay-400 ${isOpen ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-4'}`, style: {
3784
+ function ChatHistorySidebar({ chats, currentChatId, switchChat, newChat, onCloseChat, expandOnHover = true, theme, isOpen, }) {
3785
+ const [historyExpanded, setHistoryExpanded] = React.useState(false);
3786
+ const leaveTimerRef = React.useRef(null);
3787
+ React.useEffect(() => {
3788
+ if (!isOpen)
3789
+ setHistoryExpanded(false);
3790
+ }, [isOpen]);
3791
+ const clearLeaveTimer = React.useCallback(() => {
3792
+ if (leaveTimerRef.current != null) {
3793
+ clearTimeout(leaveTimerRef.current);
3794
+ leaveTimerRef.current = null;
3795
+ }
3796
+ }, []);
3797
+ React.useEffect(() => () => clearLeaveTimer(), [clearLeaveTimer]);
3798
+ const handleSidebarEnter = React.useCallback(() => {
3799
+ clearLeaveTimer();
3800
+ if (expandOnHover)
3801
+ setHistoryExpanded(true);
3802
+ }, [expandOnHover, clearLeaveTimer]);
3803
+ const handleSidebarLeave = React.useCallback(() => {
3804
+ if (!expandOnHover)
3805
+ return;
3806
+ clearLeaveTimer();
3807
+ leaveTimerRef.current = setTimeout(() => {
3808
+ setHistoryExpanded(false);
3809
+ leaveTimerRef.current = null;
3810
+ }, 220);
3811
+ }, [expandOnHover, clearLeaveTimer]);
3812
+ const listExpanded = !expandOnHover || historyExpanded;
3813
+ const widthClass = expandOnHover
3814
+ ? listExpanded
3815
+ ? 'w-[min(52vw,220px)] max-w-[220px]'
3816
+ : 'w-14'
3817
+ : 'w-[150px]';
3818
+ const chatRows = Object.keys(chats)
3819
+ .sort((a, b) => Number(b) - Number(a))
3820
+ .map((chatId) => (jsxRuntime.jsxs("div", { className: "flex w-full cursor-pointer items-center gap-1 rounded-full px-2 py-2 transition-colors", style: {
3821
+ backgroundColor: chatId === currentChatId
3822
+ ? theme.colors.primary[900]
3823
+ : 'transparent',
3824
+ color: chatId === currentChatId
3825
+ ? theme.colors.primary[100]
3826
+ : theme.colors.text.secondary,
3827
+ fontWeight: chatId === currentChatId ? 'bold' : 'normal',
3828
+ }, onMouseEnter: (e) => {
3829
+ if (chatId !== currentChatId) {
3830
+ e.currentTarget.style.backgroundColor = theme.colors.surface.secondary;
3831
+ }
3832
+ }, onMouseLeave: (e) => {
3833
+ if (chatId !== currentChatId) {
3834
+ e.currentTarget.style.backgroundColor = 'transparent';
3835
+ }
3836
+ }, onClick: () => switchChat(chatId), title: (chats[chatId]?.[0]
3837
+ ? getTextFromMessage(chats[chatId][0])
3838
+ : '')?.slice(0, 30) ||
3839
+ `Chat started at ${new Date(Number(chatId)).toLocaleString()}`, children: [jsxRuntime.jsx("span", { className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full", style: {
3840
+ backgroundColor: theme.colors.surface.secondary,
3841
+ color: theme.colors.primary[400],
3842
+ }, children: jsxRuntime.jsx("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: jsxRuntime.jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) }), jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntime.jsx("div", { className: "truncate font-semibold", children: (chats[chatId]?.[0]
3843
+ ? getTextFromMessage(chats[chatId][0])
3844
+ : '')?.slice(0, 18) || 'New chat' }), jsxRuntime.jsx("div", { className: "text-xs", style: { color: theme.colors.text.tertiary }, children: (() => {
3845
+ const now = Date.now();
3846
+ const diff = Math.floor((now - Number(chatId)) / 1000);
3847
+ if (diff < 60)
3848
+ return 'Just now';
3849
+ if (diff < 3600)
3850
+ return `${Math.floor(diff / 60)}m ago`;
3851
+ if (diff < 86400)
3852
+ return `${Math.floor(diff / 3600)}h ago`;
3853
+ return `${Math.floor(diff / 86400)}d ago`;
3854
+ })() })] }), onCloseChat && (jsxRuntime.jsx("button", { type: "button", className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-md text-base font-semibold leading-none transition-colors", style: {
3855
+ color: theme.colors.text.primary,
3856
+ backgroundColor: theme.colors.surface.secondary,
3857
+ border: `1px solid ${theme.colors.border.secondary}`,
3858
+ }, title: "Close chat", "aria-label": "Close chat", onClick: (e) => {
3859
+ e.stopPropagation();
3860
+ onCloseChat(chatId);
3861
+ }, onMouseEnter: (e) => {
3862
+ e.currentTarget.style.backgroundColor = theme.colors.surface.tertiary;
3863
+ }, onMouseLeave: (e) => {
3864
+ e.currentTarget.style.backgroundColor = theme.colors.surface.secondary;
3865
+ }, children: "\u00D7" }))] }, chatId)));
3866
+ return (jsxRuntime.jsx("div", { className: `flex h-full flex-shrink-0 flex-grow-0 flex-col overflow-hidden border-r transition-[width] duration-300 ease-out ${isOpen ? 'translate-x-0 opacity-100' : 'translate-x-4 opacity-0'} ${widthClass}`, style: {
3736
3867
  backgroundColor: theme.colors.background.secondary,
3737
3868
  borderColor: theme.colors.border.primary,
3738
- }, children: jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto flex flex-col items-center gap-2 p-2 custom-scrollbar", children: [jsxRuntime.jsx("button", { className: "rounded-lg w-full py-2 font-bold text-xl mb-2 shadow transition-colors", style: {
3739
- backgroundColor: theme.colors.primary[600],
3740
- color: theme.colors.text.inverse,
3741
- borderColor: theme.colors.primary[700],
3742
- }, onMouseEnter: (e) => {
3743
- e.currentTarget.style.backgroundColor = theme.colors.primary[700];
3744
- }, onMouseLeave: (e) => {
3745
- e.currentTarget.style.backgroundColor = theme.colors.primary[600];
3746
- }, onClick: newChat, children: "+" }), Object.keys(chats)
3747
- .sort((a, b) => Number(b) - Number(a))
3748
- .map((chatId) => (jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 rounded-lg cursor-pointer transition-colors w-full", style: {
3749
- backgroundColor: chatId === currentChatId
3750
- ? theme.colors.primary[900]
3751
- : theme.colors.surface.primary,
3752
- color: chatId === currentChatId
3753
- ? theme.colors.primary[100]
3754
- : theme.colors.text.secondary,
3755
- fontWeight: chatId === currentChatId ? 'bold' : 'normal',
3756
- }, onMouseEnter: (e) => {
3757
- if (chatId !== currentChatId) {
3758
- e.currentTarget.style.backgroundColor =
3759
- theme.colors.surface.secondary;
3760
- }
3761
- }, onMouseLeave: (e) => {
3762
- if (chatId !== currentChatId) {
3763
- e.currentTarget.style.backgroundColor =
3764
- theme.colors.surface.primary;
3765
- }
3766
- }, onClick: () => switchChat(chatId), title: (chats[chatId]?.[0]
3767
- ? getTextFromMessage(chats[chatId][0])
3768
- : '')?.slice(0, 30) ||
3769
- `Chat started at ${new Date(Number(chatId)).toLocaleString()}`, children: [jsxRuntime.jsx("span", { className: "flex items-center justify-center w-7 h-7 rounded-full bg-blue-50", children: jsxRuntime.jsx("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: jsxRuntime.jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsx("div", { className: "truncate font-semibold", children: (chats[chatId]?.[0]
3770
- ? getTextFromMessage(chats[chatId][0])
3771
- : '')?.slice(0, 18) || 'New chat' }), jsxRuntime.jsx("div", { className: "text-xs text-gray-400", children: (() => {
3772
- const now = Date.now();
3773
- const diff = Math.floor((now - Number(chatId)) / 1000);
3774
- if (diff < 60)
3775
- return 'Just now';
3776
- if (diff < 3600)
3777
- return `${Math.floor(diff / 60)}m ago`;
3778
- if (diff < 86400)
3779
- return `${Math.floor(diff / 3600)}h ago`;
3780
- return `${Math.floor(diff / 86400)}d ago`;
3781
- })() })] })] }, chatId)))] }) }));
3869
+ }, onMouseEnter: handleSidebarEnter, onMouseLeave: handleSidebarLeave, children: expandOnHover && !listExpanded ? (jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-center gap-2 px-1 py-3", children: [jsxRuntime.jsx("button", { type: "button", className: "inline-flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full text-xl font-bold transition-colors", style: {
3870
+ backgroundColor: theme.colors.surface.tertiary,
3871
+ color: theme.colors.primary[400],
3872
+ border: `1px solid ${theme.colors.border.secondary}`,
3873
+ }, title: "New chat", "aria-label": "New chat", onClick: () => {
3874
+ newChat();
3875
+ setHistoryExpanded(true);
3876
+ }, children: "+" }), jsxRuntime.jsx("button", { type: "button", className: "inline-flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full transition-transform hover:scale-105", style: {
3877
+ backgroundColor: theme.colors.surface.tertiary,
3878
+ border: `1px solid ${theme.colors.border.secondary}`,
3879
+ }, title: "Open chat history", "aria-label": "Open chat history", onClick: () => setHistoryExpanded(true), children: jsxRuntime.jsx("svg", { width: "18", height: "18", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", style: { color: theme.colors.primary[400] }, children: jsxRuntime.jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) })] })) : (jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1 flex-col p-2", children: jsxRuntime.jsxs("div", { className: "custom-scrollbar flex flex-1 flex-col items-center gap-2 overflow-y-auto p-2", children: [jsxRuntime.jsx("button", { className: "mb-2 w-full rounded-full py-2 text-xl font-bold shadow transition-colors", style: {
3880
+ backgroundColor: theme.colors.primary[600],
3881
+ color: theme.colors.text.inverse,
3882
+ borderColor: theme.colors.primary[700],
3883
+ }, onMouseEnter: (e) => {
3884
+ e.currentTarget.style.backgroundColor = theme.colors.primary[700];
3885
+ }, onMouseLeave: (e) => {
3886
+ e.currentTarget.style.backgroundColor = theme.colors.primary[600];
3887
+ }, onClick: newChat, children: "+" }), chatRows] }) })) }));
3782
3888
  }
3783
3889
  /**
3784
3890
  * FloatingChatButton component
@@ -60,6 +60,12 @@ interface ChatPanelProps {
60
60
  * (e.g. MUI AppBar ~1100, custom sidebars ~999). Default Tailwind z-50 is too low for many shells.
61
61
  */
62
62
  overlayZIndex?: number;
63
+ /**
64
+ * When true (default) and `showHistory` is on, only the chat history column is a narrow strip
65
+ * until hover (or tap) expands it; the main conversation area stays full width.
66
+ * Set to false to keep the history sidebar always fully expanded (~150px).
67
+ */
68
+ expandOnHover?: boolean;
63
69
  }
64
70
  /**
65
71
  * ChatPanel component
@@ -98,7 +104,7 @@ showHistory, // Default to hidden
98
104
  showProfileBubbles, // Default to hidden
99
105
  modalPosition, // Default to left position
100
106
  serverConfig, models, defaultModel, showUsageStats, maxFileSize, features, showFloatingButton, floatingButtonIcon, floatingButtonPosition, floatingButtonSize, floatingButtonClassName, chats, setChats, currentChatId, setCurrentChatId, chatLevel, initialQuery, setInitialQuery, headerIcon, // Default to bot icon
101
- headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
107
+ headerTitle, headerSubtitle, onSuggestionSelect, overlayZIndex, expandOnHover, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
102
108
  /**
103
109
  * ChatInput component
104
110
  * @param query - The current query
@@ -61,6 +61,10 @@ interface ConversationProps {
61
61
  showClearChat?: boolean;
62
62
  onClearChat?: () => void;
63
63
  additionalContext?: string | Record<string, unknown>;
64
+ /** Optional ref to the main chat textarea (for parent focus control). */
65
+ chatInputRef?: React.RefObject<HTMLTextAreaElement | null>;
66
+ /** Increment to move focus to the main input (panel open, chat switch, new chat). */
67
+ focusChatNonce?: number;
64
68
  }
65
69
  /**
66
70
  * Conversation component - displays a single chat conversation
@@ -72,5 +76,5 @@ interface ConversationProps {
72
76
  * @param autoScroll - Whether to auto-scroll to bottom on new messages
73
77
  * @param maxHeight - Maximum height of the conversation container
74
78
  */
75
- export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
79
+ export declare function Conversation({ chat: externalChat, onSuggestionClick, theme, showProfileBubbles, className, autoScroll, maxHeight, userId, serverConfig, formData, chatLevel, chats: externalChats, setChats: externalSetChats, currentChatId: externalCurrentChatId, setCurrentChatId: externalSetCurrentChatId, query: externalQuery, setQuery: externalSetQuery, onSend: externalOnSend, isLoading: externalIsLoading, attachedFiles: externalAttachedFiles, setAttachedFiles: externalSetAttachedFiles, models, defaultModel, showUsageStats, maxFileSize, features, currentModelSelection: externalCurrentModelSelection, onModelSelectionChange: externalOnModelSelectionChange, showInput, initialQuery, setInitialQuery, showClearChat, onClearChat, additionalContext, chatInputRef: externalChatInputRef, focusChatNonce, }: ConversationProps): import("react/jsx-runtime").JSX.Element;
76
80
  export {};
package/dist/styles.css CHANGED
@@ -1,2 +1,2 @@
1
- *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.-right-2{right:-.5rem}.-top-1{top:-.25rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-2{bottom:.5rem}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:.5rem}.left-6{left:1.5rem}.left-\[0\.5px\]{left:.5px}.right-0{right:0}.right-1{right:.25rem}.right-2{right:.5rem}.right-4{right:1rem}.right-6{right:1.5rem}.right-\[-4px\]{right:-4px}.right-full{right:100%}.top-0{top:0}.top-1{top:.25rem}.top-2{top:.5rem}.top-4{top:1rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-50{z-index:50}.z-\[10000\]{z-index:10000}.z-\[60\]{z-index:60}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.line-clamp-2{-webkit-box-orient:vertical;-webkit-line-clamp:2;display:-webkit-box;overflow:hidden}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.contents{display:contents}.hidden{display:none}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-full{height:100%}.max-h-32{max-height:8rem}.max-h-64{max-height:16rem}.max-h-80{max-height:20rem}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-\[3\.5rem\]{min-height:3.5rem}.min-h-\[72px\]{min-height:72px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-\[150px\]{width:150px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-80{min-width:20rem}.max-w-32{max-width:8rem}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow-0{flex-grow:0}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-2{--tw-translate-x:0.5rem}.translate-x-4{--tw-translate-x:1rem}.translate-x-4,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x:100%}.translate-y-0{--tw-translate-y:0px}.translate-y-0,.translate-y-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-2{--tw-translate-y:0.5rem}.translate-y-4{--tw-translate-y:1rem}.translate-y-4,.translate-y-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-full{--tw-translate-y:100%}.rotate-0{--tw-rotate:0deg}.rotate-0,.rotate-12{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-12{--tw-rotate:12deg}.rotate-180{--tw-rotate:180deg}.rotate-180,.rotate-45{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-45{--tw-rotate:45deg}.rotate-90{--tw-rotate:90deg}.rotate-90,.scale-100{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.scale-75{--tw-scale-x:.75;--tw-scale-y:.75}.scale-75,.scale-95{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-95{--tw-scale-x:.95;--tw-scale-y:.95}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.resize-none{resize:none}.resize{resize:both}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.125rem*var(--tw-space-y-reverse));margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-l-lg{border-bottom-left-radius:.5rem;border-top-left-radius:.5rem}.rounded-r-lg{border-bottom-right-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity,1))}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.border-current{border-color:currentColor}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-orange-200{--tw-border-opacity:1;border-color:rgb(254 215 170/var(--tw-border-opacity,1))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.border-yellow-200{--tw-border-opacity:1;border-color:rgb(254 240 138/var(--tw-border-opacity,1))}.border-opacity-50{--tw-border-opacity:0.5}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/70{background-color:rgba(0,0,0,.7)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-orange-100{--tw-bg-opacity:1;background-color:rgb(255 237 213/var(--tw-bg-opacity,1))}.bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity,1))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-white\/10{background-color:hsla(0,0%,100%,.1)}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity,1))}.bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity,1))}.bg-opacity-20{--tw-bg-opacity:0.2}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-bottom:.125rem;padding-top:.125rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pr-4{padding-right:1rem}.pr-6{padding-right:1.5rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-amber-700{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity,1))}.text-orange-700{--tw-text-opacity:1;color:rgb(194 65 12/var(--tw-text-opacity,1))}.text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity,1))}.text-purple-600{--tw-text-opacity:1;color:rgb(147 51 234/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.text-red-800{--tw-text-opacity:1;color:rgb(153 27 27/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/70{color:hsla(0,0%,100%,.7)}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.text-yellow-700{--tw-text-opacity:1;color:rgb(161 98 7/var(--tw-text-opacity,1))}.text-yellow-800{--tw-text-opacity:1;color:rgb(133 77 14/var(--tw-text-opacity,1))}.line-through{text-decoration-line:line-through}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.delay-100{transition-delay:.1s}.delay-200{transition-delay:.2s}.delay-300{transition-delay:.3s}.delay-500{transition-delay:.5s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus-within\:shadow-sm:focus-within{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:bg-amber-200:hover{--tw-bg-opacity:1;background-color:rgb(253 230 138/var(--tw-bg-opacity,1))}.hover\:bg-black\/70:hover{background-color:rgba(0,0,0,.7)}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-orange-200:hover{--tw-bg-opacity:1;background-color:rgb(254 215 170/var(--tw-bg-opacity,1))}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-white\/20:hover{background-color:hsla(0,0%,100%,.2)}.hover\:text-amber-700:hover{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.hover\:text-blue-500:hover{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.hover\:text-orange-700:hover{--tw-text-opacity:1;color:rgb(194 65 12/var(--tw-text-opacity,1))}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-xl:hover{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(191 219 254/var(--tw-ring-opacity,1))}.active\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:w-\[80vw\]{width:80vw}.sm\:w-\[90vw\]{width:90vw}}@media (min-width:768px){.md\:w-\[550px\]{width:550px}.md\:w-\[700px\]{width:700px}}
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.-right-2{right:-.5rem}.-top-1{top:-.25rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-2{bottom:.5rem}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:.5rem}.left-6{left:1.5rem}.left-\[0\.5px\]{left:.5px}.right-0{right:0}.right-1{right:.25rem}.right-2{right:.5rem}.right-4{right:1rem}.right-6{right:1.5rem}.right-\[-4px\]{right:-4px}.right-full{right:100%}.top-0{top:0}.top-1{top:.25rem}.top-2{top:.5rem}.top-4{top:1rem}.top-6{top:1.5rem}.z-10{z-index:10}.z-50{z-index:50}.z-\[10000\]{z-index:10000}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.line-clamp-2{-webkit-box-orient:vertical;-webkit-line-clamp:2;display:-webkit-box;overflow:hidden}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.contents{display:contents}.hidden{display:none}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-full{height:100%}.max-h-32{max-height:8rem}.max-h-64{max-height:16rem}.max-h-80{max-height:20rem}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-\[3\.5rem\]{min-height:3.5rem}.min-h-\[72px\]{min-height:72px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[150px\]{width:150px}.w-\[min\(52vw\2c 220px\)\]{width:min(52vw,220px)}.w-\[min\(80vw\2c 550px\)\]{width:min(80vw,550px)}.w-\[min\(90vw\2c 700px\)\]{width:min(90vw,700px)}.w-full{width:100%}.min-w-0{min-width:0}.min-w-80{min-width:20rem}.max-w-32{max-width:8rem}.max-w-\[220px\]{max-width:220px}.max-w-\[550px\]{max-width:550px}.max-w-\[700px\]{max-width:700px}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow-0{flex-grow:0}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-2{--tw-translate-x:0.5rem}.translate-x-4{--tw-translate-x:1rem}.translate-x-4,.translate-x-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x:100%}.translate-y-0{--tw-translate-y:0px}.translate-y-0,.translate-y-2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-2{--tw-translate-y:0.5rem}.translate-y-4{--tw-translate-y:1rem}.translate-y-4,.translate-y-full{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-full{--tw-translate-y:100%}.rotate-0{--tw-rotate:0deg}.rotate-0,.rotate-12{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-12{--tw-rotate:12deg}.rotate-180{--tw-rotate:180deg}.rotate-180,.rotate-45{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-45{--tw-rotate:45deg}.rotate-90{--tw-rotate:90deg}.rotate-90,.scale-100{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.scale-75{--tw-scale-x:.75;--tw-scale-y:.75}.scale-75,.scale-95{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-95{--tw-scale-x:.95;--tw-scale-y:.95}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.resize-none{resize:none}.resize{resize:both}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.125rem*var(--tw-space-y-reverse));margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-l-lg{border-bottom-left-radius:.5rem;border-top-left-radius:.5rem}.rounded-r-lg{border-bottom-right-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity,1))}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity,1))}.border-current{border-color:currentColor}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1))}.border-orange-200{--tw-border-opacity:1;border-color:rgb(254 215 170/var(--tw-border-opacity,1))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.border-yellow-200{--tw-border-opacity:1;border-color:rgb(254 240 138/var(--tw-border-opacity,1))}.border-opacity-50{--tw-border-opacity:0.5}.\!bg-transparent{background-color:transparent!important}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/70{background-color:rgba(0,0,0,.7)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity,1))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity,1))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-orange-100{--tw-bg-opacity:1;background-color:rgb(255 237 213/var(--tw-bg-opacity,1))}.bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity,1))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-white\/10{background-color:hsla(0,0%,100%,.1)}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(254 249 195/var(--tw-bg-opacity,1))}.bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity,1))}.bg-opacity-20{--tw-bg-opacity:0.2}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-0{padding-left:0;padding-right:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-bottom:.125rem;padding-top:.125rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pr-4{padding-right:1rem}.pr-6{padding-right:1.5rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-amber-700{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-blue-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-orange-500{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity,1))}.text-orange-600{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity,1))}.text-orange-700{--tw-text-opacity:1;color:rgb(194 65 12/var(--tw-text-opacity,1))}.text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity,1))}.text-purple-600{--tw-text-opacity:1;color:rgb(147 51 234/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.text-red-800{--tw-text-opacity:1;color:rgb(153 27 27/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/70{color:hsla(0,0%,100%,.7)}.text-yellow-600{--tw-text-opacity:1;color:rgb(202 138 4/var(--tw-text-opacity,1))}.text-yellow-700{--tw-text-opacity:1;color:rgb(161 98 7/var(--tw-text-opacity,1))}.text-yellow-800{--tw-text-opacity:1;color:rgb(133 77 14/var(--tw-text-opacity,1))}.line-through{text-decoration-line:line-through}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-\[width\]{transition-duration:.15s;transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.delay-100{transition-delay:.1s}.delay-200{transition-delay:.2s}.delay-300{transition-delay:.3s}.delay-500{transition-delay:.5s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.focus-within\:shadow-sm:focus-within{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:bg-amber-200:hover{--tw-bg-opacity:1;background-color:rgb(253 230 138/var(--tw-bg-opacity,1))}.hover\:bg-black\/70:hover{background-color:rgba(0,0,0,.7)}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-orange-200:hover{--tw-bg-opacity:1;background-color:rgb(254 215 170/var(--tw-bg-opacity,1))}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-white\/20:hover{background-color:hsla(0,0%,100%,.2)}.hover\:text-amber-700:hover{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.hover\:text-blue-500:hover{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.hover\:text-orange-700:hover{--tw-text-opacity:1;color:rgb(194 65 12/var(--tw-text-opacity,1))}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-xl:hover{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(191 219 254/var(--tw-ring-opacity,1))}.active\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:opacity-100{opacity:1}
2
2
  /*# sourceMappingURL=styles.css.map */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchid-ai",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "type": "module",
5
5
  "description": "AI-powered command processing and chat interface for React applications",
6
6
  "main": "dist/index.js",