import { useIsVisible } from '../hooks/use-is-visible'; import React, { ReactNode, useCallback, useEffect, useRef, useState, } from 'react'; import { TimesIcon } from './icons/times-icon'; import { Composer } from './composer'; import { Botz, Message } from '../lib/botz'; import { BotzStatus } from '../hooks/use-botz'; const parseMarkDown = (text: string) => { return text.replace( /\[([^\[]+)]\((.*)\)/gm, '$1' ); }; interface MessageProps extends Message {} function MessageBubble({ author, body, variant }: MessageProps) { const ref = useRef(null); useEffect(() => { const target = ref.current; if (!target) return; requestAnimationFrame(() => { target.parentElement!.dataset.visible = 'true'; }); }, [ref]); return (
{author === 'bot' ? (
) : (
{body}
)}
); } interface MessengerFrameProps { isOpen?: boolean; close?: () => void; logo?: ReactNode; bot: Botz; status: BotzStatus; } export function MessengerFrame({ isOpen, close, bot, logo, status, }: MessengerFrameProps) { const isVisible = useIsVisible({ open: isOpen, timeout: 3000 }); const scrollable = useRef(null); const [messages, setMessages] = useState([]); const [placeholder, setPlaceholder] = useState('Send a message…'); useEffect(() => { bot.on('message', (message) => { setMessages((c) => [...c, message]); }); bot.on('question', (question) => { setPlaceholder(question); }); }, [bot]); useEffect(() => { const target = scrollable.current; if (!target) return; requestAnimationFrame(() => target.scrollTo({ top: target.scrollHeight, behavior: 'smooth', }) ); }, [messages.length, scrollable, isVisible]); const handleMessage = useCallback( (message: string) => { if (message.trim().length === 0) return; bot.parse(message); }, [bot] ); return (
{isVisible ? ( <>
{logo || (
Hi! 👋 Shoot us a message!
)}
{messages.map((message, idx) => ( ))}
) : null}
); }