import React, { useState, MouseEvent } from "react"; import { MessageCircle, X } from "lucide-react"; import { renderSlot, SlotValue } from "../../lib/slots"; import { cn } from "../../lib/utils"; import { CopilotChatDefaultLabels, useCopilotChatConfiguration, } from "../../providers/CopilotChatConfigurationProvider"; const DefaultOpenIcon: React.FC> = ({ className, ...props }) => ( ); const DefaultCloseIcon: React.FC> = ({ className, ...props }) => ( ); DefaultOpenIcon.displayName = "CopilotChatToggleButton.OpenIcon"; DefaultCloseIcon.displayName = "CopilotChatToggleButton.CloseIcon"; export interface CopilotChatToggleButtonProps extends Omit< React.ButtonHTMLAttributes, "children" > { /** Optional slot override for the chat (closed) icon. */ openIcon?: SlotValue; /** Optional slot override for the close icon. */ closeIcon?: SlotValue; } const ICON_TRANSITION_STYLE: React.CSSProperties = Object.freeze({ transition: "opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)", }); const ICON_WRAPPER_BASE = "cpk:pointer-events-none cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:will-change-transform"; const BUTTON_BASE_CLASSES = cn( "copilotKitButton", "cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center", "cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground", "cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out", "cpk:hover:scale-[1.04] cpk:hover:shadow-md", "cpk:cursor-pointer", "cpk:active:scale-[0.96]", "cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background", "cpk:disabled:pointer-events-none cpk:disabled:opacity-60", ); export const CopilotChatToggleButton = React.forwardRef< HTMLButtonElement, CopilotChatToggleButtonProps >(function CopilotChatToggleButton( { openIcon, closeIcon, className, ...buttonProps }, ref, ) { const { onClick, type, disabled, ...restProps } = buttonProps; const configuration = useCopilotChatConfiguration(); const labels = configuration?.labels ?? CopilotChatDefaultLabels; const [fallbackOpen, setFallbackOpen] = useState(false); const isOpen = configuration?.isModalOpen ?? fallbackOpen; const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen; const handleClick = (event: MouseEvent) => { if (disabled) { return; } if (onClick) { onClick(event); } if (event.defaultPrevented) { return; } const nextOpen = !isOpen; setModalOpen(nextOpen); }; const renderedOpenIcon = renderSlot(openIcon, DefaultOpenIcon, { className: "cpk:h-6 cpk:w-6", "aria-hidden": true, focusable: false, }); const renderedCloseIcon = renderSlot(closeIcon, DefaultCloseIcon, { className: "cpk:h-6 cpk:w-6", "aria-hidden": true, focusable: false, }); const openIconElement = ( ); const closeIconElement = ( ); return ( ); }); CopilotChatToggleButton.displayName = "CopilotChatToggleButton"; export default CopilotChatToggleButton; export { DefaultOpenIcon as CopilotChatToggleButtonOpenIcon, DefaultCloseIcon as CopilotChatToggleButtonCloseIcon, };