2D: Inline-Text-Editor nicht mehr zoomabhängig skaliert (riesig/winzig-Bug)

Nutzer-Report nach dem Sichtbarkeits-Fix: Editor erscheint "riesig", nicht
über dem Ankerpunkt, Enter erzeugt keine neue Zeile. Ursache: die Editor-
Box (Toolbar + Text) bekam via transform:scale() dieselbe Skalierung wie
die Modell-Geometrie (scale = heightM·pxPerMeter/16) — bei normalem/nahem
Arbeits-Zoom beim Textplatzieren wird das schnell 3-15x, die GESAMTE Toolbar
(Buttons, Dropdowns) skaliert mit hoch und sprengt den Bildschirm. Plausible
Folge fürs Enter-Problem: bei so einer Verzerrung landet der Fokus nicht
zuverlässig in der eigentlichen Text-Fläche (rt-surface), sondern z. B. auf
einem der riesigen Toolbar-Buttons, wo Enter nichts mit Zeilenumbruch zu tun
hat.

Fix: kein transform:scale() mehr. Die ANKER-Position folgt weiter dem
echten Zoom (vbToClient/toScreen, WO die Box aufgeht bleibt korrekt), aber
die Editor-GRÖSSE (Schrift/Toolbar) bleibt jetzt immer bei ihrer normalen,
zoomunabhängigen CSS-Grösse — wie im Raumstempel-/Layout-Dialog. Die
Textspalten-Breite (wrapWidth) folgt weiterhin der Modell-Breite, aber über
eine FESTE Umrechnung (220px/m) statt dem Live-Zoom, damit der Rahmen beim
Rein-/Rauszoomen während des Tippens nicht ständig neu umbricht.

tsc -b / vitest run (919/919) / npm run build grün. Konnte die konkrete
DOM-Fokus-Kette nicht interaktiv nachvollziehen (kein Browser-Tool
verfügbar) — Nutzer prüft erneut.
This commit is contained in:
2026-08-20 21:59:19 +02:00
parent 73d147b37d
commit 7d3fd40cac
+12 -13
View File
@@ -2496,23 +2496,24 @@ export const PlanView = forwardRef<PlanViewHandle, PlanViewProps>(
); );
if (!prim) return null; if (!prim) return null;
const doc = prim.doc ?? docFromText(prim.text, prim.marks ?? {}); const doc = prim.doc ?? docFromText(prim.text, prim.marks ?? {});
const pxPerM = currentPxPerMeter(); // Anker-POSITION folgt weiter dem echten Zoom (vbToClient/toScreen) —
// die Box soll am richtigen Ort aufgehen. Die Editor-GRÖSSE (Schrift +
// Toolbar) bleibt dagegen bewusst zoomUNabhängig (keine transform:scale
// mehr): bei nahem Zoom wurde das vorher riesig (Toolbar skalierte mit
// hoch), bei fernem Zoom unbenutzbar winzig — Nutzer-Report. Die
// Editor-Breite folgt bei der Textspalte trotzdem der Modell-Breite,
// aber über eine FESTE (nicht Live-Zoom-)Umrechnung, damit der Rahmen
// nicht bei jedem Rein-/Rauszoomen während des Tippens die Zeilen
// neu umbricht.
const EDIT_PX_PER_M = 220;
const topAnchor = toScreen({ x: prim.at.x, y: prim.at.y + prim.heightM }); const topAnchor = toScreen({ x: prim.at.x, y: prim.at.y + prim.heightM });
const screen = vbToClient(topAnchor.x, topAnchor.y); const screen = vbToClient(topAnchor.x, topAnchor.y);
const FONT_PX_AT_12PT = 16; // 12pt @ 96dpi (RichTextEditor-Default, s. LayoutSheet.tsx).
const scale = (prim.heightM * pxPerM) / FONT_PX_AT_12PT;
// MIT wrapWidth (Textspalte): feste Breite, Editor bricht live um (nowrap
// AUS). OHNE (Text-Werkzeug): keine feste Breite — `.planview-inline-text
// .rt-surface` steht auf nowrap (s. styles.css), die Box wächst mit jedem
// Zeichen; eine Mindestbreite verhindert eine unsichtbare 0px-Box beim
// leeren Start (der eigentliche Grund, warum der Anker bisher unsichtbar
// blieb — `width:undefined` kollabierte auf shrink-to-fit von NICHTS).
const hasWrap = !!prim.wrapWidth; const hasWrap = !!prim.wrapWidth;
const widthPx = hasWrap ? (prim.wrapWidth! * pxPerM) / scale : undefined; const widthPx = hasWrap ? prim.wrapWidth! * EDIT_PX_PER_M : undefined;
const minWidthPx = hasWrap ? undefined : 160; const minWidthPx = hasWrap ? undefined : 160;
// Aufgezogener Textspalten-Rahmen (textbox.ts): dessen Höhe als // Aufgezogener Textspalten-Rahmen (textbox.ts): dessen Höhe als
// Mindesthöhe des Editors — wächst bei mehr Text darüber hinaus. // Mindesthöhe des Editors — wächst bei mehr Text darüber hinaus.
const minHeightPx = editTextMinHeightM ? (editTextMinHeightM * pxPerM) / scale : undefined; const minHeightPx = editTextMinHeightM ? editTextMinHeightM * EDIT_PX_PER_M : undefined;
return ( return (
<> <>
<div <div
@@ -2527,8 +2528,6 @@ export const PlanView = forwardRef<PlanViewHandle, PlanViewProps>(
width: widthPx, width: widthPx,
minWidth: minWidthPx, minWidth: minWidthPx,
minHeight: minHeightPx, minHeight: minHeightPx,
transform: `scale(${scale})`,
transformOrigin: "0 0",
}} }}
onPointerDown={(e) => e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()}
onKeyDown={(e) => { onKeyDown={(e) => {