{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "block-selection-docs",
  "title": "Block Selection",
  "description": "Documentation for Block Selection",
  "files": [
    {
      "path": "../../content/docs/(plugins)/(functionality)/block-selection.mdx",
      "content": "---\ntitle: Block Selection\ndocs:\n  - route: /docs/components/block-selection\n    title: Block Selection\n---\n\n<ComponentPreview name=\"block-selection-demo\" />\n\n<PackageInfo>\n\nThe Block Selection feature allows users to select and manipulate entire text blocks, as opposed to individual words or characters.\n\n## Features\n\n- Select entire blocks with a single action.\n- Multi-block selection using mouse drag or keyboard shortcuts.\n- Copy, cut, and delete operations on selected blocks.\n- Keyboard shortcuts for quick selection:\n  - `Cmd+A`: Select all blocks.\n  - Arrow keys: Select the block above or below.\n- Customizable styling for selected blocks.\n\n</PackageInfo>\n\n## Kit Usage\n\n<Steps>\n\n### Installation\n\nThe fastest way to add Block Selection is with the `BlockSelectionKit`, which includes the pre-configured `BlockSelectionPlugin` and the [`BlockSelection`](/docs/components/block-selection) UI component.\n\n<ComponentSource name=\"block-selection-kit\" />\n\n- [`BlockSelection`](/docs/components/block-selection): Renders the selection rectangle around selected blocks.\n\n### Add Kit\n\nThe `BlockSelectionKit` enables the context menu by default and provides a default `isSelectable` logic to exclude common non-selectable blocks like code lines and table cells.\n\n```tsx\nimport { createPlateEditor } from 'platejs/react';\nimport { BlockSelectionKit } from '@/components/editor/plugins/block-selection-kit';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    ...BlockSelectionKit,\n  ],\n});\n```\n\n</Steps>\n\n## Manual Usage\n\n<Steps>\n\n### Installation\n\n```bash\nnpm install @platejs/selection\n```\n\n### Add Plugin\n\n```tsx\nimport { BlockSelectionPlugin } from '@platejs/selection/react';\nimport { createPlateEditor } from 'platejs/react';\n\nconst editor = createPlateEditor({\n  plugins: [\n    // ...otherPlugins,\n    BlockSelectionPlugin,\n  ],\n});\n```\n\nPut this plugin before any other plugins overriding `selectAll` – `Cmd+A` (code block, table, column, etc.) to avoid any conflicts.\n\n#### Excluding Blocks from Selection\n\nYou can control which blocks are selectable using `options.isSelectable`. This function receives an element and its path, and should return `true` if the block is selectable.\n\nFor example, to exclude code lines, columns, and table cells:\n\n```tsx\nimport { BlockSelectionPlugin } from '@platejs/selection/react';\n\nBlockSelectionPlugin.configure({\n  options: {\n    isSelectable: (element, path) => {\n      if (['code_line', 'column', 'td'].includes(element.type)) {\n        return false;\n      }\n      // Exclude blocks inside table rows\n      if (editor.api.block({ above: true, at: path, match: { type: 'tr' } })) {\n        return false;\n      }\n      return true;\n    },\n  },\n});\n```\n\n#### Customizing Scroll Behavior\n\nIf your editor is inside a scrollable container, you may need to configure the selection area's boundaries and scroll speed.\n\n1.  Add an `id` to your scroll container, e.g., `id={editor.meta.uid}`.\n2.  Set `position: relative` on the container.\n3.  Use the `areaOptions` to configure the boundaries and scrolling behavior.\n\n```ts\nBlockSelectionPlugin.configure({\n  options: {\n    areaOptions: {\n      boundaries: `#${editor.meta.uid}`,\n      container: `#${editor.meta.uid}`,\n      behaviour: {\n        scrolling: {\n          // Recommended speed, close to native\n          speedDivider: 0.8,\n        },\n        // Threshold to start selection area\n        startThreshold: 4,\n      },\n    },\n  },\n});\n```\n\n#### Full Page Selection\n\nYou can enable block selection for elements outside the `<Editor />` component by adding the `data-plate-selectable` attribute.\n\n```tsx\n<Cover data-plate-selectable />\n<Sidebar data-plate-selectable />\n```\n\nTo prevent unselecting blocks when clicking on certain elements (e.g., a toolbar button), add the `data-plate-prevent-unselect` attribute.\n\n```tsx\n<YourToolbarButton data-plate-prevent-unselect />\n```\n\nTo reset the selection when clicking outside selectable areas, you can use a click handler or call the API directly:\n\n```tsx\n// 1. Direct API call\neditor.api.blockSelection.deselect();\n\n// 2. Click outside handler\nconst handleClickOutside = (event: MouseEvent) => {\n  if (!(event.target as HTMLElement).closest('[data-plate-selectable]')) {\n    editor.api.blockSelection.deselect();\n  }\n};\n```\n\n</Steps>\n\n## Styling\n\n### Selection Area\n\nStyle the selection area by targeting the `.slate-selection-area` class, which is added to the editor container.\n\n```css\n/* Example using Tailwind CSS utility classes */\n'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10'\n```\n\n### Selected Element\n\nUse the `useBlockSelected` hook to determine if a block is selected. You can render a visual indicator, like the [`BlockSelection`](/docs/components/block-selection) component, which is designed for this purpose.\n\nPlate UI renders this component for all selectable blocks using `render.belowRootNodes`:\n\n```tsx\nrender: {\n  belowRootNodes: (props) => {\n    if (!props.className?.includes('slate-selectable')) return null;\n\n    return <BlockSelection />;\n  },\n},\n```\n\n## Plugins\n\n### `BlockSelectionPlugin`\n\nPlugin for block selection functionality.\n\n<API name=\"BlockSelectionPlugin\">\n<APIOptions>\n  <APIItem name=\"areaOptions\" type=\"PartialSelectionOptions\" optional>\n    Options for the selection area. See [SelectionJS docs](https://github.com/Simonwep/selection-js) for all available options.\n    \n```ts\n{\n  boundaries: [`#${editor.meta.uid}`],\n  container: [`#${editor.meta.uid}`],\n  selectables: [`#${editor.meta.uid} .slate-selectable`],\n  selectionAreaClass: 'slate-selection-area',\n}\n```\n    \n  </APIItem>\n  <APIItem name=\"enableContextMenu\" type=\"boolean\" optional>\n    Enables or disables the context menu for block selection.\n    - **Default:** `false`\n  </APIItem>\n  <APIItem name=\"isSelecting\" type=\"boolean\" optional>\n    Indicates whether block selection is currently active.\n    - **Default:** `false`\n  </APIItem>\n  <APIItem name=\"onKeyDownSelecting\" type=\"(e: KeyboardEvent) => void\" optional>\n    A function to handle the keydown event when selecting.\n  </APIItem>\n  <APIItem name=\"query\" type=\"QueryNodeOptions\" optional>\n    Options for querying nodes during block selection.\n    - **Default:** `{ maxLevel: 1 }`\n  </APIItem>\n  <APIItem name=\"selectedIds\" type=\"Set<string>\" optional>\n    A set of IDs for the currently selected blocks.\n    - **Default:** `new Set()`\n  </APIItem>\n  <APIItem name=\"anchorId\" type=\"string | null\" optional>\n    (Internal) The ID of the anchor block in the current selection. Used for shift-based selection.\n    - **Default:** `null`\n  </APIItem>\n  <APIItem name=\"isSelectable\" type=\"(element: TElement, path: Path) => boolean\" optional>\n    Function to determine if a block element is selectable.\n    - **Default:** `() => true`\n  </APIItem>\n</APIOptions>\n</API>\n\n## API\n\n### `api.blockSelection.add`\n\nAdds one or more blocks to the selection.\n\n<API name=\"add\">\n  <APIParameters>\n    <APIItem name=\"id\" type=\"string | string[]\">\n      The ID(s) of the block(s) to be selected.\n    </APIItem>\n  </APIParameters>\n</API>\n\n### `api.blockSelection.clear`\n\nResets the set of selected IDs to an empty set.\n\n### `api.blockSelection.delete`\n\nRemoves one or more blocks from the selection.\n\n<API name=\"delete\">\n  <APIParameters>\n    <APIItem name=\"id\" type=\"string | string[]\">\n      The ID(s) of the block(s) to remove from selection.\n    </APIItem>\n  </APIParameters>\n</API>\n\n### `api.blockSelection.deselect`\n\nDeselects all blocks and sets the `isSelecting` flag to false.\n\n### `api.blockSelection.focus`\n\nFocuses the block selection shadow input. This input handles copy, delete, and paste events for selected blocks.\n\n### `api.blockSelection.getNodes`\n\nGets the selected blocks in the editor.\n\n<API name=\"getNodes\">\n<APIParameters>\n  <APIItem name=\"options\" type=\"{ selectionFallback?: boolean }\" optional>\n    Options for getting nodes.\n  </APIItem>\n</APIParameters>\n\n<APIOptions type=\"object\">\n  <APIItem name=\"selectionFallback\" type=\"boolean\" optional>\n    If true, and no blocks are selected by block selection, the method will use\n    the editor's original selection to retrieve blocks. - **Default:** `false`\n  </APIItem>\n</APIOptions>\n\n<APIReturns type=\"NodeEntry[]\">\n  Array of selected block entries.\n</APIReturns>\n</API>\n\n### `api.blockSelection.has`\n\nChecks if one or more blocks are selected.\n\n<API name=\"has\">\n  <APIParameters>\n    <APIItem name=\"id\" type=\"string | string[]\">\n      The ID(s) of the block(s) to check.\n    </APIItem>\n  </APIParameters>\n  <APIReturns>\n    <APIItem type=\"boolean\">Whether the block(s) are selected.</APIItem>\n  </APIReturns>\n</API>\n\n### `api.blockSelection.isSelectable`\n\nChecks if a block at a given path is selectable based on the `isSelectable` plugin option.\n\n<API name=\"isSelectable\">\n  <APIParameters>\n    <APIItem name=\"element\" type=\"TElement\">\n      Block element to check.\n    </APIItem>\n    <APIItem name=\"path\" type=\"Path\">\n      Path to the block element.\n    </APIItem>\n  </APIParameters>\n  <APIReturns type=\"boolean\">Whether the block is selectable.</APIReturns>\n</API>\n\n### `api.blockSelection.moveSelection`\n\nMoves the selection up or down to the next selectable block.\n\nWhen moving up:\n\n- Gets the previous selectable block from the top-most selected block\n- Sets it as the new anchor\n- Clears previous selection and selects only this block\n  When moving down:\n- Gets the next selectable block from the bottom-most selected block\n- Sets it as the new anchor\n- Clears previous selection and selects only this block\n\n<API name=\"moveSelection\">\n  <APIParameters>\n    <APIItem name=\"direction\" type=\"'up' | 'down'\">\n      Direction to move selection.\n    </APIItem>\n  </APIParameters>\n</API>\n\n### `api.blockSelection.selectAll`\n\nSelects all selectable blocks in the editor.\n\n### `api.blockSelection.set`\n\nSets the selection to one or more blocks, clearing any existing selection.\n\n<API name=\"set\">\n  <APIParameters>\n    <APIItem name=\"id\" type=\"string | string[]\">\n      The ID(s) of the block(s) to be selected.\n    </APIItem>\n  </APIParameters>\n</API>\n\n### `api.blockSelection.shiftSelection`\n\nExpands or shrinks the selection based on the anchor block.\n\nFor `Shift+ArrowDown`:\n\n- If anchor is top-most: Expands down by adding block below bottom-most\n- Otherwise: Shrinks from top-most (unless top-most is the anchor)\n  For `Shift+ArrowUp`:\n- If anchor is bottom-most: Expands up by adding block above top-most\n- Otherwise: Shrinks from bottom-most (unless bottom-most is the anchor)\n  The anchor block always remains selected. If no anchor is set, it defaults to:\n- Bottom-most block for `Shift+ArrowUp`\n- Top-most block for `Shift+ArrowDown`\n\n<API name=\"shiftSelection\">\n  <APIParameters>\n    <APIItem name=\"direction\" type=\"'up' | 'down'\">\n      Direction to expand/shrink selection.\n    </APIItem>\n  </APIParameters>\n</API>\n\n## Transforms\n\n### `tf.blockSelection.duplicate`\n\nDuplicates the selected blocks.\n\n### `tf.blockSelection.removeNodes`\n\nRemoves the selected nodes from the editor.\n\n### `tf.blockSelection.select`\n\nSelects the nodes returned by `getNodes()` in the editor and resets selected IDs.\n\n### `tf.blockSelection.setNodes`\n\nSets properties on the selected nodes.\n\n<API name=\"setNodes\">\n  <APIParameters>\n    <APIItem name=\"props\" type=\"Partial<NodeProps<TElement>>\">\n      Properties to set on selected nodes.\n    </APIItem>\n    <APIItem name=\"options\" type=\"SetNodesOptions\" optional>\n      Options for setting nodes.\n    </APIItem>\n  </APIParameters>\n</API>\n\n### `tf.blockSelection.setTexts`\n\nSets text properties on the selected nodes.\n\n<API name=\"setTexts\">\n  <APIParameters>\n    <APIItem name=\"props\" type=\"Partial<NodeProps<TText>>\">\n      Text properties to set on selected nodes.\n    </APIItem>\n    <APIItem name=\"options\" type=\"Omit<SetNodesOptions, 'at'>\" optional>\n      Options for setting text nodes, excluding the 'at' property.\n    </APIItem>\n  </APIParameters>\n</API>\n\n## Hooks\n\n### `useBlockSelectable`\n\nA hook that provides props for making a block element selectable, including context menu behavior.\n\n<API name=\"useBlockSelectable\">\n  <APIReturns type=\"object\">\n    <APIItem name=\"props\" type=\"object\">\n      Props to be spread on the block element.\n      <APISubList>\n        <APISubListItem parent=\"props\" name=\"className\" type=\"string\">\n          Required class for selection functionality. - **Default:**\n          `'slate-selectable'`\n        </APISubListItem>\n        <APISubListItem\n          parent=\"props\"\n          name=\"onContextMenu\"\n          type=\"(event: React.MouseEvent) => void\"\n        >\n          Handles right-click context menu behavior: - Opens context menu for\n          selected blocks - Opens for void elements - Opens for elements with\n          `data-plate-open-context-menu=\"true\"` - Adds block to selection with\n          Shift key for multi-select\n        </APISubListItem>\n      </APISubList>\n    </APIItem>\n  </APIReturns>\n</API>\n\n### `useBlockSelected`\n\n<API name=\"useBlockSelected\">\n  <APIReturns type=\"boolean\">Whether the context block is selected.</APIReturns>\n</API>\n\n### `useBlockSelectionNodes`\n\n<API name=\"useBlockSelectionNodes\">\n  <APIReturns type=\"NodeEntry[]\">Array of selected block entries.</APIReturns>\n</API>\n\n### `useBlockSelectionFragment`\n\n<API name=\"useBlockSelectionFragment\">\n  <APIReturns type=\"Node[]\">Array of selected block nodes.</APIReturns>\n</API>\n\n### `useBlockSelectionFragmentProp`\n\n<API name=\"useBlockSelectionFragmentProp\">\n  <APIReturns type=\"Node[]\">Fragment prop for selected blocks.</APIReturns>\n</API>\n\n### `useSelectionArea`\n\nInitialize and manage selection area functionality.\n",
      "type": "registry:file",
      "target": "content/docs/plate/(plugins)/(functionality)/block-selection.mdx"
    }
  ],
  "type": "registry:file"
}