"use client"; // Overlay wrapper for the nav-driven section panels of the /trade-in/v2 // "МЕРА Оценка" design. Faithful port of the design overlay container // (МЕРА Оценка.dc.html lines 443-453 + 615-616): a glass/blur absolute layer // with HUD corner brackets, a header (section number + title + "← К ОЦЕНКЕ" // button) and a scrollable body that swaps the active view. import { useEffect, useRef } from "react"; import { tokens } from "./tokens"; import { overlayNums, overlayTitles } from "./fixtures"; import HistoryView from "./HistoryView"; import SourcesView from "./SourcesView"; import AnalyticsView from "./AnalyticsView"; import { CacheView } from "./CacheView"; import type { CacheData, HistoryData, SourcesData } from "./mappers"; import type { Analytics } from "./types"; interface SectionOverlayProps { active: number; onClose: () => void; onNavigate: (i: number) => void; // Mapped overlay data, fed by page.tsx (mapHistory / mapSources / mapAnalytics // / mapCache). Optional so unwired/storybook usage falls back to each view's // fixture default. history?: HistoryData; sources?: SourcesData; analytics?: Analytics; cache?: CacheData; // #2420 — «ПРЕДЫДУЩИЕ ОЦЕНКИ» row click: navigate to the full report for // that historical estimate. Optional (threaded straight to CacheView's own // optional onSelectRow — unwired usage leaves rows inert). onSelectEstimate?: (id: string) => void; } // Panel geometry (relative to the artboard). Kept as a constant so the click // backdrop can align its top edge to the panel — the backdrop starts BELOW the // TopNav so the top tabs stay clickable while an overlay is open. const PANEL_TOP = 80; export default function SectionOverlay({ active, onClose, onNavigate, history, sources, analytics, cache, onSelectEstimate, }: SectionOverlayProps) { // Non-modal dialog plumbing. `dialogRef` is the dialog root, `lastFocused` // keeps the element that had focus before the overlay opened so we can restore // it on close, and `onCloseRef` holds the latest onClose so the mount-only // effect (deps []) never re-runs / re-traps focus on parent re-renders even // though page.tsx passes a fresh arrow each render. const dialogRef = useRef(null); const bodyRef = useRef(null); const lastFocused = useRef(null); const onCloseRef = useRef(onClose); onCloseRef.current = onClose; // M7 — the overlay body is ONE scroller shared by every section view; switching // sections (nav within the overlay) used to inherit the previous section's // scroll offset, dropping the user into the middle of the new view. Reset to the // top whenever the active section changes. useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = 0; }, [active]); useEffect(() => { const dialog = dialogRef.current; // Remember the trigger, then move focus into the dialog. lastFocused.current = document.activeElement; dialog?.focus(); // This overlay is an HONEST NON-MODAL fullscreen view (no aria-modal): the // live top nav is a sibling that is deliberately NOT inerted, so a keyboard // user can switch sections from within the overlay. The Tab cycle therefore // spans [live nav tabs … + overlay content] in DOM order — we query the whole // artboard (the dialog's parent) and drop anything inside an inert subtree // (the dashboard body under the overlay). This keeps focus out of the hidden //
/