"use client"; import { CalendarDays, ChartGantt, ArrowLeft, ArrowUpRight, Bold, ChevronDown, Copy, FileText, FolderOpen, GitBranchPlus, GitMerge, Hand, Image as ImageIcon, Italic, ListPlus, Link2, StickyNote, Maximize, Minus, MousePointer2, Network, PanelRight, Pencil, Plus, Redo2, Save, Shapes, Tag, Trash2, Type, Underline, Undo2, Upload, Download, X, type LucideIcon, } from "lucide-react"; import { type ReactNode, useState } from "react"; import { Home, Smile, Scan, Search, MoreHorizontal, AlignLeft, AlignCenter, AlignRight, Presentation, SlidersHorizontal } from "lucide-react"; import { XmindCommandMenu } from "./xmind-command-menu"; export type FlowBoardToolId = | "selection" | "hand" | "mind" | "text" | "arrow" | "shape" | "image"; export type FlowBoardSheetTab = { id: string; title: string; }; export type FlowBoardLayoutOption = { id: string; label: string; preview: | "both" | "right" | "left" | "down" | "up" | "indent" | "fishbone" | "timeline" | "brace" | "verticalTimeline" | "treeTable" | "treeTableSide" | "spreadsheet"; }; export type FlowBoardThemeOption = { id: string; label: string; colors: [string, string, string]; }; function LayoutPreview({ direction, }: { direction: FlowBoardLayoutOption["preview"]; }) { const horizontal = direction === "right" || direction === "left"; const vertical = direction === "down" || direction === "up"; const leaf = (x: number, y: number) => ( ); const root = (x: number, y: number) => ( ); return ( ); } export function XmindEditorTopBar({ activeTool, canEditMind, currentTitle, formatPanelOpen, markerPanelOpen, isSaving, onBack, onImport, onExport, onExportImage, isExporting, onInsertChild, onInsertSibling, onRelationship, onBoundary, relationshipPending, onOpenFiles, onRedo, onSave, onSummary, onTopicDetails, onTitleChange, onTitleCommit, onToggleFormat, onToggleMarkers, onToolChange, onUndo, siteName, onSearch, onToggleZen, onToggleOutline, onPresentation, onTask, onGantt, }: { activeTool: FlowBoardToolId; canEditMind: boolean; currentTitle: string; formatPanelOpen: boolean; markerPanelOpen: boolean; isSaving: boolean; onBack: () => void; onImport: () => void; onExport: () => void; onExportImage: () => void; isExporting: boolean; onInsertChild: () => void; onInsertSibling: () => void; onRelationship: () => void; onBoundary: () => void; relationshipPending: boolean; onOpenFiles: () => void; onRedo: () => void; onSave: () => void; onSummary: () => void; onTopicDetails: (section: "notes" | "links" | "labels") => void; onTitleChange: (value: string) => void; onTitleCommit: () => void; onToggleFormat: () => void; onToggleMarkers: () => void; onToolChange: (tool: FlowBoardToolId) => void; onUndo: () => void; siteLogo: string | null; siteName: string; onTask: () => void; onGantt: () => void; onSearch: () => void; onToggleZen: () => void; onToggleOutline: () => void; onPresentation: () => void; }) { const nativeIcons: Record = {"同级主题":"topic","子主题":"subtopic","联系":"relationship","概要":"summary","外框":"boundary","ZEN 模式":"zen","演示":"pitch","格式":"sidebar","标记":"marker","导出 XMind":"export"}; const action = (label: string, Icon: LucideIcon, run: () => void, disabled = false, active = false) => ( ); return
onTitleChange(e.target.value)} onBlur={onTitleCommit} onKeyDown={e => { if (e.key === "Enter") e.currentTarget.blur(); }} /> {isSaving ? "正在保存…" : "已编辑"}
onToolChange("selection")}, {label:"画布",icon:Hand,checked:activeTool === "hand",run:() => onToolChange("hand")}, ]}>
{action("导出 XMind", Download, onExport, isExporting)}导出
{action("ZEN 模式", Scan, onToggleZen)} {action("大纲视图", FileText, onToggleOutline)} {action("演示", Presentation, onPresentation)}
{action("标记", Smile, onToggleMarkers, false, markerPanelOpen)} {action("格式", PanelRight, onToggleFormat, false, formatPanelOpen)}
; } export function XmindFormatPanel({ activeLayoutId, activeThemeId, branchColor, branchShape, branchWidth, canvasBackgroundColor, canvasGridColor, canvasGridEnabled, canvasGridSize, fontSize, isBold, isItalic, isUnderlined, layouts, nodeFill, nodeShape, onBranchColorChange, onBranchShapeChange, onBranchWidthChange, onCanvasBackgroundColorChange, onCanvasGridColorChange, onCanvasGridEnabledChange, onCanvasGridSizeChange, onClose, onFontSizeChange, onLayoutChange, onNodeFillChange, onNodeShapeChange, onTextColorChange, onThemeChange, onToggleTextMark, selectedCount, textColor, themes, }: { activeLayoutId: string; activeThemeId: string; branchColor: string; branchShape: "bight" | "polyline"; branchWidth: number; canvasBackgroundColor: string; canvasGridColor: string; canvasGridEnabled: boolean; canvasGridSize: number; fontSize: string; isBold: boolean; isItalic: boolean; isUnderlined: boolean; layouts: FlowBoardLayoutOption[]; nodeFill: string; nodeShape: "round-rectangle" | "underline"; onBranchColorChange: (value: string) => void; onBranchShapeChange: (value: "bight" | "polyline") => void; onBranchWidthChange: (value: number) => void; onCanvasBackgroundColorChange: (value: string) => void; onCanvasGridColorChange: (value: string) => void; onCanvasGridEnabledChange: (value: boolean) => void; onCanvasGridSizeChange: (value: number) => void; onClose: () => void; onFontSizeChange: (value: string) => void; onLayoutChange: (value: string) => void; onNodeFillChange: (value: string) => void; onNodeShapeChange: (value: "round-rectangle" | "underline") => void; onTextColorChange: (value: string) => void; onThemeChange: (value: string) => void; onToggleTextMark: (mark: "bold" | "italic" | "underlined") => void; selectedCount: number; textColor: string; themes: FlowBoardThemeOption[]; }) { const [activePanel, setActivePanel] = useState<"format" | "canvas">("format"); const [structuresOpen, setStructuresOpen] = useState(false); const activeLayout = layouts.find(layout => layout.id === activeLayoutId) || layouts[0]; const colorControl = (label: string, value: string, change: (value: string) => void, disabled = false) => ( change(e.target.value)} className="xmind-color-control" /> ); return ; } export function XmindSheetBar({ outlineOpen, onToggleOutline, activeSheetId, formatPanelOpen, onAddSheet, onDeleteSheet, onDuplicateSheet, onFit, onRenameSheet, onSwitchSheet, onZoomIn, onZoomOut, onZoomTo, sheets, zoomPercent, topicCount, selectedCount, }: { outlineOpen: boolean; onToggleOutline: () => void; activeSheetId: string; formatPanelOpen: boolean; onAddSheet: () => void; onDeleteSheet: (id: string) => void; onDuplicateSheet: (id: string) => void; onFit: () => void; onRenameSheet: (id: string, title: string) => void; onSwitchSheet: (id: string) => void; onZoomIn: () => void; onZoomOut: () => void; onZoomTo: (value: number) => void; sheets: FlowBoardSheetTab[]; zoomPercent: number; topicCount: number; selectedCount: number; }) { const [renamingSheetId, setRenamingSheetId] = useState(null); const [renameDraft, setRenameDraft] = useState(""); const [contextId, setContextId] = useState(null); const activeSheet = sheets.find(sheet => sheet.id === activeSheetId); const rename = (id: string) => { const sheet = sheets.find(item => item.id === id); if (sheet) { setRenamingSheetId(id); setRenameDraft(sheet.title); } }; const commitRename = () => { if (renamingSheetId && renameDraft.trim()) onRenameSheet(renamingSheetId,renameDraft.trim()); setRenamingSheetId(null); }; return ; }