symbols.ts
typescript
sha256:3c58668648c7323bb9f5c6881cfe6a3f14fc93fcb73b537d253732952a5bf8bf
chore: bump version to 0.2.0rc12
Sonnet 4.6
patch
8 days ago
| 1 | /** |
| 2 | * symbols.ts — Symbol list page behaviour. |
| 3 | * |
| 4 | * - Live text filter on symbol addresses (data-addr attribute) |
| 5 | * - Client-side kind filter via sym2-kind-select dropdown |
| 6 | * - SVG sparkline bar chart from data-weekly attribute |
| 7 | * - Op filter is server-side via ?op= query param |
| 8 | */ |
| 9 | |
| 10 | const SPARK_W = 96; |
| 11 | const SPARK_H = 28; |
| 12 | const SPARK_BARS = 12; |
| 13 | const SPARK_GAP = 2; |
| 14 | |
| 15 | function renderSparklines(): void { |
| 16 | document.querySelectorAll<HTMLElement>('.sym2-sparkline[data-weekly]').forEach((el) => { |
| 17 | const raw = el.dataset.weekly ?? ''; |
| 18 | if (!raw) { el.style.display = 'none'; return; } |
| 19 | const vals = raw.split(',').map(Number).filter((n) => !isNaN(n)); |
| 20 | if (!vals.length || vals.every((v) => v === 0)) { el.style.display = 'none'; return; } |
| 21 | |
| 22 | const max = Math.max(...vals, 1); |
| 23 | const barW = (SPARK_W - SPARK_GAP * (SPARK_BARS - 1)) / SPARK_BARS; |
| 24 | |
| 25 | const bars = vals.map((v, i) => { |
| 26 | const pct = v / max; |
| 27 | const h = Math.max(pct * SPARK_H, pct > 0 ? 2 : 0); |
| 28 | const x = i * (barW + SPARK_GAP); |
| 29 | const y = SPARK_H - h; |
| 30 | const opacity = 0.25 + pct * 0.75; |
| 31 | return `<rect x="${x.toFixed(1)}" y="${y.toFixed(1)}" width="${barW.toFixed(1)}" height="${h.toFixed(1)}" rx="1" opacity="${opacity.toFixed(2)}"/>`; |
| 32 | }).join(''); |
| 33 | |
| 34 | el.innerHTML = `<svg width="${SPARK_W}" height="${SPARK_H}" viewBox="0 0 ${SPARK_W} ${SPARK_H}" fill="currentColor" aria-hidden="true">${bars}</svg>`; |
| 35 | }); |
| 36 | } |
| 37 | |
| 38 | export function initSymbols(): void { |
| 39 | renderSparklines(); |
| 40 | |
| 41 | const searchInput = document.getElementById('sym2-search-input') as HTMLInputElement | null; |
| 42 | const kindSelect = document.getElementById('sym2-kind-select') as HTMLSelectElement | null; |
| 43 | const rows = Array.from(document.querySelectorAll<HTMLElement>('.sym2-row')); |
| 44 | |
| 45 | function applyFilter(): void { |
| 46 | const q = searchInput ? searchInput.value.toLowerCase() : ''; |
| 47 | const activeKind = kindSelect ? kindSelect.value : ''; |
| 48 | rows.forEach((row) => { |
| 49 | const addr = (row.dataset.addr ?? '').toLowerCase(); |
| 50 | const kind = row.dataset.kind ?? ''; |
| 51 | const matchQ = !q || addr.includes(q); |
| 52 | const matchKind = !activeKind || kind === activeKind; |
| 53 | row.classList.toggle('sym2-row--hidden', !(matchQ && matchKind)); |
| 54 | }); |
| 55 | } |
| 56 | |
| 57 | if (searchInput) searchInput.addEventListener('input', applyFilter); |
| 58 | if (kindSelect) kindSelect.addEventListener('change', applyFilter); |
| 59 | } |
File History
1 commit
sha256:35d76015db2541686c33edd44343ea2d9f751325b4a5556cc9c4c9c0f84edbbe
chore: bump version to 0.2.0rc12
Sonnet 4.6
patch
6 days ago