// Oberleiste (Top-Bar) — MVP nach docs/design/topbar-footer.md. // // Gruppen (links → rechts): Marke · Ansichts-Umschalter (Grundriss/Perspektive) // · Detailgrad (grob/mittel/fein) · Massstab „1:N" + Zoom (Einpassen/Auswahl/ // 100 %) · Render-Modus · Referenzlinien-Toggle · Layout-Menü · Ressourcen. // // Die Leiste ist rein gesteuert (controlled): alle Zustände kommen als Props // aus App, Aktionen melden sich über Callbacks zurück. Bezeichner englisch, // UI-Text/Kommentare deutsch (CONVENTIONS.md). import type { ReactNode } from "react"; import type { Project } from "../model/types"; import { t } from "../i18n"; import { useEffect, useRef, useState } from "react"; import { Dropdown } from "./Dropdown"; import type { DropdownItem, DropdownOption } from "./Dropdown"; import { WindowControls } from "./WindowControls"; import { RibbonTabs } from "./ribbon/RibbonBar"; import type { RibbonTabId } from "./ribbon/ribbonItems"; import { applyMark, applyPreset, commonMarkValue, DEFAULT_LINE_HEIGHT, DEFAULT_PRESETS, docLength, isMarkActive, toggleMark, } from "../text/richText"; import type { Align, BoolMark, RichTextDoc, TextRange, } from "../text/richText"; /** Ansichtstyp eines Geschosses (wie in App). */ export type ViewType = "grundriss" | "perspektive"; /** * Detailgrad der Darstellung (≙ DOSSIER Einfach/Standard/Detail). Wirkt im * Grundriss auf Tür-/Fenstersymbole + Schraffuren/Linienfeinheit (siehe * generatePlan.DetailLevel); in der Perspektive noch ohne Wirkung (deferred). */ export type DetailLevel = "grob" | "mittel" | "fein"; /** * Render-/Anzeigemodus der 3D-Ansicht: schattiert, einheitlich weiss (Clay-Look), * texturiert (echte PBR-Materialien je Bauteil), Drahtgitter, Verdeckte Kanten * (Hidden-Line). Wirkt nur in der Perspektive. Der Slot „section" (Schnitt- * schraffur, Welle B) ist bewusst freigelassen. */ export type RenderMode = | "shaded" | "white" | "textured" | "wireframe" | "hidden"; /** * Kanonischer Blickwinkel der 3D-Ansicht (Vectorworks/DOSSIER-Stil). „front", * „top", „side", „iso" springen auf die jeweilige Standardansicht; „perspective" * ist der freie 3/4-Blick. Wirkt nur in der Perspektive. */ export type View3d = "front" | "top" | "side" | "iso" | "perspective"; /** * Farb-Modus des Grundrisses: „color" zeigt Kategorie-/Element-Farben (heutiges * Verhalten), „mono" erzeugt einen reinen Schwarz-Weiss-Plan. Wirkt nur im * Grundriss (orthogonal zum Linien-Modus Display/Print). */ export type PlanColorMode = "color" | "mono"; /** * Massstab-Presets „1:N" (Nenner). `null` steht für „frei" (benutzerdefiniert, * per Eingabe). Quelle für die Anzeige in Top-Bar und Status-Leiste. */ export const SCALE_PRESETS: number[] = [1, 5, 10, 20, 50, 100, 200, 500, 1000]; /** * Gemeinsame Breite (px) von Massstab-Dropdown und Zoom-Segmentpille im * Zoom-Cluster — beide sollen exakt gleich breit sein (Nutzer-Wunsch). */ const ZOOM_CLUSTER_WIDTH = 140; export interface TopBarProps { project: Project; // Ribbon-Tab-Reiter (2D/3D/BIM/Ansichten) sitzen in DIESER Zeile — der Ribbon- // Inhalt darunter (RibbonBar). Der aktive Tab liegt in App (geteilter State). ribbonTab: RibbonTabId; onRibbonTab: (id: RibbonTabId) => void; // Ansichts-/Zoom-/Darstellungs-Steuerung ist in den „Ansichten"-Ribbon-Tab // gewandert (siehe ViewRibbonTab). Die TopBar ist nur noch die schmale globale // Leiste: Marke/Ressourcen · Tabs · Text-Formatierung · Datei/Export/Einstell. /** Ob Zoom/Plan aktiv ist — steuert nur noch, ob Export im Datei-Menü geht. */ zoomEnabled: boolean; /** Öffnet den PDF-Export-Dialog (nur im Grundriss sinnvoll). */ onExportPdf: () => void; /** Öffnet den DXF-Export-Dialog (nur im Grundriss sinnvoll). */ onExportDxf: () => void; /** Lädt die Bauteilliste des Projekts als CSV herunter. */ onExportSchedule: () => void; // Ressourcen-Fenster. resourcesOpen: boolean; onToggleResources: () => void; /** Öffnet das Einstellungs-Fenster (Darstellungsfarben, Projekt-Felder). */ onOpenSettings: () => void; /** Layout-Menü (von App geliefert, damit dessen Logik dort bleibt). */ layoutMenu: ReactNode; // ── Datei-Menü (Burger, ganz rechts) ─────────────────────────────────────── /** Öffnet den DXF/DWG-Import-Datei-Dialog. */ onImport: () => void; /** Projekt als Datei speichern (JSON-Export des gesamten Projekts). */ onSaveProject: () => void; /** Projekt aus einer Datei laden. */ onOpenProject: () => void; // Die Text-/Font-Formatierung (TextGroup) liegt jetzt im „Text"-Ribbon-Tab // (App reicht sie via RibbonBar.tabContent), nicht mehr in dieser Leiste. } /** * Beschreibt das aktuell formatierbare Rich-Text-Ziel der Oberleiste. `apply` * schreibt das neue Dokument zurück in den App-State (z. B. via setRoomStampDoc). */ export interface TextTarget { doc: RichTextDoc; range: TextRange | null; apply: (doc: RichTextDoc) => void; } /** * Verdrahtung der beiden Kombinations-Dropdowns (Vectorworks-Stil). App liefert * die Speicher-/Lade-/Lösch-Logik; die Komponente bleibt rein gesteuert. */ export interface ComboMenuHandlers { // Ebenen-Kombinationen. listLayerCombos: () => string[]; saveLayerCombo: (name: string) => void; loadLayerCombo: (name: string) => void; deleteLayerCombo: (name: string) => void; // Zeichnungs-Kombinationen. listDrawingCombos: () => string[]; saveDrawingCombo: (name: string) => void; loadDrawingCombo: (name: string) => void; deleteDrawingCombo: (name: string) => void; } /** Kleiner vertikaler Trenner zwischen Gruppen. */ function Sep() { return