{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "direct-chat", "title": "Direct Chat", "description": "Chat widget with message bubbles (left/right aligned), contacts panel toggle, and message input.", "registryDependencies": [ "https://raw.githubusercontent.com/dnachavez/adminlte-next/master/public/r/adminlte-theme.json", "https://raw.githubusercontent.com/dnachavez/adminlte-next/master/public/r/box.json", "https://raw.githubusercontent.com/dnachavez/adminlte-next/master/public/r/use-direct-chat.json" ], "files": [ { "path": "registry/new-york/direct-chat/components/direct-chat.tsx", "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/registry/new-york/adminlte-theme/lib/cn\"\n\n/* ---------------------------------------------------------------------------\n * Types\n * -------------------------------------------------------------------------- */\n\ninterface DirectChatMessageData {\n id: string\n name: string\n avatarUrl: string\n text: string\n time: string\n isOwn?: boolean\n}\n\ninterface DirectChatContactData {\n id: string\n name: string\n avatarUrl: string\n status?: \"online\" | \"offline\" | \"away\" | \"busy\"\n lastMessage?: string\n}\n\n/* ---------------------------------------------------------------------------\n * DirectChatMessage\n * -------------------------------------------------------------------------- */\n\ninterface DirectChatMessageProps extends React.HTMLAttributes {\n name: string\n avatarUrl: string\n text: string\n time: string\n isOwn?: boolean\n variant?: string\n}\n\nconst DirectChatMessage = React.forwardRef(\n ({ className, name, avatarUrl, text, time, isOwn = false, variant, ...props }, ref) => {\n return (\n \n {/* Avatar */}\n \n\n {/* Message content */}\n
\n {/* Name and time */}\n \n {name}\n {time}\n
\n\n {/* Message bubble */}\n \n {text}\n \n \n \n )\n }\n)\nDirectChatMessage.displayName = \"DirectChatMessage\"\n\n/* ---------------------------------------------------------------------------\n * DirectChatContacts\n * -------------------------------------------------------------------------- */\n\ninterface DirectChatContactsProps extends React.HTMLAttributes {\n contacts: DirectChatContactData[]\n visible?: boolean\n}\n\nconst statusColors: Record = {\n online: \"bg-[#00a65a]\",\n offline: \"bg-[#d2d6de]\",\n away: \"bg-[#f39c12]\",\n busy: \"bg-[#dd4b39]\",\n}\n\nconst DirectChatContacts = React.forwardRef(\n ({ className, contacts, visible = false, ...props }, ref) => {\n return (\n \n \n \n )\n }\n)\nDirectChatContacts.displayName = \"DirectChatContacts\"\n\n/* ---------------------------------------------------------------------------\n * DirectChat\n * -------------------------------------------------------------------------- */\n\ninterface DirectChatProps extends React.HTMLAttributes {\n messages?: DirectChatMessageData[]\n contacts?: DirectChatContactData[]\n variant?: string\n height?: number\n onSendMessage?: (text: string) => void\n}\n\nconst DirectChat = React.forwardRef(\n (\n {\n className,\n messages = [],\n contacts = [],\n variant,\n height = 250,\n onSendMessage,\n children,\n ...props\n },\n ref\n ) => {\n const [inputValue, setInputValue] = React.useState(\"\")\n const [contactsVisible, setContactsVisible] = React.useState(false)\n\n const handleSend = () => {\n if (inputValue.trim() && onSendMessage) {\n onSendMessage(inputValue.trim())\n setInputValue(\"\")\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\") {\n e.preventDefault()\n handleSend()\n }\n }\n\n return (\n \n {/* Box tools - contacts toggle */}\n {contacts.length > 0 && (\n
\n setContactsVisible(!contactsVisible)}\n aria-label=\"Toggle contacts\"\n >\n \n {contactsVisible ? \"\\u2715\" : \"\\u2630\"}\n \n \n
\n )}\n\n {/* Messages container */}\n \n {messages.map((msg) => (\n \n ))}\n {children}\n \n\n {/* Input area */}\n
\n
\n setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n />\n \n Send\n \n
\n
\n\n {/* Contacts overlay */}\n {contacts.length > 0 && (\n \n )}\n \n )\n }\n)\nDirectChat.displayName = \"DirectChat\"\n\nexport { DirectChat, DirectChatMessage, DirectChatContacts }\nexport type {\n DirectChatProps,\n DirectChatMessageProps,\n DirectChatContactsProps,\n DirectChatMessageData,\n DirectChatContactData,\n}\n", "type": "registry:component" } ], "type": "registry:component" }