import { useEffect, useState } from 'react' import Icon from './components/Icon' import { onMessage, notifyReady } from './lib/rhinoBridge' function send(type, payload = {}) { if (!window.RHINO_MODE) { console.log('[LayoutDialog] →', type, payload); return } document.title = 'RHINOMSG::' + JSON.stringify({ type, payload }) } const PAPER_SIZES = ['A4', 'A3', 'A2', 'A1', 'A0', 'Letter'] export default function LayoutDialogApp() { const initial = (typeof window !== 'undefined' && window.PANEL_PARAMS) || {} const [mode, setMode] = useState(initial.mode || 'new') const [layout, setLayout] = useState(initial.layout || null) const [name, setName] = useState('') const [format, setFormat] = useState('A3') const [landscape, setLandscape] = useState(true) const [cw, setCw] = useState('420') const [ch, setCh] = useState('297') useEffect(() => { onMessage('LAYOUT_DIALOG_STATE', (p) => { if (p.mode) setMode(p.mode) if (p.layout) { setLayout(p.layout) if (p.mode === 'edit') { setFormat('custom') setCw(String(Math.round(p.layout.width || 420))) setCh(String(Math.round(p.layout.height || 297))) } } }) notifyReady() const blockContext = (ev) => ev.preventDefault() document.addEventListener('contextmenu', blockContext) return () => document.removeEventListener('contextmenu', blockContext) }, []) const editing = mode === 'edit' const submit = () => { const payload = { name: name.trim(), format, landscape } if (format === 'custom') { const w = parseFloat(cw), h = parseFloat(ch) if (!(w > 0) || !(h > 0)) { alert('Bitte gültige Größe eingeben.'); return } payload.customWidth = w payload.customHeight = h } send('SAVE', payload) } return (
{/* Body */}
{!editing && ( setName(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') submit() }} placeholder="z.B. Grundriss EG" autoFocus style={{ width: '100%', fontSize: 12, padding: '6px 8px' }} /> )}
{PAPER_SIZES.map(f => ( ))}
{format === 'custom' ? (
setCw(e.target.value)} placeholder="Breite" style={{ flex: 1, fontFamily: 'DM Mono, monospace', fontSize: 12, textAlign: 'right', padding: '6px 8px' }} /> × setCh(e.target.value)} placeholder="Höhe" style={{ flex: 1, fontFamily: 'DM Mono, monospace', fontSize: 12, textAlign: 'right', padding: '6px 8px' }} /> mm
) : (
)} {/* Preview */}
{/* Footer */}
) } function Field({ label, children }) { return (
{label} {children}
) } const PAPER_DIMS = { A0: [841, 1189], A1: [594, 841], A2: [420, 594], A3: [297, 420], A4: [210, 297], Letter: [216, 279], } function FormatPreview({ format, landscape, customW, customH }) { let w, h if (format === 'custom') { w = customW; h = customH } else { const dims = PAPER_DIMS[format] if (!dims) return null w = dims[0]; h = dims[1] if (landscape) { w = dims[1]; h = dims[0] } } if (!(w > 0) || !(h > 0)) return null const MAX = 120 const scale = Math.min(MAX / w, MAX / h) const pw = w * scale, ph = h * scale return (
{Math.round(w)} × {Math.round(h)} mm
) }