// Shared UI primitives — Metal Padrão const fmtBRL = (n) => (n || 0).toLocaleString("pt-BR", { style: "currency", currency: "BRL" }); const fmtNumber = (n, d = 0) => (n || 0).toLocaleString("pt-BR", { minimumFractionDigits: d, maximumFractionDigits: d }); const fmtDate = (iso) => { if (!iso) return "—"; const [y, m, d] = iso.split("-"); return `${d}/${m}/${y}`; }; const fmtDateShort = (iso) => { if (!iso) return "—"; const [, m, d] = iso.split("-"); const meses = ["jan","fev","mar","abr","mai","jun","jul","ago","set","out","nov","dez"]; return `${d} ${meses[parseInt(m,10)-1]}`; }; // Button const Button = ({ children, variant = "primary", size = "md", icon, onClick, type = "button", disabled, full, ...rest }) => { const cls = ["btn", `btn--${variant}`, `btn--${size}`, full && "btn--full", disabled && "btn--disabled"].filter(Boolean).join(" "); return ( ); }; // Field wrapper const Field = ({ label, required, hint, error, children, span = 12 }) => ( ); // Input const Input = React.forwardRef(({ prefix, suffix, ...rest }, ref) => (
{prefix && {prefix}} {suffix && {suffix}}
)); // Select const Select = ({ options, value, onChange, placeholder, ...rest }) => (
); // Currency input const InputMoney = ({ value, onChange, ...rest }) => { const handle = (e) => { const raw = e.target.value.replace(/[^\d]/g, ""); onChange?.(raw ? parseInt(raw, 10) / 100 : 0); }; return (
R$
); }; // Badge / status const Badge = ({ children, color, bg, dot, size = "md" }) => ( {dot && } {children} ); const StatusBadge = ({ statusId }) => { const s = window.MP_DATA.statusList.find(x => x.id === statusId); if (!s) return null; return {s.nome}; }; const CnpjPill = ({ cnpjId }) => { const c = window.MP_DATA.cnpjs.find(x => x.id === cnpjId); if (!c) return null; return {c.nome}; }; // Avatar (vendedor) const Avatar = ({ vendedorId, size = 28 }) => { const v = window.MP_DATA.vendedores.find(x => x.id === vendedorId); if (!v) return null; return ( {v.iniciais} ); }; // Card const Card = ({ children, title, action, padded = true, className = "" }) => (
{(title || action) && (
{title}
{action}
)}
{children}
); // KPI tile const KPI = ({ label, value, sub, accent, icon }) => (
{icon && } {label}
{value}
{sub &&
{sub}
}
); // Empty state const Empty = ({ icon = "sparkle", title, hint, action }) => (
{title}
{hint &&
{hint}
} {action &&
{action}
}
); // Modal const Modal = ({ open, onClose, title, children, footer, size = "md" }) => { if (!open) return null; return (
e.stopPropagation()}>

{title}

{children}
{footer &&
{footer}
}
); }; // Drawer (slide from right) const Drawer = ({ open, onClose, title, subtitle, children, footer }) => { if (!open) return null; return (
e.stopPropagation()}>
{title}
{subtitle &&
{subtitle}
}
{children}
{footer &&
{footer}
}
); }; Object.assign(window, { Button, Field, Input, InputMoney, Select, Badge, StatusBadge, CnpjPill, Avatar, Card, KPI, Empty, Modal, Drawer, fmtBRL, fmtNumber, fmtDate, fmtDateShort, });