{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chat-messages-2",
  "title": "Chat Messages 2",
  "description": "Solace UI chat messages component variation 2.",
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "files": [
    {
      "path": "src/registry/components/chat-messages/two/index.tsx",
      "content": "\"use client\";\r\n\r\nimport { useState } from \"react\";\r\nimport Chat, { type User } from \"@/registry/components/chat-messages/chat\";\r\nimport type { Message } from \"@/registry/components/chat-messages/chat-message\";\r\nimport IphoneFrame from \"@/registry/components/chat-messages/iphone-frame\";\r\n\r\nexport default function ChatMessagesReverse() {\r\n    const users: User[] = [\r\n        {\r\n            name: \"User1\",\r\n            avatar:\r\n                \"https://assets.solaceui.com/solaceui-member-five.png\", // Replace with actual avatar URL\r\n        },\r\n        {\r\n            name: \"User2\",\r\n            avatar:\r\n                \"https://assets.solaceui.com/solaceui-member-four.png\", // Replace with actual avatar URL\r\n        },\r\n    ];\r\n\r\n    const [messages] = useState<Message[]>([\r\n        {\r\n            id: \"n1\",\r\n            name: \"User1\",\r\n            message: \"Hey, what is the best component library?\",\r\n        },\r\n        {\r\n            id: \"n2\",\r\n            name: \"User2\",\r\n            message: \"I think Solace UI is awesome it is simple and easy to use.\",\r\n        },\r\n        {\r\n            id: \"n3\",\r\n            name: \"User1\",\r\n            message: \"So, it is reliable and has a clean design?\",\r\n        },\r\n        {\r\n            id: \"n4\",\r\n            name: \"User2\",\r\n            message: \"Yes, exactly. It makes development a breeze.\",\r\n        },\r\n    ]);\r\n\r\n    return (\r\n        <main className=\"relative flex flex-col items-center justify-center p-4 \">\r\n            {/* Clipping Wrapper */}\r\n            <div className=\"mx-auto overflow-hidden w-[300px] h-[360px] sm:w-[350px] sm:h-[420px]\">\r\n                <IphoneFrame>\r\n                    <Chat\r\n                        messages={messages}\r\n                        currentUser=\"User1\"\r\n                        users={users} // Pass the users array with avatars\r\n                    />\r\n                </IphoneFrame>\r\n\r\n\r\n            </div>\r\n            <div\r\n                className=\"absolute bottom-0 left-0 right-0 z-50 h-24 sm:h-32 bg-linear-to-t from-background to-transparent pointer-events-none\"\r\n                aria-hidden=\"true\"></div>\r\n        </main>\r\n    );\r\n}\r\n",
      "type": "registry:component",
      "target": "components/chat-messages-2.tsx"
    },
    {
      "path": "src/registry/components/chat-messages/chat.tsx",
      "content": "\"use client\";\r\n\r\nimport { type FC, useRef, useEffect, useState, useLayoutEffect } from \"react\";\r\nimport { motion, AnimatePresence } from \"motion/react\";\r\nimport ChatMessage, { type Message } from \"@/registry/components/chat-messages/chat-message\";\n\r\nexport interface User {\r\n    name: string;\r\n    avatar: string;\r\n}\r\n\r\ninterface ChatProps {\r\n    messages: Message[];\r\n    currentUser: string;\r\n    users: User[];\r\n}\r\n\r\nconst Chat: FC<ChatProps> = ({ messages, currentUser, users }) => {\r\n    const containerRef = useRef<HTMLDivElement>(null);\r\n    const [visibleMessages, setVisibleMessages] = useState<Message[]>([]);\r\n\r\n    useEffect(() => {\r\n        if (messages.length === 0) return;\r\n\r\n        setVisibleMessages([]);\r\n        let cancelled = false;\r\n\r\n        (async () => {\r\n            for (const msg of messages) {\r\n                if (cancelled) return; // guard before delay\r\n                await new Promise((r) => setTimeout(r, 700));\r\n                if (cancelled) return; // guard after delay\r\n                setVisibleMessages((prev) => [...prev, msg]);\r\n            }\r\n        })();\r\n\r\n        return () => {\r\n            cancelled = true;\r\n        };\r\n    }, [messages]);\r\n\r\n    useLayoutEffect(() => {\r\n        const el = containerRef.current;\r\n        if (el) el.scrollTop = el.scrollHeight;\r\n    }, [visibleMessages]);\r\n\r\n    const getUserAvatar = (name: string) =>\r\n        users.find((u) => u.name === name)?.avatar ??\r\n        \"/placeholder.svg?height=40&width=40\";\r\n\r\n    return (\r\n        <div\r\n            ref={containerRef}\r\n            className=\"w-full h-full overflow-y-auto p-2 bg-white dark:bg-[#212121] flex flex-col py-[2rem]\"\r\n        >\r\n            <AnimatePresence initial={false} mode=\"popLayout\">\r\n                {visibleMessages.map((message) => (\r\n                    <motion.div\r\n                        key={message.id}\r\n                        layout\r\n                        initial={{ opacity: 0, y: 20 }}\r\n                        animate={{ opacity: 1, y: 0 }}\r\n                        exit={{ opacity: 0, y: 20 }}\r\n                        transition={{ duration: 0.4 }}\r\n                        className={`flex mb-4 ${message.name === currentUser ? \"justify-end\" : \"justify-start\"\r\n                            } items-end`}\r\n                    >\r\n                        <ChatMessage\r\n                            message={message}\r\n                            isCurrentUser={message.name === currentUser}\r\n                            avatar={getUserAvatar(message.name)}\r\n                        />\r\n                    </motion.div>\r\n                ))}\r\n            </AnimatePresence>\r\n\r\n            {visibleMessages.length > 0 &&\r\n                visibleMessages[visibleMessages.length - 1].name === currentUser && (\r\n                    <div className=\"text-xs text-right mt-1 mr-2 dark:text-white text-black\">\r\n                        Delivered\r\n                    </div>\r\n                )}\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default Chat;\r\n",
      "type": "registry:component",
      "target": "components/chat.tsx"
    },
    {
      "path": "src/registry/components/chat-messages/chat-message.tsx",
      "content": "\"use client\";\r\n\r\nimport { motion } from \"motion/react\";\r\nimport type { FC } from \"react\";\r\nimport Image from \"next/image\";\r\n\r\nexport interface Message {\r\n    id: string;\r\n    name: string;\r\n    message: string;\r\n    timestamp?: string;\r\n}\r\n\r\ninterface ChatMessageProps {\r\n    message: Message;\r\n    isCurrentUser: boolean;\r\n    avatar: string;\r\n}\r\n\r\nconst ChatMessage: FC<ChatMessageProps> = ({\r\n    message,\r\n    isCurrentUser,\r\n    avatar,\r\n}) => {\r\n    return (\r\n        <motion.div\r\n            layout\r\n            initial={{ opacity: 0, y: 20 }}\r\n            animate={{ opacity: 1, y: 0 }}\r\n            exit={{ opacity: 0, y: 20 }}\r\n            transition={{ duration: 0.4 }}\r\n            className={`flex mb-4 ${isCurrentUser ? \"justify-end\" : \"justify-start\"\r\n                } items-end`}\r\n        >\r\n            {!isCurrentUser && (\r\n                <div className=\"flex-shrink-0 mr-2\">\r\n                    <div className=\"w-8 h-8 rounded-full overflow-hidden\">\r\n                        <Image\r\n                            src={avatar || \"/placeholder.svg\"}\r\n                            alt={`${message.name}'s avatar`}\r\n                            width={32}\r\n                            height={32}\r\n                            className=\"object-cover\"\r\n                          unoptimized\r\n                        />\r\n                    </div>\r\n                </div>\r\n            )}\r\n\r\n            <div\r\n                className={`max-w-[70%] px-2 py-1 rounded-2xl ${isCurrentUser\r\n                        ? \"bg-blue-500 text-white rounded-br-none\"\r\n                        : \"bg-gray-200 text-black rounded-bl-none\"\r\n                    }`}\r\n            >\r\n                <p className=\"text-sm sm:text-base\">{message.message}</p>\r\n                {message.timestamp && (\r\n                    <p\r\n                        className={`text-xs mt-1 ${isCurrentUser ? \"text-blue-100\" : \"text-gray-500\"\r\n                            }`}\r\n                    >\r\n                        {message.timestamp}\r\n                    </p>\r\n                )}\r\n            </div>\r\n\r\n            {isCurrentUser && <div className=\"w-8 \"></div>}\r\n        </motion.div>\r\n    );\r\n};\r\n\r\nexport default ChatMessage;\r\n",
      "type": "registry:component",
      "target": "components/chat-message.tsx"
    },
    {
      "path": "src/registry/components/chat-messages/blur-fade.tsx",
      "content": "// Component From Motion-Primitives\r\n\r\n\"use client\";\r\n\r\nimport {\r\n    AnimatePresence,\r\n    motion,\r\n    useInView,\r\n    UseInViewOptions,\r\n    Variants,\r\n    MotionProps,\r\n} from \"motion/react\";\r\nimport { useRef } from \"react\";\r\n\r\ntype MarginType = UseInViewOptions[\"margin\"];\r\n\r\ninterface BlurFadeProps extends MotionProps {\r\n    children: React.ReactNode;\r\n    className?: string;\r\n    variant?: {\r\n        hidden: { y: number };\r\n        visible: { y: number };\r\n    };\r\n    duration?: number;\r\n    delay?: number;\r\n    offset?: number;\r\n    direction?: \"up\" | \"down\" | \"left\" | \"right\";\r\n    inView?: boolean;\r\n    inViewMargin?: MarginType;\r\n    blur?: string;\r\n}\r\n\r\nexport function BlurFade({\r\n    children,\r\n    className,\r\n    variant,\r\n    duration = 0.4,\r\n    delay = 0,\r\n    offset = 6,\r\n    direction = \"down\",\r\n    inView = false,\r\n    inViewMargin = \"-50px\",\r\n    blur = \"6px\",\r\n    ...props\r\n}: BlurFadeProps) {\r\n    const ref = useRef(null);\r\n    const inViewResult = useInView(ref, { once: true, margin: inViewMargin });\r\n    const isInView = !inView || inViewResult;\r\n    const defaultVariants: Variants = {\r\n        hidden: {\r\n            [direction === \"left\" || direction === \"right\" ? \"x\" : \"y\"]:\r\n                direction === \"right\" || direction === \"down\" ? -offset : offset,\r\n            opacity: 0,\r\n            filter: `blur(${blur})`,\r\n        },\r\n        visible: {\r\n            [direction === \"left\" || direction === \"right\" ? \"x\" : \"y\"]: 0,\r\n            opacity: 1,\r\n            filter: `blur(0px)`,\r\n        },\r\n    };\r\n    const combinedVariants = variant || defaultVariants;\r\n    return (\r\n        <AnimatePresence>\r\n            <motion.div\r\n                ref={ref}\r\n                initial=\"hidden\"\r\n                animate={isInView ? \"visible\" : \"hidden\"}\r\n                exit=\"hidden\"\r\n                variants={combinedVariants}\r\n                transition={{\r\n                    delay: 0.04 + delay,\r\n                    duration,\r\n                    ease: \"easeOut\",\r\n                }}\r\n                className={className}\r\n                {...props}\r\n            >\r\n                {children}\r\n            </motion.div>\r\n        </AnimatePresence>\r\n    );\r\n}\r\n",
      "type": "registry:component",
      "target": "components/blur-fade.tsx"
    },
    {
      "path": "src/registry/components/chat-messages/iphone-frame.tsx",
      "content": "import type { FC, ReactNode } from \"react\";\r\nimport {\r\n    WifiIcon as LuWifi,\r\n    BatteryMediumIcon as LuBatteryMedium,\r\n    SignalIcon as LuSignal,\r\n} from \"lucide-react\";\r\n\r\ninterface IphoneFrameProps {\r\n    children: ReactNode;\r\n    className?: string;\r\n}\r\n\r\nconst IphoneFrame: FC<IphoneFrameProps> = ({ children, className = \"\" }) => {\r\n    // Get current time in format HH:MM\r\n    const getCurrentTime = () => {\r\n        const now = new Date();\r\n        const hours = now.getHours().toString().padStart(2, \"0\");\r\n        const minutes = now.getMinutes().toString().padStart(2, \"0\");\r\n        return `${hours}:${minutes}`;\r\n    };\r\n\r\n    return (\r\n        // The main phone body\r\n        <div\r\n            className={`relative mx-auto border-[10px] border-gray-900 bg-[#212121] dark:border-gray-200 dark:bg-gray-100 rounded-[44px] shadow-xl overflow-hidden w-[300px] h-[600px] sm:w-[350px] sm:h-[700px] ${className}`}\r\n        >\r\n            {/* Status Bar */}\r\n            <div className=\"absolute top-0 left-0 right-0 h-8 z-20 px-6 flex justify-between items-center text-black dark:text-white dark:bg-[#212121] bg-white\">\r\n                {/* Left side - Time */}\r\n                <div className=\"text-xs font-semibold flex items-center\">\r\n                    <LuSignal className=\"w-3.5 h-3.5 mr-1\" />\r\n                    {getCurrentTime()}\r\n                </div>\r\n\r\n                {/* Notch (center) */}\r\n                <div\r\n                    className=\"absolute top-0 left-1/2 -translate-x-1/2 w-[45%] h-[24px] bg-black dark:bg-gray-100 rounded-b-xl z-30 flex justify-center items-center space-x-2 p-1\"\r\n                >\r\n                    {/* Notch Details (Speaker/Camera) */}\r\n                    <div\r\n                        className=\"w-10 h-2 rounded-full bg-white dark:bg-black\"></div>\r\n                    <div\r\n                        className=\"w-2 h-2 rounded-full bg-white dark:bg-black\"></div>\r\n                </div>\r\n\r\n                {/* Right side - WiFi and Battery */}\r\n                <div className=\"text-xs font-semibold flex items-center\">\r\n                    <LuWifi className=\"w-4 h-4 mr-1\" />\r\n                    <LuBatteryMedium className=\"w-5 h-5\" />\r\n                </div>\r\n            </div>\r\n\r\n            {/* The screen area */}\r\n            <div\r\n                className=\"w-full h-full (bg-white dark:bg-black) rounded-[34px] overflow-hidden pt-8\"\r\n            >\r\n                {children}\r\n            </div>\r\n\r\n            {/* Side Buttons */}\r\n            {/* Volume Up */}\r\n            <div\r\n                className=\"absolute -left-[12px] top-[100px] w-[4px] h-[50px] rounded-l-md bg-gray-800 dark:bg-gray-300\"></div>\r\n            {/* Volume Down */}\r\n            <div\r\n                className=\"absolute -left-[12px] top-[160px] w-[4px] h-[50px] rounded-l-md bg-gray-800 dark:bg-gray-300\"></div>\r\n            {/* Power/Side Button */}\r\n            <div\r\n                className=\"absolute -right-[12px] top-[130px] w-[4px] h-[80px] rounded-r-md bg-gray-800 dark:bg-gray-300\"></div>\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default IphoneFrame;\r\n",
      "type": "registry:component",
      "target": "components/iphone-frame.tsx"
    }
  ],
  "type": "registry:component"
}