// shared.jsx — shared UI primitives for Absensi MOTOART
const STATUS_LABEL = { hadir: 'Hadir', telat: 'Telat', izin: 'Izin', absen: 'Tidak Hadir', belum: 'Belum Absen' };
function StatusChip({ status, sm }) {
return (
{STATUS_LABEL[status] || status}
);
}
function Avatar({ init, size = 44, fs }) {
return (
{init}
);
}
// animated donut ring
function Ring({ value, size = 132, sw = 13, label, sub, color = 'var(--accent)' }) {
const r = (size - sw) / 2;
const circ = 2 * Math.PI * r;
const off = circ * (1 - value / 100);
return (
);
}
function ProgressBar({ value, color = 'var(--accent)' }) {
return
;
}
// stylized "map" with abstract streets + pulsing pin
function MiniMap({ height = 132, pinLabel }) {
return (
{pinLabel && (
{pinLabel}
)}
);
}
function BottomNav({ tabs, active, onChange }) {
return (
{tabs.map(t => (
))}
);
}
function AppHeader({ title, sub, right, avatar }) {
return (
);
}
function IconBtn({ name, onClick, badge }) {
return (
);
}
function Logo({ h = 28, chip = true, pad = 6, radius = 11 }) {
const img =
;
if (!chip) return img;
return (
{img}
);
}
function Toast({ children, icon = 'checkCircle' }) {
return {children}
;
}
function StatCard({ label, value, unit, icon, tone = 'accent', delta }) {
const toneColor = { accent: 'var(--accent)', success: 'var(--success)', warn: 'var(--warn)', danger: 'var(--danger)' }[tone];
const toneWeak = { accent: 'var(--accent-weak)', success: 'var(--success-weak)', warn: 'var(--warn-weak)', danger: 'var(--danger-weak)' }[tone];
return (
{value}{unit && {unit}}
{label}
);
}
Object.assign(window, { STATUS_LABEL, StatusChip, Avatar, Ring, ProgressBar, MiniMap, BottomNav, AppHeader, IconBtn, Logo, Toast, StatCard });