Keep ScaleInfo pinned to the map corner and move the centered timeline above collisions, preventing the previous conditional offset from lifting the scale. Remove collapsed Agent rail width reservation and add timeline state transitions.
156 lines
4.9 KiB
TypeScript
156 lines
4.9 KiB
TypeScript
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;
|
|
}
|