hydropd / website /src /components /SequenceInput.tsx
rikardsaqe's picture
User fixes + full Impeccable critique pass
4548710 verified
Raw
History Blame Contribute Delete
1.88 kB
import { useMemo } from 'react'
import FileDropZone from './FileDropZone'
import { parseSequences } from '../lib/parseSequences'
interface SequenceInputProps {
value: string
onChange: (v: string) => void
label: string
placeholder?: string
onLoadExample?: () => void
}
export default function SequenceInput({
value,
onChange,
label,
placeholder,
onLoadExample,
}: SequenceInputProps) {
const parsed = useMemo(() => parseSequences(value), [value])
return (
<div className="field">
<div
className="field-label"
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}
>
<span>{label}</span>
{onLoadExample && (
<button
type="button"
className="btn btn-ghost btn-sm"
onClick={onLoadExample}
>
Load example
</button>
)}
</div>
<FileDropZone onFile={(text) => onChange(text)} />
<div style={{ margin: '10px 0 6px', fontSize: 'var(--text-sm)' }} className="muted">
…or paste sequences (FASTA, one-per-line, or comma-separated):
</div>
<textarea
value={value}
placeholder={
placeholder ??
'>protein_1\nMAKLVFSLCFLL...\n\nor: PEPTIDE, PEPTIDE, ...'
}
onChange={(e) => onChange(e.target.value)}
/>
<div
style={{ marginTop: 8, display: 'flex', gap: 8, alignItems: 'center' }}
>
<span className={'badge' + (parsed.length ? ' badge-accent' : '')}>
{parsed.length} sequence{parsed.length === 1 ? '' : 's'} parsed
</span>
{value && (
<button
type="button"
className="btn btn-ghost btn-sm"
onClick={() => onChange('')}
>
Clear
</button>
)}
</div>
</div>
)
}