export const WORKBENCH_LAYOUT = { headerHeight: 56, desktopMinWidth: 1024, persistentConditionMinWidth: 1280, wideMinWidth: 1536, collapsedAgentWidth: 0, maxAgentWidth: 720, agentPanelLeftInset: 12, conditionPanelRightInset: 64, minimumAgentMapCorridor: 256, mapEdgeGap: 24, desktop: { agentWidth: 500, conditionWidth: 432, conditionExpandedWidth: 880, toolbarWidth: 48, tickerWidth: 420 }, wide: { agentWidth: 540, conditionWidth: 432, conditionExpandedWidth: 960, toolbarWidth: 48, tickerWidth: 460 }, mobileSheet: { halfViewportRatio: 0.52, fullTopGap: 68 } } as const; export function clampAgentPanelWidth( width: number, viewportWidth: number, conditionExpanded = false ) { const minWidth = getAgentPanelDefaultWidth(viewportWidth, conditionExpanded); return Math.round( Math.min(Math.max(width, minWidth), getAgentPanelMaxWidth(viewportWidth, conditionExpanded)) ); } export function getAgentPanelDefaultWidth(viewportWidth: number, conditionExpanded = false) { const layout = getWorkbenchViewportLayout(viewportWidth); if (viewportWidth < WORKBENCH_LAYOUT.desktopMinWidth) { return layout.agentWidth; } const conditionWidth = conditionExpanded ? layout.conditionExpandedWidth : layout.conditionWidth; const collisionSafeWidth = viewportWidth - WORKBENCH_LAYOUT.agentPanelLeftInset - WORKBENCH_LAYOUT.mapEdgeGap - conditionWidth - WORKBENCH_LAYOUT.mapEdgeGap - layout.toolbarWidth; return Math.min(layout.agentWidth, collisionSafeWidth); } export function getAgentPanelMaxWidth(viewportWidth: number, conditionExpanded = false) { const layout = getWorkbenchViewportLayout(viewportWidth); const conditionWidth = conditionExpanded ? layout.conditionExpandedWidth : layout.conditionWidth; const defaultWidth = getAgentPanelDefaultWidth(viewportWidth, conditionExpanded); const widthWithMapCorridor = viewportWidth - WORKBENCH_LAYOUT.agentPanelLeftInset - WORKBENCH_LAYOUT.conditionPanelRightInset - conditionWidth - WORKBENCH_LAYOUT.minimumAgentMapCorridor; return Math.max(defaultWidth, Math.min(WORKBENCH_LAYOUT.maxAgentWidth, widthWithMapCorridor)); } export type WorkbenchPanelState = { agentOpen: boolean; agentWidth?: number; conditionOpen: boolean; conditionExpanded?: boolean; }; export type WorkbenchBasemapTone = "light" | "satellite" | "none"; export type WorkbenchViewportLayout = { agentWidth: number; conditionWidth: number; conditionExpandedWidth: number; toolbarWidth: number; tickerWidth: number; }; export function getWorkbenchViewportLayout(viewportWidth: number): WorkbenchViewportLayout { return viewportWidth >= WORKBENCH_LAYOUT.wideMinWidth ? WORKBENCH_LAYOUT.wide : WORKBENCH_LAYOUT.desktop; } export function getWorkbenchBasemapTone(activeBaseLayerId: string): WorkbenchBasemapTone { if (activeBaseLayerId === "mapbox-light") { return "light"; } if (activeBaseLayerId === "mapbox-satellite") { return "satellite"; } return "none"; } export function getWorkbenchCameraPadding(viewportWidth: number, panels: WorkbenchPanelState) { if (viewportWidth < WORKBENCH_LAYOUT.desktopMinWidth) { return { top: 72, right: 24, bottom: 72, left: 24 }; } const layout = getWorkbenchViewportLayout(viewportWidth); const agentWidth = panels.agentOpen ? panels.agentWidth === undefined ? getAgentPanelDefaultWidth( viewportWidth, panels.conditionOpen && Boolean(panels.conditionExpanded) ) : clampAgentPanelWidth( panels.agentWidth, viewportWidth, panels.conditionOpen && Boolean(panels.conditionExpanded) ) : WORKBENCH_LAYOUT.collapsedAgentWidth; const conditionWidth = panels.conditionOpen ? panels.conditionExpanded ? layout.conditionExpandedWidth : layout.conditionWidth : 0; return { top: WORKBENCH_LAYOUT.headerHeight + 16, right: WORKBENCH_LAYOUT.mapEdgeGap + layout.toolbarWidth + conditionWidth, bottom: 32, left: WORKBENCH_LAYOUT.mapEdgeGap + agentWidth }; } export function getWorkbenchLayoutCssVariables() { return { "--workbench-agent-width": `${WORKBENCH_LAYOUT.desktop.agentWidth}px`, "--workbench-agent-width-wide": `${WORKBENCH_LAYOUT.wide.agentWidth}px`, "--workbench-condition-width": `${WORKBENCH_LAYOUT.desktop.conditionWidth}px`, "--workbench-condition-width-wide": `${WORKBENCH_LAYOUT.wide.conditionWidth}px`, "--workbench-condition-expanded-width": `${WORKBENCH_LAYOUT.desktop.conditionExpandedWidth}px`, "--workbench-condition-expanded-width-wide": `${WORKBENCH_LAYOUT.wide.conditionExpandedWidth}px`, "--workbench-toolbar-width": `${WORKBENCH_LAYOUT.desktop.toolbarWidth}px`, "--workbench-ticker-width": `${WORKBENCH_LAYOUT.desktop.tickerWidth}px`, "--workbench-ticker-width-wide": `${WORKBENCH_LAYOUT.wide.tickerWidth}px` } as const; }