'use client' import { useState, useEffect, useCallback } from 'react' import { useTheme } from '@/lib/ThemeContext' import { useLanguage } from '@/lib/LanguageContext' import { useWorksheet } from '@/lib/worksheet-editor/WorksheetContext' import { AVAILABLE_FONTS, DEFAULT_TYPOGRAPHY_PRESETS } from '@/app/worksheet-editor/types' interface PropertiesPanelProps { className?: string } export function PropertiesPanel({ className = '' }: PropertiesPanelProps) { const { isDark } = useTheme() const { t } = useLanguage() const { selectedObjects, canvas, saveToHistory } = useWorksheet() // Local state for properties const [fontFamily, setFontFamily] = useState('Arial') const [fontSize, setFontSize] = useState(16) const [fontWeight, setFontWeight] = useState<'normal' | 'bold'>('normal') const [fontStyle, setFontStyle] = useState<'normal' | 'italic'>('normal') const [textAlign, setTextAlign] = useState<'left' | 'center' | 'right'>('left') const [lineHeight, setLineHeight] = useState(1.4) const [charSpacing, setCharSpacing] = useState(0) const [fill, setFill] = useState('#000000') const [stroke, setStroke] = useState('#000000') const [strokeWidth, setStrokeWidth] = useState(2) const [opacity, setOpacity] = useState(100) // Get selected object (cast to any for Fabric.js properties) const selectedObject = selectedObjects[0] as any const objType = selectedObject?.type const isText = objType === 'i-text' || objType === 'text' || objType === 'textbox' const isShape = objType === 'rect' || objType === 'circle' || objType === 'line' || objType === 'path' const isImage = objType === 'image' // Update local state when selection changes useEffect(() => { if (!selectedObject) return if (isText) { setFontFamily(selectedObject.fontFamily || 'Arial') setFontSize(selectedObject.fontSize || 16) setFontWeight(selectedObject.fontWeight || 'normal') setFontStyle(selectedObject.fontStyle || 'normal') setTextAlign(selectedObject.textAlign || 'left') setLineHeight(selectedObject.lineHeight || 1.4) setCharSpacing(selectedObject.charSpacing || 0) setFill(selectedObject.fill || '#000000') } if (isShape) { setFill(selectedObject.fill || 'transparent') setStroke(selectedObject.stroke || '#000000') setStrokeWidth(selectedObject.strokeWidth || 2) } setOpacity(Math.round((selectedObject.opacity || 1) * 100)) }, [selectedObject, isText, isShape]) // Update object property const updateProperty = useCallback((property: string, value: any) => { if (!selectedObject || !canvas) return selectedObject.set(property, value) canvas.renderAll() saveToHistory(`property:${property}`) }, [selectedObject, canvas, saveToHistory]) // Glassmorphism styles const panelStyle = isDark ? 'backdrop-blur-xl bg-white/10 border border-white/20' : 'backdrop-blur-xl bg-white/70 border border-black/10 shadow-xl' const inputStyle = isDark ? 'bg-white/10 border-white/20 text-white placeholder-white/40 focus:border-purple-400' : 'bg-white/50 border-black/10 text-slate-900 placeholder-slate-400 focus:border-purple-500' const labelStyle = isDark ? 'text-white/70' : 'text-slate-600' const selectStyle = isDark ? 'bg-white/10 border-white/20 text-white' : 'bg-white/50 border-black/10 text-slate-900' // No selection if (!selectedObject) { return (

Eigenschaften

Wählen Sie ein Element aus, um seine Eigenschaften zu bearbeiten.

) } return (

Eigenschaften

{/* Text Properties */} {isText && (
{/* Typography Presets */}
{/* Font Family */}
{/* Font Size */}
{ const value = parseInt(e.target.value) setFontSize(value) updateProperty('fontSize', value) }} className="flex-1" /> { const value = parseInt(e.target.value) || 16 setFontSize(value) updateProperty('fontSize', value) }} className={`w-16 px-2 py-1 rounded-lg border text-sm text-center ${inputStyle}`} />
{/* Font Style Buttons */}
{/* Text Alignment */}
{(['left', 'center', 'right'] as const).map(align => ( ))}
{/* Line Height */}
{ const value = parseFloat(e.target.value) setLineHeight(value) updateProperty('lineHeight', value) }} className="flex-1" /> {lineHeight.toFixed(1)}
{/* Text Color */}
{ setFill(e.target.value) updateProperty('fill', e.target.value) }} className="w-10 h-10 rounded-lg cursor-pointer" /> { setFill(e.target.value) updateProperty('fill', e.target.value) }} className={`flex-1 px-3 py-2 rounded-xl border text-sm ${inputStyle}`} />
)} {/* Shape Properties */} {isShape && (
{/* Fill Color */}
{ setFill(e.target.value) updateProperty('fill', e.target.value) }} className="w-10 h-10 rounded-lg cursor-pointer" /> { setFill(e.target.value) updateProperty('fill', e.target.value) }} className={`flex-1 px-3 py-2 rounded-xl border text-sm ${inputStyle}`} />
{/* Stroke Color */}
{ setStroke(e.target.value) updateProperty('stroke', e.target.value) }} className="w-10 h-10 rounded-lg cursor-pointer" /> { setStroke(e.target.value) updateProperty('stroke', e.target.value) }} className={`flex-1 px-3 py-2 rounded-xl border text-sm ${inputStyle}`} />
{/* Stroke Width */}
{ const value = parseInt(e.target.value) setStrokeWidth(value) updateProperty('strokeWidth', value) }} className="flex-1" /> {strokeWidth}px
)} {/* Image Properties */} {isImage && (

Bildgröße und Position können durch Ziehen der Eckpunkte angepasst werden.

)} {/* Common Properties */}
{/* Opacity */}
{ const value = parseInt(e.target.value) setOpacity(value) updateProperty('opacity', value / 100) }} className="flex-1" /> {opacity}%
{/* Delete Button */}
) }