// Pieces several views draw the same way. import { h, hue, safeHref } from './util.js'; import { icon, iconEl } from './icons.js'; export function avatar(c, size) { const sym = (c.s || c.n || '?').replace(/^\$/, ''); const el = h('div.av', size ? { style: { width: size + 'px', height: size + 'px' } } : null); const ph = h('div.ph', { style: { background: `linear-gradient(135deg, hsl(${hue(c.m || sym)} 45% 28%), hsl(${(hue(c.m || sym) + 40) % 360} 50% 16%))` } }, sym.slice(0, 2).toUpperCase()); el.append(ph); if (c.img) setImg(el, c.img); return el; } export function setImg(av, src) { if (av.dataset.src === src) return; av.dataset.src = src; av.querySelector('img')?.remove(); const img = new Image(); img.decoding = 'async'; img.loading = 'lazy'; img.alt = ''; img.referrerPolicy = 'no-referrer'; img.onload = () => { img.classList.add('ok'); av.querySelector('.ph')?.remove(); }; // a picture that fails is asked for again at a later update, twice at most img.onerror = () => { img.remove(); av._tries = (av._tries || 0) + 1; if (av._tries <= 2) setTimeout(() => { if (av.dataset.src === src) delete av.dataset.src; }, 8000); }; img.src = src; av.append(img); } export function socials(c, size = 14) { const box = h('div.soc'); const add = (href, ic, title) => { const u = href && safeHref(href); const a = h('a', { href: u || '#', target: '_blank', rel: 'noopener noreferrer', title, html: icon(ic, size), onclick: e => e.stopPropagation() }); if (!u) a.classList.add('off'); box.append(a); }; add(c.tw, 'xlogo', 'X'); add(c.web, 'globe', 'Website'); add(c.tg, 'tg', 'Telegram'); add(`https://x.com/search?q=${encodeURIComponent(c.m)}&f=live`, 'search', 'Search the address on X'); return box; } // green when low, amber in between, red when high (for holder concentration numbers) export function level(v, good, bad) { if (!Number.isFinite(v) || v === 0) return ''; return v <= good ? 'lv-g' : v >= bad ? 'lv-b' : 'lv-m'; } export function chip(ic, text, cls = '', title = '') { const el = h('span.chip' + (cls ? '.' + cls : ''), { title }); el.append(iconEl(ic, 12), document.createTextNode(text)); return el; } export function traceSvg() { const t = document.createElement('template'); t.innerHTML = ''; return t.content.firstChild; } export function emptyState(title, text) { return h('div.empty', null, traceSvg(), h('b', null, title), text ? h('span', null, text) : null); }