Text-Editor: Default-Stile + Stil-Picker im Dialog
User-Wunsch: vorgespeicherte Stile (Heading, Paragraph Helvetica/Georgia) direkt im Editor anwendbar. Backend (text_create.py): - _DEFAULT_STYLES: 7 sinnvolle Architektur-Defaults — Titel (0.40m bold), Heading 1 (0.30m bold), Heading 2 (0.20m bold), Paragraph Helvetica (0.15m), Paragraph Georgia (0.15m Georgia), Notiz (0.10m italic), Bildlegende (0.08m italic) - list_styles: seedet die Defaults beim ersten Zugriff falls noch keine Styles im Doc existieren (analog mass_style) - Bestehende save_style/delete_style/apply_style funktionieren weiter Backend (text_editor.py): - INIT-Payload erweitert um styles[] (Liste aller verfuegbaren Stile mit id/name/font/size/bold/italic/underline/align) Frontend (TextEditorApp.jsx): - Neuer Stil-Picker als erstes Dropdown in Toolbar-Row 1 (150px) - Optionen: "— Stil wählen —" + alle verfuegbaren Stile - onChange: applyStyle(style) — setzt Toolbar-State + appliziert via execCommand auf die aktuelle Selektion im WYSIWYG-Editor (oder als Default fuer kommendes Tippen wenn keine Selektion) - queryCommandState-Check fuer Bold/Italic/Underline damit nur toggled wird wenn nicht schon im gewuenschten State Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+47
-1
@@ -207,11 +207,13 @@ export default function TextEditorApp() {
|
||||
const [rotation, setRotation] = useState(0)
|
||||
const [maskMargin, setMaskMargin] = useState(0)
|
||||
const [symbolsOpen, setSymbolsOpen] = useState(false)
|
||||
const [styles, setStyles] = useState([])
|
||||
const editorRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
onMessage('INIT', (data) => {
|
||||
setFonts(data.fonts || [])
|
||||
setStyles(data.styles || [])
|
||||
const s = data.settings || {}
|
||||
if (s.font) setFont(s.font)
|
||||
if (s.size != null) setSize(s.size)
|
||||
@@ -245,6 +247,37 @@ export default function TextEditorApp() {
|
||||
exec(a === 'center' ? 'justifyCenter' : a === 'right' ? 'justifyRight' : 'justifyLeft') }
|
||||
const doSup = () => exec('superscript')
|
||||
const doSub = () => exec('subscript')
|
||||
// Stil anwenden: Toolbar-State setzen + (wenn Auswahl im Editor) via
|
||||
// execCommand auf die Selektion applizieren.
|
||||
const applyStyle = (style) => {
|
||||
if (!style) return
|
||||
// Toolbar-State synchronisieren
|
||||
if (style.font) setFont(style.font)
|
||||
if (style.size != null) setSize(style.size)
|
||||
setBold(!!style.bold)
|
||||
setItalic(!!style.italic)
|
||||
setUnderline(!!style.underline)
|
||||
if (style.align) setAlign(style.align)
|
||||
// Auf Selektion applizieren (oder zumindest fuer kommendes Tippen)
|
||||
try {
|
||||
const sel = window.getSelection()
|
||||
const hasSel = sel && sel.rangeCount > 0 && sel.toString().length > 0
|
||||
document.execCommand('styleWithCSS', false, true)
|
||||
if (style.font) document.execCommand('fontName', false, style.font)
|
||||
// Bold/Italic/Underline togglen, falls Selektion da ist oder nicht
|
||||
const wantBold = !!style.bold
|
||||
const wantItal = !!style.italic
|
||||
const wantUnd = !!style.underline
|
||||
if (document.queryCommandState('bold') !== wantBold)
|
||||
document.execCommand('bold')
|
||||
if (document.queryCommandState('italic') !== wantItal)
|
||||
document.execCommand('italic')
|
||||
if (document.queryCommandState('underline') !== wantUnd)
|
||||
document.execCommand('underline')
|
||||
} catch (e) { console.error('applyStyle', e) }
|
||||
editorRef.current?.focus()
|
||||
}
|
||||
|
||||
const onColorPick = (hex) => {
|
||||
const m = hex.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i)
|
||||
if (m) setColor([parseInt(m[1],16), parseInt(m[2],16), parseInt(m[3],16)])
|
||||
@@ -279,8 +312,21 @@ export default function TextEditorApp() {
|
||||
background: 'var(--bg-panel)',
|
||||
boxSizing: 'border-box', overflow: 'hidden',
|
||||
}}>
|
||||
{/* Toolbar Row 1: Font | Size | Color | Layer-Reset */}
|
||||
{/* Toolbar Row 1: Stil | Font | Size | Color | Layer-Reset */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<Dropdown value=""
|
||||
onChange={(v) => {
|
||||
const st = styles.find(s => s.id === v)
|
||||
if (st) applyStyle(st)
|
||||
}}
|
||||
width={150}
|
||||
title="Text-Stil anwenden (auf Selektion oder als Default fuer kommendes Tippen)"
|
||||
options={[
|
||||
<option key="__none__" value="">— Stil wählen —</option>,
|
||||
...styles.map(s => (
|
||||
<option key={s.id} value={s.id}>{s.name}</option>
|
||||
)),
|
||||
]} />
|
||||
<Dropdown value={font} onChange={(v) => { setFont(v); exec('fontName', v) }}
|
||||
width={150} title="Schrift"
|
||||
options={
|
||||
|
||||
Reference in New Issue
Block a user