forked from rajun/ar-test
refactor: enhance FileOrUrlField with reusable UI components and existing file support
This commit is contained in:
parent
e9aad1afe3
commit
d329bd7789
@ -1,4 +1,6 @@
|
|||||||
import { Upload, Link, X } from 'lucide-react';
|
import { Upload, Link, X } from 'lucide-react';
|
||||||
|
import { Input } from '~/components/ui/input';
|
||||||
|
import { Label } from '~/components/ui/label';
|
||||||
|
|
||||||
export type InputMode = 'url' | 'file';
|
export type InputMode = 'url' | 'file';
|
||||||
|
|
||||||
@ -14,21 +16,24 @@ export interface FileOrUrlFieldProps {
|
|||||||
url: string;
|
url: string;
|
||||||
onUrlChange: (u: string) => void;
|
onUrlChange: (u: string) => void;
|
||||||
urlPlaceholder: string;
|
urlPlaceholder: string;
|
||||||
|
existingFileName?: string;
|
||||||
|
onClearExistingFile?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FileOrUrlField({
|
export function FileOrUrlField({
|
||||||
label, required, mode, onModeChange,
|
label, required, mode, onModeChange,
|
||||||
accept, file, onFileChange, inputRef,
|
accept, file, onFileChange, inputRef,
|
||||||
url, onUrlChange, urlPlaceholder,
|
url, onUrlChange, urlPlaceholder,
|
||||||
|
existingFileName, onClearExistingFile,
|
||||||
}: FileOrUrlFieldProps) {
|
}: FileOrUrlFieldProps) {
|
||||||
return (
|
return (
|
||||||
<div className='space-y-1.5'>
|
<div className='space-y-1.5'>
|
||||||
{/* Label + toggle */}
|
{/* Label + toggle */}
|
||||||
<div className='flex items-center justify-between ml-1'>
|
<div className='flex items-center justify-between ml-1'>
|
||||||
<label className='text-xs font-bold text-neutral-400 uppercase tracking-wider'>
|
<Label>
|
||||||
{label}{required && <span className='text-orange-500 ml-0.5'>*</span>}
|
{label}{required && <span className='text-orange-500 ml-0.5'>*</span>}
|
||||||
</label>
|
</Label>
|
||||||
<div className='flex items-center gap-1 rounded-xl bg-[#181818] border border-neutral-800 p-1 text-xs'>
|
<div className='flex items-center gap-1 rounded-xl bg-[#181818] border border-neutral-850 p-1 text-xs'>
|
||||||
<button
|
<button
|
||||||
type='button'
|
type='button'
|
||||||
onClick={() => onModeChange('file')}
|
onClick={() => onModeChange('file')}
|
||||||
@ -60,7 +65,7 @@ export function FileOrUrlField({
|
|||||||
<div
|
<div
|
||||||
onClick={() => inputRef.current?.click()}
|
onClick={() => inputRef.current?.click()}
|
||||||
className={`flex cursor-pointer items-center gap-3 rounded-xl border-2 border-dashed px-4 py-4 transition-all duration-200 ${
|
className={`flex cursor-pointer items-center gap-3 rounded-xl border-2 border-dashed px-4 py-4 transition-all duration-200 ${
|
||||||
file
|
file || existingFileName
|
||||||
? 'border-orange-500/50 bg-[#161616]'
|
? 'border-orange-500/50 bg-[#161616]'
|
||||||
: 'border-neutral-800 hover:border-neutral-700 bg-[#161616]/40 hover:bg-[#161616]/70'
|
: 'border-neutral-800 hover:border-neutral-700 bg-[#161616]/40 hover:bg-[#161616]/70'
|
||||||
}`}
|
}`}
|
||||||
@ -97,6 +102,30 @@ export function FileOrUrlField({
|
|||||||
<X size={15} />
|
<X size={15} />
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
|
) : existingFileName ? (
|
||||||
|
<>
|
||||||
|
<div className='flex flex-1 items-center gap-3.5 min-w-0'>
|
||||||
|
<div className='w-8 h-8 rounded-lg bg-orange-500/10 border border-orange-500/20 flex items-center justify-center shrink-0'>
|
||||||
|
<Upload size={14} className='text-orange-500' />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col min-w-0">
|
||||||
|
<span className='text-sm text-white font-semibold truncate'>{existingFileName}</span>
|
||||||
|
<span className='text-[10px] text-neutral-500 font-medium mt-0.5'>
|
||||||
|
Existing File (Keep)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (onClearExistingFile) onClearExistingFile();
|
||||||
|
}}
|
||||||
|
className='shrink-0 text-neutral-500 hover:text-white p-1 hover:bg-neutral-800 rounded-lg transition-colors cursor-pointer'
|
||||||
|
>
|
||||||
|
<X size={15} />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className='flex flex-1 items-center gap-3 text-neutral-500 py-1'>
|
<div className='flex flex-1 items-center gap-3 text-neutral-500 py-1'>
|
||||||
<Upload size={16} className="text-neutral-600" />
|
<Upload size={16} className="text-neutral-600" />
|
||||||
@ -107,9 +136,8 @@ export function FileOrUrlField({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<input
|
<Input
|
||||||
type='url'
|
type='url'
|
||||||
className='w-full bg-[#181818] border border-neutral-800 rounded-xl px-4 py-3 text-sm text-white placeholder-neutral-700 focus:border-orange-500 focus:outline-none transition-colors duration-200'
|
|
||||||
placeholder={urlPlaceholder}
|
placeholder={urlPlaceholder}
|
||||||
value={url}
|
value={url}
|
||||||
onChange={(e) => onUrlChange(e.target.value)}
|
onChange={(e) => onUrlChange(e.target.value)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user