feat: click-drag drawing, layer tree, settings modal, UI improvements

- interaction: click-drag drawing for 2-point tools (line, rect, circle, dimension, leader)
- interaction: preview rendering during drag with setPreviewElement
- interaction: handleDrawDown only sets phase=drawing on first point
- CanvasArea: sync activeLayerId to LayerManager
- CanvasArea: callback refresh useEffect prevents stale closures
- App.tsx: functional setElements updates for handleElementCreated/Deleted/Modified
- LayerPanel: tree structure with sub-layers (onReorder, onAddSubLayer)
- TreeView: drag-and-drop reordering support
- RightSidebar: onReorder, onAddSubLayer, onUpdateElement props
- PropertiesPanel: onUpdateElement prop
- SettingsModal: personal/password/language/theme/users/plugins/AI tabs
- styles.css: extensive UI styling additions
- types: updated RightSidebarProps, CanvasAreaProps, LayerPanelProps
This commit is contained in:
2026-06-27 14:12:37 +02:00
parent 39422a4348
commit 4303076ce4
17 changed files with 929 additions and 144 deletions
+9 -21
View File
@@ -11,17 +11,10 @@ import { SelectionEngine } from '../canvas/SelectionEngine';
import { SpatialIndex } from '../canvas/SpatialIndex';
import { LayerManager } from '../canvas/LayerManager';
const viewTabs: Array<{ mode: ViewMode; label: string }> = [
{ mode: '2d', label: '2D' },
{ mode: 'iso', label: 'ISO' },
{ mode: 'front', label: 'Front' },
{ mode: 'top', label: 'Top' },
];
const CanvasArea: React.FC<CanvasAreaProps> = ({
cursorPos, viewMode, onViewChange, gridEnabled, orthoEnabled, snapEnabled,
polarEnabled,
activeTool, elements, layers, onElementCreated, onElementsDeleted, onElementsModified, onCursorMoved, onToolStateChanged,
activeTool, elements, layers, activeLayerId, onElementCreated, onElementsDeleted, onElementsModified, onCursorMoved, onToolStateChanged,
onToggleGrid, onToggleOrtho, onToggleSnap, onZoomIn, onZoomOut, onZoomFit, onTextEdit, onCommandTrigger, blocks, onBlockDrop, onSelectionChange, selectedTemplate, bgConfig, remoteCursors,
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
@@ -156,6 +149,14 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [blocks]);
// Sync active layer to LayerManager
useEffect(() => {
const layerManager = layerManagerRef.current;
if (!layerManager || !activeLayerId) return;
layerManager.setActiveLayer(activeLayerId);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeLayerId, layers]);
// Sync grid/snap/ortho toggles
useEffect(() => {
const renderEngine = renderEngineRef.current;
@@ -261,19 +262,6 @@ const CanvasArea: React.FC<CanvasAreaProps> = ({
<span style={{ color: 'var(--color-text-faint)' }}>m</span>
</div>
<div className="canvas-view-tabs" role="tablist" aria-label="Ansicht umschalten">
{viewTabs.map((tab) => (
<button
key={tab.mode}
className={`canvas-view-tab${viewMode === tab.mode ? ' active' : ''}`}
data-view={tab.mode}
onClick={() => onViewChange(tab.mode)}
>
{tab.label}
</button>
))}
</div>
<canvas
ref={canvasRef}
className="canvas-svg"