lthn.io/public/widget.js
Claude c0ab4aa27b
fix: update API URLs for production domain separation
Widget.js default API URL changed to api.lthn.io. API docs page "Try"
links now use configurable API_URL. Base URL display is dynamic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 09:50:37 +01:00

104 lines
5 KiB
JavaScript

/**
* Lethean .lthn Name Search Widget
*
* Embed on any site:
* <div id="lthn-search"></div>
* <script src="https://lthn.io/widget.js"></script>
*/
(function() {
var script = document.currentScript;
var theme = (script && script.getAttribute('data-theme')) || 'dark';
var orderUrl = (script && script.getAttribute('data-order-url')) || 'https://order.lthn.ai/order/';
var apiUrl = (script && script.getAttribute('data-api')) || 'https://api.lthn.io';
var containerId = (script && script.getAttribute('data-container')) || 'lthn-search';
var c = theme === 'light'
? { bg: '#f8fafc', border: '#e2e8f0', text: '#1e293b', muted: '#64748b', accent: '#818cf8', green: '#22c55e', amber: '#f59e0b', inputBg: '#fff' }
: { bg: '#111827', border: '#1f2937', text: '#e5e7eb', muted: '#9ca3af', accent: '#818cf8', green: '#34d399', amber: '#fbbf24', inputBg: '#0a0e17' };
function el(tag, style, text) {
var e = document.createElement(tag);
if (style) Object.assign(e.style, style);
if (text) e.textContent = text;
return e;
}
function render() {
var container = document.getElementById(containerId);
if (!container) return;
container.textContent = '';
var wrap = el('div', { fontFamily: '-apple-system,BlinkMacSystemFont,sans-serif', background: c.bg, border: '1px solid ' + c.border, borderRadius: '12px', padding: '1.5rem', maxWidth: '480px' });
var title = el('div', { textAlign: 'center', marginBottom: '1rem' });
var t1 = el('span', { fontSize: '1.1rem', fontWeight: '700', color: c.text }, 'Find your ');
var t2 = el('span', { fontSize: '1.1rem', fontWeight: '700', color: c.accent }, '.lthn');
var t3 = el('span', { fontSize: '1.1rem', fontWeight: '700', color: c.text }, ' name');
title.appendChild(t1); title.appendChild(t2); title.appendChild(t3);
wrap.appendChild(title);
var row = el('div', { display: 'flex', gap: '8px' });
var input = el('input', { flex: '1', padding: '10px 14px', border: '1px solid ' + c.border, borderRadius: '8px', background: c.inputBg, color: c.text, fontSize: '0.95rem', outline: 'none' });
input.type = 'text'; input.placeholder = 'myname';
var btn = el('button', { padding: '10px 20px', background: c.accent, color: '#fff', border: 'none', borderRadius: '8px', fontWeight: '600', cursor: 'pointer', fontSize: '0.9rem' }, 'Check');
row.appendChild(input); row.appendChild(btn);
wrap.appendChild(row);
var result = el('div', { marginTop: '12px', minHeight: '24px' });
wrap.appendChild(result);
var footer = el('div', { textAlign: 'center', marginTop: '10px' });
var link = el('a', { color: c.muted, fontSize: '0.7rem', textDecoration: 'none' }, 'Powered by .lthn TLD');
link.href = 'https://lthn.io'; link.target = '_blank';
footer.appendChild(link);
wrap.appendChild(footer);
container.appendChild(wrap);
function check() {
var name = input.value.trim().toLowerCase().replace(/\.lthn$/, '');
if (!name) return;
result.textContent = '';
var loading = el('span', { color: c.muted, fontSize: '0.85rem' }, 'Checking...');
result.appendChild(loading);
btn.disabled = true;
fetch(apiUrl + '/v1/names/available/' + encodeURIComponent(name), { headers: { 'Accept': 'application/json' } })
.then(function(r) { return r.json(); })
.then(function(data) {
btn.disabled = false;
result.textContent = '';
if (data.available && !data.reserved) {
var row2 = el('div', { display: 'flex', alignItems: 'center', justifyContent: 'space-between' });
row2.appendChild(el('span', { color: c.green, fontWeight: '600', fontSize: '0.9rem' }, name + '.lthn is available!'));
var regLink = el('a', { padding: '6px 16px', background: c.green, color: '#fff', borderRadius: '6px', textDecoration: 'none', fontSize: '0.8rem', fontWeight: '600' }, 'Register');
regLink.href = orderUrl; regLink.target = '_blank';
row2.appendChild(regLink);
result.appendChild(row2);
} else if (data.reserved) {
result.appendChild(el('span', { color: c.amber, fontSize: '0.85rem' }, name + '.lthn is reserved during sunrise period.'));
} else {
var taken = el('span', { color: c.amber, fontSize: '0.85rem' }, name + '.lthn is already taken. ');
var detailLink = el('a', { color: c.accent }, 'View details');
detailLink.href = apiUrl + '/names/' + name; detailLink.target = '_blank';
taken.appendChild(detailLink);
result.appendChild(taken);
}
})
.catch(function() {
btn.disabled = false;
result.textContent = '';
result.appendChild(el('span', { color: c.amber, fontSize: '0.85rem' }, 'Could not check availability. Try again.'));
});
}
btn.addEventListener('click', check);
input.addEventListener('keypress', function(e) { if (e.key === 'Enter') check(); });
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', render);
} else {
render();
}
})();