138 lines
4.3 KiB
TypeScript
138 lines
4.3 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||
|
|
import { Label } from '@/components/ui/label';
|
||
|
|
import { Input } from '@/components/ui/input';
|
||
|
|
import { Button } from '@/components/ui/button';
|
||
|
|
import { Slider } from '@/components/ui/slider';
|
||
|
|
import {
|
||
|
|
Select,
|
||
|
|
SelectContent,
|
||
|
|
SelectItem,
|
||
|
|
SelectTrigger,
|
||
|
|
SelectValue,
|
||
|
|
} from '@/components/ui/select';
|
||
|
|
import type { ErrorCorrectionLevel } from '@/types/qrcode';
|
||
|
|
|
||
|
|
interface QROptionsProps {
|
||
|
|
errorCorrection: ErrorCorrectionLevel;
|
||
|
|
foregroundColor: string;
|
||
|
|
backgroundColor: string;
|
||
|
|
margin: number;
|
||
|
|
onErrorCorrectionChange: (ec: ErrorCorrectionLevel) => void;
|
||
|
|
onForegroundColorChange: (color: string) => void;
|
||
|
|
onBackgroundColorChange: (color: string) => void;
|
||
|
|
onMarginChange: (margin: number) => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
const EC_OPTIONS: { value: ErrorCorrectionLevel; label: string }[] = [
|
||
|
|
{ value: 'L', label: 'Low (7%)' },
|
||
|
|
{ value: 'M', label: 'Medium (15%)' },
|
||
|
|
{ value: 'Q', label: 'Quartile (25%)' },
|
||
|
|
{ value: 'H', label: 'High (30%)' },
|
||
|
|
];
|
||
|
|
|
||
|
|
export function QROptions({
|
||
|
|
errorCorrection,
|
||
|
|
foregroundColor,
|
||
|
|
backgroundColor,
|
||
|
|
margin,
|
||
|
|
onErrorCorrectionChange,
|
||
|
|
onForegroundColorChange,
|
||
|
|
onBackgroundColorChange,
|
||
|
|
onMarginChange,
|
||
|
|
}: QROptionsProps) {
|
||
|
|
const isTransparent = backgroundColor === '#00000000';
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Card>
|
||
|
|
<CardHeader>
|
||
|
|
<CardTitle>Options</CardTitle>
|
||
|
|
</CardHeader>
|
||
|
|
<CardContent className="space-y-4">
|
||
|
|
{/* Error Correction */}
|
||
|
|
<div className="space-y-1.5">
|
||
|
|
<Label className="text-xs">Error Correction</Label>
|
||
|
|
<Select value={errorCorrection} onValueChange={(v) => onErrorCorrectionChange(v as ErrorCorrectionLevel)}>
|
||
|
|
<SelectTrigger className="w-full">
|
||
|
|
<SelectValue />
|
||
|
|
</SelectTrigger>
|
||
|
|
<SelectContent>
|
||
|
|
{EC_OPTIONS.map((opt) => (
|
||
|
|
<SelectItem key={opt.value} value={opt.value}>
|
||
|
|
{opt.label}
|
||
|
|
</SelectItem>
|
||
|
|
))}
|
||
|
|
</SelectContent>
|
||
|
|
</Select>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Colors */}
|
||
|
|
<div className="space-y-3">
|
||
|
|
<div className="space-y-1.5">
|
||
|
|
<Label className="text-xs">Foreground</Label>
|
||
|
|
<div className="flex gap-2">
|
||
|
|
<Input
|
||
|
|
type="color"
|
||
|
|
className="w-9 p-1 h-9 shrink-0"
|
||
|
|
value={foregroundColor}
|
||
|
|
onChange={(e) => onForegroundColorChange(e.target.value)}
|
||
|
|
/>
|
||
|
|
<Input
|
||
|
|
className="font-mono text-xs"
|
||
|
|
value={foregroundColor}
|
||
|
|
onChange={(e) => onForegroundColorChange(e.target.value)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div className="space-y-1.5">
|
||
|
|
<div className="flex items-center justify-between">
|
||
|
|
<Label className="text-xs">Background</Label>
|
||
|
|
<Button
|
||
|
|
variant={isTransparent ? 'default' : 'outline'}
|
||
|
|
size="xs"
|
||
|
|
className="h-5 text-[10px] px-1.5"
|
||
|
|
onClick={() =>
|
||
|
|
onBackgroundColorChange(isTransparent ? '#ffffff' : '#00000000')
|
||
|
|
}
|
||
|
|
>
|
||
|
|
Transparent
|
||
|
|
</Button>
|
||
|
|
</div>
|
||
|
|
<div className="flex gap-2">
|
||
|
|
<Input
|
||
|
|
type="color"
|
||
|
|
className="w-9 p-1 h-9 shrink-0"
|
||
|
|
disabled={isTransparent}
|
||
|
|
value={backgroundColor}
|
||
|
|
onChange={(e) => onBackgroundColorChange(e.target.value)}
|
||
|
|
/>
|
||
|
|
<Input
|
||
|
|
className="font-mono text-xs"
|
||
|
|
disabled={isTransparent}
|
||
|
|
value={backgroundColor}
|
||
|
|
onChange={(e) => onBackgroundColorChange(e.target.value)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Margin */}
|
||
|
|
<div className="space-y-1.5">
|
||
|
|
<div className="flex items-center justify-between">
|
||
|
|
<Label className="text-xs">Margin</Label>
|
||
|
|
<span className="text-xs text-muted-foreground">{margin}</span>
|
||
|
|
</div>
|
||
|
|
<Slider
|
||
|
|
value={[margin]}
|
||
|
|
onValueChange={([v]) => onMarginChange(v)}
|
||
|
|
min={0}
|
||
|
|
max={8}
|
||
|
|
step={1}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</CardContent>
|
||
|
|
</Card>
|
||
|
|
);
|
||
|
|
}
|