From 1ab76c252243f4ba18c565bddffcb66fa62cd5e1 Mon Sep 17 00:00:00 2001 From: Matias Perez Date: Mon, 29 Dec 2025 03:02:01 -0300 Subject: [PATCH 1/3] feat(mention): add controlled mention demo and update documentation - Introduced a new demo for controlled mentions, showcasing user interactions with mentions in a chat-like interface. - Updated the registry to include the new demo and its dependencies. - Enhanced documentation to include the new demo under the mentions section, providing users with a clear example of usage. - Added necessary JSON files for the new demo in the public registry. --- docs/__registry__/index.tsx | 14 ++ docs/content/docs/components/mention.mdx | 4 + docs/public/r/mention-controlled-demo.json | 15 ++ docs/public/r/registry.json | 13 ++ .../examples/mention-controlled-demo.tsx | 141 ++++++++++++++++++ docs/registry/registry-examples.ts | 11 ++ packages/mention/src/mention-highlighter.tsx | 21 ++- packages/mention/src/mention-input.tsx | 66 ++++++-- 8 files changed, 264 insertions(+), 21 deletions(-) create mode 100644 docs/public/r/mention-controlled-demo.json create mode 100644 docs/registry/default/examples/mention-controlled-demo.tsx diff --git a/docs/__registry__/index.tsx b/docs/__registry__/index.tsx index 8a11d479e..0c211a6d5 100644 --- a/docs/__registry__/index.tsx +++ b/docs/__registry__/index.tsx @@ -2239,6 +2239,20 @@ export const Index: Record = { source: "", chunks: [] }, + "mention-controlled-demo": { + name: "mention-controlled-demo", + description: "", + type: "registry:example", + registryDependencies: undefined, + files: [{ + path: "registry/default/examples/mention-controlled-demo.tsx", + type: "registry:example", + target: "" + }], + component: React.lazy(() => import("@/registry/default/examples/mention-controlled-demo.tsx")), + source: "", + chunks: [] + }, "mention-custom-filter-demo": { name: "mention-custom-filter-demo", description: "", diff --git a/docs/content/docs/components/mention.mdx b/docs/content/docs/components/mention.mdx index 35b90f830..73ff3ecd5 100644 --- a/docs/content/docs/components/mention.mdx +++ b/docs/content/docs/components/mention.mdx @@ -76,6 +76,10 @@ return ( +### Controlled + + + ## API Reference ### Mention diff --git a/docs/public/r/mention-controlled-demo.json b/docs/public/r/mention-controlled-demo.json new file mode 100644 index 000000000..cc5225035 --- /dev/null +++ b/docs/public/r/mention-controlled-demo.json @@ -0,0 +1,15 @@ +{ + "name": "mention-controlled-demo", + "dependencies": [ + "@diceui/mention" + ], + "files": [ + { + "path": "examples/mention-controlled-demo.tsx", + "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport {\n Mention,\n MentionContent,\n MentionInput,\n MentionItem,\n} from \"@/registry/default/ui/mention\";\n\nconst users = [\n {\n id: \"1\",\n name: \"Olivia Martin\",\n email: \"olivia@email.com\",\n },\n {\n id: \"2\",\n name: \"Isabella Nguyen\",\n email: \"isabella@email.com\",\n },\n {\n id: \"3\",\n name: \"Emma Wilson\",\n email: \"emma@email.com\",\n },\n {\n id: \"4\",\n name: \"Jackson Lee\",\n email: \"jackson@email.com\",\n },\n {\n id: \"5\",\n name: \"William Kim\",\n email: \"will@email.com\",\n },\n];\n\ninterface Message {\n id: string;\n content: string;\n mentions: string[];\n}\n\nfunction renderMessageContent(content: string, mentions: string[]) {\n if (mentions.length === 0) return content;\n\n const escaped = mentions.map((n) => n.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n const pattern = new RegExp(`(@(?:${escaped.join(\"|\")}))`, \"g\");\n\n return content.split(pattern).map((part, i) =>\n part.startsWith(\"@\") && mentions.includes(part.slice(1)) ? (\n \n {part}\n \n ) : (\n part\n )\n );\n}\n\nexport default function MentionControlledDemo() {\n const [open, setOpen] = React.useState(false);\n const [value, setValue] = React.useState([]);\n const [inputValue, setInputValue] = React.useState(\"\");\n const [messages, setMessages] = React.useState([]);\n\n function onSend() {\n if (!inputValue.trim()) return;\n\n setMessages((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n content: inputValue,\n mentions: value,\n },\n ]);\n setInputValue(\"\");\n setValue([]);\n }\n\n return (\n
\n
\n
\n {messages.length > 0 && (\n
\n {messages.map((message) => (\n \n

\n {renderMessageContent(message.content, message.mentions)}\n

\n
\n ))}\n
\n )}\n
\n
\n \n \n