d38bafe237
移除 chrome.i18n 后,将各功能页面、布局与工具模块的 UI 文案改为内联中文; 删除冗余注释与过度抽象(如 ToolCard、StatCard),精简 props 与状态管理; 同步优化 JsonTools、StorageCleaner、Timestamp、TestDataGenerator、Dashboard、 Base64Converter、RightClickRestorer、TextStatistics、TopBar、RouterProvider、 ThemeModeProvider 及生成器库与 utils 工具文件。
82 lines
2.3 KiB
TypeScript
82 lines
2.3 KiB
TypeScript
import SwitchButtonGroup from '@/components/SwitchButtonGroup';
|
|
import { Input } from '@/components/ui/input';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@/components/ui/select';
|
|
import { cn } from '@/lib/utils';
|
|
import {
|
|
CARD_CLASS,
|
|
INPUT_PLACEHOLDERS,
|
|
MODE_OPTIONS,
|
|
UNIT_OPTIONS,
|
|
ZONES,
|
|
type ZoneType,
|
|
} from '../constants';
|
|
import type { UseTimestampConverterReturn } from '../useTimestampConverter';
|
|
|
|
type ConverterFormProps = Omit<UseTimestampConverterReturn, 'result' | 'handleUseNow'>;
|
|
|
|
export default function ConverterForm({
|
|
mode,
|
|
input,
|
|
unit,
|
|
zone,
|
|
error,
|
|
setMode,
|
|
setInput,
|
|
setUnit,
|
|
setZone,
|
|
}: ConverterFormProps) {
|
|
return (
|
|
<div className={cn(CARD_CLASS, 'gap-4')}>
|
|
<SwitchButtonGroup value={mode} options={MODE_OPTIONS} onChange={setMode} size="small" />
|
|
|
|
<div className="flex flex-col gap-1.5">
|
|
<Input
|
|
type="text"
|
|
placeholder={INPUT_PLACEHOLDERS[mode]}
|
|
value={input}
|
|
onChange={(e) => setInput(e.target.value)}
|
|
className={cn(
|
|
'font-mono font-semibold h-10 shadow-sm placeholder:text-muted-foreground/60 focus:bg-background',
|
|
error && 'border-destructive focus-visible:ring-destructive',
|
|
)}
|
|
/>
|
|
|
|
{error && <p className="text-destructive text-xs font-medium px-0.5">{error}</p>}
|
|
</div>
|
|
|
|
<div className="flex flex-col sm:flex-row items-stretch gap-3 w-full">
|
|
<SwitchButtonGroup
|
|
value={unit}
|
|
options={UNIT_OPTIONS}
|
|
onChange={setUnit}
|
|
size="small"
|
|
className="sm:w-auto shrink-0"
|
|
/>
|
|
|
|
<Select value={zone} onValueChange={(v: string) => setZone(v as ZoneType)}>
|
|
<SelectTrigger className="flex-1 font-mono font-semibold h-9 shadow-sm bg-background">
|
|
<SelectValue placeholder="选择时区" />
|
|
</SelectTrigger>
|
|
<SelectContent className="max-h-64 font-mono">
|
|
{ZONES.map((z) => (
|
|
<SelectItem
|
|
key={z}
|
|
value={z}
|
|
className="text-xs font-semibold focus:bg-accent cursor-pointer"
|
|
>
|
|
{z}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|