// ===== Shared parts for Peeka v2 ===== const { useState, useEffect, useRef, useMemo } = React; const rupiah = (n) => "Rp " + n.toLocaleString("id-ID"); const toPascal = (s) => s .split("-") .map((w) => w[0].toUpperCase() + w.slice(1)) .join(""); const Icon = ({ name, className = "", size = 20, strokeWidth = 2 }) => { const ref = useRef(null); useEffect(() => { if (ref.current && window.lucide) { ref.current.innerHTML = ""; const svg = window.lucide.createElement( window.lucide[toPascal(name)] || window.lucide.Circle, ); svg.setAttribute("width", size); svg.setAttribute("height", size); svg.setAttribute("stroke-width", strokeWidth); svg.setAttribute("class", className); ref.current.appendChild(svg); } }, [name, className, size, strokeWidth]); return ; }; // ===== Fireflies ===== const Fireflies = ({ count = 14 }) => { const flies = useMemo( () => Array.from({ length: count }, () => ({ top: Math.random() * 90 + 2, left: Math.random() * 95 + 2, delay: Math.random() * 3, driftDelay: Math.random() * 9, scale: 0.5 + Math.random() * 1.2, })), [count], ); return ( ); }; // ===== Reveal on scroll ===== const useReveal = () => { useEffect(() => { const els = document.querySelectorAll(".reveal"); const io = new IntersectionObserver( (entries) => { entries.forEach((e) => { if (e.isIntersecting) e.target.classList.add("in"); }); }, { threshold: 0.12 }, ); els.forEach((el) => io.observe(el)); return () => io.disconnect(); }, []); }; // ===== Logo ===== const Logo = ({ light = false }) => (
Peeka
Peeka
); // ===== Telegram Chat Bubble — native feel ===== // Telegram uses: sky-blue user bubbles (right), white bot bubbles (left), rounded 18px, tail on last bubble const ChatBubble = ({ side = "bot", children, time, tail = true, delay = 0, avatar = null, name = null, }) => { const [show, setShow] = useState(delay === 0); useEffect(() => { if (delay > 0) { const t = setTimeout(() => setShow(true), delay); return () => clearTimeout(t); } }, [delay]); if (!show) return null; const isUser = side === "user"; return (
{!isUser && avatar && (
{avatar}
)}
{!isUser && name && (
{name}
)}
{children}
{time && (
{time} {isUser && ( )}
)} {tail && ( )}
); }; // ===== Telegram Window frame ===== const TelegramWindow = ({ children, botName = "Peeka Bot", subtitle = "bot", }) => (
{/* Header */}
P
{botName}
{subtitle}
{/* Chat body */}
\"), linear-gradient(135deg, #E6E9F0 0%, #D7E3F0 100%)", }} > {children}
{/* Composer */}
Message
); // ===== Nav ===== const Nav = () => { const [open, setOpen] = useState(false); const [scrolled, setScrolled] = useState(false); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 20); window.addEventListener("scroll", onScroll); return () => window.removeEventListener("scroll", onScroll); }, []); return (
Coba di Telegram
{open && (
setOpen(false)} className="block"> Fitur setOpen(false)} className="block" > Cara Pakai setOpen(false)} className="block"> Menu Bot setOpen(false)} className="block"> Harga setOpen(false)} className="block"> UMKM setOpen(false)} className="block bg-glow-400 text-navy-900 font-semibold text-center py-2.5 rounded-full" > Coba di Telegram
)}
); }; Object.assign(window, { rupiah, Icon, Fireflies, useReveal, Logo, ChatBubble, TelegramWindow, Nav, });