{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "chat-message-area-demo-streaming",
	"type": "registry:example",
	"files": [
		{
			"path": "./src/registry/examples/chat-message-area-demo-streaming.tsx",
			"content": "\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n\tChatMessage,\n\tChatMessageAuthor,\n\tChatMessageAvatar,\n\tChatMessageAvatarFallback,\n\tChatMessageAvatarImage,\n\tChatMessageContainer,\n\tChatMessageContent,\n\tChatMessageHeader,\n\tChatMessageMarkdown,\n\tChatMessageTimestamp,\n} from \"@/registry/ui/chat-message\";\nimport {\n\tChatMessageArea,\n\tChatMessageAreaContent,\n\tChatMessageAreaScrollButton,\n} from \"@/registry/ui/chat-message-area\";\n\nconst userMessage: UIMessage<{\n\tmember: {\n\t\timage: string;\n\t\tname: string;\n\t};\n}> = {\n\tid: \"1\",\n\tparts: [\n\t\t{\n\t\t\ttype: \"text\",\n\t\t\ttext: \"Can you tell me a magical story?\",\n\t\t},\n\t],\n\trole: \"user\",\n\tmetadata: {\n\t\tmember: {\n\t\t\timage: \"/avatar-1.png\",\n\t\t\tname: \"You\",\n\t\t},\n\t},\n};\n\nconst STORY = `# The Tale of the Enchanted Forest\n\nDeep in a mystical realm, there lay an ancient forest that held secrets beyond imagination. The trees here weren't mere plants; they were the keepers of ancient wisdom, their leaves whispering tales of ages past.\n\n## The Guardian's Call\n\nIn this magical place lived a young spirit named Aria, chosen by the forest itself to be its guardian. Her hair flowed like silver moonlight, and her eyes held the depth of ancient pools.\n\n### The First Challenge\n\n* One morning, Aria discovered that something was amiss\n* The usually vibrant crystal flowers had begun to fade\n* The ancient whispers of the trees grew fainter\n* A shadow crept through the undergrowth\n\n## The Journey Begins\n\nAria knew she had to act quickly. She gathered:\n1. Dewdrops from spider webs at dawn\n2. Starlight captured in moonflower petals\n3. Songs of the morning birds\n4. Tears of the evening mist\n\n> \"In the heart of every forest lies a truth waiting to be discovered\" - Ancient Forest Proverb\n\n### The Discovery\n\nAs Aria ventured deeper into the forest's heart, she found an ancient clearing. Here, the very air seemed to pulse with magic. Crystal formations emerged from the earth like frozen rainbows, each one containing memories of the forest's past.\n\n## The Ancient Guardians\n\nIn her quest, Aria encountered the spirits of previous guardians:\n\n* The Flame Keeper, whose torch lit the darkest paths\n* The Wind Whisperer, who knew the language of storms\n* The Earth Mother, who could heal the land with a touch\n* The Star Walker, who mapped the celestial dance\n\nEach spirit shared their wisdom:\n\n1. \"Change is the only constant in nature\"\n2. \"Listen to the silence between heartbeats\"\n3. \"Growth comes from embracing the unknown\"\n4. \"Every ending is a new beginning\"\n\n### The Hidden Valley\n\nBeyond the ancient clearing, Aria discovered a hidden valley where:\n\n* Rainbow falls cascaded into pools of liquid starlight\n* Flowers sang melodies of forgotten lullabies\n* Butterflies painted the air with trails of golden dust\n* Ancient runes danced on stone walls, telling stories of old\n\n## The Dark Challenge\n\nAs night fell, shadows gathered and formed into creatures of doubt:\n\n1. The Mist Wraith, who clouded clear thoughts\n2. The Echo Thief, who stole confident voices\n3. The Dream Weaver, who tangled hopes in fear\n4. The Time Shifter, who made moments feel eternal\n\n> \"Courage is not the absence of fear, but the wisdom to dance with it\" - Whispers of the Wise Trees\n\n### The Battle Within\n\nAria faced her greatest challenge not in the physical realm, but within herself. She learned that:\n\n* True power comes from acceptance\n* Change can be beautiful and terrifying\n* Magic flows through all living things\n* Every creature has its own song to sing\n\n## The Resolution\n\nThrough her connection with the forest, Aria learned that the fading magic was not a sign of decay, but of transformation. The forest wasn't dying; it was evolving, preparing for a new age of wonders.\n\n### The New Beginning\n\n* The crystal flowers bloomed again, brighter than ever\n* New forms of magic emerged from the ancient earth\n* The whispers of the trees grew stronger, carrying new songs\n* And Aria, forever changed, became one with the forest's heart\n\n## The Legacy\n\nAs the forest renewed itself:\n\n1. Ancient spells transformed into new forms of magic\n2. Lost pathways revealed themselves to worthy wanderers\n3. The boundary between dreams and reality grew thin\n4. Nature's wisdom found new ways to express itself\n\n### The Eternal Dance\n\nThe forest continues its eternal dance:\n\n* Seasons shift in kaleidoscope patterns\n* Magic pulses in harmony with the earth's heartbeat\n* New guardians arise when they're needed most\n* Stories weave themselves into the fabric of reality\n\n---\n\n*And so, the tale of the Enchanted Forest continues, ever-changing, ever-growing, in the endless cycle of magic and wonder. Each day brings new mysteries, and each night holds its own enchantments, as the forest and its guardian dance their eternal dance of transformation and renewal...*`;\n\nexport default function ChatMessageAreaDemo() {\n\tconst [streamContent, setStreamContent] = useState(\"\");\n\tconst [isStreaming, setIsStreaming] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (!isStreaming) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet currentIndex = 0;\n\t\tconst words = STORY.split(\" \");\n\n\t\tconst streamInterval = setInterval(() => {\n\t\t\tif (currentIndex >= words.length) {\n\t\t\t\tclearInterval(streamInterval);\n\t\t\t\tsetIsStreaming(false);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst nextChunk = words.slice(0, currentIndex + 3).join(\" \");\n\t\t\tsetStreamContent(nextChunk);\n\t\t\tcurrentIndex += 3;\n\t\t}, 70);\n\n\t\treturn () => clearInterval(streamInterval);\n\t}, [isStreaming]);\n\n\tconst handleStart = () => {\n\t\tsetStreamContent(\"\");\n\t\tsetIsStreaming(true);\n\t};\n\n\treturn (\n\t\t<div className=\"space-y-4 w-full h-full\">\n\t\t\t<Button\n\t\t\t\tonClick={handleStart}\n\t\t\t\tdisabled={isStreaming}\n\t\t\t\tclassName=\"w-full\"\n\t\t\t>\n\t\t\t\t{streamContent ? \"Restart Story\" : \"Start Story\"}{\" \"}\n\t\t\t\t{isStreaming && \"(Streaming...)\"}\n\t\t\t</Button>\n\t\t\t<div className=\"border rounded-md h-[320px] overflow-y-auto\">\n\t\t\t\t<ChatMessageArea>\n\t\t\t\t\t<ChatMessageAreaContent>\n\t\t\t\t\t\t<ChatMessage key={userMessage.id}>\n\t\t\t\t\t\t\t<ChatMessageAvatar>\n\t\t\t\t\t\t\t\t<ChatMessageAvatarImage\n\t\t\t\t\t\t\t\t\tsrc={userMessage.metadata?.member.image}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<ChatMessageAvatarFallback>\n\t\t\t\t\t\t\t\t\t{userMessage.metadata?.member.name\n\t\t\t\t\t\t\t\t\t\t.charAt(0)\n\t\t\t\t\t\t\t\t\t\t.toUpperCase()}\n\t\t\t\t\t\t\t\t</ChatMessageAvatarFallback>\n\t\t\t\t\t\t\t</ChatMessageAvatar>\n\n\t\t\t\t\t\t\t<ChatMessageContainer>\n\t\t\t\t\t\t\t\t<ChatMessageHeader>\n\t\t\t\t\t\t\t\t\t<ChatMessageAuthor>\n\t\t\t\t\t\t\t\t\t\t{userMessage.metadata?.member.name}\n\t\t\t\t\t\t\t\t\t</ChatMessageAuthor>\n\t\t\t\t\t\t\t\t\t<ChatMessageTimestamp\n\t\t\t\t\t\t\t\t\t\tcreatedAt={new Date()}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</ChatMessageHeader>\n\n\t\t\t\t\t\t\t\t<ChatMessageContent>\n\t\t\t\t\t\t\t\t\t{userMessage.parts\n\t\t\t\t\t\t\t\t\t\t.filter((part) => part.type === \"text\")\n\t\t\t\t\t\t\t\t\t\t.map((part) => (\n\t\t\t\t\t\t\t\t\t\t\t<ChatMessageMarkdown\n\t\t\t\t\t\t\t\t\t\t\t\tkey={part.type}\n\t\t\t\t\t\t\t\t\t\t\t\tcontent={part.text}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</ChatMessageContent>\n\t\t\t\t\t\t\t</ChatMessageContainer>\n\t\t\t\t\t\t</ChatMessage>\n\n\t\t\t\t\t\t{streamContent && (\n\t\t\t\t\t\t\t<ChatMessage key=\"2\" id=\"2\">\n\t\t\t\t\t\t\t\t<ChatMessageAvatar>\n\t\t\t\t\t\t\t\t\t<ChatMessageAvatarImage src=\"/avatar-2.png\" />\n\t\t\t\t\t\t\t\t\t<ChatMessageAvatarFallback>\n\t\t\t\t\t\t\t\t\t\tA\n\t\t\t\t\t\t\t\t\t</ChatMessageAvatarFallback>\n\t\t\t\t\t\t\t\t</ChatMessageAvatar>\n\n\t\t\t\t\t\t\t\t<ChatMessageContainer>\n\t\t\t\t\t\t\t\t\t<ChatMessageHeader>\n\t\t\t\t\t\t\t\t\t\t<ChatMessageAuthor>\n\t\t\t\t\t\t\t\t\t\t\tAssistant\n\t\t\t\t\t\t\t\t\t\t</ChatMessageAuthor>\n\t\t\t\t\t\t\t\t\t\t<ChatMessageTimestamp\n\t\t\t\t\t\t\t\t\t\t\tcreatedAt={new Date()}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</ChatMessageHeader>\n\n\t\t\t\t\t\t\t\t\t<ChatMessageContent>\n\t\t\t\t\t\t\t\t\t\t<ChatMessageMarkdown\n\t\t\t\t\t\t\t\t\t\t\tcontent={streamContent}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</ChatMessageContent>\n\t\t\t\t\t\t\t\t</ChatMessageContainer>\n\t\t\t\t\t\t\t</ChatMessage>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</ChatMessageAreaContent>\n\t\t\t\t\t<ChatMessageAreaScrollButton />\n\t\t\t\t</ChatMessageArea>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n",
			"type": "registry:example"
		}
	]
}
