agent-ecosystem/src/shared/constants/trafficLights.ts

60 lines
2 KiB
TypeScript

/**
* Shared macOS traffic-light geometry.
*
* Keep this as the single source of truth for both:
* - main process native button positioning
* - renderer process left padding reservation
*/
/** IPC event channel emitted by main when zoom changes */
export const WINDOW_ZOOM_FACTOR_CHANGED_CHANNEL = 'window:zoom-factor-changed';
/** Base traffic-light origin at 100% zoom (native coordinates) */
const MACOS_TRAFFIC_LIGHT_BASE_POSITION = { x: 12, y: 12 } as const;
/** Header row height used by SidebarHeader and TabBar */
export const HEADER_ROW1_HEIGHT = 40;
/** Native button-group frame height (used to vertically center in header row) */
const MACOS_TRAFFIC_LIGHT_GROUP_HEIGHT = 16;
/** Approximate total width of the 3 traffic lights group in native px */
const MACOS_TRAFFIC_LIGHT_GROUP_WIDTH = 52;
/** Visual gap between traffic lights and first left-aligned content */
const MACOS_TRAFFIC_LIGHT_CONTENT_GAP = 16;
const MIN_ZOOM_FACTOR = 0.25;
function sanitizeZoomFactor(zoomFactor: number): number {
if (!Number.isFinite(zoomFactor) || zoomFactor <= 0) {
return 1;
}
return Math.max(zoomFactor, MIN_ZOOM_FACTOR);
}
/**
* Native traffic-light position for the given zoom.
* Uses linear scaling to keep vertical alignment with zoomed title rows.
*/
export function getTrafficLightPositionForZoom(
zoomFactor: number
): Readonly<{ x: number; y: number }> {
const zoom = sanitizeZoomFactor(zoomFactor);
return {
x: Math.round(MACOS_TRAFFIC_LIGHT_BASE_POSITION.x * zoom),
y: Math.round((HEADER_ROW1_HEIGHT * zoom - MACOS_TRAFFIC_LIGHT_GROUP_HEIGHT) / 2),
};
}
/**
* CSS left padding (in CSS px) needed to avoid overlap with native buttons.
* Produces a stable physical gap between traffic lights and content at any zoom.
*/
export function getTrafficLightPaddingForZoom(zoomFactor: number): number {
const zoom = sanitizeZoomFactor(zoomFactor);
return Math.ceil(
MACOS_TRAFFIC_LIGHT_BASE_POSITION.x +
(MACOS_TRAFFIC_LIGHT_GROUP_WIDTH + MACOS_TRAFFIC_LIGHT_CONTENT_GAP) / zoom
);
}