import type { Theme } from "../themes.js"; import type { BorderResult } from "./types.js"; const TITLE_BAR_HEIGHT = 28; const SIDE_PADDING = 0; const BOTTOM_PADDING = 0; const CORNER_RADIUS = 8; const SHADOW_PADDING = 16; /** Traffic light button colors */ const TRAFFIC_LIGHTS = [ { cx: 20, fill: "#ff5f56" }, { cx: 40, fill: "#ffbd2e" }, { cx: 60, fill: "#27c93f" }, ]; /** * Darken a hex color by mixing it toward black. * Amount 0 = unchanged, 1 = fully black. */ function darken(hex: string, amount: number): string { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); const dr = Math.round(r * (1 - amount)); const dg = Math.round(g * (1 - amount)); const db = Math.round(b * (1 - amount)); return `#${dr.toString(16).padStart(2, "0")}${dg.toString(16).padStart(2, "0")}${db.toString(16).padStart(2, "0")}`; } /** macOS-style window chrome with traffic lights, title bar, and drop shadow. */ export function macosBorder( innerWidth: number, innerHeight: number, theme: Theme, title?: string ): BorderResult { const outerWidth = innerWidth + SIDE_PADDING * 2; const outerHeight = innerHeight + TITLE_BAR_HEIGHT + BOTTOM_PADDING; // Total SVG dimensions include shadow bleed const width = outerWidth + SHADOW_PADDING * 2; const height = outerHeight + SHADOW_PADDING * 2; const titleBarBg = darken(theme.background, 0.15); const titleColor = theme.type === "dark" ? "#999999" : "#666666"; const defs = ` `; const trafficLightsSvg = TRAFFIC_LIGHTS.map( (tl) => ` ` ).join("\n"); const titleSvg = title ? ` ${title}` : ""; const beforeContent = ` ${trafficLightsSvg} ${titleSvg}`; const contentTransform = `translate(${SIDE_PADDING}, ${TITLE_BAR_HEIGHT})`; const afterContent = ` `; return { width, height, contentTransform, defs, beforeContent, afterContent }; }