import { useEffect, useState } from "react"; import type { MobileWorkbenchSheetSnap } from "../components/mobile-workbench-sheet"; import { WORKBENCH_LAYOUT } from "../layout/workbench-layout"; const CONDITION_FEED_EXIT_MS = 170; const CONDITION_FEED_EXPANDED_MIN_WIDTH = 1440; const LARGE_SCREEN_QUERY = "(min-width: 1024px)"; type WorkbenchMobileSheet = "agent" | "condition" | "timeline" | null; type UseWorkbenchResponsiveLayoutOptions = { activeToolOpen: boolean; agentPanelOpen: boolean; devPanelOpen: boolean; collapseAgentPanel: () => void; expandAgentPanel: () => void; onClearActiveTool: () => void; }; export function useWorkbenchResponsiveLayout({ activeToolOpen, agentPanelOpen, devPanelOpen, collapseAgentPanel, expandAgentPanel, onClearActiveTool }: UseWorkbenchResponsiveLayoutOptions) { const [isLargeScreen, setIsLargeScreen] = useState(false); const [viewportWidth, setViewportWidth] = useState(WORKBENCH_LAYOUT.desktopMinWidth); const [agentPanelWidth, setAgentPanelWidth] = useState( WORKBENCH_LAYOUT.desktop.agentWidth ); const [conditionFeedVisible, setConditionFeedVisible] = useState(false); const [conditionFeedMounted, setConditionFeedMounted] = useState(false); const [conditionFeedExpanded, setConditionFeedExpanded] = useState(false); const [mobileSheet, setMobileSheet] = useState(null); const [mobileSheetSnap, setMobileSheetSnap] = useState("half"); const [agentCollapsedForCondition, setAgentCollapsedForCondition] = useState(false); useEffect(() => { const mediaQuery = window.matchMedia(LARGE_SCREEN_QUERY); const handleViewportChange = () => { setIsLargeScreen(mediaQuery.matches); setViewportWidth(window.innerWidth); if (mediaQuery.matches) { setMobileSheet(null); } }; handleViewportChange(); setConditionFeedVisible(false); mediaQuery.addEventListener("change", handleViewportChange); window.addEventListener("resize", handleViewportChange); return () => { mediaQuery.removeEventListener("change", handleViewportChange); window.removeEventListener("resize", handleViewportChange); }; }, []); const shouldShowConditionFeed = conditionFeedVisible && !activeToolOpen; useEffect(() => { if (shouldShowConditionFeed) { setConditionFeedMounted(true); return; } const timeoutId = window.setTimeout(() => { setConditionFeedMounted(false); }, CONDITION_FEED_EXIT_MS); return () => window.clearTimeout(timeoutId); }, [shouldShowConditionFeed]); function closeMobileSheet() { setMobileSheet(null); } function openAgentPanelForViewport() { if (isLargeScreen) { if (conditionFeedExpanded && viewportWidth < CONDITION_FEED_EXPANDED_MIN_WIDTH) { setConditionFeedExpanded(false); setAgentCollapsedForCondition(false); } expandAgentPanel(); return; } setMobileSheet("agent"); setMobileSheetSnap("half"); } function handleConditionExpandedChange(nextExpanded: boolean) { if (nextExpanded && isLargeScreen && viewportWidth < CONDITION_FEED_EXPANDED_MIN_WIDTH) { setAgentCollapsedForCondition(agentPanelOpen); collapseAgentPanel(); } else if (!nextExpanded && agentCollapsedForCondition) { setAgentCollapsedForCondition(false); expandAgentPanel(); } setConditionFeedExpanded(nextExpanded); } useEffect(() => { if (!isLargeScreen || shouldShowConditionFeed || !conditionFeedExpanded) { return; } setConditionFeedExpanded(false); if (agentCollapsedForCondition) { setAgentCollapsedForCondition(false); expandAgentPanel(); } }, [ agentCollapsedForCondition, conditionFeedExpanded, expandAgentPanel, isLargeScreen, shouldShowConditionFeed ]); function toggleConditionFeedForViewport() { onClearActiveTool(); if (isLargeScreen) { setConditionFeedVisible((current) => !current); return; } if (mobileSheet === "condition") { closeMobileSheet(); return; } setConditionFeedExpanded(false); setMobileSheetSnap("half"); setMobileSheet("condition"); } function openConditionFeedForViewport() { setConditionFeedVisible(true); onClearActiveTool(); if (!isLargeScreen) { setMobileSheet("condition"); setMobileSheetSnap("half"); } } function openTimelineForViewport() { if (isLargeScreen) return; setMobileSheet("timeline"); setMobileSheetSnap("half"); } const leftPanelOpen = isLargeScreen && agentPanelOpen; const rightPanelOpen = isLargeScreen && (devPanelOpen || shouldShowConditionFeed); const rightPanelExpanded = isLargeScreen && shouldShowConditionFeed && conditionFeedExpanded && !devPanelOpen; return { agentPanelWidth, closeMobileSheet, conditionFeedExpanded, conditionFeedMounted, handleConditionExpandedChange, isLargeScreen, leftPanelOpen, mobileSheet, mobileSheetSnap, openAgentPanelForViewport, openConditionFeedForViewport, openTimelineForViewport, rightPanelExpanded, rightPanelOpen, setAgentPanelWidth, setMobileSheetSnap, shouldShowConditionFeed, toggleConditionFeedForViewport, viewportWidth }; }