import { useState, useCallback, useMemo, memo } from 'react'; import throttle from 'lodash/throttle'; import { ResizablePanel, ResizablePanelGroup, useMediaQuery } from '@librechat/client'; import ArtifactsPanel from './ArtifactsPanel'; import { normalizeLayout } from '~/utils'; interface SidePanelProps { defaultLayout?: number[] | undefined; defaultCollapsed?: boolean; navCollapsedSize?: number; fullPanelCollapse?: boolean; artifacts?: React.ReactNode; children: React.ReactNode; } const SidePanelGroup = memo( ({ defaultLayout = [97, 3], artifacts, children, }: SidePanelProps) => { const [shouldRenderArtifacts, setShouldRenderArtifacts] = useState(artifacts != null); const isSmallScreen = useMediaQuery('(max-width: 767px)'); const calculateLayout = useCallback(() => { if (artifacts == null) { const navSize = defaultLayout.length === 2 ? defaultLayout[1] : defaultLayout[2]; return [100 - navSize, navSize]; } else { const navSize = 0; const remainingSpace = 100 - navSize; const newMainSize = Math.floor(remainingSpace / 2); const artifactsSize = remainingSpace - newMainSize; return [newMainSize, artifactsSize, navSize]; } }, [artifacts, defaultLayout]); const currentLayout = useMemo(() => normalizeLayout(calculateLayout()), [calculateLayout]); const throttledSaveLayout = useMemo( () => throttle((sizes: number[]) => { const normalizedSizes = normalizeLayout(sizes); localStorage.setItem('react-resizable-panels:layout', JSON.stringify(normalizedSizes)); }, 350), [], ); const minSizeMain = useMemo(() => (artifacts != null ? 15 : 30), [artifacts]); return ( <> throttledSaveLayout(sizes)} className="relative h-full w-full flex-1 overflow-auto bg-presentation" > {children} {!isSmallScreen && ( )} {artifacts != null && isSmallScreen && (
{artifacts}
)} ); }, ); SidePanelGroup.displayName = 'SidePanelGroup'; export default SidePanelGroup;