"use client"; import { useEffect, useState } from "react"; import { SidebarNav } from "./SidebarNav"; import { WatchlistSidebar } from "./WatchlistSidebar"; import { SymbolHeader } from "./SymbolHeader"; import { MobileTabNav } from "./MobileTabNav"; import { CommandPalette } from "./CommandPalette"; import { CollapsibleProvider, useCollapsibleContext } from "@/lib/collapsible-context"; import { useKeyboardShortcuts } from "@/lib/useKeyboardShortcuts"; const MOBILE_BREAKPOINT = 768; const TABLET_BREAKPOINT = 1024; function useViewport() { const [width, setWidth] = useState(typeof window !== "undefined" ? window.innerWidth : 1200); useEffect(() => { const handler = () => setWidth(window.innerWidth); window.addEventListener("resize", handler); return () => window.removeEventListener("resize", handler); }, []); return width; } /** * Inner component that attaches the global Escape listener. * Wrapped in CollapsibleProvider so all CollapsibleSections can register. */ function LayoutShellInner({ children }: { children: React.ReactNode }) { const { openSectionId, setOpenSectionId } = useCollapsibleContext(); const viewportWidth = useViewport(); const isMobile = viewportWidth < MOBILE_BREAKPOINT; const isTablet = viewportWidth >= MOBILE_BREAKPOINT && viewportWidth < TABLET_BREAKPOINT; // Keyboard shortcuts: Escape closes open sections, modals useKeyboardShortcuts([ { key: "Escape", handler: () => { if (openSectionId) { setOpenSectionId(null); } }, }, ]); // Global Escape listener: collapse the currently open section. useEffect(() => { const handler = (e: KeyboardEvent) => { if (e.key === "Escape" && openSectionId) { e.preventDefault(); // Collapse the currently open section by clearing the shared state. // Individual CollapsibleSection Escape handlers also respond to this. setOpenSectionId(null); } }; window.addEventListener("keydown", handler, true); // capture phase return () => window.removeEventListener("keydown", handler, true); }, [openSectionId, setOpenSectionId]); return (