// ui.jsx — shared presentational primitives const { useState } = React; function Avatar({ src, size = 38, ring }) { return
; } function CatChip({ name }) { return {name}; } function StatusBadge({ status }) { const map = { pending: ['st-pending', 'Pending'], published: ['st-published', 'Published'], rejected: ['st-rejected', 'Rejected'], review: ['st-review', 'Under review'], }; const [cls, lbl] = map[status] || map.pending; return {lbl}; } // statistic chips (upvote/downvote/comment/views). Interactive when onVote provided. function StatChips({ idea, vote, onVote }) { const Icon = window.Icon; const up = idea.up + (vote === 'up' ? 1 : 0); const down = idea.down + (vote === 'down' ? 1 : 0); const stop = (e, dir) => { e.stopPropagation(); onVote && onVote(dir); }; const iv = !!onVote; // interactive only when a handler is provided return (
onVote && e.stopPropagation()}> {idea.comments} {window.fmt(idea.views)}
); } function StatCard({ s }) { const Icon = window.Icon; const down = s.trend < 0; return (
{Math.abs(s.trend)}%
{s.value}
{s.label}
); } Object.assign(window, { Avatar, CatChip, StatusBadge, StatChips, StatCard });