"use client"; import { useMemo, useState } from "react"; import { TooltipProvider } from "@/components/ui/tooltip"; import type { InboxItem } from "@/hooks/use-inbox"; import { useIsMobile } from "@/hooks/use-mobile"; import { cn } from "@/lib/utils"; import { SidebarProvider, useSidebarState } from "../../hooks"; import { useSidebarResize } from "../../hooks/useSidebarResize"; import type { ChatItem, NavItem, PageUsage, SearchSpace, User } from "../../types/layout.types"; import { Header } from "../header"; import { IconRail } from "../icon-rail"; import { AllPrivateChatsSidebar, AllSharedChatsSidebar, InboxSidebar, MobileSidebar, MobileSidebarTrigger, Sidebar, } from "../sidebar"; // Tab-specific data source props interface TabDataSource { items: InboxItem[]; unreadCount: number; loading: boolean; loadingMore?: boolean; hasMore?: boolean; loadMore?: () => void; } // Inbox-related props with separate data sources per tab interface InboxProps { isOpen: boolean; onOpenChange: (open: boolean) => void; /** Mentions tab data source with independent pagination */ mentions: TabDataSource; /** Status tab data source with independent pagination */ status: TabDataSource; /** Combined unread count for nav badge */ totalUnreadCount: number; markAsRead: (id: number) => Promise; markAllAsRead: () => Promise; /** Whether the inbox is docked (permanent) */ isDocked?: boolean; /** Callback to change docked state */ onDockedChange?: (docked: boolean) => void; } interface LayoutShellProps { searchSpaces: SearchSpace[]; activeSearchSpaceId: number | null; onSearchSpaceSelect: (id: number) => void; onSearchSpaceDelete?: (searchSpace: SearchSpace) => void; onSearchSpaceSettings?: (searchSpace: SearchSpace) => void; onAddSearchSpace: () => void; searchSpace: SearchSpace | null; navItems: NavItem[]; onNavItemClick?: (item: NavItem) => void; chats: ChatItem[]; sharedChats?: ChatItem[]; activeChatId?: number | null; onNewChat: () => void; onChatSelect: (chat: ChatItem) => void; onChatRename?: (chat: ChatItem) => void; onChatDelete?: (chat: ChatItem) => void; onChatArchive?: (chat: ChatItem) => void; onViewAllSharedChats?: () => void; onViewAllPrivateChats?: () => void; user: User; onSettings?: () => void; onManageMembers?: () => void; onUserSettings?: () => void; onLogout?: () => void; pageUsage?: PageUsage; breadcrumb?: React.ReactNode; theme?: string; setTheme?: (theme: "light" | "dark" | "system") => void; defaultCollapsed?: boolean; isChatPage?: boolean; children: React.ReactNode; className?: string; // Inbox props inbox?: InboxProps; isLoadingChats?: boolean; // All chats panel props allSharedChatsPanel?: { open: boolean; onOpenChange: (open: boolean) => void; searchSpaceId: string; }; allPrivateChatsPanel?: { open: boolean; onOpenChange: (open: boolean) => void; searchSpaceId: string; }; } export function LayoutShell({ searchSpaces, activeSearchSpaceId, onSearchSpaceSelect, onSearchSpaceDelete, onSearchSpaceSettings, onAddSearchSpace, searchSpace, navItems, onNavItemClick, chats, sharedChats, activeChatId, onNewChat, onChatSelect, onChatRename, onChatDelete, onChatArchive, onViewAllSharedChats, onViewAllPrivateChats, user, onSettings, onManageMembers, onUserSettings, onLogout, pageUsage, breadcrumb, theme, setTheme, defaultCollapsed = false, isChatPage = false, children, className, inbox, isLoadingChats = false, allSharedChatsPanel, allPrivateChatsPanel, }: LayoutShellProps) { const isMobile = useIsMobile(); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const { isCollapsed, setIsCollapsed, toggleCollapsed } = useSidebarState(defaultCollapsed); const { sidebarWidth, handleMouseDown: onResizeMouseDown, isDragging: isResizing, } = useSidebarResize(); // Memoize context value to prevent unnecessary re-renders const sidebarContextValue = useMemo( () => ({ isCollapsed, setIsCollapsed, toggleCollapsed, sidebarWidth }), [isCollapsed, setIsCollapsed, toggleCollapsed, sidebarWidth] ); // Mobile layout if (isMobile) { return (
setMobileMenuOpen(true)} />} />
{children}
{/* Mobile Inbox Sidebar - only render when open to avoid scroll blocking */} {inbox?.isOpen && ( setMobileMenuOpen(false)} /> )} {/* Mobile All Shared Chats - slide-out panel */} {allSharedChatsPanel && ( setMobileMenuOpen(false)} /> )} {/* Mobile All Private Chats - slide-out panel */} {allPrivateChatsPanel && ( setMobileMenuOpen(false)} /> )}
); } // Desktop layout return (
{/* Main container with sidebar and content - relative for inbox positioning */}
{/* Docked Inbox Sidebar - renders as flex sibling between sidebar and content */} {inbox?.isDocked && ( )}
{children}
{/* Floating Inbox Sidebar - positioned absolutely on top of content */} {inbox && !inbox.isDocked && ( )} {/* All Shared Chats - slide-out panel */} {allSharedChatsPanel && ( )} {/* All Private Chats - slide-out panel */} {allPrivateChatsPanel && ( )}
); }