// Inhalts-Panel „Attribute" — die Attribut-Palette (Vectorworks-Stil) für die // aktuelle Auswahl. Zeigt die EFFEKTIV aufgelösten Stift-/Füll-Eigenschaften des // ersten selektierten Elements und erlaubt das direkte Bearbeiten (Farbe, // Strichstärke, Füllschraffur). // // Daten/Handler kommen ausschließlich über usePanelHost (kein Prop-Drilling). // Es werden NUR Eigenschaften angeboten, die der Host-Kontrakt tatsächlich // setzen kann — keine Stubs/Fake-Setter (Konvention wire-dont-stub). Felder ohne // echten Setter (Linienstil) werden read-only/informativ gezeigt; Felder, die // das Modell gar nicht trägt (Deckkraft, Caps, Schlagschatten), werden bewusst // weggelassen, um die Palette ehrlich und schlank zu halten. // // DOSSIER-Tabellen-Look: KEINE wiederholten Feld-Labels pro Zeile — ein kompaktes // Label→Wert-Grid. Bezeichner englisch, UI-Text/Kommentare deutsch (CONVENTIONS.md). // Alle sichtbaren Texte über t(...). import { t } from "../i18n"; import { formatM } from "../model/types"; import { PEN_WEIGHTS } from "../model/types"; import { usePanelHost } from "./host"; export function AttributesPanel() { const host = usePanelHost(); const sel = host.selection; const { project } = host; // Leerzustand: kompakter Hinweis, wenn nichts (Sinnvolles) selektiert ist. if (sel === null) { return (
{t("attr.empty")}
); } const isDrawing = sel.kind === "drawing2d"; // Strichstärke wirkt laut Kontrakt nur auf Drawing2D; Wände erben sie aus der // Ebene und sind daher hier nicht editierbar. const weightEditable = isDrawing; // Füllung nur bei geschlossener 2D-Form sinnvoll. const fillEditable = isDrawing && sel.closed === true; // Effektiver Linienstil rein informativ (kein Setter im Kontrakt → kein Fake). // Wir leiten ihn aus dem Modell-Element ab, wenn explizit gesetzt; sonst „—". const drawing = isDrawing ? project.drawings2d.find((d) => d.id === sel.id) : undefined; const lineStyle = drawing?.lineStyleId ? project.lineStyles.find((l) => l.id === drawing.lineStyleId) : undefined; const bboxW = sel.bbox.maxX - sel.bbox.minX; const bboxH = sel.bbox.maxY - sel.bbox.minY; return (
{t("attr.title")}
{/* ── Stift/Strich ──────────────────────────────────────────────── */}
{t("attr.stroke")}
{/* Farbe — gilt für Wand UND Drawing2D (Kontrakt setzt beide). */} {t("attr.color")} {/* Strichstärke (mm) — nur Drawing2D editierbar; Wände erben aus Ebene. */} {t("attr.weight")} { const v = Number(e.target.value); if (Number.isFinite(v)) host.onSetSelectionWeight(v); }} /> {PEN_WEIGHTS.map((w) => ( {/* Linienstil — read-only/informativ (kein Setter im Kontrakt). */} {t("attr.lineStyle")} {lineStyle ? lineStyle.name : "—"}
{/* ── Füllung (nur geschlossene 2D-Form) ────────────────────────── */}
{t("attr.fill")}
{/* Vollton-Füllfarbe (getrennt von der Strichfarbe). „keine" = transparent. */} {t("attr.fillColor")} {t("attr.hatch")}
{/* ── Maße (informativ, aus der bbox) ───────────────────────────── */}
{t("attr.size")}
{t("attr.width")} {formatM(bboxW)} {t("attr.height")} {formatM(bboxH)}
); }