diff --git a/.changeset/config.json b/.changeset/config.json index 17b9abdcde..af53e39d80 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -2,7 +2,17 @@ "$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json", "changelog": ["./changelog-config", { "repo": "udecode/plate" }], "commit": false, - "linked": [["@udecode/*"]], + "linked": [ + [ + "@udecode/plate", + "@udecode/plate*", + "@udecode/slate", + "@udecode/slate*", + "@udecode/react*", + "@udecode/cn", + "@udecode/utils" + ] + ], "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", diff --git a/.changeset/itchy-cups-wonder.md b/.changeset/itchy-cups-wonder.md deleted file mode 100644 index e8bf89880e..0000000000 --- a/.changeset/itchy-cups-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@udecode/plate-dnd': patch ---- - -Fix: `useDndNode` calls a state setter during its render function diff --git a/.eslintrc.cjs b/.eslintrc.cjs index e4b702d0ab..326e0906d6 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -36,6 +36,14 @@ module.exports = { '**/scripts/*.mts', ], overrides: [ + { + files: ['**/registry/default/**/*'], + rules: { + 'jsx-a11y/iframe-has-title': 'off', + 'jsx-a11y/media-has-caption': 'off', + 'react/jsx-no-comment-textnodes': 'off', + }, + }, { files: ['*.ts', '*.tsx', '*.mts'], parserOptions: { diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index 9ff93ba845..ecfd36216d 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -1,5 +1,37 @@ For older changelogs, see https://github.com/udecode/plate/blob/main/docs +# 40.0.0 + +## @udecode/slate-react@40.0.0 + +### Major Changes + +- [#3744](https://github.com/udecode/plate/pull/3744) by [@zbeyens](https://github.com/zbeyens) – + - Add `slate-dom` as a peer dependency. + - Update `slate-react` peer dependency to `>=0.111.0` + +## @udecode/plate-ai@40.0.0 + +### Major Changes + +- [#3744](https://github.com/udecode/plate/pull/3744) by [@zbeyens](https://github.com/zbeyens) – + - Remove `scrollContainerSelector` option in favor of `useEditorContainerRef` + +## @udecode/plate-heading@40.0.0 + +### Major Changes + +- [#3744](https://github.com/udecode/plate/pull/3744) by [@zbeyens](https://github.com/zbeyens) – + - Remove `scrollContainerSelector` option in favor of `useEditorContainerRef` + +## @udecode/plate-layout@40.0.0 + +### Major Changes + +- [#3744](https://github.com/udecode/plate/pull/3744) by [@zbeyens](https://github.com/zbeyens) – + - Remove `toggleColumns` in favor of `toggleColumnGroup` + - Remove `insertEmptyColumn` in favor of `insertColumn` + # 39.0.0 ## @udecode/plate-dnd@39.0.0 diff --git a/README.md b/README.md index 9275f058e0..148d2c95a4 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,6 @@ Plate -
- -Udecode - - -
-
- Powered by Vercel -
-

![hero](apps/www/public/og.png) @@ -35,12 +25,11 @@ Plate You can choose one of the following templates to get started: -| Option | NextJS | Plate | Plugins | AI & Backend | -| --------------------------------------------------------------------------------- | ------ | ----- | ------- | ------------ | -| [Notion-like template](https://pro.platejs.org/docs/templates/potion) | ✅ | ✅ | ✅ | ✅ | -| [Plate playground template](https://github.com/udecode/plate-playground-template) | ✅ | ✅ | ✅ | | -| [Plate minimal template](https://github.com/udecode/plate-template) | ✅ | ✅ | | | -| [NextJS template](https://platejs.org/docs/components/installation/next) | ✅ | | | | +| Option | Plate | Plugins | AI | Backend | +| --------------------------------------------------------------------------------- | ----- | ------- | --- | ------- | +| [Notion-like template](https://pro.platejs.org/docs/templates/potion) | ✅ | ✅ | ✅ | ✅ | +| [Plate playground template](https://github.com/udecode/plate-playground-template) | ✅ | ✅ | ✅ | | +| [Plate minimal template](https://github.com/udecode/plate-template) | ✅ | | | | ## Documentation diff --git a/apps/www/content/docs/ai.mdx b/apps/www/content/docs/ai.mdx index 21d8766ffb..7d5ae429eb 100644 --- a/apps/www/content/docs/ai.mdx +++ b/apps/www/content/docs/ai.mdx @@ -1,12 +1,11 @@ --- title: AI -description: AI menu with commands, streaming responses in a preview or directly into the editor. docs: - route: https://pro.platejs.org/docs/examples/ai title: AI --- - + @@ -172,7 +171,6 @@ const plugins = [ ? PROMPT_TEMPLATES.userSelecting : PROMPT_TEMPLATES.userDefault; }, - scrollContainerSelector: '#scroll_container', systemTemplate: ({ isBlockSelecting, isSelecting }) => { return isBlockSelecting ? PROMPT_TEMPLATES.systemBlockSelecting @@ -183,18 +181,11 @@ const plugins = [ }, render: { afterEditable: () => }, }), - SelectionOverlayPlugin, ]; ``` - [AIMenu](/docs/components/ai-menu) -The [SelectionOverlayPlugin](https://pro.platejs.org/docs/components/cursor-overlay): - -- Maintains selection highlight when editor loses focus -- Essential for AI menu and other external input interactions -- Prevents double selection with `data-plate-prevent-overlay` attribute - ### AI SDK This plugin is depending on the [ai](https://npmjs.com/package/ai) package: @@ -278,14 +269,6 @@ Template for generating prompts. Supports placeholders: - - -CSS selector for scrollable container. - -- **Default:** `'#scroll_container'` - - - Template for system messages. Supports same placeholders as `promptTemplate`. diff --git a/apps/www/content/docs/alignment.mdx b/apps/www/content/docs/alignment.mdx index b56f61b62d..ec03790708 100644 --- a/apps/www/content/docs/alignment.mdx +++ b/apps/www/content/docs/alignment.mdx @@ -1,12 +1,11 @@ --- title: Alignment -description: Align your content to different positions. docs: - route: /docs/components/align-dropdown-menu title: Align Dropdown Menu --- - + @@ -66,6 +65,7 @@ The editor instance. The alignment value. +Options for the `setNodes` function. diff --git a/apps/www/content/docs/api/core.mdx b/apps/www/content/docs/api/core.mdx index f033d49df0..985d573cf1 100644 --- a/apps/www/content/docs/api/core.mdx +++ b/apps/www/content/docs/api/core.mdx @@ -160,6 +160,18 @@ a A new `PlatePlugin` with precise type control. +### useEditorContainerRef + +Get the editor container DOM reference. + +### useEditorScrollRef + +Get the editor scroll container reference. + +### useScrollRef + +Get the editor scroll container reference. Returns the scroll ref if it exists, otherwise returns the container ref. + ### useEditorPlugin Get editor and plugin context. diff --git a/apps/www/content/docs/api/core/plate-plugin.mdx b/apps/www/content/docs/api/core/plate-plugin.mdx index 617b9dbea9..b97aec51b4 100644 --- a/apps/www/content/docs/api/core/plate-plugin.mdx +++ b/apps/www/content/docs/api/core/plate-plugin.mdx @@ -63,6 +63,28 @@ Defines how the plugin injects functionality into other plugins or the editor. Properties used by Plate to inject props into any node component. + + + +An array of plugin keys to exclude from node prop injection. + + + +An array of plugin keys. Node prop injection will be excluded for any nodes that are descendants of elements with these plugin types. + + +If true, only matches block elements. Used to restrict prop injection to block-level nodes. + + + +If true, only matches element nodes. Used to restrict prop injection to element nodes. + + +If true, only matches leaf nodes. Used to restrict prop injection to leaf nodes. + + +Maximum nesting level for node prop injection. Nodes deeper than this level will not receive injected props. + Property that can be used by a plugin to allow other plugins to inject code. diff --git a/apps/www/content/docs/api/core/plate.mdx b/apps/www/content/docs/api/core/plate.mdx index 8f03361f75..8bd88de24a 100644 --- a/apps/www/content/docs/api/core/plate.mdx +++ b/apps/www/content/docs/api/core/plate.mdx @@ -25,7 +25,7 @@ Controlled callback called when the editor state changes. Callback called when the editor selection changes. - + Callback called when the editor value changes. @@ -49,6 +49,9 @@ Custom render function for leaf nodes. Props for the [Editable](https://docs.slatejs.org/libraries/slate-react/editable) component. Extends `TextareaHTMLAttributes`. + +Automatically focus the editor when it transitions from read-only to editable mode (when `readOnly` changes from `true` to `false`). + Custom `Editable` node. diff --git a/apps/www/content/docs/api/core/store.mdx b/apps/www/content/docs/api/core/store.mdx index e4cead40b0..1e00ae52e1 100644 --- a/apps/www/content/docs/api/core/store.mdx +++ b/apps/www/content/docs/api/core/store.mdx @@ -29,6 +29,10 @@ A unique ID used as a provider scope. Use it if you have multiple `Plate` in the - **Default:** random id + +A reference to the editor container element. + + Function used to decorate ranges in the editor. diff --git a/apps/www/content/docs/api/floating.mdx b/apps/www/content/docs/api/floating.mdx new file mode 100644 index 0000000000..c0c1c63706 --- /dev/null +++ b/apps/www/content/docs/api/floating.mdx @@ -0,0 +1,164 @@ +--- +title: Floating +description: API reference for floating UI components and hooks. +--- + + + +## Features + +- Virtual floating elements that follow cursor position +- Floating toolbar that appears on text selection +- Built on top of Floating UI +- Customizable positioning and behavior +- Automatic updates on scroll and resize + + + +## Installation + +```bash +npm install @udecode/plate-floating +``` + +## API Hooks + +### useVirtualFloating + +Creates a floating element with a controlled virtual element, typically used to follow cursor position. + + + + Options for the virtual floating element. + + + Function to get the bounding client rect. + - **Default:** Returns a zero-sized rect at (0,0) + + + Controls visibility of the floating element. + + + Callback when elements are mounted. + - **Default:** `autoUpdate` (updates on scroll and resize) + + + + + + + + Style object to apply to the floating element. + + + Reference to the virtual element. + + + References for floating UI positioning. + + + Function to manually update positioning. + + + +### useFloatingToolbar + +Creates a floating toolbar that appears when text is selected in the editor. + + + + State options for the floating toolbar. + + + Options passed to useVirtualFloating. + + + Force hide the toolbar. + + + Show toolbar in read-only mode. + + + + + + + + Ref to detect clicks outside the toolbar. + + + Whether the toolbar should be hidden. + + + Props to spread on the toolbar element. + + + Ref to attach to the toolbar element. + + + +## API + +### getBoundingClientRect + +Gets the bounding client rectangle for a location or array of locations in the editor. + + + + The editor instance. + + + The location(s) to get the bounding rectangle for. If not provided, uses the current editor selection. + + + + + + The merged bounding client rectangle of all specified locations, or undefined if no valid rectangles found. + + + +### getDOMSelectionBoundingClientRect + +Gets the bounding client rectangle of the current DOM selection. + + + + The bounding client rectangle of the DOM selection. Returns a zero-sized rect at (0,0) if no selection exists. + + + +### getRangeBoundingClientRect + +Gets the bounding client rectangle for a specific Slate range. + + + + The editor instance. + + + The Slate range to get the bounding rectangle for. + + + + + + The bounding client rectangle of the range. Returns a zero-sized rect at (0,0) if the range is null or invalid. + + + +### getSelectionBoundingClientRect + +Gets the bounding client rectangle of the current editor selection. + + + + The editor instance. + + + + + + The bounding client rectangle of the selection. Returns a zero-sized rect at (0,0) if the selection is not expanded. + + \ No newline at end of file diff --git a/apps/www/content/docs/api/resizable.mdx b/apps/www/content/docs/api/resizable.mdx new file mode 100644 index 0000000000..49454388d4 --- /dev/null +++ b/apps/www/content/docs/api/resizable.mdx @@ -0,0 +1,206 @@ +--- +title: Resizable +--- + + + +## Features + +- Resizable elements with handles +- Configurable min/max width constraints +- Center/left/right alignment support +- Width persistence in editor state + + + +## Installation + +```bash +npm install @udecode/plate-resizable +``` + +## API + +### useResizableState + +Manages state for resizable elements. + + + + + + Node alignment. + - **Default:** `'center'` + + + Maximum width constraint. + - **Default:** `'100%'` + + + Minimum width constraint. + - **Default:** `92` + + + Whether the element is resizable in read-only mode. + + + + + + + + Current alignment setting. + + + Maximum width constraint. + + + Minimum width constraint. + + + Updates node width in editor state. + + + Updates width in local state. + + + Current width value. + + + +### useResizable + +Provides resize behavior props and handlers for resizable elements. + + + + State from useResizableState. + + + + + + + + Handler for resize events. + + + + + Style props for the resizable element: + - maxWidth: Maximum width constraint + - minWidth: Minimum width constraint + - position: 'relative' + - width: Current width + + + Style props for the wrapper element: + - position: 'relative' + + + Reference to the wrapper element. + + + +### useResizeHandleState + +Manages state for resize handle elements. + + + + + + Direction of resize. + - **Default:** `'left'` + + + Initial size of the resizable element. + + + Callback when handle is hovered. + + + Callback when handle hover ends. + + + Custom mouse down handler. + + + Custom resize handler. Falls back to store handler if not provided. + + + Custom touch start handler. + + + + + + + + Current resize direction. + + + Initial cursor/touch position. + + + Initial element size. + + + Whether resize direction is horizontal. + + + Whether resize is in progress. + + + Editor read-only state. + + + Update initial position. + + + Update initial size. + + + Update resize state. + + + Hover callback. + + + Hover end callback. + + + Mouse down handler. + + + Resize handler. + + + Touch start handler. + + + +### useResizeHandle + +Provides handlers and props for resize handle elements. + + + + State from useResizeHandleState. + + + + + + Whether the handle should be hidden (in read-only mode). + + + Props to spread on the handle element: + - onMouseDown: Mouse down event handler + - onMouseOut: Mouse out event handler + - onMouseOver: Mouse over event handler + - onTouchEnd: Touch end event handler + - onTouchMove: Touch move event handler + - onTouchStart: Touch start event handler + + \ No newline at end of file diff --git a/apps/www/content/docs/api/slate-utils.mdx b/apps/www/content/docs/api/slate-utils.mdx index 1d93561ca5..a7126f8fe3 100644 --- a/apps/www/content/docs/api/slate-utils.mdx +++ b/apps/www/content/docs/api/slate-utils.mdx @@ -771,6 +771,19 @@ The number of children moved. +### removeEditorText + +Removes all non-empty text nodes from the editor. + + + + The editor instance. + + + Options for removing nodes. The `match` function in options will be combined with the text length check. + + + ### removeMark Removes a mark and triggers `onChange` if the selection is collapsed. diff --git a/apps/www/content/docs/api/utils.mdx b/apps/www/content/docs/api/utils.mdx index 204b23a8c1..c6d32c03b5 100644 --- a/apps/www/content/docs/api/utils.mdx +++ b/apps/www/content/docs/api/utils.mdx @@ -121,6 +121,16 @@ If true, merges its props onto its immediate child. ## Hooks +### useEditorString + +A hook that returns the entire text content of the editor as a string. + + + + The concatenated text content of all text nodes in the editor. + + + ### useMarkToolbarButtonState Generates the state for a mark toolbar button. diff --git a/apps/www/content/docs/autoformat.mdx b/apps/www/content/docs/autoformat.mdx index 7aacbb6529..296d5568a5 100644 --- a/apps/www/content/docs/autoformat.mdx +++ b/apps/www/content/docs/autoformat.mdx @@ -1,6 +1,5 @@ --- title: Autoformat -description: Apply formatting automatically using shortcodes. docs: - route: /docs/basic-elements title: Basic Elements @@ -12,7 +11,7 @@ docs: title: List --- - + diff --git a/apps/www/content/docs/basic-elements.mdx b/apps/www/content/docs/basic-elements.mdx index 6c7e185ae1..512f46359b 100644 --- a/apps/www/content/docs/basic-elements.mdx +++ b/apps/www/content/docs/basic-elements.mdx @@ -1,6 +1,5 @@ --- title: Basic Elements -description: Enhance your editor with essential formatting elements. docs: - route: /docs/components/blockquote-element title: Block Quote Element @@ -14,7 +13,7 @@ docs: title: Heading Element --- - + diff --git a/apps/www/content/docs/basic-marks.mdx b/apps/www/content/docs/basic-marks.mdx index 2174419934..4b74d8b24a 100644 --- a/apps/www/content/docs/basic-marks.mdx +++ b/apps/www/content/docs/basic-marks.mdx @@ -1,12 +1,11 @@ --- title: Basic Marks -description: Set of essential text formatting options. docs: - route: /docs/components/mark-toolbar-button title: Mark Toolbar Button --- - + diff --git a/apps/www/content/docs/block-menu.mdx b/apps/www/content/docs/block-menu.mdx index 79689f632b..cce8309711 100644 --- a/apps/www/content/docs/block-menu.mdx +++ b/apps/www/content/docs/block-menu.mdx @@ -1,6 +1,5 @@ --- title: Block Menu -description: Provides quick access to block-specific actions. docs: - route: /docs/components/block-context-menu title: Block Context Menu @@ -13,7 +12,7 @@ docs: --- - + @@ -45,18 +44,6 @@ const plugins = [ NodeIdPlugin, BlockSelectionPlugin.configure({ options: { - areaOptions: { - behaviour: { - scrolling: { - speedDivider: 1.5, - }, - startThreshold: 10, - }, - boundaries: '#scroll_container', - container: '#scroll_container', - selectables: '#scroll_container .slate-selectable', - selectionAreaClass: 'slate-selection-area', - }, enableContextMenu: true, }, }), diff --git a/apps/www/content/docs/block-selection.mdx b/apps/www/content/docs/block-selection.mdx index 643ebe5a9a..d737855c04 100644 --- a/apps/www/content/docs/block-selection.mdx +++ b/apps/www/content/docs/block-selection.mdx @@ -1,9 +1,11 @@ --- title: Block Selection -description: Select and manipulate entire text blocks. +docs: + - route: /docs/components/block-selection + title: Block Selection --- - + @@ -42,162 +44,134 @@ const plugins = [ ]; ``` -## Configuration +### Exclude blocks from selection -### Set scrollable container +You can exclude certain plugins from block selection using: -To control the scrollable container, configure the `boundaries` and `container` options within `areaOptions`. These options accept CSS selectors, such as `#selection-demo #scroll_container`, which are used with `document.querySelector()`. +```ts +BlockSelectionPlugin.configure({ + inject: { + // Exclude blocks below table rows + excludeBelowPlugins: ['tr'], + // Exclude block types + excludePlugins: ['table', 'code_line', 'column_group', 'column'], + } +}) +``` -For this to work effectively: +- `excludeBelowPlugins`: Plugin keys of non-selectable block descendants. Use this to prevent selection below specific blocks. For example, excluding 'tr' prevents selecting individual cells while still allowing table row selection. -1. Add an `id` or `className` to your scroll container.If you not sure about the container, you can add it to the `` component. -2. Use the appropriate selector in your configuration. -3. Don't forget to set `position: relative` to your scroll container. +- `excludePlugins`: Plugin keys of non-selectable blocks. -Example configuration: +### Set scrollable container -```js -{ - areaOptions: { - boundaries: '#your-scroll-container-id', - container: '#your-scroll-container-id', - selectables: '#your-scroll-container-id .slate-selectable', - selectionAreaClass: 'slate-selection-area', - } -} -``` +If you're using `EditorContainer` from [Editor](/docs/components/editor), you can skip this section. -This setup ensures that the block selection functionality is properly constrained within your designated scrollable area. +To control the scrollable container, configure the `boundaries` and `container` options within `areaOptions`. These options accept CSS selectors, such as `#selection-demo #${editor.uid}`, which are used with `document.querySelector()`. -### Set selectable element +For this to work effectively: -Add data-plate-selectable to the container or the element you want to start block selection. +1. Add an `id` or `className` to your scroll container. If you're not sure about the container, you can add it to the `` component. We recommend using `id={editor.uid}`. +2. Use the appropriate selector in your configuration. +3. Don't forget to set `position: relative` to the container. -Example: -```tsx - +Default configuration: + +```js +BlockSelectionPlugin.configure({ + options: { + areaOptions: { + boundaries: `#${editor.uid}`, + container: `#${editor.uid}`, + selectables: `#${editor.uid} .slate-selectable`, + }, + }, +}); ``` ### Set scroll speed -useing `options.areaOptions.behaviour.scrolling.speedDivider` to set the scroll speed. +Use `options.areaOptions.behaviour.scrolling.speedDivider` to set the scroll speed. -The value of `1.5` is our recommended speed.Since it's same with the default speed of the browser. +The value `0.8` is our recommended speed since it's near the browser-native speed. ```ts - areaOptions: { +BlockSelectionPlugin.configure({ + options: { + areaOptions: { behaviour: { - scrolling: { - speedDivider: 1.5, - }, - }, - }, -``` - -Full configuration recommended: - -```ts -options: { - areaOptions: { - behaviour: { scrolling: { + // You can slow down the scroll speed by setting a bigger value. speedDivider: 1.5, }, // The distance needed to move for the selection area to appear. - // If it’s too small, it may cause the mouse click event to be blocked. 30 is a good default. - startThreshold: 30, + // If it’s too small, it may cause the mouse click event to be blocked. 10 is a good default. + startThreshold: 4, }, - boundaries: '#your-scroll-container-id', - container: '#your-scroll-container-id', - selectables: '#your-scroll-container-id .slate-selectable', - selectionAreaClass: 'slate-selection-area', }, - // if not using plate-ui context menu, set it to false - enableContextMenu: true, -}, +} ``` -## Styling - -### Selection area - -Style the selection area using `.slate-selection-area` class to your `EditorContainer` component. For example: +### Add selectable element -```js -'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10' -``` +Add `data-plate-selectable="true"` to any element you want to start block selection. -### Selected element +### Prevent unselect -To determine if an element is selected, use the new `useBlockSelected` hook. You can render a visual indicator around selected blocks using our `BlockSelection` component or create your own: +To prevent unselecting blocks when clicking on certain elements, add the `data-plate-prevent-unselect` attribute to those components +For example: ```tsx -import React from 'react'; -import { useBlockSelected } from '@udecode/plate-selection/react'; - -export function BlockSelection() { - const isBlockSelected = useBlockSelected(); - - return ( -
- ); -} + ``` -This component should be rendered inside each block element for consistent selection feedback. Plate UI is doing it in `plate-element.tsx`. +### Full Page Selection -## Selectable and resetable +#### Making Elements Selectable -### full page selectable +You can enable block selection for elements outside the `` component, similar to the [Potion](https://potion.platejs.org/) template. Add the `data-plate-selectable` attribute to any component you want to make selectable: -Like the [potion](https://potion.platejs.org/) template, you can enable block selection outside of the `` component. +```tsx + + +``` -Simply add the `data-plate-selectable` attribute to any component outside the editor that you want to make selectable. You can even make the entire page selectable if desired. +This works for any element, even those outside the editor's DOM tree. -For example: +#### Resetting Selection +There are two ways to handle resetting selection across the full page: + +1. Direct API call: ```tsx - +editor.api.blockSelection.unselect(); ``` -### full page resetable +2. Click outside handler: +```tsx +const handleClickOutside = (event: MouseEvent) => { + if (!(event.target as HTMLElement).closest('[data-plate-selectable]')) { + editor.api.blockSelection.unselect(); + } +}; +``` -To reset the selection, you need call the `api.blockSelection.unselect();` method. +## Styling -If you want to make the full page resetable by click, this means you need to be able to access the editor outside of ``. +### Selection area -Or you can implement a click outside handler to reset the selection. +Style the selection area by adding the `.slate-selection-area` class to your editor container component. For example: +```js +'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10' +``` -## Prevent unselect +### Selected element -To prevent unselecting blocks when clicking on certain elements, add the `data-plate-prevent-unselect` attribute to those components +To determine if an element is selected, use `useBlockSelected` hook. You can render a visual indicator around selected blocks using our [BlockSelection](/docs/components/block-selection) component or create your own. -For example: -```tsx - -``` +This component should be rendered inside each block element for consistent selection feedback. Plate UI is doing it in [PlateElement](/docs/components/plate-element). ## Plugins @@ -209,9 +183,9 @@ Options for the selection area. Example: ```ts { - boundaries: ['#selection-demo #scroll_container'], - container: ['#selection-demo #scroll_container'], - selectables: ['#selection-demo #scroll_container .slate-selectable'], + boundaries: [`#${editor.uid}`], + container: [`#${editor.uid}`], + selectables: [`#${editor.uid} .slate-selectable`], selectionAreaClass: 'slate-selection-area', } ``` @@ -254,7 +228,6 @@ A set of IDs for the currently selected blocks. ## API - ### editor.api.blockSelection.focus Focuses the block selection shadow input. This input handles copy, delete, and paste events for selected blocks. @@ -268,9 +241,6 @@ Adds a selected row to the block selection. - - The HTML node above which to add the selection. - Whether to clear existing selections before adding the new one. - **Default:** `true` @@ -364,68 +334,34 @@ Sets text properties on the selected nodes. -## API Components +## Hooks + +### useBlockSelectable -### BlockSelectable +A hook that provides props for making a block element selectable, including context menu behavior. - - + + + Props to be spread on the block element: - - The element to render the block selectable. + + `'slate-selectable'` - Required class for selection functionality - - Whether the selection is active. + + Handles right-click context menu behavior: + - Opens context menu for selected blocks + - Opens for void elements + - Opens for elements with `data-plate-open-context-menu="true"` + - Adds block to selection with Shift key for multi-select - - -### BlockSelection - -A wrapper component that adds block selection functionality to its children. - - - - The content to be wrapped with block selection functionality. - - - -## Hooks + ### useBlockSelected Returns true if context block is selected. -### useBlockSelectableState - - - - Whether the block is active for selection. - - - The element associated with the block. - - - The path of the block in the editor. - - - A ref to the block's DOM element. - - - -### useBlockSelectable - - - - Props to be spread on the block's wrapper element. - - - -### useSelectionArea - -A hook that initializes and manages the selection area functionality. - ### useBlockSelectionNodes Returns an array of node entries for the currently selected blocks. @@ -437,3 +373,7 @@ Returns an array of nodes for the currently selected blocks. ### useBlockSelectionFragmentProp Returns fragment prop for the currently selected blocks. + +### useSelectionArea + +A hook that initializes and manages the selection area functionality. diff --git a/apps/www/content/docs/callout.mdx b/apps/www/content/docs/callout.mdx index b634f38dab..6320c23ef8 100644 --- a/apps/www/content/docs/callout.mdx +++ b/apps/www/content/docs/callout.mdx @@ -1,6 +1,5 @@ --- title: Callout -description: Highlight important information or add special notes. docs: - route: https://pro.platejs.org/docs/components/callout-element title: Callout Element diff --git a/apps/www/content/docs/caption.mdx b/apps/www/content/docs/caption.mdx index 03a9930a14..382585b112 100644 --- a/apps/www/content/docs/caption.mdx +++ b/apps/www/content/docs/caption.mdx @@ -1,12 +1,11 @@ --- title: Caption -description: Add captions to your blocks. docs: - - route: /docs/components/draggable - title: Draggable + - route: /docs/components/caption + title: Caption --- - + @@ -26,25 +25,35 @@ npm install @udecode/plate-caption ```tsx import { CaptionPlugin } from '@udecode/plate-caption/react'; -import { ImagePlugin, MediaEmbedPlugin } from '@udecode/plate-media/react'; +import { + AudioPlugin, + FilePlugin, + ImagePlugin, + MediaEmbedPlugin, + VideoPlugin, +} from '@udecode/plate-media/react'; +``` +```tsx const plugins = [ // ...otherPlugins, - CaptionPlugin, ImagePlugin, + VideoPlugin, + AudioPlugin, + FilePlugin, MediaEmbedPlugin, -]; - -const editor = createPlateEditor({ - plugins, - override: { - plugins: { - [CaptionPlugin.key]: { - plugins: [ImagePlugin.key, MediaEmbedPlugin.key], - }, + CaptionPlugin.configure({ + options: { + plugins: [ + ImagePlugin, + VideoPlugin, + AudioPlugin, + FilePlugin, + MediaEmbedPlugin, + ], }, - }, -}); + }), +]; ``` ## Plugins diff --git a/apps/www/content/docs/collaboration.mdx b/apps/www/content/docs/collaboration.mdx index cdcec9197d..c6a959e7d2 100644 --- a/apps/www/content/docs/collaboration.mdx +++ b/apps/www/content/docs/collaboration.mdx @@ -1,6 +1,5 @@ --- title: Collaboration -description: Collaborate with others in a single document. --- @@ -14,6 +13,8 @@ description: Collaborate with others in a single document. ## Features - The yjs plugin enables support for collaboration using [slate-yjs](https://docs.slate-yjs.dev/) and [Hocuspocus](https://docs.slate-yjs.dev/walkthroughs/collaboration-hocuspocus). +- By default remote cursors are not rendered unless you install the remote cursor overlay and include it in the config. +- Cursors are rendered slightly faded and become solid on hover. Use the `data` field in `cursorOptions` to customise the display name and color. @@ -29,15 +30,24 @@ npm install @udecode/plate-yjs ```tsx import { YjsPlugin } from '@udecode/plate-yjs/react'; +import { RemoteCursorOverlay } from '@/components/plate-ui/remote-cursor-overlay'; const editor = createPlateEditor({ plugins: [ // ...otherPlugins, YjsPlugin.configure({ options: { + render: { + afterEditable: RemoteCursorOverlay, + }, + cursorOptions: { + autoSend: true, + data: { name: 'A plate user', color: '#5AC990' }, + }, + disableCursors: false, hocuspocusProviderOptions: { - url: "https://hocuspocus.test/hocuspocus", - name: "test", + url: 'https://hocuspocus.test/hocuspocus', + name: 'test', }, }, }), @@ -45,6 +55,23 @@ const editor = createPlateEditor({ }); ``` +### Editor Container + +The editor requires a container component above `PlateContent` to ensure correct cursor overlay positioning: + +```tsx +export const EditorContainer = ( + props: React.HTMLAttributes +) => { + const editor = useEditorRef(); + const containerRef = useEditorContainerRef(); + + return
; +}; +``` + +This component is available in [Editor](/docs/components/editor). + ## Backend Follow the backend instructions in [Hocuspocus docs](https://tiptap.dev/hocuspocus/getting-started). diff --git a/apps/www/content/docs/column.mdx b/apps/www/content/docs/column.mdx index 4a0305841f..310c0d55c2 100644 --- a/apps/www/content/docs/column.mdx +++ b/apps/www/content/docs/column.mdx @@ -1,6 +1,5 @@ --- title: Column -description: Add Columns to your document. docs: - route: /docs/components/column-element title: Column Element @@ -8,7 +7,7 @@ docs: title: Column Group Element --- - + @@ -77,9 +76,13 @@ Insert a columnGroup with two empty columns. The editor instance. + + - `layout`: Array of column widths or number of equal-width columns (default: 2) + - Other InsertNodesOptions to control insert behavior + -### insertEmptyColumn +### insertColumn Insert an empty column. You can set the width by options.width default is "33%" @@ -125,6 +128,19 @@ If you want to set the `layout` use setNodes. +### toggleColumnGroup + +Convert a block into a column group layout. The selected block becomes the content of the first column. + + + + The editor instance. + + + - `layout`: Array of column widths or number of equal-width columns (default: 2) + + + ## API Components ### useColumnState diff --git a/apps/www/content/docs/combobox.mdx b/apps/www/content/docs/combobox.mdx index d2048ff989..9d8001d03f 100644 --- a/apps/www/content/docs/combobox.mdx +++ b/apps/www/content/docs/combobox.mdx @@ -1,80 +1,219 @@ --- title: Combobox -description: Utilities for adding comboboxes to your editor. +docs: + - route: /docs/mention + title: Mention Plugin + - route: /docs/slash-command + title: Slash Command Plugin + - route: /docs/emoji + title: Emoji Plugin --- -The `TriggerComboboxPluginOptions` mixin configures your plugin to insert a combobox input element when the user types a specified trigger character. +The `TriggerComboboxPluginOptions` configures your plugin to insert a combobox input element when the user types a specified trigger character. -For example, the [Mention](/docs/mention) plugin uses TriggerComboboxPluginOptions to insert an `MentionInputPlugin.key` whenever the user types `@`. +For example: +- [Mention](/docs/mention) plugin inserts a combobox when typing `@` +- [Slash Command](/docs/slash-command) plugin activates with `/` +- [Emoji](/docs/emoji) plugin shows suggestions with `:` -### Usage +## Usage -Extend the editor using `withTriggerCombobox` and specify default values for the required options. (See below for the full list of options). +Create an input plugin for the combobox: ```ts -import { withTriggerCombobox } from '@udecode/plate-combobox'; +const ComboboxInputPlugin = createPlatePlugin({ + key: 'combobox_input', + node: { + isElement: true, + isInline: true, + isVoid: true, + }, +}); +``` + + +Create your main plugin with `withTriggerCombobox`: + +```ts const MyPlugin = createPlatePlugin({ - // ... + key: 'my_plugin', extendEditor: withTriggerCombobox, + // Plugin node options + node: { + isElement: true, + isInline: true, + isVoid: true, + }, + // Combobox options options: { createComboboxInput: (trigger) => ({ children: [{ text: '' }], trigger, - type: 'input', + type: ComboboxInputPlugin.key, }), trigger: '@', triggerPreviousCharPattern: /^\s?$/, - } as TriggerComboboxPluginOptions, + }, + // Include the input plugin + plugins: [ComboboxInputPlugin], }); ``` - + -Define your input element as an inline void element. It's often useful to do this inside a nested plugin. - -```ts -const MyPlugin = createPlatePlugin({ - // ... - plugins: [ - createPlatePlugin({ - key: 'input', - node: { - isElement: true, - isInline: true, - isVoid: true, - }, - }), - ], -}); -``` - -The input element component can be built using [Inline Combobox](/docs/components/inline-combobox). +The input element component can be built using [Inline Combobox](/docs/components/inline-combobox). - -### Options - - - - - A function to create the input node. - - - - The character that triggers the combobox. - - - - Only trigger the combobox if the char before the trigger character matches a regular expression. For example, `/^\s?$/` matches beginning of the line or a space. - - - - A query function to enable the behavior. - +## Examples + + + + + +## Types + +### TriggerComboboxPluginOptions + + + + Function to create the input node when trigger is activated. + + + Character(s) that trigger the combobox. Can be: + - A single character (e.g. '@') + - An array of characters + - A regular expression + + + Pattern to match the character before trigger. + - **Example:** `/^\s?$/` matches start of line or space + + + Custom query function to control when trigger is active. + + + +## Hooks + +### useComboboxInput + +Hook for managing combobox input behavior and keyboard interactions. + + + + + + Reference to the input element. + + + Auto focus the input when mounted. + - **Default:** `true` + + + Cancel on arrow keys. + - **Default:** `true` + + + Cancel on backspace at start. + - **Default:** `true` + + + Cancel on blur. + - **Default:** `true` + + + Cancel when deselected. + - **Default:** `true` + + + Cancel on escape key. + - **Default:** `true` + + + Current cursor position state. + + + Forward undo/redo to editor. + - **Default:** `true` + + + Callback when input is cancelled. + + + + + + + + Function to cancel the input. + + + + + Blur event handler. + + + Keydown event handler. + + + + + Function to remove the input node. + + + +Example: + +```tsx +const MyCombobox = () => { + const inputRef = useRef(null); + const cursorState = useHTMLInputCursorState(inputRef); + + const { props: inputProps, removeInput } = useComboboxInput({ + ref: inputRef, + cursorState, + cancelInputOnBlur: false, + onCancelInput: (cause) => { + if (cause !== 'backspace') { + insertText(editor, trigger + value); + } + if (cause === 'arrowLeft' || cause === 'arrowRight') { + moveSelection(editor, { + distance: 1, + reverse: cause === 'arrowLeft', + }); + } + }, + }); + + return ; +}; +``` - \ No newline at end of file +### useHTMLInputCursorState + +Hook for tracking cursor position in an HTML input element. + + + + Reference to the input element to track. + + + + + + + + Whether cursor is at the start of input. + + + Whether cursor is at the end of input. + + + + \ No newline at end of file diff --git a/apps/www/content/docs/comments.mdx b/apps/www/content/docs/comments.mdx index 0796c4cf46..652b59fda2 100644 --- a/apps/www/content/docs/comments.mdx +++ b/apps/www/content/docs/comments.mdx @@ -1,6 +1,5 @@ --- title: Comments -description: Add comments to text as marks. docs: - route: /docs/components/comment-leaf title: Comment Leaf @@ -10,7 +9,7 @@ docs: title: Comments Popover --- - + @@ -79,7 +78,7 @@ The currently active comment. ## API -### editor.insert.comment +### editor.tf.insert.comment Insert a new comment mark. diff --git a/apps/www/content/docs/components/changelog.mdx b/apps/www/content/docs/components/changelog.mdx index 9724dd1e57..abfeefd01f 100644 --- a/apps/www/content/docs/components/changelog.mdx +++ b/apps/www/content/docs/components/changelog.mdx @@ -11,6 +11,93 @@ Use the [CLI](https://platejs.org/docs/components/cli) to install the latest ver ## November 2024 #16 +### November 26 #16.9 + +https://github.com/udecode/plate/pull/3809/files +- Add `select-editor`, `tag-element`, `label`, `form` +- Replace `cmdk` dependency with `@udecode/cmdk`. It's a controllable version of `cmdk`. +- `command`: add variants +- `editor`: add `select` variant +- `popover`: add `animate` variant + +https://github.com/udecode/plate/pull/3807/files +- `toc-element`: remove `