Files
mnote/wolai-frontend/src/components/editor/blocks/MindmapToolbar.tsx
T

278 lines
6.4 KiB
TypeScript

import React from "react";
import {
BoxSelect,
Braces,
Cable,
Download,
FileText,
FolderOpen,
Image as ImageIcon,
Link as LinkIcon,
PaintRoller,
Paperclip,
Plus,
Redo2,
Save,
Sigma,
Smile,
Sparkles,
StickyNote,
Tag,
Trash2,
Undo2,
} from "lucide-react";
type ToolbarProps = {
canBack: boolean;
canForward: boolean;
activeCount: number;
painterMode: boolean;
onUndo: () => void;
onRedo: () => void;
onPainter: () => void;
onSibling: () => void;
onChild: () => void;
onDelete: () => void;
onImage: () => void;
onIcon: () => void;
onLink: () => void;
onNote: () => void;
onTag: () => void;
onSummary: () => void;
onAssociativeLine: () => void;
onFormula: () => void;
onAttachment: () => void;
onOuterFrame: () => void;
onAi: () => void;
onImport: (e: React.ChangeEvent<HTMLInputElement>) => void;
onNew: () => void;
onOpenDirectory: () => void;
onSaveAs: () => void;
onExportJson: () => void;
onExportPng: () => void;
fileInputRef: React.RefObject<HTMLInputElement>;
};
const ToolbarButton = ({
icon: Icon,
label,
onClick,
disabled = false,
active = false,
className = "",
}: {
icon: React.ElementType;
label: string;
onClick?: () => void;
disabled?: boolean;
active?: boolean;
className?: string;
}) => (
<button
type="button"
onClick={onClick}
disabled={disabled}
className={`flex flex-col items-center justify-center gap-1 px-2 py-1 transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-40 ${
active ? "bg-blue-50 text-blue-600" : "text-gray-600"
} ${className}`}
title={label}
>
<div
className={`flex h-7 w-7 items-center justify-center rounded border shadow-sm transition-colors ${
active ? "border-blue-200 bg-white" : "border-gray-200 bg-white"
}`}
>
<Icon className="h-4 w-4" />
</div>
<span className="text-[10px] font-medium leading-tight">{label}</span>
</button>
);
const Divider = () => <div className="mx-1 h-8 w-px bg-gray-200" />;
export const MindmapToolbar = ({
canBack,
canForward,
activeCount,
painterMode,
onUndo,
onRedo,
onPainter,
onSibling,
onChild,
onDelete,
onImage,
onIcon,
onLink,
onNote,
onTag,
onSummary,
onAssociativeLine,
onFormula,
onAttachment,
onOuterFrame,
onAi,
onImport,
onNew,
onOpenDirectory,
onSaveAs,
onExportJson,
onExportPng,
fileInputRef,
}: ToolbarProps) => {
return (
<div className="flex w-full items-center justify-between gap-4 overflow-x-auto pb-2 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-gray-200">
{/* Left Section: Edit & Node Operations */}
<div className="flex shrink-0 items-center gap-1 rounded-lg border border-gray-100 bg-white px-2 py-1 shadow-sm">
<ToolbarButton
icon={Undo2}
label="回退"
onClick={onUndo}
disabled={!canBack}
/>
<ToolbarButton
icon={Redo2}
label="前进"
onClick={onRedo}
disabled={!canForward}
/>
<ToolbarButton
icon={PaintRoller}
label="格式刷"
onClick={onPainter}
active={painterMode}
/>
<Divider />
<ToolbarButton
icon={Plus} // Sibling
label="同级"
onClick={onSibling}
disabled={!activeCount}
/>
<ToolbarButton
icon={Sparkles} // Child
label="下级"
onClick={onChild}
disabled={!activeCount}
/>
<ToolbarButton
icon={Trash2}
label="删除"
onClick={onDelete}
disabled={!activeCount}
/>
<Divider />
<ToolbarButton
icon={ImageIcon}
label="图片"
onClick={onImage}
disabled={!activeCount}
/>
<ToolbarButton
icon={Smile}
label="图标"
onClick={onIcon}
disabled={!activeCount}
/>
<ToolbarButton
icon={LinkIcon}
label="链接"
onClick={onLink}
disabled={!activeCount}
/>
<ToolbarButton
icon={StickyNote}
label="备注"
onClick={onNote}
disabled={!activeCount}
/>
<ToolbarButton
icon={Tag}
label="标签"
onClick={onTag}
disabled={!activeCount}
/>
<ToolbarButton
icon={Braces}
label="概要"
onClick={onSummary}
disabled={!activeCount}
/>
<ToolbarButton
icon={Cable}
label="关联线"
onClick={onAssociativeLine}
disabled={!activeCount}
/>
<ToolbarButton
icon={Sigma}
label="公式"
onClick={onFormula}
disabled={!activeCount}
/>
<ToolbarButton
icon={Paperclip}
label="附件"
onClick={onAttachment}
disabled={!activeCount}
/>
<ToolbarButton
icon={BoxSelect}
label="外框"
onClick={onOuterFrame}
disabled={!activeCount}
/>
<ToolbarButton
icon={Sparkles} // AI
label="AI"
onClick={onAi}
/>
</div>
{/* Right Section: File & Export Actions */}
<div className="flex shrink-0 items-center gap-1 rounded-lg border border-gray-100 bg-white px-2 py-1 shadow-sm">
<ToolbarButton
icon={FolderOpen}
label="目录"
onClick={onOpenDirectory}
/>
<ToolbarButton icon={FileText} label="新建" onClick={onNew} />
<ToolbarButton
icon={FolderOpen}
label="打开"
onClick={() => fileInputRef.current?.click()}
/>
{/* Hidden Input */}
<input
ref={fileInputRef}
type="file"
accept=".json,application/json"
className="hidden"
onChange={onImport}
/>
<Divider />
<ToolbarButton
icon={Save} // Save As
label="另存为"
onClick={onSaveAs}
/>
<ToolbarButton
icon={Download} // Export
label="导出"
onClick={onExportJson}
/>
<ToolbarButton
icon={ImageIcon} // Export PNG
label="PNG"
onClick={onExportPng}
/>
</div>
</div>
);
};