diff --git a/packages/learningmap/src/EditorCanvas.tsx b/packages/learningmap/src/EditorCanvas.tsx index 5abb721..74db906 100644 --- a/packages/learningmap/src/EditorCanvas.tsx +++ b/packages/learningmap/src/EditorCanvas.tsx @@ -1,5 +1,5 @@ -import { useCallback, memo } from "react"; -import { ReactFlow, Controls, Background, ControlButton, OnSelectionChangeFunc, Node, Edge } from "@xyflow/react"; +import { useCallback, memo, useEffect } from "react"; +import { ReactFlow, Controls, Background, ControlButton, OnSelectionChangeFunc, Node, Edge, useReactFlow } from "@xyflow/react"; import { Info, Redo, Undo } from "lucide-react"; import { useEditorStore, useTemporalStore } from "./editorStore"; import { TaskNode } from "./nodes/TaskNode"; @@ -45,9 +45,22 @@ export const EditorCanvas = memo(({ defaultLanguage = "en" }: EditorCanvasProps) const setEdgeDrawerOpen = useEditorStore(state => state.setEdgeDrawerOpen); const setHelpOpen = useEditorStore(state => state.setHelpOpen); + const { setViewport } = useReactFlow(); + const language = settings?.language || defaultLanguage; const t = getTranslations(language); + // Apply viewport from settings on mount or when settings change + useEffect(() => { + if (settings?.viewport) { + setViewport({ + x: settings.viewport.x, + y: settings.viewport.y, + zoom: settings.viewport.zoom, + }); + } + }, [settings?.viewport, setViewport]); + // Temporal store for undo/redo const { undo, redo, canUndo, canRedo } = useTemporalStore((state) => ({ undo: state.undo, @@ -105,7 +118,6 @@ export const EditorCanvas = memo(({ defaultLanguage = "en" }: EditorCanvasProps) nodeTypes={nodeTypes} selectionOnDrag={false} edgeTypes={edgeTypes} - fitView proOptions={{ hideAttribution: true }} defaultEdgeOptions={defaultEdgeOptions} nodesDraggable={true} diff --git a/packages/learningmap/src/LearningMap.tsx b/packages/learningmap/src/LearningMap.tsx index da3cb11..0e9dd31 100644 --- a/packages/learningmap/src/LearningMap.tsx +++ b/packages/learningmap/src/LearningMap.tsx @@ -81,9 +81,9 @@ export function LearningMap({ useEffect(() => { loadRoadmapData(parsedRoadmap, initialState); setViewport({ - x: initialState?.x || 0, - y: initialState?.y || 0, - zoom: initialState?.zoom || 1, + x: initialState?.x || settings?.viewport?.x || 0, + y: initialState?.y || settings?.viewport?.y || 0, + zoom: initialState?.zoom || settings?.viewport?.zoom || 1, }); }, [roadmapData, initialState]); diff --git a/packages/learningmap/src/SettingsDrawer.tsx b/packages/learningmap/src/SettingsDrawer.tsx index d292cd6..f36b7f8 100644 --- a/packages/learningmap/src/SettingsDrawer.tsx +++ b/packages/learningmap/src/SettingsDrawer.tsx @@ -44,6 +44,18 @@ export const SettingsDrawer: React.FC = ({ onClose(); }; + const handleUseCurrentViewport = () => { + const viewport = getViewport(); + setLocalSettings(settings => ({ + ...settings, + viewport: { + x: Math.round(viewport.x), + y: Math.round(viewport.y), + zoom: parseFloat(viewport.zoom.toFixed(2)), + } + })); + }; + return ( <>
@@ -82,6 +94,59 @@ export const SettingsDrawer: React.FC = ({ onChange={color => setLocalSettings(settings => ({ ...settings, background: { ...settings.background, color } }))} />
+ +
+ +
+
+ + setLocalSettings(settings => ({ + ...settings, + viewport: { ...settings.viewport, x: parseFloat(e.target.value) || 0, y: settings.viewport?.y ?? 0, zoom: settings.viewport?.zoom ?? 1 } + }))} + style={{ width: '100%' }} + /> +
+
+ + setLocalSettings(settings => ({ + ...settings, + viewport: { ...settings.viewport, y: parseFloat(e.target.value) || 0, x: settings.viewport?.x ?? 0, zoom: settings.viewport?.zoom ?? 1 } + }))} + style={{ width: '100%' }} + /> +
+
+ + setLocalSettings(settings => ({ + ...settings, + viewport: { ...settings.viewport, zoom: parseFloat(e.target.value) || 1, x: settings.viewport?.x ?? 0, y: settings.viewport?.y ?? 0 } + }))} + style={{ width: '100%' }} + /> +
+
+ +
diff --git a/packages/learningmap/src/translations.ts b/packages/learningmap/src/translations.ts index 12cbfb0..772fda4 100644 --- a/packages/learningmap/src/translations.ts +++ b/packages/learningmap/src/translations.ts @@ -184,6 +184,13 @@ export interface Translations { languageEnglish: string; languageGerman: string; + // Viewport settings + initialViewport: string; + viewportX: string; + viewportY: string; + viewportZoom: string; + useCurrentViewport: string; + // Welcome message welcomeTitle: string; welcomeSubtitle: string; @@ -380,6 +387,13 @@ const en: Translations = { languageEnglish: "English", languageGerman: "German", + // Viewport settings + initialViewport: "Initial Viewport", + viewportX: "X Position", + viewportY: "Y Position", + viewportZoom: "Zoom", + useCurrentViewport: "Use Current Viewport", + // Welcome message welcomeTitle: "Learningmap", welcomeSubtitle: "All data is stored locally in your browser", @@ -578,6 +592,13 @@ const de: Translations = { languageEnglish: "Englisch", languageGerman: "Deutsch", + // Viewport settings + initialViewport: "Initialer Ansichtsbereich", + viewportX: "X-Position", + viewportY: "Y-Position", + viewportZoom: "Zoom", + useCurrentViewport: "Aktuellen Ansichtsbereich verwenden", + // Welcome message welcomeTitle: "Learningmap", welcomeSubtitle: "Alle Daten werden lokal in Ihrem Browser gespeichert",