import classnames from 'classnames'; import { motion } from 'framer-motion'; import type { CSSProperties, HTMLAttributes, MouseEvent as ReactMouseEvent, ReactNode, } from 'react'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useWindowSize } from 'react-use'; import { useSidebarDisplay } from '../hooks/useSidebarDisplay'; import { WINDOW_FLOATING_SIDEBAR_WIDTH } from '../lib/constants'; import { Button } from './core/Button'; import { HStack } from './core/Stacks'; import { Overlay } from './Overlay'; import { RequestResponse } from './RequestResponse'; import { ResizeHandle } from './ResizeHandle'; import { Sidebar } from './Sidebar'; import { SidebarActions } from './SidebarActions'; import { WorkspaceHeader } from './WorkspaceHeader'; const side = { gridArea: 'side' }; const head = { gridArea: 'head' }; const body = { gridArea: 'body' }; const drag = { gridArea: 'drag' }; export default function Workspace() { const sidebar = useSidebarDisplay(); const windowSize = useWindowSize(); const [floating, setFloating] = useState(false); const [isResizing, setIsResizing] = useState(false); const moveState = useRef<{ move: (e: MouseEvent) => void; up: (e: MouseEvent) => void } | null>( null, ); // float/un-float sidebar on window resize useEffect(() => { if (windowSize.width <= WINDOW_FLOATING_SIDEBAR_WIDTH) { setFloating(true); sidebar.hide(); } else { setFloating(false); sidebar.show(); } }, [windowSize.width]); const unsub = () => { if (moveState.current !== null) { document.documentElement.removeEventListener('mousemove', moveState.current.move); document.documentElement.removeEventListener('mouseup', moveState.current.up); } }; const handleResizeStart = useCallback( (e: ReactMouseEvent) => { if (sidebar.width === undefined) return; unsub(); const mouseStartX = e.clientX; const startWidth = sidebar.width; moveState.current = { move: async (e: MouseEvent) => { e.preventDefault(); // Prevent text selection and things sidebar.set(startWidth + (e.clientX - mouseStartX)); }, up: (e: MouseEvent) => { e.preventDefault(); unsub(); setIsResizing(false); }, }; document.documentElement.addEventListener('mousemove', moveState.current.move); document.documentElement.addEventListener('mouseup', moveState.current.up); setIsResizing(true); }, [sidebar.width, sidebar.hidden], ); const sideWidth = sidebar.hidden ? 0 : sidebar.width; const styles = useMemo( () => ({ gridTemplate: floating ? ` ' ${head.gridArea}' auto ' ${body.gridArea}' minmax(0,1fr) / 1fr` : ` ' ${head.gridArea} ${head.gridArea} ${head.gridArea}' auto ' ${side.gridArea} ${drag.gridArea} ${body.gridArea}' minmax(0,1fr) / ${sideWidth}px 0 1fr`, }), [sideWidth, floating], ); if (windowSize.width <= 100) { return (
); } return (
{floating ? ( ) : ( <>
)}
); } interface HeaderSizeProps extends HTMLAttributes { children: ReactNode; } function HeaderSize({ className, ...props }: HeaderSizeProps) { return (
); }