import { ResizableHandle, ResizablePanel, ResizablePanelGroup, } from '@affine/admin/components/ui/resizable'; import { Separator } from '@affine/admin/components/ui/separator'; import { TooltipProvider } from '@affine/admin/components/ui/tooltip'; import { cn } from '@affine/admin/utils'; import { AlignJustifyIcon } from 'lucide-react'; import type { PropsWithChildren, ReactNode, RefObject } from 'react'; import { createContext, useCallback, useContext, useEffect, useRef, useState, } from 'react'; import type { ImperativePanelHandle } from 'react-resizable-panels'; import { Button } from '../components/ui/button'; import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger, } from '../components/ui/sheet'; import { Logo } from './accounts/components/logo'; import { NavContext } from './nav/context'; import { Nav } from './nav/nav'; interface RightPanelContextType { isOpen: boolean; rightPanelContent: ReactNode; setRightPanelContent: (content: ReactNode) => void; togglePanel: () => void; openPanel: () => void; closePanel: () => void; } const RightPanelContext = createContext( undefined ); export const useRightPanel = () => { const context = useContext(RightPanelContext); if (!context) { throw new Error('useRightPanel must be used within a RightPanelProvider'); } return context; }; export function useMediaQuery(query: string) { const [value, setValue] = useState(false); useEffect(() => { function onChange(event: MediaQueryListEvent) { setValue(event.matches); } const result = matchMedia(query); result.addEventListener('change', onChange); setValue(result.matches); return () => result.removeEventListener('change', onChange); }, [query]); return value; } export function Layout({ children }: PropsWithChildren) { const [rightPanelContent, setRightPanelContent] = useState(null); const [open, setOpen] = useState(false); const rightPanelRef = useRef(null); const [activeTab, setActiveTab] = useState(''); const [activeSubTab, setActiveSubTab] = useState('auth'); const [currentModule, setCurrentModule] = useState('auth'); const handleExpand = useCallback(() => { if (rightPanelRef.current?.getSize() === 0) { rightPanelRef.current?.resize(30); } setOpen(true); }, [rightPanelRef]); const handleCollapse = useCallback(() => { if (rightPanelRef.current?.getSize() !== 0) { rightPanelRef.current?.resize(0); } setOpen(false); }, [rightPanelRef]); const openPanel = useCallback(() => { handleExpand(); rightPanelRef.current?.expand(); }, [handleExpand]); const closePanel = useCallback(() => { handleCollapse(); rightPanelRef.current?.collapse(); }, [handleCollapse]); const togglePanel = useCallback( () => (rightPanelRef.current?.isCollapsed() ? openPanel() : closePanel()), [closePanel, openPanel] ); return (
{children}
); } export const LeftPanel = () => { const isSmallScreen = useMediaQuery('(max-width: 768px)'); if (isSmallScreen) { return ( AFFiNE Admin panel for managing accounts, AI, config, and settings
AFFiNE
); } return (
AFFiNE
); }; export const RightPanel = ({ rightPanelRef, onExpand, onCollapse, }: { rightPanelRef: RefObject; onExpand: () => void; onCollapse: () => void; }) => { const isSmallScreen = useMediaQuery('(max-width: 768px)'); const { rightPanelContent, isOpen } = useRightPanel(); const onOpenChange = useCallback( (open: boolean) => { if (open) { onExpand(); } else { onCollapse(); } }, [onExpand, onCollapse] ); if (isSmallScreen) { return ( Right Panel For displaying additional information {rightPanelContent} ); } return ( <> {rightPanelContent} ); };