/* ============================================================
CHAINUS — shared UI primitives
============================================================ */
function Logo({ height = 24 }) {
return (
);
}
function ArrowIcon() { return ; }
function ChevronIcon() { return ; }
function AppleGlyph() { return ; }
function PlayGlyph() { return ; }
function Glyph({ kind, w = 22 }) {
const s = { width: w, height: w };
const k = { stroke: 'currentColor', strokeWidth: 1.8, fill: 'none', strokeLinecap: 'round', strokeLinejoin: 'round' };
if (kind === 'feed') return ;
if (kind === 'tokenize') return ;
if (kind === 'learn') return ;
if (kind === 'intel') return ;
if (kind === 'shield') return ;
if (kind === 'eye') return ;
if (kind === 'key') return ;
if (kind === 'exit') return ;
if (kind === 'phone') return ;
if (kind === 'web') return ;
if (kind === 'sync') return ;
if (kind === 'spark') return ;
if (kind === 'cart') return ;
if (kind === 'chart') return ;
if (kind === 'book') return ;
if (kind === 'globe') return ;
if (kind === 'bolt') return ;
if (kind === 'tag') return ;
if (kind === 'gas') return ;
return null;
}
/* App Store + Google Play badges */
function StoreBadges({ t }) {
return (
);
}
function MagneticButton({ children, className = '', onClick, style }) {
const ref = useMagnetic(0.22);
return ;
}
/* Theme toggle — sun/moon morph */
function ThemeToggle({ theme, onToggle }) {
const dark = theme === 'dark';
return (
);
}
function FramePreview({ slotId = '', type = 'web', placeholder = '' }) {
const id = String(slotId).toLowerCase();
const mode = id.includes('market') || id.includes('web') ? 'market'
: id.includes('token') || id.includes('mint') ? 'mint'
: id.includes('tablet') || id.includes('sync') ? 'sync'
: 'feed';
const title = mode === 'market' ? 'Market pulse' : mode === 'mint' ? 'Token studio' : mode === 'sync' ? 'Synced workspace' : 'Community feed';
const metric = mode === 'market' ? '+12.8%' : mode === 'mint' ? 'Ready' : mode === 'sync' ? 'Live' : '24K';
const chips = mode === 'market' ? ['BTC', 'RWA', 'NFT'] : mode === 'mint' ? ['Upload', 'Price', 'Mint'] : mode === 'sync' ? ['Mobile', 'Web', 'Tablet'] : ['Follow', 'Discuss', 'Collect'];
const rows = mode === 'market'
? [['ETH', '$3,892', '+2.4%'], ['SOL', '$164', '+4.8%'], ['RWA', '$82M', '+8.1%']]
: mode === 'mint'
? [['Digital work', 'Verified', 'Ready'], ['Royalty', '2.5%', 'Set'], ['Listing', 'Fixed', 'Live']]
: mode === 'sync'
? [['Feed draft', 'Mobile', 'Saved'], ['Market watch', 'Web', 'Open'], ['Mint status', 'Tablet', 'Synced']]
: [['NovaDAO', 'Proposal live', '18K'], ['RWA desk', 'Token drop', '6.4K'], ['ChainUs', placeholder || 'Daily brief', '2.1K']];
return (
ChainUs
Live
{title}
{metric}
{chips.map((chip) => {chip})}
{Array.from({ length: 14 }).map((_, i) => )}
{rows.map((row) => (
{row[0]}
{row[1]}
{row[2]}
))}
);
}
const FRAME_SHOTS = {
'hero-web': 'assets/v3/overview-page-desktop.png',
'hero-phone': 'assets/v3/overview-page-mobile.png',
'feature-feed': 'assets/v3/feed-mobile.jpg',
'any-phone': 'assets/v3/overview-page-mobile.png',
'any-web': 'assets/v3/overview-page-desktop.png',
'any-tablet': 'assets/v3/market-page-desktop.png',
'shot-home': 'assets/v3/feed-mobile.jpg',
'shot-tokenize': 'assets/v3/nft-page-mobile.png',
'shot-market': 'assets/v3/market-page-mobile.png'
};
function frameShotFor(slotId = '', type = 'web') {
if (Object.prototype.hasOwnProperty.call(FRAME_SHOTS, slotId)) return FRAME_SHOTS[slotId];
if (type === 'phone') return 'assets/v3/overview-page-mobile.png';
if (type === 'tablet') return 'assets/v3/market-page-desktop.png';
return 'assets/v3/overview-page-desktop.png';
}
/* Phone frame */
function PhoneFrame({ slotId, placeholder, width = 280, children, glow = false }) {
const h = Math.round(width * 2.04);
const shot = frameShotFor(slotId, 'phone');
return (
{children || (!shot && )}
);
}
/* Desktop / browser window */
function DesktopFrame({ slotId, placeholder, url = 'chainus.org', children, className = '', ratio = '16 / 10' }) {
const shot = frameShotFor(slotId, 'web');
return (
{url}
{children || (!shot && )}
);
}
/* Tablet frame */
function TabletFrame({ slotId, placeholder, width = 360, children }) {
const h = Math.round(width * 1.34);
const shot = frameShotFor(slotId, 'tablet');
return (
{children || (!shot && )}
);
}
/* Ecosystem wordmark marquee (quiet) */
function Logos({ t }) {
const names = ['Ledgerly', 'NovaPay', 'Mintlab', 'Polychain', 'Aurora', 'Beacon', 'Driftwave', 'Helios'];
const row = names.concat(names);
return (
{t.dir === 'zh' ? '与 120+ 链上社区与团队共建' : 'Trusted across 120+ on-chain communities & teams'}
);
}
function SectionHead({ eyebrow, title, sub, center, max, align, showEyebrow = false }) {
return (
{showEyebrow && eyebrow && {eyebrow}}
{title}
{sub && {sub}}
);
}
Object.assign(window, {
Logo, ArrowIcon, ChevronIcon, AppleGlyph, PlayGlyph, Glyph,
StoreBadges, MagneticButton, ThemeToggle, FramePreview, frameShotFor, PhoneFrame, DesktopFrame, TabletFrame, Logos, SectionHead
});