143 lines
3.9 KiB
TypeScript
143 lines
3.9 KiB
TypeScript
import React, { memo } from 'react'
|
|
import { cn } from '@/utils/cn'
|
|
import {
|
|
Tooltip,
|
|
TooltipTrigger,
|
|
TooltipContent,
|
|
TooltipProvider,
|
|
} from '../ui/tooltip'
|
|
import { IconButton } from '../ui/icon'
|
|
import { useDominoStore } from '../canvas'
|
|
|
|
export interface BottomToolbarProps {
|
|
className?: string
|
|
onAddArtboard?: () => void
|
|
onAddImage?: () => void
|
|
onAddText?: () => void
|
|
}
|
|
|
|
const BottomToolbar: React.FC<BottomToolbarProps> = ({
|
|
className,
|
|
onAddArtboard,
|
|
onAddImage,
|
|
onAddText,
|
|
}) => {
|
|
const mode = useDominoStore(s => s.mode)
|
|
const setMode = useDominoStore(s => s.setMode)
|
|
const undo = useDominoStore(s => s.undo)
|
|
const redo = useDominoStore(s => s.redo)
|
|
const past = useDominoStore(s => s.past)
|
|
const future = useDominoStore(s => s.future)
|
|
|
|
const isPanMode = mode === 'pan'
|
|
|
|
const canUndo = past.length > 0
|
|
const canRedo = future.length > 0
|
|
|
|
const tools = [
|
|
{
|
|
id: 'select-pan',
|
|
icon: isPanMode ? 'pan-mode' : 'select-mode',
|
|
label: isPanMode ? '平移' : '选择',
|
|
isMode: true,
|
|
onClick: () => setMode(isPanMode ? 'select' : 'pan'),
|
|
},
|
|
{
|
|
id: 'artboard',
|
|
icon: 'artboard-mode',
|
|
label: '智能画板',
|
|
onClick: onAddArtboard,
|
|
},
|
|
{
|
|
id: 'image',
|
|
icon: 'image-mode',
|
|
label: '上传图片',
|
|
onClick: onAddImage,
|
|
},
|
|
{
|
|
id: 'text',
|
|
icon: 'text-mode',
|
|
label: '文字',
|
|
onClick: onAddText,
|
|
},
|
|
]
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
'domino-toolbar absolute bottom-[40px] left-1/2 -translate-x-1/2 z-[10] pointer-events-none',
|
|
'editor-floating-panel-soft flex items-center gap-[2px] rounded-[100px] p-[4px]',
|
|
className,
|
|
)}
|
|
>
|
|
<div className='flex items-center gap-[2px] pointer-events-auto'>
|
|
{tools.map(tool => (
|
|
<TooltipProvider key={tool.id} delayDuration={200}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<IconButton
|
|
icon={tool.icon}
|
|
size='w-[28px] h-[28px]'
|
|
iconSize='w-[16px] h-[16px]'
|
|
className={cn(
|
|
'rounded-full',
|
|
tool.isMode
|
|
? 'editor-toolbar-chip-active'
|
|
: 'text-muted-foreground hover:bg-accent',
|
|
)}
|
|
onClick={tool.onClick}
|
|
/>
|
|
</TooltipTrigger>
|
|
<TooltipContent>{tool.label}</TooltipContent>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
))}
|
|
|
|
<div className='editor-toolbar-divider mx-[2px] h-[16px] w-[0.5px]' />
|
|
|
|
<TooltipProvider delayDuration={200}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<IconButton
|
|
icon='undo'
|
|
size='w-[28px] h-[28px]'
|
|
iconSize='w-[16px] h-[16px]'
|
|
className={cn(
|
|
'rounded-full text-muted-foreground',
|
|
canUndo
|
|
? 'hover:bg-accent'
|
|
: 'opacity-30 cursor-not-allowed',
|
|
)}
|
|
onClick={undo}
|
|
/>
|
|
</TooltipTrigger>
|
|
<TooltipContent>撤销</TooltipContent>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
|
|
<TooltipProvider delayDuration={200}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<IconButton
|
|
icon='redo'
|
|
size='w-[28px] h-[28px]'
|
|
iconSize='w-[16px] h-[16px]'
|
|
className={cn(
|
|
'rounded-full text-muted-foreground',
|
|
canRedo
|
|
? 'hover:bg-accent'
|
|
: 'opacity-30 cursor-not-allowed',
|
|
)}
|
|
onClick={redo}
|
|
/>
|
|
</TooltipTrigger>
|
|
<TooltipContent>重做</TooltipContent>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default memo(BottomToolbar)
|