{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tabbable-docs",
  "title": "Tabbable",
  "description": "Documentation for Tabbable",
  "files": [
    {
      "path": "../../content/docs/(plugins)/(functionality)/tabbable.mdx",
      "content": "---\ntitle: Tabbable\n---\n\n<ComponentPreview name=\"tabbable-demo\" />\n\n<PackageInfo>\n\n## Features\n\n- Ensures consistent tab order between tabbable elements in the editor\n- Manages focus transitions between void elements and external DOM elements\n\n</PackageInfo>\n\n## Kit Usage\n\n<Steps>\n\n### Installation\n\nThe fastest way to add the tabbable plugin is with the `TabbableKit`, which includes pre-configured `TabbablePlugin` with smart query logic to avoid conflicts with other plugins.\n\n<ComponentSource name=\"tabbable-kit\" />\n\n### Add Kit\n\n```tsx\nimport { createPlateEditor } from 'platejs/react';\nimport { TabbableKit } from '@/components/editor/plugins/tabbable-kit';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    ...TabbableKit,\n  ],\n});\n```\n\n</Steps>\n\n## Manual Usage\n\n<Steps>\n\n### Installation\n\n```bash\nnpm install @platejs/tabbable\n```\n\n### Add Plugin\n\n```tsx\nimport { TabbablePlugin } from '@platejs/tabbable/react';\nimport { createPlateEditor } from 'platejs/react';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    TabbablePlugin,\n  ],\n});\n```\n\n### Configure Plugin\n\n```tsx\nimport { TabbablePlugin } from '@platejs/tabbable/react';\nimport { createPlateEditor } from 'platejs/react';\nimport { KEYS } from 'platejs';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    TabbablePlugin.configure({\n      options: {\n        query: (event) => {\n          // Disable when in lists or code blocks\n          const inList = editor.api.some({ match: { type: KEYS.li } });\n          const inCodeBlock = editor.api.some({ match: { type: KEYS.codeBlock } });\n          return !inList && !inCodeBlock;\n        },\n        globalEventListener: true,\n        isTabbable: (tabbableEntry) => \n          editor.api.isVoid(tabbableEntry.slateNode),\n      },\n    }),\n  ],\n});\n```\n\n- `options.query`: Function to dynamically enable/disable the plugin based on editor state.\n- `options.globalEventListener`: When `true`, adds event listener to document instead of editor.\n- `options.isTabbable`: Function to determine which elements should be included in tab order.\n\n</Steps>\n\n## Advanced Usage\n\n### Conflicts with Other Plugins\n\nThe Tabbable plugin may cause issues with other plugins that handle the `Tab` key, such as:\n\n- Lists\n- Code blocks\n- Indent plugin\n\nUse the `query` option to disable the Tabbable plugin when the `Tab` key should be handled by another plugin:\n\n```tsx\nquery: (event) => {\n  const inList = editor.api.some({ match: { type: KEYS.li } });\n  const inCodeBlock = editor.api.some({ match: { type: KEYS.codeBlock } });\n  return !inList && !inCodeBlock;\n},\n```\n\nAlternatively, if you're using the Indent plugin, you can enable the Tabbable plugin only when a specific type of node is selected, such as voids:\n\n```tsx\nquery: (event) => !!editor.api.some({\n  match: (node) => editor.api.isVoid(node),\n}),\n```\n\n### Non-void Slate Nodes\n\nOne `TabbableEntry` will be created for each tabbable DOM element in the editor, as determined using the [tabbable](https://www.npmjs.com/package/tabbable) NPM package. The list of tabbables is then filtered using `isTabbable`.\n\nBy default, `isTabbable` only returns true for entries inside void Slate nodes. You can override `isTabbable` to add support for DOM elements contained in other types of Slate node:\n\n```tsx\n// Enable tabbable DOM elements inside CUSTOM_ELEMENT\nisTabbable: (tabbableEntry) => (\n  tabbableEntry.slateNode.type === CUSTOM_ELEMENT ||\n  editor.api.isVoid(tabbableEntry.slateNode)\n),\n```\n\n### DOM Elements Outside the Editor\n\nIn some circumstances, you may want to allow users to tab from the editor to a DOM element rendered outside the editor, such as an interactive popover.\n\nTo do this, override `insertTabbableEntries` to return an array of `TabbableEntry` objects, one for each DOM element outside the editor that you want to include in the tabbable list. The `slateNode` and `path` of the `TabbableEntry` should refer to the Slate node the user's cursor will be inside when the DOM element should be tabbable to.\n\nSet the `globalEventListener` option to `true` to make sure the Tabbable plugin is able to return the user's focus to the editor.\n\nFor example, if the DOM element appears when a link is selected, the `slateNode` and `path` should be that of the link.\n\n```tsx\n// Add buttons inside .my-popover to the list of tabbables\nglobalEventListener: true,\ninsertTabbableEntries: (event) => {\n  const [selectedNode, selectedNodePath] = editor.api.node(editor.selection);\n\n  return [\n    ...document.querySelectorAll('.my-popover > button'),\n  ].map((domNode) => ({\n    domNode,\n    slateNode: selectedNode,\n    path: selectedNodePath,\n  }));\n},\n```\n\n## Plugins\n\n### TabbablePlugin\n\nPlugin for managing tab order between tabbable elements.\n\n<API name=\"TabbablePlugin\">\n<APIOptions>\n  <APIItem name=\"query\" type=\"(event: KeyboardEvent) => boolean\" optional>\n    Enable/disable plugin dynamically.\n    - **Default:** `() => true`\n  </APIItem>\n  <APIItem name=\"globalEventListener\" type=\"boolean\" optional>\n    Add event listener to document instead of editor.\n    - **Default:** `false`\n  </APIItem>\n  <APIItem name=\"insertTabbableEntries\" type=\"(event: KeyboardEvent) => TabbableEntry[]\" optional>\n    Add additional tabbable entries outside editor.\n    - **Default:** `() => []`\n  </APIItem>\n  <APIItem name=\"isTabbable\" type=\"(tabbableEntry: TabbableEntry) => boolean\" optional>\n    Determine if element should be tabbable.\n    - **Default:** `(tabbableEntry) => editor.api.isVoid(tabbableEntry.slateNode)`\n  </APIItem>\n</APIOptions>\n</API>\n\n## Types\n\n### TabbableEntry\n\nDefines the properties of a tabbable entry.\n\n<API name=\"TabbableEntry\">\n<APIAttributes>\n  <APIItem name=\"domNode\" type=\"HTMLElement\">\n    HTML element representing tabbable entry.\n  </APIItem>\n  <APIItem name=\"slateNode\" type=\"TNode\">\n    Corresponding Slate node.\n  </APIItem>\n  <APIItem name=\"path\" type=\"Path\">\n    Path to Slate node in document.\n  </APIItem>\n</APIAttributes>\n</API>",
      "type": "registry:file",
      "target": "content/docs/plate/(plugins)/(functionality)/tabbable.mdx"
    }
  ],
  "type": "registry:file"
}