| |
| 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(); }; |
| |
| 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; |
| } |
| |
| |
| 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 = '<svg class="trace" viewBox="0 0 120 32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 18h22l6-12 9 22 7-16 5 6h12l5-8 6 14 5-6h39"/></svg>'; |
| 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); |
| } |