{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "installation-react-docs",
  "title": "React",
  "description": "Install and configure Plate UI for React",
  "files": [
    {
      "path": "../../content/docs/installation/react.mdx",
      "content": "---\ntitle: React\ndescription: Install and configure Plate UI for React\n---\n\n<Callout type=\"warning\" title=\"Prerequisites\">\n  Before you begin, ensure you have installed and configured [shadcn/ui](https://ui.shadcn.com/docs/installation) (adapted for your framework, e.g., Vite) and [Plate UI](/docs/installation/plate-ui).\n</Callout>\n\nThis guide walks you through incrementally building a Plate editor in your project.\n\n<Steps>\n\n### Create Your First Editor\n\nStart by adding the core [Editor](/docs/components/editor) component to your project:\n\n```bash\nnpx shadcn@latest add @plate/editor\n```\n\nNext, create a basic editor in your main application file (e.g. `src/App.tsx`). This example sets up a simple editor within an `EditorContainer`.\n\n```tsx showLineNumbers title=\"src/App.tsx\"\nimport { Plate, usePlateEditor } from 'platejs/react';\n\nimport { Editor, EditorContainer } from '@/components/ui/editor';\n\nexport default function App() {\n  const editor = usePlateEditor(); // Initializes the editor instance\n\n  return (\n    <Plate editor={editor}>      {/* Provides editor context */}\n      <EditorContainer>         {/* Styles the editor area */}\n        <Editor placeholder=\"Type your amazing content here...\" />\n      </EditorContainer>\n    </Plate>\n  );\n}\n```\n\n<Callout type=\"info\">\n  `usePlateEditor` creates a memoized editor instance, ensuring stability across re-renders. For a non-memoized version, use `createPlateEditor`.\n</Callout>\n\n<ComponentPreview name=\"installation-next-01-editor-demo\" height=\"200px\" />\n\n### Adding Basic Marks\n\nEnhance your editor with text formatting. Add the **Basic Nodes Kit**, [FixedToolbar](/docs/components/fixed-toolbar) and [MarkToolbarButton](/docs/components/mark-toolbar-button) components:\n\n```bash\nnpx shadcn@latest add @plate/basic-nodes-kit @plate/fixed-toolbar @plate/mark-toolbar-button\n```\n\n<Callout type=\"info\">\n  The `basic-nodes-kit` includes all the basic plugins (bold, italic, underline, headings, blockquotes, etc.) and their components that we'll use in the following steps.\n</Callout>\n\nUpdate your `src/App.tsx` to include these components and the basic mark plugins.\nThis example adds bold, italic, and underline functionality.\n\n```tsx showLineNumbers title=\"src/App.tsx\" {2,4-8,15-16,18-31,35-36,41-45}\nimport * as React from 'react';\nimport type { Value } from 'platejs';\n\nimport {\n  BoldPlugin,\n  ItalicPlugin,\n  UnderlinePlugin,\n} from '@platejs/basic-nodes/react';\nimport {\n  Plate,\n  usePlateEditor,\n} from 'platejs/react';\n\nimport { Editor, EditorContainer } from '@/components/ui/editor';\nimport { FixedToolbar } from '@/components/ui/fixed-toolbar';\nimport { MarkToolbarButton } from '@/components/ui/mark-toolbar-button';\n\nconst initialValue: Value = [\n  {\n    type: 'p',\n    children: [\n      { text: 'Hello! Try out the ' },\n      { text: 'bold', bold: true },\n      { text: ', ' },\n      { text: 'italic', italic: true },\n      { text: ', and ' },\n      { text: 'underline', underline: true },\n      { text: ' formatting.' },\n    ],\n  },\n];\n\nexport default function App() {\n  const editor = usePlateEditor({\n    plugins: [BoldPlugin, ItalicPlugin, UnderlinePlugin], // Add the mark plugins\n    value: initialValue,         // Set initial content\n  });\n\n  return (\n    <Plate editor={editor}>\n      <FixedToolbar className=\"justify-start rounded-t-lg\">\n        <MarkToolbarButton nodeType=\"bold\" tooltip=\"Bold (⌘+B)\">B</MarkToolbarButton>\n        <MarkToolbarButton nodeType=\"italic\" tooltip=\"Italic (⌘+I)\">I</MarkToolbarButton>\n        <MarkToolbarButton nodeType=\"underline\" tooltip=\"Underline (⌘+U)\">U</MarkToolbarButton>\n      </FixedToolbar>\n      <EditorContainer>\n        <Editor placeholder=\"Type your amazing content here...\" />\n      </EditorContainer>\n    </Plate>\n  );\n}\n```\n\n<ComponentPreview name=\"installation-next-02-marks-demo\" height=\"200px\" />\n\n### Adding Basic Elements\n\nIntroduce block-level elements like headings and blockquotes with custom components.\n\n```tsx showLineNumbers title=\"src/App.tsx\" {5,7-9,18,21,23,26-33,50-53,61-65}\nimport * as React from 'react';\nimport type { Value } from 'platejs';\n\nimport {\n  BlockquotePlugin,\n  BoldPlugin,\n  H1Plugin,\n  H2Plugin,\n  H3Plugin,\n  ItalicPlugin,\n  UnderlinePlugin,\n} from '@platejs/basic-nodes/react';\nimport {\n  Plate,\n  usePlateEditor,\n} from 'platejs/react';\n\nimport { BlockquoteElement } from '@/components/ui/blockquote-node';\nimport { Editor, EditorContainer } from '@/components/ui/editor';\nimport { FixedToolbar } from '@/components/ui/fixed-toolbar';\nimport { H1Element, H2Element, H3Element } from '@/components/ui/heading-node';\nimport { MarkToolbarButton } from '@/components/ui/mark-toolbar-button';\nimport { ToolbarButton } from '@/components/ui/toolbar'; // Generic toolbar button\n\nconst initialValue: Value = [\n  {\n    children: [{ text: 'Title' }],\n    type: 'h3',\n  },\n  {\n    children: [\n      {\n        children: [{ text: 'This is a quote.' }],\n        type: 'p',\n      },\n    ],\n    type: 'blockquote',\n  },\n  {\n    children: [\n      { text: 'With some ' },\n      { bold: true, text: 'bold' },\n      { text: ' text for emphasis!' },\n    ],\n    type: 'p',\n  },\n];\n\nexport default function App() {\n  const editor = usePlateEditor({\n    plugins: [\n      BoldPlugin,\n      ItalicPlugin,\n      UnderlinePlugin,\n      H1Plugin.withComponent(H1Element),\n      H2Plugin.withComponent(H2Element),\n      H3Plugin.withComponent(H3Element),\n      BlockquotePlugin.withComponent(BlockquoteElement),\n    ],\n    value: initialValue,\n  });\n\n  return (\n    <Plate editor={editor}>\n      <FixedToolbar className=\"flex justify-start gap-1 rounded-t-lg\">\n        {/* Element Toolbar Buttons */}\n        <ToolbarButton onClick={() => editor.tf.h1.toggle()}>H1</ToolbarButton>\n        <ToolbarButton onClick={() => editor.tf.h2.toggle()}>H2</ToolbarButton>\n        <ToolbarButton onClick={() => editor.tf.h3.toggle()}>H3</ToolbarButton>\n        <ToolbarButton onClick={() => editor.tf.blockquote.toggle()}>Quote</ToolbarButton>\n        {/* Mark Toolbar Buttons */}\n        <MarkToolbarButton nodeType=\"bold\" tooltip=\"Bold (⌘+B)\">B</MarkToolbarButton>\n        <MarkToolbarButton nodeType=\"italic\" tooltip=\"Italic (⌘+I)\">I</MarkToolbarButton>\n        <MarkToolbarButton nodeType=\"underline\" tooltip=\"Underline (⌘+U)\">U</MarkToolbarButton>\n      </FixedToolbar>\n      <EditorContainer>\n        <Editor placeholder=\"Type your amazing content here...\" />\n      </EditorContainer>\n    </Plate>\n  );\n}\n```\n\n<ComponentPreview name=\"installation-next-03-elements-demo\" height=\"200px\" />\n\n<Callout type=\"info\" title=\"Component Registration\">\n  Notice how we use `Plugin.withComponent(Component)` to register components with their respective plugins. This is the recommended approach for associating React components with Plate plugins.\n\n  For a quicker start with common plugins and components pre-configured, use the `editor-basic` block:\n  ```bash\n  npx shadcn@latest add @plate/editor-basic\n  ```\n  This handles much of the boilerplate for you.\n</Callout>\n\n### Handling Editor Value\n\nTo make the editor content persistent, let's integrate `localStorage` to save and load the editor's value.\n\n```tsx showLineNumbers title=\"src/App.tsx\" {55-58,64-66,76-82}\nimport * as React from 'react';\nimport type { Value } from 'platejs';\n\nimport {\n  BlockquotePlugin,\n  BoldPlugin,\n  H1Plugin,\n  H2Plugin,\n  H3Plugin,\n  ItalicPlugin,\n  UnderlinePlugin,\n} from '@platejs/basic-nodes/react';\nimport {\n  Plate,\n  usePlateEditor,\n} from 'platejs/react';\n\nimport { BlockquoteElement } from '@/components/ui/blockquote-node';\nimport { Editor, EditorContainer } from '@/components/ui/editor';\nimport { FixedToolbar } from '@/components/ui/fixed-toolbar';\nimport { H1Element, H2Element, H3Element } from '@/components/ui/heading-node';\nimport { MarkToolbarButton } from '@/components/ui/mark-toolbar-button';\nimport { ToolbarButton } from '@/components/ui/toolbar';\n\nconst initialValue: Value = [\n  {\n    children: [{ text: 'Title' }],\n    type: 'h3',\n  },\n  {\n    children: [\n      {\n        children: [{ text: 'This is a quote.' }],\n        type: 'p',\n      },\n    ],\n    type: 'blockquote',\n  },\n  {\n    children: [\n      { text: 'With some ' },\n      { bold: true, text: 'bold' },\n      { text: ' text for emphasis!' },\n    ],\n    type: 'p',\n  },\n];\n\nexport default function App() {\n  const editor = usePlateEditor({\n    plugins: [\n      BoldPlugin,\n      ItalicPlugin,\n      UnderlinePlugin,\n      H1Plugin.withComponent(H1Element),\n      H2Plugin.withComponent(H2Element),\n      H3Plugin.withComponent(H3Element),\n      BlockquotePlugin.withComponent(BlockquoteElement),\n    ],\n    value: () => {\n      const savedValue = localStorage.getItem('installation-react-demo');\n      return savedValue ? JSON.parse(savedValue) : initialValue;\n    },\n  });\n\n  return (\n    <Plate\n      editor={editor}\n      onChange={({ value }) => {\n        localStorage.setItem('installation-react-demo', JSON.stringify(value));\n      }}\n    >\n      <FixedToolbar className=\"flex justify-start gap-1 rounded-t-lg\">\n        <ToolbarButton onClick={() => editor.tf.h1.toggle()}>H1</ToolbarButton>\n        <ToolbarButton onClick={() => editor.tf.h2.toggle()}>H2</ToolbarButton>\n        <ToolbarButton onClick={() => editor.tf.h3.toggle()}>H3</ToolbarButton>\n        <ToolbarButton onClick={() => editor.tf.blockquote.toggle()}>Quote</ToolbarButton>\n        <MarkToolbarButton nodeType=\"bold\" tooltip=\"Bold (⌘+B)\">B</MarkToolbarButton>\n        <MarkToolbarButton nodeType=\"italic\" tooltip=\"Italic (⌘+I)\">I</MarkToolbarButton>\n        <MarkToolbarButton nodeType=\"underline\" tooltip=\"Underline (⌘+U)\">U</MarkToolbarButton>\n        <div className=\"flex-1\" />\n        <ToolbarButton\n          className=\"px-2\"\n          onClick={() => editor.tf.setValue(initialValue)}\n        >\n          Reset\n        </ToolbarButton>\n      </FixedToolbar>\n      <EditorContainer>\n        <Editor placeholder=\"Type your amazing content here...\" />\n      </EditorContainer>\n    </Plate>\n  );\n}\n```\n\n<ComponentPreview name=\"installation-next-demo\" />\n\n### Next Steps\n\nCongratulations! You've built a foundational Plate editor in your project.\n\nTo further enhance your editor:\n\n*   **Explore Components:** Discover [Toolbars, Menus, Node components](/docs/components), and more.\n*   **Add Plugins:** Integrate features like [Tables](/docs/plugins/table), [Mentions](/docs/plugins/mention), [AI](/docs/plugins/ai), or [Markdown](/docs/plugins/markdown).\n*   **Use Editor Blocks:** Quickly set up pre-configured editors:\n    *   Basic editor: `npx shadcn@latest add @plate/editor-basic`\n    *   AI-powered editor: `npx shadcn@latest add @plate/editor-ai`\n*   **Learn More:**\n    *   [Editor Configuration](/docs/editor)\n    *   [Plugin Configuration](/docs/plugin)\n    *   [Plugin Components](/docs/plugin-components)\n\n</Steps>\n",
      "type": "registry:file",
      "target": "content/docs/plate/installation/react.mdx"
    }
  ],
  "type": "registry:file"
}