// Shared components — Central da Vida
// ── Brand Logo "Mente Central" v3 ───────────────────────────
// Usa a logo oficial em PNG (assets/logo.png). Quando exibido sem texto,
// o crop CSS mostra apenas o ícone (brain + ring + satélites) escondendo
// o texto que vem na imagem. Quando withText, renderiza o título ao lado.
const BrandLogo = ({ size = 44, withText = false, animated = false, light = false }) => {
const s = size;
return (
{withText && (
)}
);
};
// ── Status bar (custom, dark) ───────────────────────────────
const StatusBar = ({ time = '9:41' }) => (
);
// ── Home indicator ─────────────────────────────────────────
const HomeIndicator = ({ light = false }) => {
const isLightMode = CDV._mode === 'light';
const bg = isLightMode
? 'rgba(0,0,0,0.40)'
: (light ? 'rgba(255,255,255,0.95)' : 'rgba(255,255,255,0.75)');
return (
);
};
// ── Dynamic Island ─────────────────────────────────────────
const DynamicIsland = ({ children }) => (
{children}
);
// ── Card ───────────────────────────────────────────────────
const Card = ({ children, style = {}, onClick, gradient = false, padding = 16, glow = false }) => (
{children}
);
// ── Sheet (modal coming from bottom) ────────────────────────
const Sheet = ({ open, onClose, children, title }) => {
if (!open) return null;
return (
{title && (
)}
{children}
);
};
// ── Pill button ─────────────────────────────────────────────
const Pill = ({ children, color = CDV.brand, bg, onClick, style = {}, size = 'md' }) => {
const sizes = { sm: { px: 10, py: 4, fs: 11 }, md: { px: 12, py: 5, fs: 12 } };
const s = sizes[size];
return (
{children}
);
};
// ── Section header (with optional action) ──────────────────
const SectionHeader = ({ title, action, onAction, accent }) => (
{accent ? {title} : title}
{action && (
{action}
)}
);
// ── Checkbox with draw animation ───────────────────────────
const Checkbox = ({ checked, onChange, color = CDV.brand, size = 22 }) => (
{ e.stopPropagation(); onChange(!checked); }}
style={{
width: size, height: size, borderRadius: 8,
border: checked ? `1.5px solid ${color}` : `1.5px solid ${CDV.textFaint}`,
background: checked ? color : 'transparent',
display: 'flex', alignItems: 'center', justifyContent: 'center',
transition: 'all .2s', flexShrink: 0,
}}>
{checked && (
)}
);
// ── Progress ring ──────────────────────────────────────────
const ProgressRing = ({ percent = 0, size = 56, stroke = 5, color = CDV.brand, bg = 'rgba(255,255,255,0.07)', children }) => {
const r = (size - stroke) / 2;
const c = 2 * Math.PI * r;
const offset = c - (percent / 100) * c;
return (
);
};
// ── Linear progress ────────────────────────────────────────
const ProgressBar = ({ percent, color = CDV.brand, bg = 'rgba(255,255,255,0.06)', height = 6, gradient }) => (
);
// ── Icon tile ──────────────────────────────────────────────
const IconTile = ({ name, color, size = 38, bg, soft = true }) => (
);
// ── Bottom tab nav ─────────────────────────────────────────
const BottomNav = ({ active, onChange, onAI }) => {
const tabs = [
{ id: 'dashboard', icon: 'home', label: 'Início' },
{ id: 'tasks', icon: 'tasks', label: 'Tarefas' },
{ id: 'ai', icon: 'sparkle', label: 'IA', center: true },
{ id: 'finance', icon: 'wallet', label: 'Finanças' },
{ id: 'more', icon: 'grid', label: 'Mais' },
];
return (
{tabs.map(t => {
const isActive = active === t.id;
if (t.center) {
return (
onChange(t.id))} style={{
flex: 1, height: 56, background: 'transparent', border: 'none',
display: 'flex', justifyContent: 'center', alignItems: 'center',
padding: 0,
}}>
);
}
return (
onChange(t.id)} style={{
flex: 1, height: 56, background: 'transparent', border: 'none',
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
gap: 2, color: isActive ? CDV.text : CDV.textMuted, padding: 0,
}}>
{t.label}
);
})}
);
};
// ── Header (large title + actions) ──────────────────────────
const Header = ({ title, subtitle, onBack, right, big = true }) => (
{(onBack || right) && (
{onBack ? (
) :
}
{right ||
}
)}
{subtitle &&
{subtitle}
}
{big ? (
{title}
) : (
{title}
)}
);
// ── Toast (small floating) ─────────────────────────────────
const Toast = ({ text, icon = 'check', visible }) => (
);
Object.assign(window, {
StatusBar, HomeIndicator, DynamicIsland, Card, Sheet, Pill, SectionHeader,
Checkbox, ProgressRing, ProgressBar, IconTile, BottomNav, Header, Toast,
BrandLogo,
});