// mb-ui.jsx — shared UI primitives & icon set for Morar Bem // ── Icons (stroke, 24 viewBox) ─────────────────────────────── function Icon({ name, size = 22, color = "currentColor", fill = "none", sw = 1.9, style }) { const p = { fill: "none", stroke: color, strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round" }; const paths = { search: <>, filter: <>, sliders: <>, pin: <>, list: <>, map: <>, bag: <>, wallet: <>, receipt: <>, user: <>, star: , heart: , chevR: , chevL: , chevD: , plus: , minus: , target: <>, clock: <>, bike: <>, store: <>, check: , close: , arrowL: , info: <>, bolt: , coin: <>, food: <>, home: <>, health: <>, beauty: <>, fun: <>, pet: <>, trash: <>, bell: <>, card: <>, ticket: <>, share: <>, edit: <>, gift: <>, headset: <>, logout: <>, eye: <>, eyeoff: <>, lock: <>, mail: <>, phone: <>, apple: , bolt2: , book: <>, }; // SVG inline colado manualmente — força currentColor em fill/stroke // para que a cor seja controlada pela prop color sem precisar ajustar o SVG if (name && (name.trimStart().startsWith(" com fill colorido (fundo de exportações Figma/design tools) .replace(/]*fill="(?!none\b)[^"]*"[^>]*(?:\/>|>[^<]*<\/rect>)/g, '') .replace(/width="[^"]*"/g, `width="${size}"`) .replace(/height="[^"]*"/g, `height="${size}"`) .replace(/\s+fill="(?!none\b)[^"]*"/g, ' fill="currentColor"') .replace(/\s+stroke="(?!none\b)[^"]*"/g, ' stroke="currentColor"'); return ; } // Iconify icon: formato "lucide/utensils" guardado no banco // Usa mask-image para respeitar a prop color de forma precisa if (name && name.includes("/")) { const [set, icon] = name.split("/"); const url = `https://api.iconify.design/${set}/${icon}.svg`; return
; } return {paths[name]}; } const segIcon = (id) => ({ comer: "food", morar: "home", saude: "health", beleza: "beauty", lazer: "fun", pet: "pet" }[id] || "bag"); // ── Image placeholder (striped) ────────────────────────────── function Ph({ label = "imagem", h = 120, r = 14, style, className }) { return (
{label}
); } // ── Badges ─────────────────────────────────────────────────── function Cashback({ pct, small }) { return ( {pct}% ); } function Turbo({ pct, small }) { return ( +{pct}% ); } function Stars({ value = 5, size = 13, gap = 1 }) { return ( {[1, 2, 3, 4, 5].map(i => ( ))} ); } // ── Buttons ────────────────────────────────────────────────── function Btn({ children, onClick, variant = "primary", full, disabled, style }) { const base = { display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8, height: 52, padding: "0 22px", borderRadius: 15, border: "none", cursor: "pointer", font: "650 16px var(--ui)", width: full ? "100%" : undefined, transition: "transform .12s, filter .15s, background .15s", opacity: disabled ? 0.45 : 1, pointerEvents: disabled ? "none" : "auto", }; const v = { primary: { background: "var(--accent)", color: "var(--accent-ink)" }, dark: { background: "var(--brand)", color: "#fff" }, soft: { background: "var(--accent-50)", color: "var(--accent)" }, ghost: { background: "var(--surface)", color: "var(--text)", border: "1.5px solid var(--line)" }, }[variant]; return ( ); } function Chip({ children, active, onClick, icon, style }) { return ( ); } // Circular icon button function IconBtn({ name, onClick, size = 40, badge, color = "var(--text)", bg = "var(--surface)", style }) { return ( ); } Object.assign(window, { Icon, segIcon, Ph, Cashback, Turbo, Stars, Btn, Chip, IconBtn });