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.
- package/dist/cli/components/ChatPanel.d.ts +7 -1
- package/dist/cli/components/Conversation.d.ts +5 -1
- package/dist/components/ChatPanel.d.ts +7 -1
- package/dist/components/Conversation.d.ts +5 -1
- package/dist/index.esm.js +204 -98
- package/dist/index.js +204 -98
- package/dist/server/components/ChatPanel.d.ts +7 -1
- package/dist/server/components/Conversation.d.ts +5 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -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:
|
|
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", {
|
|
3385
|
-
e.currentTarget.style.color = theme.colors.primary[
|
|
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.
|
|
3388
|
-
|
|
3389
|
-
|
|
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[
|
|
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.
|
|
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,
|
|
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,
|
|
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
|
|
3682
|
-
|
|
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
|
-
|
|
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: [
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
3737
|
-
backgroundColor: theme.colors.
|
|
3738
|
-
color: theme.colors.
|
|
3739
|
-
|
|
3740
|
-
},
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
: theme.colors.
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
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:
|
|
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", {
|
|
3387
|
-
e.currentTarget.style.color = theme.colors.primary[
|
|
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.
|
|
3390
|
-
|
|
3391
|
-
|
|
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[
|
|
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.
|
|
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,
|
|
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,
|
|
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
|
|
3684
|
-
|
|
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
|
-
|
|
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.
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
3739
|
-
backgroundColor: theme.colors.
|
|
3740
|
-
color: theme.colors.
|
|
3741
|
-
|
|
3742
|
-
},
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
.
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
: theme.colors.
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
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 */
|