feat: canvas options
This commit is contained in:
@@ -34,8 +34,6 @@ export type CanvasMenubarProps = {
|
||||
canDuplicate?: boolean
|
||||
canCopy?: boolean
|
||||
onFitView?: () => void
|
||||
showMinimap?: boolean
|
||||
onToggleMinimap?: (visible: boolean) => void
|
||||
}
|
||||
|
||||
const UNDO_KEYS = { key: 'z', shiftKey: false }
|
||||
@@ -59,8 +57,6 @@ export function CanvasMenubar({
|
||||
canDuplicate = false,
|
||||
canCopy = false,
|
||||
onFitView,
|
||||
showMinimap = false,
|
||||
onToggleMinimap,
|
||||
}: CanvasMenubarProps) {
|
||||
const { projectId } = useParams<{ projectId: string }>()
|
||||
const { projects, renameProject } = usePlatform()
|
||||
@@ -233,18 +229,6 @@ export function CanvasMenubar({
|
||||
</span>
|
||||
</MenubarItem>
|
||||
)}
|
||||
{onToggleMinimap != null && (
|
||||
<>
|
||||
<MenubarSeparator />
|
||||
<MenubarCheckboxItem
|
||||
checked={showMinimap}
|
||||
onCheckedChange={(checked) => onToggleMinimap(checked)}
|
||||
className="gap-2"
|
||||
>
|
||||
Minimap
|
||||
</MenubarCheckboxItem>
|
||||
</>
|
||||
)}
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
</Menubar>
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
import { AnimatedEdge } from '@/components/base/AnimatedEdge'
|
||||
import FlowContext from '@/lib/flowContext'
|
||||
import { useTheme } from '@/lib/themeContext'
|
||||
import { usePlatform } from '@/app/platform/platformContext'
|
||||
import { useGraphStateWithHistory } from '@/hooks/useGraphStateWithHistory'
|
||||
import {
|
||||
ContextMenu,
|
||||
@@ -148,6 +149,7 @@ function getInitialGraph(projectId: string | undefined): { nodes: AppNode[]; edg
|
||||
|
||||
export function CanvasPage({ projectId }: CanvasPageProps) {
|
||||
const { theme } = useTheme()
|
||||
const { showMinimap } = usePlatform()
|
||||
const initialGraph = useMemo(() => getInitialGraph(projectId), [projectId])
|
||||
const {
|
||||
nodes,
|
||||
@@ -190,7 +192,6 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
||||
const [lastCreatedNodeId, setLastCreatedNodeId] = React.useState<string | null>(null)
|
||||
const [isPanning, setIsPanning] = React.useState(false)
|
||||
const [isSelecting, setIsSelecting] = React.useState(false)
|
||||
const [showMinimap, setShowMinimap] = React.useState(false)
|
||||
const [ariaAnnouncement, setAriaAnnouncement] = React.useState<string | null>(null)
|
||||
const nodesRef = useRef(nodes)
|
||||
nodesRef.current = nodes
|
||||
@@ -570,8 +571,6 @@ export function CanvasPage({ projectId }: CanvasPageProps) {
|
||||
canDuplicate={selectedNodes.length > 0}
|
||||
canCopy={selectedNodes.length === 1}
|
||||
onFitView={() => flowActionsRef.current?.fitView?.()}
|
||||
showMinimap={showMinimap}
|
||||
onToggleMinimap={setShowMinimap}
|
||||
/>
|
||||
{apiTodosCount !== null && (
|
||||
<div className="shrink-0 px-3 py-1 text-xs text-muted-foreground border-b border-border/50">
|
||||
|
||||
@@ -18,8 +18,10 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { useTheme } from '@/lib/themeContext'
|
||||
import type { Theme } from '@/lib/themeContext'
|
||||
import { usePlatform } from './platformContext'
|
||||
import { Sun, Sparkles } from 'lucide-react'
|
||||
|
||||
type SettingsSection = 'appearance' | 'ai'
|
||||
@@ -32,6 +34,7 @@ export function SettingsDialog({
|
||||
const [open, setOpen] = useState(false)
|
||||
const [section, setSection] = useState<SettingsSection>('appearance')
|
||||
const { theme, setTheme } = useTheme()
|
||||
const { showMinimap, setShowMinimap } = usePlatform()
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
@@ -88,6 +91,21 @@ export function SettingsDialog({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-3 pt-2 border-t">
|
||||
<h4 className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||
Canvas
|
||||
</h4>
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-center">
|
||||
<label htmlFor="settings-minimap" className="text-sm font-medium">
|
||||
Minimap
|
||||
</label>
|
||||
<Switch
|
||||
id="settings-minimap"
|
||||
checked={showMinimap}
|
||||
onCheckedChange={setShowMinimap}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{section === 'ai' && (
|
||||
|
||||
@@ -11,8 +11,24 @@ import { PROJECT_VERSION } from './projectGraphStorage'
|
||||
const STORAGE_KEY = 'zui_platform_projects'
|
||||
const ORDER_STORAGE_KEY = 'zui_platform_project_order'
|
||||
const RECENT_STORAGE_KEY = 'zui_platform_recent_project_ids'
|
||||
const CANVAS_MINIMAP_KEY = 'zui_canvas_show_minimap'
|
||||
const RECENT_MAX = 5
|
||||
|
||||
function loadShowMinimap(): boolean {
|
||||
try {
|
||||
const raw = localStorage.getItem(CANVAS_MINIMAP_KEY)
|
||||
if (raw === 'true') return true
|
||||
if (raw === 'false') return false
|
||||
} catch {}
|
||||
return false
|
||||
}
|
||||
|
||||
function saveShowMinimap(value: boolean) {
|
||||
try {
|
||||
localStorage.setItem(CANVAS_MINIMAP_KEY, JSON.stringify(value))
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function loadOrder(): string[] {
|
||||
try {
|
||||
const raw = localStorage.getItem(ORDER_STORAGE_KEY)
|
||||
@@ -107,6 +123,9 @@ export type PlatformContextValue = {
|
||||
updateLastEdited: (id: string) => void
|
||||
reorderProjects: (orderedIds: string[]) => void
|
||||
restoreProject: (project: Project, graphSnapshot: GraphSnapshot | null) => void
|
||||
/** Canvas: show React Flow minimap (persisted) */
|
||||
showMinimap: boolean
|
||||
setShowMinimap: (value: boolean) => void
|
||||
}
|
||||
|
||||
const PlatformContext = createContext<PlatformContextValue | null>(null)
|
||||
@@ -115,6 +134,12 @@ export function PlatformProvider({ children }: { children: React.ReactNode }) {
|
||||
const [projects, setProjects] = useState<Project[]>(loadProjects)
|
||||
const [projectOrder, setProjectOrder] = useState<string[]>(loadOrder)
|
||||
const [recentProjectIds, setRecentProjectIds] = useState<string[]>(loadRecentIds)
|
||||
const [showMinimap, setShowMinimapState] = useState<boolean>(loadShowMinimap)
|
||||
|
||||
const setShowMinimap = useCallback((value: boolean) => {
|
||||
setShowMinimapState(value)
|
||||
saveShowMinimap(value)
|
||||
}, [])
|
||||
|
||||
const persist = useCallback((next: Project[]) => {
|
||||
setProjects(next)
|
||||
@@ -220,6 +245,8 @@ export function PlatformProvider({ children }: { children: React.ReactNode }) {
|
||||
updateLastEdited,
|
||||
reorderProjects,
|
||||
restoreProject,
|
||||
showMinimap,
|
||||
setShowMinimap,
|
||||
}),
|
||||
[
|
||||
projects,
|
||||
@@ -234,6 +261,8 @@ export function PlatformProvider({ children }: { children: React.ReactNode }) {
|
||||
updateLastEdited,
|
||||
reorderProjects,
|
||||
restoreProject,
|
||||
showMinimap,
|
||||
setShowMinimap,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user