// ========================================================== // VoAIs Call — shared UI: icons, primitives, sample data // Exposes everything on window so other Babel scripts can use. // ========================================================== // ---------- Icon set (stroke-style, 1.6 weight) ---------- const Ic = ({ d, size = 16, fill = "none", stroke = "currentColor", w = 1.6, children, ...rest }) => ( {d ? : children} ); const I = { dashboard: (p) => , campaigns: (p) => , agents: (p) => , flow: (p) => , monitor: (p) => , history: (p) => , contacts: (p) => , analytics: (p) => , kb: (p) => , integrations: (p) => , settings: (p) => , billing: (p) => , search: (p) => , bell: (p) => , chevD: (p) => , chevR: (p) => , chevL: (p) => , chevU: (p) => , plus: (p) => , filter: (p) => , more: (p) => , phone: (p) => , phoneIn: (p) => , phoneOut: (p) => , mic: (p) => , micOff: (p) => , play: (p) => , pause: (p) => , upload: (p) => , download: (p) => , edit: (p) => , trash: (p) => , copy: (p) => , pin: (p) => , check: (p) => , x: (p) => , star: (p) => , fire: (p) => , bot: (p) => , spark: (p) => , globe: (p) => , shield: (p) => , zap: (p) => , logout: (p) => , sun: (p) => , moon: (p) => , collapse: (p) => , expand: (p) => , user: (p) => , users: (p) => , server: (p) => , tag: (p) => , arrow_up_right: (p) => , arrow_right: (p) => , arrow_left: (p) => , drag: (p) => , link: (p) => , brain: (p) => , message: (p) => , alert: (p) => , calendar: (p) => , network: (p) => , whatsapp: (p) => , inbox: (p) => , send: (p) => , paperclip: (p) => , smile: (p) => , template: (p) => , reply: (p) => , email: (p) => , archive: (p) => , }; // ---------- Primitives ---------- function Badge({ tone = "gray", children, dot }) { return {dot && }{children}; } function Btn({ kind = "primary", size, icon, children, onClick, className = "", ...rest }) { const sizeCls = size === "sm" ? "sm" : size === "lg" ? "lg" : ""; const iconOnly = icon && !children ? "icon-only" : ""; return ( ); } function Card({ children, className = "", padded = true, ...rest }) { return
{children}
; } function CardHead({ title, subtitle, right, icon }) { return (
{icon}

{title}

{subtitle &&
{subtitle}
}
{right}
); } function Segmented({ value, options, onChange }) { return (
{options.map(o => { const v = typeof o === "string" ? o : o.value; const label = typeof o === "string" ? o : o.label; return ( ); })}
); } function Tabs({ value, options, onChange }) { return (
{options.map(o => { const v = typeof o === "string" ? o : o.value; const label = typeof o === "string" ? o : o.label; const count = typeof o === "object" ? o.count : null; return (
onChange?.(v)}> {label}{count != null && {count}}
); })}
); } function Avatar({ name = "?", src, size = 32, color }) { const initials = name.split(/\s+/).slice(0, 2).map(s => s[0]).join("").toUpperCase(); const palette = ["linear-gradient(135deg,#FFB199,#C46AFF)","linear-gradient(135deg,#5B8FFF,#00D49F)","linear-gradient(135deg,#FFD27D,#FF6F91)","linear-gradient(135deg,#A78BFA,#3B7BFF)","linear-gradient(135deg,#00D49F,#4DD0E1)","linear-gradient(135deg,#FF8A3D,#F4C53D)"]; const bg = color || palette[(name.charCodeAt(0) || 0) % palette.length]; return ( {initials || "?"} ); } function Toggle({ value, onChange }) { return onChange?.(!value)} role="switch" aria-checked={!!value}/>; } function Field({ label, hint, children }) { return (
{label && } {children} {hint &&
{hint}
}
); } // Sparkline (mini chart for KPI cards) function Sparkline({ data, color = "var(--accent)", width = 80, height = 28 }) { if (!data?.length) return null; const max = Math.max(...data), min = Math.min(...data); const rng = max - min || 1; const pts = data.map((v, i) => { const x = (i / (data.length - 1)) * width; const y = height - ((v - min) / rng) * (height - 4) - 2; return `${x},${y}`; }); const area = `M0,${height} L${pts.join(" L")} L${width},${height} Z`; return ( ); } // Donut chart function Donut({ data, size = 160, thickness = 22, center }) { const total = data.reduce((a, b) => a + b.value, 0) || 1; const radius = (size - thickness) / 2; const circ = 2 * Math.PI * radius; let offset = 0; return ( {data.map((d, i) => { const len = (d.value / total) * circ; const seg = ( ); offset += len; return seg; })} {center && (
{center}
)}
); } // Bar chart for revenue/calls function BarChart({ data, height = 220, accentIndex = null, format = (v) => v.toLocaleString() }) { const max = Math.max(...data.map(d => d.value)); const yLines = [0, 0.25, 0.5, 0.75, 1].map(p => Math.round(max * p)); return (
{[...yLines].reverse().map((v, i) =>
{v >= 1000 ? (v/1000).toFixed(1)+"k" : v}
)}
{[0, 0.25, 0.5, 0.75, 1].map((p, i) => (
))} {data.map((d, i) => { const isAcc = i === accentIndex; return (
{isAcc && (
▲ {d.delta}
)}
{!isAcc && (
)} {isAcc && (
{format(d.value)}
)}
{d.label}
); })}
); } // Live waveform (animated) function Waveform({ count = 36, color = "var(--accent)", height = 36, running = true }) { return (
{Array.from({ length: count }).map((_, i) => { const seed = Math.sin(i * 1.3) * 0.5 + 0.5; const h = 25 + seed * 75; const delay = (i % 8) * 0.08; return ( ); })}
); } // Empty state function Empty({ title, sub, action, icon }) { return (
{icon &&
{icon}
}
{title}
{sub &&
{sub}
} {action &&
{action}
}
); } // expose globally Object.assign(window, { I, Ic, Badge, Btn, Card, CardHead, Segmented, Tabs, Avatar, Toggle, Field, Sparkline, Donut, BarChart, Waveform, Empty });