HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1import { Cpu } from 'lucide-react';2import { cn } from '@/lib/cn';34/**5 * GET form for /hardware/fit — no JavaScript needed. Memory presets are grouped by platform; a free numeric field6 * overrides the preset when filled. Quantization and context are plain selects (the API accepts 4bit|8bit|fp16 and7 * any positive context; we offer the three common windows).8 */9export const APPLE_PRESETS = [16, 24, 32, 36, 48, 64, 96, 128, 192, 256, 512];10export const NVIDIA_PRESETS = [24, 32, 80, 141, 192];11export const QUANTS = [12 { value: '4bit', label: '4-bit (≈ 0.5 byte / param)' },13 { value: '8bit', label: '8-bit (1 byte / param)' },14 { value: 'fp16', label: 'fp16 / bf16 (2 bytes / param)' },15];16export const CONTEXTS = [17 { value: '8192', label: '8k tokens' },18 { value: '32768', label: '32k tokens' },19 { value: '131072', label: '128k tokens' },20];2122export function FitForm({ memory, quant, context, className }: { memory?: string; quant?: string; context?: string; className?: string }) {23 const cls = 'h-11 w-full border border-rule bg-surface px-2.5 text-[15px] text-ink focus:border-accent focus:outline-none';24 const presetSelected = memory && [...APPLE_PRESETS, ...NVIDIA_PRESETS].includes(Number(memory)) ? memory : '';25 return (26 <form action="/hardware/fit" method="get" className={cn('grid gap-3 sm:grid-cols-2 lg:grid-cols-[1.4fr_1fr_1.1fr_1fr_auto] lg:items-end', className)}>27 <label className="block min-w-0">28 <span className="eyebrow block pb-1">Device memory (preset)</span>29 <select name="memory_gb" defaultValue={presetSelected} className={cls} aria-describedby="fit-memory-hint">30 <option value="">Choose a preset…</option>31 <optgroup label="Apple silicon (unified memory)">32 {APPLE_PRESETS.map((g) => (33 <option key={`a${g}`} value={g}>34 {g} GB35 </option>36 ))}37 </optgroup>38 <optgroup label="NVIDIA (VRAM)">39 {NVIDIA_PRESETS.map((g) => (40 <option key={`n${g}`} value={g}>41 {g} GB42 </option>43 ))}44 </optgroup>45 </select>46 </label>47 <label className="block min-w-0">48 <span className="eyebrow block pb-1">…or any memory (GB)</span>49 <input name="memory_custom" inputMode="decimal" pattern="[0-9]*\.?[0-9]*" defaultValue={presetSelected ? '' : memory ?? ''} placeholder="e.g. 20" className={cls} />50 </label>51 <label className="block min-w-0">52 <span className="eyebrow block pb-1">Quantization</span>53 <select name="quant" defaultValue={quant ?? '4bit'} className={cls}>54 {QUANTS.map((q) => (55 <option key={q.value} value={q.value}>56 {q.label}57 </option>58 ))}59 </select>60 </label>61 <label className="block min-w-0">62 <span className="eyebrow block pb-1">Context window</span>63 <select name="context" defaultValue={context ?? '8192'} className={cls}>64 {CONTEXTS.map((c) => (65 <option key={c.value} value={c.value}>66 {c.label}67 </option>68 ))}69 </select>70 </label>71 <button type="submit" className="inline-flex h-11 items-center justify-center gap-1.5 bg-ink px-4 text-sm font-medium text-canvas hover:opacity-90 sm:col-span-2 lg:col-span-1">72 <Cpu className="size-4" aria-hidden /> Estimate fit73 </button>74 <p id="fit-memory-hint" className="text-xs text-ink-3 sm:col-span-2 lg:col-span-5">75 The custom field wins over the preset when both are filled. Estimates reserve 2 GB for the OS and framework.76 </p>77 </form>78 );79}80