import { AnimatePresence, motion } from 'framer-motion' import { Home, MessageCirclePlus, NotebookText, Plus, SquareCode } from 'lucide-react' import { ComponentProps, ReactNode, useEffect, useEffectEvent, useState } from 'react' import { cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, TabsTrigger, } from 'ui' import { ProjectLayoutWithAuth } from '../ProjectLayout' import { EditorTabs } from '../Tabs/Tabs' import { type ExplorerResourceType } from './ExplorerLayout.constants' import { ExplorerNavChats } from './ExplorerNavChats' import { ExplorerNavHeader } from './ExplorerNavHeader' import { ExplorerNavHome } from './ExplorerNavHome' import { ExplorerNavNotebooks } from './ExplorerNavNotebooks' import { ExplorerPreferencesDropdown } from './ExplorerPreferencesDropdown' import { ExplorerProvider } from './ExplorerProvider' import { useExplorerPreferences } from '@/components/interfaces/Account/Preferences/useExplorerPreferences' import { ExplorerNotebookTabCoordinator } from '@/components/interfaces/Explorer/ExplorerNotebookTabCoordinator' import { ExplorerQueryTabCoordinator } from '@/components/interfaces/Explorer/ExplorerQueryTabCoordinator' import { useCreateChat, useCreateNotebook, useCreateQuery, } from '@/components/interfaces/Explorer/hooks' import { useDashboardHistory } from '@/hooks/misc/useDashboardHistory' import { editorEntityTypes, EXPLORER_HOME_TAB, EXPLORER_HOME_TAB_ID, useTabsStateSnapshot, type Tab, } from '@/state/tabs' export interface ExplorerLayoutProps extends ComponentProps { children: ReactNode title?: string } export const ExplorerLayout = ({ browserTitle, children, title }: ExplorerLayoutProps) => { const tabs = useTabsStateSnapshot() const { setLastVisitedExplorerTab } = useDashboardHistory() const { home, hasCompletedOnboarding, isReady } = useExplorerPreferences() const shouldShowHomeTab = isReady && (!hasCompletedOnboarding || home === 'home') const [section, setSection] = useState() const activeTab = tabs.activeTab ? tabs.tabsMap[tabs.activeTab] : undefined const isActiveExplorerTab = activeTab !== undefined && editorEntityTypes.explorer.includes(activeTab.type) const activeTabLabel = isActiveExplorerTab ? activeTab.label || 'Untitled' : 'Explorer' const mergedBrowserTitle = { ...browserTitle, section: title ?? browserTitle?.section, entity: browserTitle?.entity ?? activeTabLabel, } const handleTabChange = (id: string) => { if (id === EXPLORER_HOME_TAB_ID) setLastVisitedExplorerTab(undefined) } return ( setSection(undefined)} rootAction={} /> } productMenu={
{section === undefined && } {section === 'notebook' && } {section === 'chat' && }
} >
: undefined} newTabButton={} onTabChange={handleTabChange} />
{children}
) } const TabClassName = 'flex items-center justify-center min-w-(--header-height) min-h-(--header-height) hover:bg-surface-100 shrink-0' const HomeTabButton = () => { const tabs = useTabsStateSnapshot() const openTabs = tabs.openTabs .map((id) => tabs.tabsMap[id]) .filter((tab) => tab !== undefined) as Tab[] const explorerTabs = openTabs.filter((tab) => editorEntityTypes['explorer']?.includes(tab.type)) const ensureHomeTab = useEffectEvent(() => { tabs.ensurePinnedTab(EXPLORER_HOME_TAB) }) useEffect(() => ensureHomeTab(), []) return ( Open Explorer home
) } const NewTabButton = () => { const { createNotebook } = useCreateNotebook() const { createQuery } = useCreateQuery() const { createChat } = useCreateChat() return ( {}} initial={{ opacity: 0, scale: 0.8, x: -10 }} animate={{ opacity: 1, scale: 1, x: 0 }} transition={{ duration: 0.2 }} > createQuery()}> Run SQL createNotebook()}> New notebook createChat()}> New chat ) }