Build [v1.14.28]
This commit is contained in:
@@ -42,15 +42,15 @@ export default function CameraView({
|
||||
const cn = (...classes: any[]) => classes.filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-md mx-auto flex flex-col gap-3 md:gap-4">
|
||||
<div className="w-full max-w-md mx-auto flex flex-col gap-3 md:gap-4 font-sans">
|
||||
{/* Video Viewport Area */}
|
||||
<div className="relative w-full aspect-square overflow-hidden rounded-[2.5rem] shadow-[0_20px_50px_rgba(0,0,0,0.5)] bg-background border-2 border-slate-800/50 p-4 sm:p-6 lg:p-8 xl:p-10">
|
||||
<div className="relative w-full aspect-square overflow-hidden rounded-none shadow-none bg-[#131313] border-2 border-[#222222] p-4 sm:p-6 lg:p-8 xl:p-10">
|
||||
<div className="absolute inset-4 sm:inset-6 z-10 pointer-events-none flex items-center justify-center">
|
||||
<div className="w-full h-full border border-primary/30 rounded-[2rem] relative">
|
||||
<div className="absolute top-0 left-0 w-10 h-10 border-t-4 border-l-4 border-primary rounded-tl-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
|
||||
<div className="absolute top-0 right-0 w-10 h-10 border-t-4 border-r-4 border-primary rounded-tr-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
|
||||
<div className="absolute bottom-0 left-0 w-10 h-10 border-b-4 border-l-4 border-primary rounded-bl-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
|
||||
<div className="absolute bottom-0 right-0 w-10 h-10 border-b-4 border-r-4 border-primary rounded-br-2xl shadow-[0_0_15px_rgba(59,130,246,0.5)]" />
|
||||
<div className="w-full h-full border border-primary/30 rounded-none relative">
|
||||
<div className="absolute top-0 left-0 w-10 h-10 border-t-4 border-l-4 border-primary rounded-none shadow-none" />
|
||||
<div className="absolute top-0 right-0 w-10 h-10 border-t-4 border-r-4 border-primary rounded-none shadow-none" />
|
||||
<div className="absolute bottom-0 left-0 w-10 h-10 border-b-4 border-l-4 border-primary rounded-none shadow-none" />
|
||||
<div className="absolute bottom-0 right-0 w-10 h-10 border-b-4 border-r-4 border-primary rounded-none shadow-none" />
|
||||
|
||||
{isStarted && !paused && !isSelecting && (
|
||||
<div className="absolute top-0 left-0 right-0 h-1 bg-primary animate-scan-fast" />
|
||||
@@ -58,11 +58,11 @@ export default function CameraView({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id={scannerId} data-testid="camera-indicator" className="w-full h-full bg-surface object-cover" />
|
||||
<div id={scannerId} data-testid="camera-indicator" className="w-full h-full bg-[#0A0A0A] object-cover" />
|
||||
|
||||
{/* Selection UI */}
|
||||
{isSelecting && capturedImage && (
|
||||
<div className="absolute inset-0 z-50 bg-background flex flex-col">
|
||||
<div className="absolute inset-0 z-50 bg-[#131313] flex flex-col">
|
||||
<div className="relative flex-1 bg-black flex items-center justify-center overflow-hidden">
|
||||
<img
|
||||
src={capturedImage || undefined}
|
||||
@@ -77,7 +77,7 @@ export default function CameraView({
|
||||
key={i}
|
||||
onClick={() => onWordSelect(w.text)}
|
||||
aria-label={`Select text: ${w.text}`}
|
||||
className="absolute border border-primary bg-primary/20 rounded-sm active:bg-primary/50 cursor-pointer transition-colors pointer-events-auto focus:ring-2 focus:ring-primary focus:outline-none"
|
||||
className="absolute border border-primary bg-primary/20 rounded-none active:bg-primary/50 cursor-pointer transition-colors pointer-events-auto focus:ring-2 focus:ring-primary focus:outline-none"
|
||||
style={{
|
||||
left: `${(w.bbox.x0 / 1600) * 100}%`,
|
||||
top: `${(w.bbox.y0 / (1600 * (9 / 16))) * 100}%`,
|
||||
@@ -89,15 +89,15 @@ export default function CameraView({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 lg:p-8 xl:p-10 bg-surface/90 border-t border-slate-800 flex flex-col gap-4">
|
||||
<div className="p-6 lg:p-8 xl:p-10 bg-[#0A0A0A]/90 border-t border-[#222222] flex flex-col gap-4">
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<p className="text-sm font-normal text-white italic text-center">Text Found</p>
|
||||
<p className="text-xs text-muted font-normal text-center">Tap any text to use it</p>
|
||||
<p className="text-xs text-[#888888] font-normal text-center">Tap any text to use it</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={onCancelSelection}
|
||||
aria-label="Cancel text selection"
|
||||
className="w-full py-4 bg-slate-800 hover:bg-slate-700 text-white rounded-2xl font-normal text-xs cursor-pointer transition-all active:scale-95 border border-slate-700 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
className="w-full py-4 bg-[#1A1A1A] hover:bg-[#222222] text-white rounded-none font-normal text-xs cursor-pointer transition-all active:scale-95 border border-[#222222] focus:ring-2 focus:ring-primary focus:outline-none"
|
||||
>
|
||||
Close OCR Preview
|
||||
</button>
|
||||
@@ -106,23 +106,23 @@ export default function CameraView({
|
||||
)}
|
||||
|
||||
{!isStarted && !error && (
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-surface text-secondary gap-4">
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-[#0A0A0A] text-[#888888] gap-4">
|
||||
<RefreshCw className="w-8 h-8 animate-spin text-primary" />
|
||||
<p className="text-sm font-normal">Initializing camera...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-surface text-secondary px-8 text-center gap-4">
|
||||
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center bg-[#0A0A0A] text-[#888888] px-8 text-center gap-4">
|
||||
<XCircle className="w-10 h-10 text-red-500" />
|
||||
<div>
|
||||
<p className="font-normal text-white">Camera Error</p>
|
||||
<p className="text-xs text-secondary mt-1">{error}</p>
|
||||
<p className="text-xs text-[#888888] mt-1">{error}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => window.location.reload()}
|
||||
aria-label="Reload page and try again"
|
||||
className="mt-4 px-6 py-2 bg-slate-800 rounded-full text-sm font-normal cursor-pointer hover:bg-slate-700 transition-colors focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
className="mt-4 px-6 py-2 bg-[#1A1A1A] rounded-none text-sm font-normal cursor-pointer hover:bg-[#222222] transition-colors focus:ring-2 focus:ring-primary focus:outline-none border border-[#222222]"
|
||||
>
|
||||
Try Again
|
||||
</button>
|
||||
@@ -131,7 +131,7 @@ export default function CameraView({
|
||||
</div>
|
||||
|
||||
{/* External Controls Area */}
|
||||
<div className="flex flex-col gap-4 bg-surface/50 p-5 lg:p-6 xl:p-8 rounded-[2.5rem] border border-slate-800/50 shadow-2xl">
|
||||
<div className="flex flex-col gap-4 bg-[#0A0A0A]/50 p-5 lg:p-6 xl:p-8 rounded-none border border-[#222222] shadow-none">
|
||||
<div className="flex items-center gap-3 w-full">
|
||||
{hasZoom && (
|
||||
<button
|
||||
@@ -146,27 +146,27 @@ export default function CameraView({
|
||||
}}
|
||||
data-testid="zoom-control"
|
||||
aria-label={`Zoom ${zoom.toFixed(1)}x`}
|
||||
className="h-14 px-5 bg-slate-800/80 hover:bg-slate-700 border border-slate-700 text-white rounded-2xl flex flex-col items-center justify-center shadow-lg cursor-pointer transition-all active:scale-95 shrink-0 focus:ring-2 focus:ring-blue-500 focus:outline-none"
|
||||
className="h-14 px-5 bg-[#1A1A1A] hover:bg-[#222222] border border-[#222222] text-white rounded-none flex flex-col items-center justify-center shadow-none cursor-pointer transition-all active:scale-95 shrink-0 focus:ring-2 focus:ring-primary focus:outline-none"
|
||||
>
|
||||
<span className="text-xs font-normal tabular-nums">{zoom.toFixed(1)}x</span>
|
||||
<span className="text-xs text-primary font-normal tracking-tighter">Zoom</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<div className="flex-1 h-14 bg-background/40 border border-slate-800/50 rounded-2xl flex items-center justify-center gap-3 px-4 lg:px-5 xl:px-6 relative overflow-hidden group">
|
||||
<div className="flex-1 h-14 bg-black/40 border border-[#222222] rounded-none flex items-center justify-center gap-3 px-4 lg:px-5 xl:px-6 relative overflow-hidden group">
|
||||
{ocrProcessing ? (
|
||||
<>
|
||||
<RefreshCw className="animate-spin text-primary" size={18} />
|
||||
<span className="text-xs font-normal text-secondary leading-none">Analyzing</span>
|
||||
<span className="text-xs font-normal text-[#888888] leading-none">Analyzing</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Search
|
||||
className={cn('text-secondary transition-colors group-hover:text-primary', !isStarted && 'opacity-20')}
|
||||
className={cn('text-[#888888] transition-colors group-hover:text-primary', !isStarted && 'opacity-20')}
|
||||
size={18}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-xs text-muted font-normal leading-none">Smart Scan</span>
|
||||
<span className="text-xs text-[#888888] font-normal leading-none">Smart Scan</span>
|
||||
<span className="text-xs font-normal text-primary leading-tight tabular-nums">
|
||||
{countdown === 0 ? 'Scanning' : `${countdown}s`}
|
||||
</span>
|
||||
@@ -176,15 +176,15 @@ export default function CameraView({
|
||||
|
||||
{/* Visual Progress Bar */}
|
||||
<div
|
||||
className="absolute bottom-0 left-0 h-0.5 bg-primary/40 transition-all duration-1000 ease-linear shadow-[0_0_10px_rgba(59,130,246,0.5)]"
|
||||
className="absolute bottom-0 left-0 h-0.5 bg-primary/40 transition-all duration-1000 ease-linear shadow-none"
|
||||
style={{ width: `${((4 - countdown) / 4) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full flex justify-center items-center gap-2">
|
||||
<div className="w-1 h-1 rounded-full bg-green-500 animate-pulse" />
|
||||
<p className="text-xs text-secondary font-normal">
|
||||
<div className="w-1 h-1 rounded-none bg-green-500 animate-pulse" />
|
||||
<p className="text-xs text-[#888888] font-normal">
|
||||
Scanner active · Use zoom or tap scan
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user