99 lines
4.5 KiB
TypeScript
99 lines
4.5 KiB
TypeScript
import { CustomButton } from './custom/CustomButton';
|
|
import React from 'react';
|
|
import type { ToolId } from '../lib/tools';
|
|
import { Popover } from './ui';
|
|
import {
|
|
SelectIcon, PanIcon, HighlightIcon, DrawIcon, CommentIcon, TextBoxIcon,
|
|
SignatureIcon, StampIcon, RedactIcon, InfoIcon, HelpIcon,
|
|
} from './icons';
|
|
|
|
interface ToolDef { id: ToolId; label: string; shortcut: string; icon: React.ReactNode; danger?: boolean }
|
|
|
|
const TOOLS: (ToolDef | 'divider')[] = [
|
|
{ id: 'select', label: 'Select & copy text', shortcut: 'V', icon: <SelectIcon /> },
|
|
{ id: 'pan', label: 'Pan', shortcut: 'H', icon: <PanIcon /> },
|
|
'divider',
|
|
{ id: 'highlight', label: 'Highlight', shortcut: 'K', icon: <HighlightIcon /> },
|
|
{ id: 'draw', label: 'Draw (ink)', shortcut: 'D', icon: <DrawIcon /> },
|
|
{ id: 'comment', label: 'Comment', shortcut: 'C', icon: <CommentIcon /> },
|
|
{ id: 'textbox', label: 'Text box', shortcut: 'T', icon: <TextBoxIcon /> },
|
|
{ id: 'signature', label: 'Signature', shortcut: 'S', icon: <SignatureIcon /> },
|
|
{ id: 'stamp', label: 'Stamp', shortcut: 'M', icon: <StampIcon /> },
|
|
'divider',
|
|
{ id: 'redact', label: 'Redact', shortcut: 'R', icon: <RedactIcon />, danger: true },
|
|
];
|
|
|
|
interface ToolRailProps {
|
|
activeTool: ToolId;
|
|
onToolChange: (t: ToolId) => void;
|
|
hasSignature: boolean;
|
|
onOpenSignature: () => void;
|
|
onOpenAbout: () => void;
|
|
}
|
|
|
|
const RailButton: React.FC<{ t: ToolDef; active: boolean; onClick: () => void }> = ({ t, active, onClick }) => (
|
|
<CustomButton variant="unstyled"
|
|
title={`${t.label} · ${t.shortcut}`}
|
|
aria-label={t.label}
|
|
aria-pressed={active}
|
|
onClick={onClick}
|
|
className={`relative flex h-11 w-11 items-center justify-center rounded-[10px] transition-colors ${
|
|
active
|
|
? t.danger ? 'bg-[#fdecec] text-[#dc2626]' : 'bg-[#eef4ff] text-[#2563eb]'
|
|
: t.danger ? 'text-[#5b6573] hover:bg-[#fdecec] hover:text-[#dc2626]'
|
|
: 'text-[#5b6573] hover:bg-[#edeff2] hover:text-[#18212e]'
|
|
}`}
|
|
>
|
|
{active && <span className="absolute left-[-10px] h-5 w-[3px] rounded-full" style={{ background: t.danger ? '#dc2626' : '#2563eb' }} />}
|
|
{React.isValidElement(t.icon) ? React.cloneElement(t.icon as React.ReactElement<{ size?: number }>, { size: 22 }) : t.icon}
|
|
</CustomButton>
|
|
);
|
|
|
|
export const ToolRail: React.FC<ToolRailProps> = ({ activeTool, onToolChange, hasSignature, onOpenSignature, onOpenAbout }) => {
|
|
const pickTool = (id: ToolId) => {
|
|
onToolChange(id);
|
|
if (id === 'signature' && !hasSignature) onOpenSignature();
|
|
};
|
|
|
|
return (
|
|
<nav className="flex h-full shrink-0 flex-col items-center gap-1.5 border-r border-[#ebedf0] bg-[#ffffff]" style={{ width: '80px', paddingTop: '14px', paddingBottom: '12px' }}>
|
|
{TOOLS.map((t, i) =>
|
|
t === 'divider'
|
|
? <div key={`d${i}`} className="my-0.5 h-px w-6 bg-[#ebedf0]" />
|
|
: <RailButton key={t.id} t={t} active={activeTool === t.id} onClick={() => pickTool(t.id)} />,
|
|
)}
|
|
|
|
<div className="flex-1" />
|
|
|
|
<CustomButton variant="unstyled" title="About Maskan PDF Editor" onClick={onOpenAbout} className="flex h-9 w-9 items-center justify-center rounded-[10px] text-[#98a1ad] transition-colors hover:bg-[#edeff2] hover:text-[#18212e]">
|
|
<InfoIcon size={19} />
|
|
</CustomButton>
|
|
|
|
<Popover
|
|
align="left"
|
|
width={210}
|
|
trigger={(open) => (
|
|
<CustomButton variant="unstyled" title="Keyboard shortcuts" className={`flex h-9 w-9 items-center justify-center rounded-[10px] transition-colors ${open ? 'bg-[#edeff2] text-[#18212e]' : 'text-[#98a1ad] hover:bg-[#edeff2] hover:text-[#18212e]'}`}>
|
|
<HelpIcon size={19} />
|
|
</CustomButton>
|
|
)}
|
|
>
|
|
<div className="text-[12px]">
|
|
<p className="mb-1.5 px-1 font-bold text-[#18212e]">Shortcuts</p>
|
|
{TOOLS.filter((t): t is ToolDef => t !== 'divider').map((t) => (
|
|
<div key={t.id} className="flex items-center justify-between px-1 py-0.5">
|
|
<span className="text-[#5b6573]">{t.label}</span>
|
|
<kbd className="rounded border border-[#ebedf0] bg-[#f6f7f9] px-1.5 text-[10px] font-semibold">{t.shortcut}</kbd>
|
|
</div>
|
|
))}
|
|
<div className="my-1 h-px bg-[#ebedf0]" />
|
|
<div className="flex items-center justify-between px-1 py-0.5">
|
|
<span className="text-[#5b6573]">Undo / Redo</span>
|
|
<kbd className="rounded border border-[#ebedf0] bg-[#f6f7f9] px-1.5 text-[10px] font-semibold">Ctrl+Z / Y</kbd>
|
|
</div>
|
|
</div>
|
|
</Popover>
|
|
</nav>
|
|
);
|
|
};
|