Spaces:
Running
Running
File size: 2,516 Bytes
5a0e691 2f67ecf d54a751 5a0e691 76fb273 5a0e691 76fb273 5a0e691 9a28cd0 5a0e691 9a28cd0 5a0e691 d54a751 5a0e691 d54a751 5a0e691 d54a751 5a0e691 9a28cd0 d54a751 9a28cd0 5a0e691 76fb273 d54a751 76fb273 d54a751 5a0e691 d54a751 5a0e691 d54a751 5a0e691 d54a751 5a0e691 2f67ecf 5a0e691 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 'use client';
import { motion } from 'framer-motion';
import { fadeUp } from '@/lib/animations';
import { CriticalButton, FlatTextarea } from '@/components/ui';
const SAMPLES = [
{
label: 'p53 (human)',
seq: `>sp|P04637|P53_HUMAN Cellular tumor antigen p53
MEEPQSDPSVEPPLSQETFSDLWKLLPENNVLSPLPSQAMDDLMLSPDDIEQWFTEDPGP
DEAPRMPEAAPPVAPAPAAPTPAAPAPAPSWPLSSSVPSQKTYPQGLNGTVNLPGRNSFEV
RVCACPHERCTEGRAVKLFSPKELNCEMAQDIINNKFNLNLLPETIPNTIICFVESQPPQGD
SVTTCFSWRGEGNEMYLHTEKEYKALKSTLSEKYMATCLLLSPKKKSLFPEALKLCNQKYS
EEFLLLDEALLSGCFAELACALHLAPAEGRYSGGFNHELYNMMTQQQQHQHHLQMQQHHQQ
HHQQHHQQHHQQQQQQQQQQQQQQQQQH`,
},
{
label: 'Insulin (human)',
seq: `>sp|P01308|INS_HUMAN Insulin
MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKTRREAED
LQVGQVELGGGPGAGSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN`,
},
];
interface SequenceInputProps {
value: string;
onChange: (value: string) => void;
onSubmit: () => void;
loading: boolean;
error?: string | null;
}
export function SequenceInput({ value, onChange, onSubmit, loading, error }: SequenceInputProps) {
const aaCount = value
.split('\n')
.filter((l) => !l.startsWith('>'))
.join('').length;
return (
<motion.div variants={fadeUp} className="data-card p-6">
<label className="block text-sm font-medium text-text-secondary mb-2">
Enter protein sequence (FASTA or plain)
</label>
<FlatTextarea
value={value}
onChange={(e) => onChange(e.target.value)}
rows={10}
placeholder={">sp|P04637|P53_HUMAN\nMEEPQSDPSVEPPLSQETFSDLWKLLPENNVLSPLPSQ..."}
/>
{error && (
<p className="mt-2 text-sm text-error">{error}</p>
)}
<div className="flex items-center justify-between mt-4">
<div className="flex items-center gap-4">
{SAMPLES.map((s) => (
<button
key={s.label}
type="button"
onClick={() => onChange(s.seq)}
className="text-sm text-accent-cyan hover:underline underline-offset-2"
>
Load {s.label}
</button>
))}
<span className="text-xs text-text-muted">
{value ? `${aaCount} aa` : '0 aa'}
</span>
</div>
<CriticalButton
onClick={onSubmit}
disabled={!value.trim()}
loading={loading}
type="button"
>
{loading ? 'Running pipeline…' : 'Run Pipeline'}
</CriticalButton>
</div>
</motion.div>
);
}
|