"use client"; import { Icon } from "@/components/icons"; import { Field, Notice, TextInput, cx } from "@/components/ui"; import { evaluateContrast } from "@/lib/qr/contrast"; import { COLOR_PRESETS, EC_LEVELS, EC_LEVEL_LABELS, MAX_SIZE, MIN_SIZE, type EcLevel, type QrDesign, } from "@/lib/qr/design"; const HEX_INPUT = /^#[0-9a-fA-F]{6}$/; function ColorField({ label, value, onChange, id, }: { label: string; value: string; onChange: (value: string) => void; id: string; }) { const valid = HEX_INPUT.test(value); return ( onChange(event.target.value.toUpperCase())} className="size-10 shrink-0 cursor-pointer rounded-lg border border-slate-300 bg-surface p-1" /> { const next = event.target.value.trim(); onChange(next.startsWith("#") ? next.toUpperCase() : `#${next.toUpperCase()}`); }} className="font-mono uppercase" /> ); } export function DesignPanel({ design, onChange, }: { design: QrDesign; onChange: (design: QrDesign) => void; }) { const patch = (changes: Partial) => onChange({ ...design, ...changes }); const contrast = evaluateContrast(design.fgColor, design.bgColor); return ( patch({ fgColor })} /> patch({ bgColor })} /> {COLOR_PRESETS.map((preset) => ( patch({ fgColor: preset.fgColor, bgColor: preset.bgColor }) } className="flex items-center gap-2 rounded-lg border border-slate-300 bg-surface py-1 pr-2.5 pl-1.5 text-xs font-medium text-slate-700 transition-colors hover:bg-slate-50" > {preset.label} ))} patch({ fgColor: design.bgColor, bgColor: design.fgColor }) } className="rounded-lg border border-slate-300 bg-surface px-2.5 py-1 text-xs font-medium text-slate-700 transition-colors hover:bg-slate-50" > Farben tauschen {contrast.message ? ( {contrast.message} Kontrastverhältnis: {contrast.ratio.toFixed(1)} : 1 ) : null} patch({ size: Number(event.target.value) })} className="h-2 w-full cursor-pointer appearance-none rounded-full bg-slate-200 accent-indigo-600" /> { const raw = Number(event.target.value); if (Number.isNaN(raw)) return; patch({ size: Math.min(MAX_SIZE, Math.max(MIN_SIZE, Math.round(raw))) }); }} className="w-24 shrink-0 rounded-lg border border-slate-300 bg-surface px-2.5 py-2 text-sm tabular-nums shadow-sm" /> {EC_LEVELS.map((level: EcLevel) => ( patch({ ecLevel: level })} className={cx( "rounded-lg border py-2 text-sm font-medium transition-colors", design.ecLevel === level ? "border-indigo-600 bg-accent-soft text-accent-soft-fg" : "border-slate-300 bg-surface text-slate-600 hover:bg-slate-50", )} > {level} ))} patch({ margin: Number(event.target.value) })} className="h-2 w-full cursor-pointer appearance-none rounded-full bg-slate-200 accent-indigo-600" /> ); }