{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "suggestion-docs",
  "title": "Suggestion",
  "description": "Documentation for Suggestion",
  "files": [
    {
      "path": "../../content/docs/(plugins)/(collaboration)/suggestion.mdx",
      "content": "---\ntitle: Suggestion\ndocs:\n  - route: https://pro.platejs.org/docs/examples/discussion\n    title: Plus\n  - route: /docs/components/suggestion-node\n    title: Suggestion Leaf\n  - route: /docs/components/suggestion-toolbar-button\n    title: Suggestion Toolbar Button\n  - route: /docs/components/block-suggestion\n    title: Block suggestion\n  - route: /docs/components/block-discussion\n    title: Block discussion\n---\n\n<ComponentPreview name=\"discussion-demo\" />\n\n<PackageInfo>\n\n## Features\n\n- **Text Suggestions:** Add suggestions as text marks with inline annotations\n- **Block Suggestions:** Create suggestions for entire blocks of content\n- **State Tracking:** Track suggestion state and user interactions\n- **Undo/Redo Support:** Full undo/redo support for suggestion changes\n- **Discussion Integration:** Works with discussion plugin for complete collaboration\n\n</PackageInfo>\n\n## Kit Usage\n\n<Steps>\n\n### Installation\n\nThe fastest way to add suggestion functionality is with the `SuggestionKit`, which includes pre-configured `SuggestionPlugin` and related components along with their [Plate UI](/docs/installation/plate-ui) components.\n\n<ComponentSource name=\"suggestion-kit\" />\n\n- [`SuggestionLeaf`](/docs/components/suggestion-node): Renders suggestion text marks\n- [`BlockSuggestion`](/docs/components/block-suggestion): Renders block-level suggestions\n- [`SuggestionLineBreak`](/docs/components/suggestion-node): Handles line breaks in suggestions\n\n### Add Kit\n\n```tsx\nimport { createPlateEditor } from 'platejs/react';\nimport { SuggestionKit } from '@/components/editor/plugins/suggestion-kit';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    ...SuggestionKit,\n  ],\n});\n```\n\n</Steps>\n\n## Manual Usage\n\n<Steps>\n\n### Installation\n\n```bash\nnpm install @platejs/suggestion\n```\n\n### Extend Suggestion Plugin\n\nCreate the suggestion plugin with extended configuration for state management:\n\n```tsx\nimport {\n  type ExtendConfig,\n  isSlateEditor,\n  isSlateElement,\n  isSlateString,\n} from 'platejs';\nimport {\n  type BaseSuggestionConfig,\n  BaseSuggestionPlugin,\n} from '@platejs/suggestion';\nimport { createPlatePlugin, toTPlatePlugin } from 'platejs/react';\nimport { BlockSuggestion } from '@/components/ui/block-suggestion';\nimport { SuggestionLeaf } from '@/components/ui/suggestion-node';\n\nexport type SuggestionConfig = ExtendConfig<\n  BaseSuggestionConfig,\n  {\n    activeId: string | null;\n    hoverId: string | null;\n  }\n>;\n\nexport const suggestionPlugin = toTPlatePlugin<SuggestionConfig>(\n  BaseSuggestionPlugin,\n  ({ editor }) => ({\n    options: {\n      activeId: null,\n      currentUserId: 'alice', // Set your current user ID\n      hoverId: null,\n    },\n    render: {\n      node: SuggestionLeaf,\n      belowRootNodes: ({ api, element }) => {\n        if (!api.suggestion!.isBlockSuggestion(element)) {\n          return null;\n        }\n\n        return <BlockSuggestion element={element} />;\n      },\n    },\n  })\n);\n```\n\n- `options.activeId`: Currently active suggestion ID for visual highlighting\n- `options.currentUserId`: ID of the current user creating suggestions  \n- `options.hoverId`: Currently hovered suggestion ID for hover effects\n- `render.node`: Assigns [`SuggestionLeaf`](/docs/components/suggestion-node) to render suggestion text marks\n- `render.belowRootNodes`: Renders [`BlockSuggestion`](/docs/components/block-suggestion) for block-level suggestions\n\n### Add Click Handler\n\nAdd click handling to manage active suggestion state:\n\n```tsx\nexport const suggestionPlugin = toTPlatePlugin<SuggestionConfig>(\n  BaseSuggestionPlugin,\n  ({ editor }) => ({\n    handlers: {\n      // Unset active suggestion when clicking outside of suggestion\n      onClick: ({ api, event, setOption, type }) => {\n        let leaf = event.target as HTMLElement;\n        let isSet = false;\n\n        const unsetActiveSuggestion = () => {\n          setOption('activeId', null);\n          isSet = true;\n        };\n\n        if (!isSlateString(leaf)) unsetActiveSuggestion();\n\n        while (\n          leaf.parentElement &&\n          !isSlateElement(leaf.parentElement) &&\n          !isSlateEditor(leaf.parentElement)\n        ) {\n          if (leaf.classList.contains(`slate-${type}`)) {\n            const suggestionEntry = api.suggestion!.node({ isText: true });\n\n            if (!suggestionEntry) {\n              unsetActiveSuggestion();\n              break;\n            }\n\n            const id = api.suggestion!.nodeId(suggestionEntry[0]);\n            setOption('activeId', id ?? null);\n            isSet = true;\n            break;\n          }\n\n          leaf = leaf.parentElement;\n        }\n\n        if (!isSet) unsetActiveSuggestion();\n      },\n    },\n    // ... previous options and render\n  })\n);\n```\n\nThe click handler tracks which suggestion is currently active:\n- **Detects suggestion clicks**: Traverses DOM to find suggestion elements\n- **Sets active state**: Updates `activeId` when clicking on suggestions\n- **Clears state**: Unsets `activeId` when clicking outside suggestions\n- **Visual feedback**: Enables hover/active styling in suggestion components\n\n### Add Plugins\n\n```tsx\nimport { createPlateEditor, createPlatePlugin } from 'platejs/react';\nimport { SuggestionLineBreak } from '@/components/ui/suggestion-node';\n\nconst suggestionLineBreakPlugin = createPlatePlugin({\n  key: 'suggestionLineBreak',\n  render: { belowNodes: SuggestionLineBreak as any },\n});\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    suggestionPlugin,\n    suggestionLineBreakPlugin,\n  ],\n});\n```\n\n- `render.belowNodes`: Renders [`SuggestionLineBreak`](/docs/components/suggestion-node) below nodes to handle line break suggestions\n\n### Enable Suggestion Mode\n\nUse the plugin's API to control suggestion mode:\n\n```tsx\nimport { useEditorRef, usePluginOption } from 'platejs/react';\n\nfunction SuggestionToolbar() {\n  const editor = useEditorRef();\n  const isSuggesting = usePluginOption(suggestionPlugin, 'isSuggesting');\n\n  const toggleSuggesting = () => {\n    editor.setOption(suggestionPlugin, 'isSuggesting', !isSuggesting);\n  };\n\n  return (\n    <button onClick={toggleSuggesting}>\n      {isSuggesting ? 'Stop Suggesting' : 'Start Suggesting'}\n    </button>\n  );\n}\n```\n\n### Add Toolbar Button\n\nYou can add [`SuggestionToolbarButton`](/docs/components/suggestion-toolbar-button) to your [Toolbar](/docs/toolbar) to toggle suggestion mode in the editor.\n\n### Discussion Integration\n\nThe suggestion plugin works with the [discussion plugin](/docs/discussion) for complete collaboration:\n\n```tsx\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    discussionPlugin,\n    suggestionPlugin.configure({\n      options: {\n        currentUserId: 'alice',\n      },\n    }),\n    suggestionLineBreakPlugin,\n  ],\n});\n```\n\n</Steps>\n\n## Keyboard Shortcuts\n\n<KeyTable>\n  <KeyTableItem hotkey=\"Cmd + Shift + S\">\n    Add a suggestion on the selected text.\n  </KeyTableItem>\n</KeyTable>\n\n## Plate Plus\n\n<ComponentPreviewPro name=\"discussion-pro\" />\n\n## Plugins\n\n### `SuggestionPlugin`\n\nPlugin for creating and managing text and block suggestions with state tracking and discussion integration.\n\n<API name=\"SuggestionPlugin\">\n<APIOptions>\n  <APIItem name=\"currentUserId\" type=\"string | null\">\n    ID of the current user creating suggestions. Required for proper suggestion attribution.\n  </APIItem>\n  <APIItem name=\"isSuggesting\" type=\"boolean\">\n    Whether the editor is currently in suggestion mode. Used internally to track state.\n  </APIItem>\n</APIOptions>\n</API>\n\n## API\n\n### `api.suggestion.dataList`\n\nGets suggestion data from a text node.\n\n<API name=\"dataList\">\n<APIParameters>\n  <APIItem name=\"node\" type=\"TSuggestionText\">\n    The suggestion text node.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"TInlineSuggestionData[]\">\n  Array of suggestion data.\n</APIReturns>\n</API>\n\n### `api.suggestion.isBlockSuggestion`\n\nChecks if a node is a block suggestion element.\n\n<API name=\"isBlockSuggestion\">\n<APIParameters>\n  <APIItem name=\"node\" type=\"TElement\">\n    The node to check.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"node is TSuggestionElement\">\n  Whether the node is a block suggestion.\n</APIReturns>\n</API>\n\n### `api.suggestion.node`\n\nGets a suggestion node entry.\n\n<API name=\"node\">\n<APIOptions type=\"EditorNodesOptions & { id?: string; isText?: boolean }\" optional>\n  Options for finding the node.\n</APIOptions>\n<APIReturns type=\"NodeEntry<TSuggestionElement | TSuggestionText> | undefined\">\n  The suggestion node entry if found.\n</APIReturns>\n</API>\n\n### `api.suggestion.nodeId`\n\nGets the ID of a suggestion from a node.\n\n<API name=\"nodeId\">\n<APIParameters>\n  <APIItem name=\"node\" type=\"TElement | TSuggestionText\">\n    The node to get ID from.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"string | undefined\">\n  The suggestion ID if found.\n</APIReturns>\n</API>\n\n### `api.suggestion.nodes`\n\nGets all suggestion node entries matching the options.\n\n<API name=\"nodes\">\n<APIOptions type=\"EditorNodesOptions\" optional>\n  Options for finding the nodes.\n</APIOptions>\n<APIReturns type=\"NodeEntry<TElement | TSuggestionText>[]\">\n  Array of suggestion node entries.\n</APIReturns>\n</API>\n\n### `api.suggestion.suggestionData`\n\nGets suggestion data from a node.\n\n<API name=\"suggestionData\">\n<APIParameters>\n  <APIItem name=\"node\" type=\"TElement | TSuggestionText\">\n    The node to get suggestion data from.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"TInlineSuggestionData | TSuggestionElement['suggestion'] | undefined\">\n  The suggestion data if found.\n</APIReturns>\n</API>\n\n### `api.suggestion.withoutSuggestions`\n\nTemporarily disables suggestions while executing a function.\n\n<API name=\"withoutSuggestions\">\n<APIParameters>\n  <APIItem name=\"fn\" type=\"() => void\">\n    The function to execute.\n  </APIItem>\n</APIParameters>\n</API>\n\n## Types\n\n### `TSuggestionText`\n\nText nodes that can contain suggestions.\n\n<API name=\"TSuggestionText\">\n<APIAttributes>\n  <APIItem name=\"suggestion\" type=\"boolean\" optional>\n    Whether this is a suggestion.\n  </APIItem>\n  <APIItem name=\"suggestion_<id>\" type=\"TInlineSuggestionData\" optional>\n    Suggestion data. Multiple suggestions can exist in one text node.\n  </APIItem>\n</APIAttributes>\n</API>\n\n### `TSuggestionElement`\n\nBlock elements that contain suggestion metadata.\n\n<API name=\"TSuggestionElement\">\n<APIAttributes>\n  <APIItem name=\"suggestion\" type=\"TSuggestionData\">\n    Block-level suggestion data including type, user, and timing information.\n  </APIItem>\n</APIAttributes>\n</API>\n\n### `TInlineSuggestionData`\n\nData structure for inline text suggestions.\n\n<API name=\"TInlineSuggestionData\">\n<APIAttributes>\n  <APIItem name=\"id\" type=\"string\">\n    Unique identifier for the suggestion.\n  </APIItem>\n  <APIItem name=\"userId\" type=\"string\">\n    ID of the user who created the suggestion.\n  </APIItem>\n  <APIItem name=\"createdAt\" type=\"number\">\n    Timestamp when the suggestion was created.\n  </APIItem>\n  <APIItem name=\"type\" type=\"'insert' | 'remove' | 'update'\">\n    Type of suggestion operation.\n  </APIItem>\n  <APIItem name=\"newProperties\" type=\"object\" optional>\n    For update suggestions, the new mark properties being suggested.\n  </APIItem>\n  <APIItem name=\"properties\" type=\"object\" optional>\n    For update suggestions, the previous mark properties.\n  </APIItem>\n</APIAttributes>\n</API>\n\n### `TSuggestionData`\n\nData structure for block-level suggestions.\n\n<API name=\"TSuggestionData\">\n<APIAttributes>\n  <APIItem name=\"id\" type=\"string\">\n    Unique identifier for the suggestion.\n  </APIItem>\n  <APIItem name=\"userId\" type=\"string\">\n    ID of the user who created the suggestion.\n  </APIItem>\n  <APIItem name=\"createdAt\" type=\"number\">\n    Timestamp when the suggestion was created.\n  </APIItem>\n  <APIItem name=\"type\" type=\"'insert' | 'remove'\">\n    Type of block suggestion operation.\n  </APIItem>\n  <APIItem name=\"isLineBreak\" type=\"boolean\" optional>\n    Whether this suggestion represents a line break insertion.\n  </APIItem>\n</APIAttributes>\n</API>\n",
      "type": "registry:file",
      "target": "content/docs/plate/(plugins)/(collaboration)/suggestion.mdx"
    }
  ],
  "type": "registry:file"
}