diff --git a/.changeset/core.md b/.changeset/core.md
new file mode 100644
index 0000000000..b87fb676c8
--- /dev/null
+++ b/.changeset/core.md
@@ -0,0 +1,5 @@
+---
+'@udecode/plate-core': patch
+---
+
+`useOptions`, `useOption` missing plugins now warn instead of erroring.
diff --git a/.changeset/dnd copy.md b/.changeset/dnd copy.md
new file mode 100644
index 0000000000..b57f6e6610
--- /dev/null
+++ b/.changeset/dnd copy.md
@@ -0,0 +1,9 @@
+---
+'@udecode/plate-dnd': minor
+---
+
+- New hooks:
+ - `useDraggableGutter`: Returns props for the draggable gutter.
+ - `useDropLine`: Returns the current drop line state and props.
+- Added `DraggableProvider` and `useDraggableStore` for managing draggable state:
+ - `dropLine`: The direction of the drop line.
diff --git a/.changeset/dnd.md b/.changeset/dnd.md
new file mode 100644
index 0000000000..84362781c8
--- /dev/null
+++ b/.changeset/dnd.md
@@ -0,0 +1,10 @@
+---
+'@udecode/plate-dnd': major
+---
+
+The following changes were made to improve performance:
+
+- Refactored `useDraggable` hook to focus on core dragging functionality:
+ - Removed `dropLine`. Use `useDropLine().dropLine` instead.
+ - Removed `groupProps` from the returned object – `isHovered`, and `setIsHovered` from the returned state. Use CSS instead.
+ - Removed `droplineProps`, and `gutterLeftProps` from the returned object. Use `useDropLine().props`, `useDraggableGutter().props` instead.
diff --git a/.changeset/selection copy.md b/.changeset/selection copy.md
new file mode 100644
index 0000000000..f9ca8e64ca
--- /dev/null
+++ b/.changeset/selection copy.md
@@ -0,0 +1,7 @@
+---
+'@udecode/plate-selection': minor
+---
+
+- `BlockSelectableProvider`, `useBlockSelectableStore` to store `selectable` state.
+- Introduced `isSelectionAreaVisible` option in `BlockSelectionPlugin` config. Useful to hide some UI when `true`.
+- New `useBlockSelected` hook for checking if a block is selected.
diff --git a/.changeset/selection.md b/.changeset/selection.md
new file mode 100644
index 0000000000..1fd0aabc99
--- /dev/null
+++ b/.changeset/selection.md
@@ -0,0 +1,9 @@
+---
+'@udecode/plate-selection': major
+---
+
+The following changes were made to improve performance:
+
+- Removed `useHooksBlockSelection` in favor of `BlockSelectionAfterEditable`
+- Removed `slate-selected` class from `BlockSelectable`. You can do it on your components using `useBlockSelected()` instead, or by using our new `block-selection.tsx` component.
+- Introduced `useBlockSelectableStore` for managing selectable state.
diff --git a/.changeset/wild-planets-wink.md b/.changeset/wild-planets-wink.md
new file mode 100644
index 0000000000..481e838f48
--- /dev/null
+++ b/.changeset/wild-planets-wink.md
@@ -0,0 +1,5 @@
+---
+'@udecode/react-utils': patch
+---
+
+New component: MemoizedChildren
diff --git a/apps/www/content/docs/block-selection.mdx b/apps/www/content/docs/block-selection.mdx
index abb68b1177..13ff71097d 100644
--- a/apps/www/content/docs/block-selection.mdx
+++ b/apps/www/content/docs/block-selection.mdx
@@ -7,17 +7,19 @@ description: Select and manipulate entire text blocks.
+The Block Selection feature allows users to select and manipulate entire text blocks, as opposed to individual words or characters. This powerful functionality enhances the editing experience by providing efficient ways to manage large sections of content.
+
## Features
-- Select entire blocks, as opposed to individual words or characters.
-- To select an entire block, mouse down outside the text area and then move the cursor into the block. Once it is selected, you'll see a background color.
-- Keep moving down or up to select multiple blocks.
-- Once selected, the available actions are: copy, cut, and delete.
-- Keyboard shortcuts:
- - `Cmd+A` (Mac) / `Ctrl+A` (Windows/Linux):
- - First press: Selects the current block
- - Double press: Selects the whole document using block selection
- - Note: This behavior can be disabled by setting `handlers.onKeyDown = null` when creating the plugin
+- Select entire blocks with a single action
+- Multi-block selection
+- Copy, cut, and delete operations on selected blocks
+- Keyboard shortcuts for quick selection:
+ - `Cmd+A`:
+ - First press: select the current block
+ - Double press: select all blocks
+ - Arrow keys: select the block above or below
+- Customizable styling for selected blocks
@@ -40,7 +42,9 @@ const plugins = [
];
```
-## Set scrollable container
+## Configuration
+
+### Set scrollable container
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()`.
@@ -64,7 +68,7 @@ Example configuration:
This setup ensures that the block selection functionality is properly constrained within your designated scrollable area.
-## Set selectable element
+### Set selectable element
Add data-plate-selectable to the container or the element you want to start block selection.
@@ -89,36 +93,48 @@ Example:
/>
```
-### Styling
+## Styling
+### Selection area
-#### Selection area
-You can style the selection area by adding this class to the container(.slate-selection-area can be changed in the plugin options):
+Style the selection area using `.slate-selection-area` class. For example:
```js
'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10'
```
-#### Selected element
+### Selected element
-You can style the selected element by adding this class to the container
+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:
-```js
-'[&_.slate-selected]:!bg-primary/20 '
-```
+```tsx
+import React from 'react';
+import { useBlockSelected } from '@udecode/plate-selection/react';
-### Disable browser default scroll behavior
-If we select some text and then move(keep pressed) the cursor to the very bottom of the page, the page will start scrolling to the bottom.
+export function BlockSelection() {
+ const isBlockSelected = useBlockSelected();
-Sometimes this scroll is so fast and confilicts with `BlockSelectionPlugin` scroll behavior(After the selection area appears, move the mouse to the bottom of the scroll container).
+ return (
+
+ );
+}
+```
-I don't find any way to disable this scroll behavior of browser.(if you find the way to disable it, please tell me that will so appreciate it)
+This component should be rendered inside each block element for consistent selection feedback. Plate UI is doing it in `plate-element.tsx`.
-So the solution is add an empty `div` above the editer's right side(The right side is the easiest place to trigger this behavior.) and set `user-select: none` to it .
+### Disable browser default scroll behavior
-This will make configuration and maintenance cumbersome so we remove this div from plate.
+When selecting text and moving the cursor to the bottom of the page, the browser's default scroll behavior can conflict with the `BlockSelectionPlugin`. To mitigate this, you can add a non-selectable area to the right side of the editor:
-If you encounter this issue, you might consider disabling it in this way.
+```tsx
+
+```
+
+This helps prevent unexpected scrolling during selection operations.
## Plugins
@@ -266,6 +282,10 @@ A wrapper component that adds block selection functionality to its children.
## Hooks
+### useBlockSelected
+
+Returns true if context block is selected.
+
### useBlockSelectableState
diff --git a/apps/www/content/docs/components/changelog.mdx b/apps/www/content/docs/components/changelog.mdx
index 07b7405781..8005f25bcc 100644
--- a/apps/www/content/docs/components/changelog.mdx
+++ b/apps/www/content/docs/components/changelog.mdx
@@ -8,15 +8,37 @@ Since Plate UI is not a component library, a changelog is maintained here.
Use the [CLI](https://platejs.org/docs/components/cli) to install the latest version of the components.
-## October 2024 #15
-### October 1 2024 #15.1
+## October 2024 #15
+### October 1 #15.1
+
+- New `block-selection.tsx` component for visual selection feedback
+- New `plate-element.tsx` component for rendering the plate element with `BlockSelection`
+- Updated `paragraph-element.tsx` and all block elements to use `plate-element.tsx`
+- `draggable.tsx`:
+ - Refactored to use new hooks: `useDraggableGutter` and `useDropLine`
+ - Removed `classNames` prop in favor of a single `className`
+ - Added `DraggableProvider` wrapper
+ - Introduced `Gutter` and `DropLine` as separate components
+- `with-draggables.tsx`:
+ - Updated to use new className format for draggable props
- fix `mention-element`: prevent IME input interruption on MacOS
+Use `--highlight` color for the following components:
+
+- `comment-leaf.tsx`
+- `highlight-leaf.tsx`
+
+Use `--brand` color for the following components:
+
+- `block-selection.tsx`
+- `draggable.tsx`
+
+
## September 2024 #14
-### September 29 2024 #14.3
+### September 29 #14.3
- fix `heading-element`: if the heading is the first block, it should not have a top margin
diff --git a/apps/www/content/docs/dnd.mdx b/apps/www/content/docs/dnd.mdx
index 2d3da83e4b..f0e553cf30 100644
--- a/apps/www/content/docs/dnd.mdx
+++ b/apps/www/content/docs/dnd.mdx
@@ -149,6 +149,16 @@ Enhances a component with draggable behavior.
## API Components
+### DraggableProvider
+
+A new component that provides context for managing draggable state.
+
+
+
+ The child components to be wrapped with the draggable context.
+
+
+
### DndScroller
A wrapper component for the `Scroller` component that is conditionally rendered based on the dragging state.
@@ -290,10 +300,6 @@ A custom hook that enables dragging of a node from the editor using the `useDrag
A custom hook that provides the necessary properties and event handlers for making an element draggable.
-
- The direction of the drop line, indicating the position where the node can
- be dropped.
-
Indicates whether the node is currently being dragged.
@@ -307,36 +313,11 @@ A custom hook that provides the necessary properties and event handlers for maki
- A reference to the HTML `div` element that serves as the preview during
- drag.
+ A reference to the HTML `div` element that serves as the preview during drag.
A reference to the drag source connector provided by `react-dnd`.
-
- Additional props to be applied to the dropline element.
-
-
- Indicates whether the dropline element should be editable.
-
-
-
-
- Additional props to be applied to the left gutter element.
-
-
- Indicates whether the dropline element should be editable.
-
-
-
### useDropBlock
@@ -347,7 +328,9 @@ A custom hook that enables dropping a block into the editor. It internally uses
The editor instance.
-
+
+ Options for the drop behavior.
+
### useDropNode
@@ -384,4 +367,37 @@ A custom hook that enables dropping a node on the editor. It uses the `useDrop`
-
\ No newline at end of file
+
+
+### useDraggableGutter
+
+Returns props for the draggable gutter.
+
+
+
+ Props to be spread on the gutter element.
+
+
+
+### useDropLine
+
+Returns the current drop line state and props.
+
+
+
+ The current direction of the drop line.
+
+
+ Props to be spread on the drop line element.
+
+
+
+### useDraggableStore
+
+Draggable store.
+
+
+
+ The current direction of the drop line.
+
+
diff --git a/apps/www/public/r/index.json b/apps/www/public/r/index.json
index 05a1d3220d..1127fcbb96 100644
--- a/apps/www/public/r/index.json
+++ b/apps/www/public/r/index.json
@@ -11,6 +11,34 @@
"registryDependencies": [],
"type": "registry:ui"
},
+ {
+ "dependencies": [
+ "@udecode/plate-selection"
+ ],
+ "files": [
+ {
+ "path": "plate-ui/block-selection.tsx",
+ "type": "registry:ui"
+ }
+ ],
+ "name": "block-selection",
+ "registryDependencies": [],
+ "type": "registry:ui"
+ },
+ {
+ "dependencies": [],
+ "files": [
+ {
+ "path": "plate-ui/plate-element.tsx",
+ "type": "registry:ui"
+ }
+ ],
+ "name": "plate-element",
+ "registryDependencies": [
+ "block-selection"
+ ],
+ "type": "registry:ui"
+ },
{
"dependencies": [
"@udecode/plate-cloud"
@@ -65,7 +93,8 @@
],
"name": "code-block-element",
"registryDependencies": [
- "command"
+ "command",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -86,7 +115,8 @@
"name": "column-element",
"registryDependencies": [
"command",
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -176,6 +206,7 @@
{
"dependencies": [
"@udecode/plate-dnd",
+ "@udecode/plate-selection",
"react-dnd",
"react-dnd-html5-backend"
],
@@ -255,7 +286,9 @@
],
"name": "emoji-input-element",
"registryDependencies": [
- "inline-combobox"
+ "inline-combobox",
+ "plate-element",
+ "use-debounce"
],
"type": "registry:ui"
},
@@ -301,7 +334,9 @@
}
],
"name": "blockquote-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -316,7 +351,8 @@
],
"name": "date-element",
"registryDependencies": [
- "calendar"
+ "calendar",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -404,7 +440,9 @@
}
],
"name": "code-line-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -514,7 +552,9 @@
}
],
"name": "excalidraw-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -596,7 +636,9 @@
}
],
"name": "heading-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -624,7 +666,9 @@
}
],
"name": "hr-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -641,7 +685,8 @@
"registryDependencies": [
"media-popover",
"caption",
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -764,7 +809,9 @@
}
],
"name": "link-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -813,7 +860,9 @@
}
],
"name": "list-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -864,7 +913,8 @@
"registryDependencies": [
"media-popover",
"caption",
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -914,7 +964,10 @@
}
],
"name": "mention-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element",
+ "use-mounted"
+ ],
"type": "registry:ui"
},
{
@@ -929,7 +982,8 @@
],
"name": "mention-input-element",
"registryDependencies": [
- "inline-combobox"
+ "inline-combobox",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -989,7 +1043,9 @@
}
],
"name": "paragraph-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -1063,7 +1119,8 @@
],
"name": "slash-input-element",
"registryDependencies": [
- "inline-combobox"
+ "inline-combobox",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -1079,7 +1136,8 @@
],
"name": "table-cell-element",
"registryDependencies": [
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -1112,7 +1170,8 @@
],
"name": "table-element",
"registryDependencies": [
- "dropdown-menu"
+ "dropdown-menu",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -1127,7 +1186,9 @@
}
],
"name": "table-row-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
@@ -1142,7 +1203,8 @@
],
"name": "todo-list-element",
"registryDependencies": [
- "checkbox"
+ "checkbox",
+ "plate-element"
],
"type": "registry:ui"
},
@@ -1157,7 +1219,9 @@
}
],
"name": "toggle-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
},
{
diff --git a/apps/www/public/r/styles/default/block-selection.json b/apps/www/public/r/styles/default/block-selection.json
new file mode 100644
index 0000000000..b0f71815c7
--- /dev/null
+++ b/apps/www/public/r/styles/default/block-selection.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": [
+ "@udecode/plate-selection"
+ ],
+ "files": [
+ {
+ "content": "import { useBlockSelected } from '@udecode/plate-selection/react';\nimport { type VariantProps, cva } from 'class-variance-authority';\n\nconst blockSelectionVariants = cva(\n 'pointer-events-none absolute inset-0 z-[1] bg-brand/[.13] transition-opacity',\n {\n defaultVariants: {\n active: false,\n },\n variants: {\n active: {\n false: 'opacity-0',\n true: 'opacity-100',\n },\n },\n }\n);\n\nexport function BlockSelection({\n className,\n ...props\n}: React.HTMLAttributes &\n VariantProps) {\n const isBlockSelected = useBlockSelected();\n\n if (!isBlockSelected) return null;\n\n return (\n
\n );\n}\n",
+ "path": "plate-ui/block-selection.tsx",
+ "target": "",
+ "type": "registry:ui"
+ }
+ ],
+ "name": "block-selection",
+ "registryDependencies": [],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/blockquote-element.json b/apps/www/public/r/styles/default/blockquote-element.json
index 5b55d29b44..6577256e16 100644
--- a/apps/www/public/r/styles/default/blockquote-element.json
+++ b/apps/www/public/r/styles/default/blockquote-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "'use client';\n\nimport React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\n\nexport const BlockquoteElement = withRef(\n ({ children, className, ...props }, ref) => {\n return (\n \n {children} \n \n );\n }\n);\n",
+ "content": "'use client';\n\nimport React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\n\nimport { PlateElement } from './plate-element';\n\nexport const BlockquoteElement = withRef(\n ({ children, className, ...props }, ref) => {\n return (\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/blockquote-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "blockquote-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/code-block-element.json b/apps/www/public/r/styles/default/code-block-element.json
index 8690146cfd..259938b53b 100644
--- a/apps/www/public/r/styles/default/code-block-element.json
+++ b/apps/www/public/r/styles/default/code-block-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "'use client';\n\nimport React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { useCodeBlockElementState } from '@udecode/plate-code-block/react';\nimport { PlateElement } from '@udecode/plate-common/react';\n\nimport { CodeBlockCombobox } from './code-block-combobox';\n\nimport './code-block-element.css';\n\nexport const CodeBlockElement = withRef(\n ({ children, className, ...props }, ref) => {\n const { element } = props;\n const state = useCodeBlockElementState({ element });\n\n return (\n \n \n {children}
\n \n\n {state.syntax && (\n \n \n
\n )}\n \n );\n }\n);\n",
+ "content": "'use client';\n\nimport React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { useCodeBlockElementState } from '@udecode/plate-code-block/react';\n\nimport { CodeBlockCombobox } from './code-block-combobox';\nimport { PlateElement } from './plate-element';\n\nimport './code-block-element.css';\n\nexport const CodeBlockElement = withRef(\n ({ children, className, ...props }, ref) => {\n const { element } = props;\n const state = useCodeBlockElementState({ element });\n\n return (\n \n \n {children}
\n \n\n {state.syntax && (\n \n \n
\n )}\n \n );\n }\n);\n",
"path": "plate-ui/code-block-element.tsx",
"target": "",
"type": "registry:ui"
@@ -24,7 +24,8 @@
],
"name": "code-block-element",
"registryDependencies": [
- "command"
+ "command",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/code-line-element.json b/apps/www/public/r/styles/default/code-line-element.json
index eed0120cb4..1d5b20b5b5 100644
--- a/apps/www/public/r/styles/default/code-line-element.json
+++ b/apps/www/public/r/styles/default/code-line-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "'use client';\n\nimport React from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\n\nexport const CodeLineElement = withRef((props, ref) => (\n \n));\n",
+ "content": "'use client';\n\nimport React from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { PlateElement } from './plate-element';\n\nexport const CodeLineElement = withRef((props, ref) => (\n \n));\n",
"path": "plate-ui/code-line-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "code-line-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/column-element.json b/apps/www/public/r/styles/default/column-element.json
index 30c842633f..7cd90b1b7b 100644
--- a/apps/www/public/r/styles/default/column-element.json
+++ b/apps/www/public/r/styles/default/column-element.json
@@ -4,13 +4,13 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport type { TColumnElement } from '@udecode/plate-layout';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement, useElement, withHOC } from '@udecode/plate-common/react';\nimport { ResizableProvider } from '@udecode/plate-resizable';\nimport { useReadOnly } from 'slate-react';\n\nexport const ColumnElement = withHOC(\n ResizableProvider,\n withRef(({ children, className, ...props }, ref) => {\n const readOnly = useReadOnly();\n const { width } = useElement();\n\n return (\n \n {children}\n \n );\n })\n);\n",
+ "content": "import React from 'react';\n\nimport type { TColumnElement } from '@udecode/plate-layout';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { useElement, withHOC } from '@udecode/plate-common/react';\nimport { ResizableProvider } from '@udecode/plate-resizable';\nimport { useReadOnly } from 'slate-react';\n\nimport { PlateElement } from './plate-element';\n\nexport const ColumnElement = withHOC(\n ResizableProvider,\n withRef(({ children, className, ...props }, ref) => {\n const readOnly = useReadOnly();\n const { width } = useElement();\n\n return (\n \n {children}\n \n );\n })\n);\n",
"path": "plate-ui/column-element.tsx",
"target": "",
"type": "registry:ui"
},
{
- "content": "import React from 'react';\n\nimport type { TColumnElement } from '@udecode/plate-layout';\n\nimport { cn, withRef } from '@udecode/cn';\nimport {\n PlateElement,\n useElement,\n useRemoveNodeButton,\n} from '@udecode/plate-common/react';\nimport {\n ColumnItemPlugin,\n useColumnState,\n useDebouncePopoverOpen,\n} from '@udecode/plate-layout/react';\nimport { useReadOnly } from 'slate-react';\n\nimport { Icons } from '@/components/icons';\n\nimport { Button } from './button';\nimport { Popover, PopoverAnchor, PopoverContent } from './popover';\nimport { Separator } from './separator';\n\nexport const ColumnGroupElement = withRef(\n ({ children, className, ...props }, ref) => {\n return (\n \n \n {children}
\n \n \n );\n }\n);\n\nexport function ColumnFloatingToolbar({ children }: React.PropsWithChildren) {\n const readOnly = useReadOnly();\n\n const {\n setDoubleColumn,\n setDoubleSideDoubleColumn,\n setLeftSideDoubleColumn,\n setRightSideDoubleColumn,\n setThreeColumn,\n } = useColumnState();\n\n const element = useElement(ColumnItemPlugin.key);\n\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n const isOpen = useDebouncePopoverOpen();\n\n if (readOnly) return <>{children}>;\n\n return (\n \n {children} \n e.preventDefault()}\n align=\"center\"\n side=\"top\"\n sideOffset={10}\n >\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n \n \n );\n}\n",
+ "content": "import React from 'react';\n\nimport type { TColumnElement } from '@udecode/plate-layout';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { useElement, useRemoveNodeButton } from '@udecode/plate-common/react';\nimport {\n ColumnItemPlugin,\n useColumnState,\n useDebouncePopoverOpen,\n} from '@udecode/plate-layout/react';\nimport { useReadOnly } from 'slate-react';\n\nimport { Icons } from '@/components/icons';\n\nimport { Button } from './button';\nimport { PlateElement } from './plate-element';\nimport { Popover, PopoverAnchor, PopoverContent } from './popover';\nimport { Separator } from './separator';\n\nexport const ColumnGroupElement = withRef(\n ({ children, className, ...props }, ref) => {\n return (\n \n \n {children}
\n \n \n );\n }\n);\n\nexport function ColumnFloatingToolbar({ children }: React.PropsWithChildren) {\n const readOnly = useReadOnly();\n\n const {\n setDoubleColumn,\n setDoubleSideDoubleColumn,\n setLeftSideDoubleColumn,\n setRightSideDoubleColumn,\n setThreeColumn,\n } = useColumnState();\n\n const element = useElement(ColumnItemPlugin.key);\n\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n const isOpen = useDebouncePopoverOpen();\n\n if (readOnly) return <>{children}>;\n\n return (\n \n {children} \n e.preventDefault()}\n align=\"center\"\n side=\"top\"\n sideOffset={10}\n >\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n \n \n );\n}\n",
"path": "plate-ui/column-group-element.tsx",
"target": "",
"type": "registry:ui"
@@ -19,7 +19,8 @@
"name": "column-element",
"registryDependencies": [
"command",
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/comment-leaf.json b/apps/www/public/r/styles/default/comment-leaf.json
index 744474f69c..7ce05e7376 100644
--- a/apps/www/public/r/styles/default/comment-leaf.json
+++ b/apps/www/public/r/styles/default/comment-leaf.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "'use client';\n\nimport React from 'react';\n\nimport type { TCommentText } from '@udecode/plate-comments';\n\nimport { cn } from '@udecode/cn';\nimport {\n useCommentLeaf,\n useCommentLeafState,\n} from '@udecode/plate-comments/react';\nimport { type PlateLeafProps, PlateLeaf } from '@udecode/plate-common/react';\n\nexport function CommentLeaf({\n className,\n ...props\n}: PlateLeafProps) {\n const { children, leaf, nodeProps } = props;\n\n const state = useCommentLeafState({ leaf });\n const { props: rootProps } = useCommentLeaf(state);\n\n if (!state.commentCount) return <>{children}>;\n\n let aboveChildren = <>{children}>;\n\n if (!state.isActive) {\n for (let i = 1; i < state.commentCount; i++) {\n aboveChildren = {aboveChildren} ;\n }\n }\n\n return (\n \n {aboveChildren}\n \n );\n}\n",
+ "content": "'use client';\n\nimport React from 'react';\n\nimport type { TCommentText } from '@udecode/plate-comments';\n\nimport { cn } from '@udecode/cn';\nimport {\n useCommentLeaf,\n useCommentLeafState,\n} from '@udecode/plate-comments/react';\nimport { type PlateLeafProps, PlateLeaf } from '@udecode/plate-common/react';\n\nexport function CommentLeaf({\n className,\n ...props\n}: PlateLeafProps) {\n const { children, leaf, nodeProps } = props;\n\n const state = useCommentLeafState({ leaf });\n const { props: rootProps } = useCommentLeaf(state);\n\n if (!state.commentCount) return <>{children}>;\n\n let aboveChildren = <>{children}>;\n\n if (!state.isActive) {\n for (let i = 1; i < state.commentCount; i++) {\n aboveChildren = {aboveChildren} ;\n }\n }\n\n return (\n \n {aboveChildren}\n \n );\n}\n",
"path": "plate-ui/comment-leaf.tsx",
"target": "",
"type": "registry:ui"
diff --git a/apps/www/public/r/styles/default/date-element.json b/apps/www/public/r/styles/default/date-element.json
index c032708515..f41f1aa0cf 100644
--- a/apps/www/public/r/styles/default/date-element.json
+++ b/apps/www/public/r/styles/default/date-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "'use client';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { setNodes } from '@udecode/plate-common';\nimport { PlateElement, findNodePath } from '@udecode/plate-common/react';\n\nimport { Calendar } from './calendar';\nimport { Popover, PopoverContent, PopoverTrigger } from './popover';\n\nexport const DateElement = withRef(\n ({ children, className, ...props }, ref) => {\n const { editor, element } = props;\n\n return (\n \n \n \n \n {element.date ? (\n (() => {\n const today = new Date();\n const elementDate = new Date(element.date as string);\n const isToday =\n elementDate.getDate() === today.getDate() &&\n elementDate.getMonth() === today.getMonth() &&\n elementDate.getFullYear() === today.getFullYear();\n\n const isYesterday =\n new Date(\n today.setDate(today.getDate() - 1)\n ).toDateString() === elementDate.toDateString();\n const isTomorrow =\n new Date(\n today.setDate(today.getDate() + 2)\n ).toDateString() === elementDate.toDateString();\n\n if (isToday) return 'Today';\n if (isYesterday) return 'Yesterday';\n if (isTomorrow) return 'Tomorrow';\n\n return elementDate.toLocaleDateString(undefined, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n });\n })()\n ) : (\n Pick a date \n )}\n \n \n \n {\n if (!date) return;\n\n setNodes(\n editor,\n { date: date.toDateString() },\n { at: findNodePath(editor, element) }\n );\n }}\n mode=\"single\"\n initialFocus\n />\n \n \n {children}\n \n );\n }\n);\n",
+ "content": "'use client';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { setNodes } from '@udecode/plate-common';\nimport { findNodePath } from '@udecode/plate-common/react';\n\nimport { Calendar } from './calendar';\nimport { PlateElement } from './plate-element';\nimport { Popover, PopoverContent, PopoverTrigger } from './popover';\n\nexport const DateElement = withRef(\n ({ children, className, ...props }, ref) => {\n const { editor, element } = props;\n\n return (\n \n \n \n \n {element.date ? (\n (() => {\n const today = new Date();\n const elementDate = new Date(element.date as string);\n const isToday =\n elementDate.getDate() === today.getDate() &&\n elementDate.getMonth() === today.getMonth() &&\n elementDate.getFullYear() === today.getFullYear();\n\n const isYesterday =\n new Date(\n today.setDate(today.getDate() - 1)\n ).toDateString() === elementDate.toDateString();\n const isTomorrow =\n new Date(\n today.setDate(today.getDate() + 2)\n ).toDateString() === elementDate.toDateString();\n\n if (isToday) return 'Today';\n if (isYesterday) return 'Yesterday';\n if (isTomorrow) return 'Tomorrow';\n\n return elementDate.toLocaleDateString(undefined, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n });\n })()\n ) : (\n Pick a date \n )}\n \n \n \n {\n if (!date) return;\n\n setNodes(\n editor,\n { date: date.toDateString() },\n { at: findNodePath(editor, element) }\n );\n }}\n mode=\"single\"\n initialFocus\n />\n \n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/date-element.tsx",
"target": "",
"type": "registry:ui"
@@ -12,7 +12,8 @@
],
"name": "date-element",
"registryDependencies": [
- "calendar"
+ "calendar",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/draggable.json b/apps/www/public/r/styles/default/draggable.json
index 823fd6f73e..6422636d15 100644
--- a/apps/www/public/r/styles/default/draggable.json
+++ b/apps/www/public/r/styles/default/draggable.json
@@ -1,18 +1,19 @@
{
"dependencies": [
"@udecode/plate-dnd",
+ "@udecode/plate-selection",
"react-dnd",
"react-dnd-html5-backend"
],
"files": [
{
- "content": "'use client';\n\nimport React from 'react';\n\nimport type { ClassNames, TEditor } from '@udecode/plate-common';\nimport type { DropTargetMonitor } from 'react-dnd';\n\nimport { cn, withRef } from '@udecode/cn';\nimport {\n type PlateElementProps,\n useEditorRef,\n} from '@udecode/plate-common/react';\nimport {\n type DragItemNode,\n useDraggable,\n useDraggableState,\n} from '@udecode/plate-dnd';\nimport { BlockSelectionPlugin } from '@udecode/plate-selection/react';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n Tooltip,\n TooltipContent,\n TooltipPortal,\n TooltipProvider,\n TooltipTrigger,\n} from './tooltip';\n\nexport interface DraggableProps\n extends PlateElementProps,\n ClassNames<{\n /** Block. */\n block: string;\n\n /** Block and gutter. */\n blockAndGutter: string;\n\n /** Block toolbar in the gutter. */\n blockToolbar: string;\n\n /**\n * Block toolbar wrapper in the gutter left. It has the height of a line\n * of the block.\n */\n blockToolbarWrapper: string;\n\n blockWrapper: string;\n\n /** Button to dnd the block, in the block toolbar. */\n dragHandle: string;\n\n /** Icon of the drag button, in the drag icon. */\n dragIcon: string;\n\n /** Show a dropline above or below the block when dragging a block. */\n dropLine: string;\n\n /** Gutter at the left side of the editor. It has the height of the block */\n gutterLeft: string;\n }> {\n /**\n * Intercepts the drop handling. If `false` is returned, the default drop\n * behavior is called after. If `true` is returned, the default behavior is\n * not called.\n */\n onDropHandler?: (\n editor: TEditor,\n props: {\n id: string;\n dragItem: DragItemNode;\n monitor: DropTargetMonitor;\n nodeRef: any;\n }\n ) => boolean;\n}\n\nconst DragHandle = () => {\n const editor = useEditorRef();\n\n return (\n \n \n \n {\n event.stopPropagation();\n event.preventDefault();\n\n // if (element.id) {\n // editor.getApi(BlockSelectionPlugin).blockSelection.addSelectedRow(element.id as string);\n // api.blockContextMenu.show(editor.id, event as any);\n // }\n }}\n onMouseDown={() => {\n editor\n .getApi(BlockSelectionPlugin)\n .blockSelection.resetSelectedIds();\n }}\n />\n \n \n Drag to move \n \n \n \n );\n};\n\nexport const Draggable = withRef<'div', DraggableProps>(\n ({ className, classNames = {}, onDropHandler, ...props }, ref) => {\n const { children, element } = props;\n\n const state = useDraggableState({ element, onDropHandler });\n const { dropLine, isDragging, isHovered } = state;\n const {\n droplineProps,\n groupProps,\n gutterLeftProps,\n previewRef,\n handleRef,\n } = useDraggable(state);\n\n return (\n \n
\n
\n
\n
\n {isHovered && }\n
\n
\n
\n
\n\n
\n {children}\n\n {!!dropLine && (\n
\n )}\n
\n
\n );\n }\n);\n",
+ "content": "'use client';\n\nimport React from 'react';\n\nimport type { TEditor } from '@udecode/plate-common';\nimport type { DropTargetMonitor } from 'react-dnd';\n\nimport { cn, withRef } from '@udecode/cn';\nimport {\n type PlateElementProps,\n MemoizedChildren,\n useEditorPlugin,\n useEditorRef,\n withHOC,\n} from '@udecode/plate-common/react';\nimport {\n type DragItemNode,\n DraggableProvider,\n useDraggable,\n useDraggableGutter,\n useDraggableState,\n useDropLine,\n} from '@udecode/plate-dnd';\nimport { BlockSelectionPlugin } from '@udecode/plate-selection/react';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n Tooltip,\n TooltipContent,\n TooltipPortal,\n TooltipProvider,\n TooltipTrigger,\n} from './tooltip';\n\nexport interface DraggableProps extends PlateElementProps {\n /**\n * Intercepts the drop handling. If `false` is returned, the default drop\n * behavior is called after. If `true` is returned, the default behavior is\n * not called.\n */\n onDropHandler?: (\n editor: TEditor,\n props: {\n id: string;\n dragItem: DragItemNode;\n monitor: DropTargetMonitor;\n nodeRef: any;\n }\n ) => boolean;\n}\n\nexport const Draggable = withHOC(\n DraggableProvider,\n withRef<'div', DraggableProps>(\n ({ className, onDropHandler, ...props }, ref) => {\n const { children, element } = props;\n\n const state = useDraggableState({ element, onDropHandler });\n const { isDragging } = state;\n const { previewRef, handleRef } = useDraggable(state);\n\n return (\n \n
\n \n \n\n
\n {children} \n\n \n
\n
\n );\n }\n )\n);\n\nconst Gutter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes\n>(({ children, className, ...props }, ref) => {\n const { useOption } = useEditorPlugin(BlockSelectionPlugin);\n const isSelectionAreaVisible = useOption('isSelectionAreaVisible');\n const gutter = useDraggableGutter();\n\n return (\n \n {children}\n
\n );\n});\n\nconst DragHandle = React.memo(() => {\n const editor = useEditorRef();\n\n return (\n \n \n \n {\n event.stopPropagation();\n event.preventDefault();\n }}\n onMouseDown={() => {\n editor\n .getApi(BlockSelectionPlugin)\n .blockSelection?.resetSelectedIds();\n }}\n />\n \n \n Drag to move \n \n \n \n );\n});\n\nconst DropLine = React.memo(\n React.forwardRef>(\n ({ children, className, ...props }, ref) => {\n const state = useDropLine();\n\n if (!state.dropLine) return null;\n\n return (\n \n {children}\n
\n );\n }\n )\n);\n",
"path": "plate-ui/draggable.tsx",
"target": "",
"type": "registry:ui"
},
{
- "content": "import type { FC } from 'react';\n\nimport { BlockquotePlugin } from '@udecode/plate-block-quote/react';\nimport { CodeBlockPlugin } from '@udecode/plate-code-block/react';\nimport {\n ParagraphPlugin,\n createNodesWithHOC,\n} from '@udecode/plate-common/react';\nimport {\n type WithDraggableOptions,\n withDraggable as withDraggablePrimitive,\n} from '@udecode/plate-dnd';\nimport { ExcalidrawPlugin } from '@udecode/plate-excalidraw/react';\nimport { HEADING_KEYS } from '@udecode/plate-heading';\nimport { ColumnPlugin } from '@udecode/plate-layout/react';\nimport {\n BulletedListPlugin,\n NumberedListPlugin,\n} from '@udecode/plate-list/react';\nimport {\n ImagePlugin,\n MediaEmbedPlugin,\n PlaceholderPlugin,\n} from '@udecode/plate-media/react';\nimport { TablePlugin } from '@udecode/plate-table/react';\nimport { TogglePlugin } from '@udecode/plate-toggle/react';\n\nimport { type DraggableProps, Draggable } from './draggable';\n\nexport const withDraggable = (\n Component: FC,\n options?: WithDraggableOptions<\n Partial>\n >\n) =>\n withDraggablePrimitive(Draggable, Component, options as any);\n\nexport const withDraggablesPrimitive = createNodesWithHOC(withDraggable);\n\nexport const withDraggables = (components: any) => {\n return withDraggablesPrimitive(components, [\n {\n keys: [\n ParagraphPlugin.key,\n BulletedListPlugin.key,\n NumberedListPlugin.key,\n ],\n level: 0,\n },\n {\n key: HEADING_KEYS.h1,\n draggableProps: {\n classNames: {\n blockToolbarWrapper: 'h-[1.3em]',\n gutterLeft: 'px-0 pb-1 text-[1.875em]',\n },\n },\n },\n {\n key: HEADING_KEYS.h2,\n draggableProps: {\n classNames: {\n blockToolbarWrapper: 'h-[1.3em]',\n gutterLeft: 'px-0 pb-1 text-[1.5em]',\n },\n },\n },\n {\n key: HEADING_KEYS.h3,\n draggableProps: {\n classNames: {\n blockToolbarWrapper: 'h-[1.3em]',\n gutterLeft: 'pt-[2px] px-0 pb-1 text-[1.25em]',\n },\n },\n },\n {\n keys: [HEADING_KEYS.h4, HEADING_KEYS.h5],\n draggableProps: {\n classNames: {\n blockToolbarWrapper: 'h-[1.3em]',\n gutterLeft: 'pt-[3px] px-0 pb-0 text-[1.1em]',\n },\n },\n },\n {\n keys: [ParagraphPlugin.key],\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-[3px] px-0 pb-0',\n },\n },\n },\n {\n keys: [HEADING_KEYS.h6, BulletedListPlugin.key, NumberedListPlugin.key],\n draggableProps: {\n classNames: {\n gutterLeft: 'px-0 pb-0',\n },\n },\n },\n {\n key: BlockquotePlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'px-0 pb-0',\n },\n },\n },\n {\n key: CodeBlockPlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-6 px-0 pb-0',\n },\n },\n },\n {\n key: ImagePlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-0 px-0 pb-0',\n },\n },\n },\n {\n key: MediaEmbedPlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-0 px-0 pb-0',\n },\n },\n },\n {\n key: ExcalidrawPlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-0 px-0 pb-0',\n },\n },\n },\n {\n key: TogglePlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-0 px-0 pb-0',\n },\n },\n },\n {\n key: ColumnPlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-0 px-0 pb-0',\n },\n },\n },\n {\n key: PlaceholderPlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-3 px-0 pb-0',\n },\n },\n },\n {\n key: TablePlugin.key,\n draggableProps: {\n classNames: {\n gutterLeft: 'pt-3 px-0 pb-0',\n },\n },\n },\n ]);\n};\n",
+ "content": "import type { FC } from 'react';\n\nimport { BlockquotePlugin } from '@udecode/plate-block-quote/react';\nimport { CodeBlockPlugin } from '@udecode/plate-code-block/react';\nimport {\n ParagraphPlugin,\n createNodesWithHOC,\n} from '@udecode/plate-common/react';\nimport {\n type WithDraggableOptions,\n withDraggable as withDraggablePrimitive,\n} from '@udecode/plate-dnd';\nimport { ExcalidrawPlugin } from '@udecode/plate-excalidraw/react';\nimport { HEADING_KEYS } from '@udecode/plate-heading';\nimport { ColumnPlugin } from '@udecode/plate-layout/react';\nimport {\n BulletedListPlugin,\n NumberedListPlugin,\n} from '@udecode/plate-list/react';\nimport {\n ImagePlugin,\n MediaEmbedPlugin,\n PlaceholderPlugin,\n} from '@udecode/plate-media/react';\nimport { TablePlugin } from '@udecode/plate-table/react';\nimport { TogglePlugin } from '@udecode/plate-toggle/react';\n\nimport { type DraggableProps, Draggable } from './draggable';\n\nexport const withDraggable = (\n Component: FC,\n options?: WithDraggableOptions<\n Partial>\n >\n) =>\n withDraggablePrimitive(Draggable, Component, options as any);\n\nexport const withDraggablesPrimitive = createNodesWithHOC(withDraggable);\n\nexport const withDraggables = (components: any) => {\n return withDraggablesPrimitive(components, [\n {\n keys: [\n ParagraphPlugin.key,\n BulletedListPlugin.key,\n NumberedListPlugin.key,\n ],\n level: 0,\n },\n {\n key: HEADING_KEYS.h1,\n draggableProps: {\n className:\n '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-1 [&_.slate-gutterLeft]:text-[1.875em]',\n },\n },\n {\n key: HEADING_KEYS.h2,\n draggableProps: {\n className:\n '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-1 [&_.slate-gutterLeft]:text-[1.5em]',\n },\n },\n {\n key: HEADING_KEYS.h3,\n draggableProps: {\n className:\n '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:pt-[2px] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-1 [&_.slate-gutterLeft]:text-[1.25em]',\n },\n },\n {\n keys: [HEADING_KEYS.h4, HEADING_KEYS.h5],\n draggableProps: {\n className:\n '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:pt-[3px] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0 [&_.slate-gutterLeft]:text-[1.1em]',\n },\n },\n {\n keys: [ParagraphPlugin.key],\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-[3px] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n keys: [HEADING_KEYS.h6, BulletedListPlugin.key, NumberedListPlugin.key],\n draggableProps: {\n className: '[&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: BlockquotePlugin.key,\n draggableProps: {\n className: '[&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: CodeBlockPlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-6 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: ImagePlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: MediaEmbedPlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: ExcalidrawPlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: TogglePlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: ColumnPlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: PlaceholderPlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-3 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n {\n key: TablePlugin.key,\n draggableProps: {\n className:\n '[&_.slate-gutterLeft]:pt-3 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',\n },\n },\n ]);\n};\n",
"path": "plate-ui/with-draggables.tsx",
"target": "",
"type": "registry:ui"
diff --git a/apps/www/public/r/styles/default/emoji-input-element.json b/apps/www/public/r/styles/default/emoji-input-element.json
index 4cd8ed33ec..5964810e4a 100644
--- a/apps/www/public/r/styles/default/emoji-input-element.json
+++ b/apps/www/public/r/styles/default/emoji-input-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React, { useMemo, useState } from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport { EmojiInlineIndexSearch, insertEmoji } from '@udecode/plate-emoji';\n\nimport { useDebounce } from '@/registry/default/hooks/use-debounce';\n\nimport {\n InlineCombobox,\n InlineComboboxContent,\n InlineComboboxEmpty,\n InlineComboboxInput,\n InlineComboboxItem,\n} from './inline-combobox';\n\nexport const EmojiInputElement = withRef(\n ({ className, ...props }, ref) => {\n const { children, editor, element } = props;\n const [value, setValue] = useState('');\n const debouncedValue = useDebounce(value, 100);\n const isPending = value !== debouncedValue;\n\n const filteredEmojis = useMemo(() => {\n if (debouncedValue.trim().length === 0) return [];\n\n return EmojiInlineIndexSearch.getInstance()\n .search(debouncedValue.replace(/:$/, ''))\n .get();\n }, [debouncedValue]);\n\n return (\n \n \n \n\n \n {!isPending && (\n No matching emoji found \n )}\n\n {filteredEmojis.map((emoji) => (\n insertEmoji(editor, emoji)}\n >\n {emoji.skins[0].native} {emoji.name}\n \n ))}\n \n \n\n {children}\n \n );\n }\n);\n",
+ "content": "import React, { useMemo, useState } from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { PlateElement } from './plate-element';\nimport { EmojiInlineIndexSearch, insertEmoji } from '@udecode/plate-emoji';\n\nimport { useDebounce } from '@/registry/default/hooks/use-debounce';\n\nimport {\n InlineCombobox,\n InlineComboboxContent,\n InlineComboboxEmpty,\n InlineComboboxInput,\n InlineComboboxItem,\n} from './inline-combobox';\n\nexport const EmojiInputElement = withRef(\n ({ className, ...props }, ref) => {\n const { children, editor, element } = props;\n const [value, setValue] = useState('');\n const debouncedValue = useDebounce(value, 100);\n const isPending = value !== debouncedValue;\n\n const filteredEmojis = useMemo(() => {\n if (debouncedValue.trim().length === 0) return [];\n\n return EmojiInlineIndexSearch.getInstance()\n .search(debouncedValue.replace(/:$/, ''))\n .get();\n }, [debouncedValue]);\n\n return (\n \n \n \n\n \n {!isPending && (\n No matching emoji found \n )}\n\n {filteredEmojis.map((emoji) => (\n insertEmoji(editor, emoji)}\n >\n {emoji.skins[0].native} {emoji.name}\n \n ))}\n \n \n\n {children}\n \n );\n }\n);\n",
"path": "plate-ui/emoji-input-element.tsx",
"target": "",
"type": "registry:ui"
@@ -12,7 +12,9 @@
],
"name": "emoji-input-element",
"registryDependencies": [
- "inline-combobox"
+ "inline-combobox",
+ "plate-element",
+ "use-debounce"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/excalidraw-element.json b/apps/www/public/r/styles/default/excalidraw-element.json
index 216544d224..7e0e94cf94 100644
--- a/apps/www/public/r/styles/default/excalidraw-element.json
+++ b/apps/www/public/r/styles/default/excalidraw-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport { useExcalidrawElement } from '@udecode/plate-excalidraw/react';\n\nexport const ExcalidrawElement = withRef(\n ({ nodeProps, ...props }, ref) => {\n const { children, element } = props;\n\n const { Excalidraw, excalidrawProps } = useExcalidrawElement({\n element,\n });\n\n return (\n \n \n
\n {Excalidraw && (\n \n )}\n
\n
\n {children}\n \n );\n }\n);\n",
+ "content": "import React from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { PlateElement } from './plate-element';\nimport { useExcalidrawElement } from '@udecode/plate-excalidraw/react';\n\nexport const ExcalidrawElement = withRef(\n ({ nodeProps, ...props }, ref) => {\n const { children, element } = props;\n\n const { Excalidraw, excalidrawProps } = useExcalidrawElement({\n element,\n });\n\n return (\n \n \n
\n {Excalidraw && (\n \n )}\n
\n
\n {children}\n \n );\n }\n);\n",
"path": "plate-ui/excalidraw-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "excalidraw-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/heading-element.json b/apps/www/public/r/styles/default/heading-element.json
index 8af1132a16..63cebfbfe0 100644
--- a/apps/www/public/r/styles/default/heading-element.json
+++ b/apps/www/public/r/styles/default/heading-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { withRef, withVariants } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport { cva } from 'class-variance-authority';\n\nconst headingVariants = cva('relative mb-1', {\n variants: {\n variant: {\n h1: 'mt-[1.6em] pb-1 font-heading text-4xl font-bold',\n h2: 'mt-[1.4em] pb-px font-heading text-2xl font-semibold tracking-tight',\n h3: 'mt-[1em] pb-px font-heading text-xl font-semibold tracking-tight',\n h4: 'mt-[0.75em] font-heading text-lg font-semibold tracking-tight',\n h5: 'mt-[0.75em] text-lg font-semibold tracking-tight',\n h6: 'mt-[0.75em] text-base font-semibold tracking-tight',\n },\n },\n});\n\nconst blockVariants = cva('', {\n variants: {\n isFirstBlock: {\n false: '',\n true: 'mt-0',\n },\n },\n});\n\nconst HeadingElementVariants = withVariants(\n withVariants(PlateElement, headingVariants, ['variant']),\n blockVariants,\n ['isFirstBlock']\n);\n\nexport const HeadingElement = withRef(\n ({ children, isFirstBlock, variant = 'h1', ...props }, ref) => {\n const { editor, element } = props;\n\n const Element = variant!;\n\n return (\n \n {children} \n \n );\n }\n);\n",
+ "content": "import React from 'react';\n\nimport { withRef, withVariants } from '@udecode/cn';\nimport { cva } from 'class-variance-authority';\n\nimport { PlateElement } from './plate-element';\n\nconst headingVariants = cva('relative mb-1', {\n variants: {\n variant: {\n h1: 'mt-[1.6em] pb-1 font-heading text-4xl font-bold',\n h2: 'mt-[1.4em] pb-px font-heading text-2xl font-semibold tracking-tight',\n h3: 'mt-[1em] pb-px font-heading text-xl font-semibold tracking-tight',\n h4: 'mt-[0.75em] font-heading text-lg font-semibold tracking-tight',\n h5: 'mt-[0.75em] text-lg font-semibold tracking-tight',\n h6: 'mt-[0.75em] text-base font-semibold tracking-tight',\n },\n },\n});\n\nconst blockVariants = cva('', {\n variants: {\n isFirstBlock: {\n false: '',\n true: 'mt-0',\n },\n },\n});\n\nconst HeadingElementVariants = withVariants(\n withVariants(PlateElement, headingVariants, ['variant']),\n blockVariants,\n ['isFirstBlock']\n);\n\nexport const HeadingElement = withRef(\n ({ children, isFirstBlock, variant = 'h1', ...props }, ref) => {\n const { editor, element } = props;\n\n return (\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/heading-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "heading-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/highlight-leaf.json b/apps/www/public/r/styles/default/highlight-leaf.json
index 69e88f4af4..b00103bc32 100644
--- a/apps/www/public/r/styles/default/highlight-leaf.json
+++ b/apps/www/public/r/styles/default/highlight-leaf.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateLeaf } from '@udecode/plate-common/react';\n\nexport const HighlightLeaf = withRef(\n ({ children, className, ...props }, ref) => (\n \n {children} \n \n )\n);\n",
+ "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateLeaf } from '@udecode/plate-common/react';\n\nexport const HighlightLeaf = withRef(\n ({ children, className, ...props }, ref) => (\n \n {children} \n \n )\n);\n",
"path": "plate-ui/highlight-leaf.tsx",
"target": "",
"type": "registry:ui"
diff --git a/apps/www/public/r/styles/default/hr-element.json b/apps/www/public/r/styles/default/hr-element.json
index 2f40010324..9c8a34ebf8 100644
--- a/apps/www/public/r/styles/default/hr-element.json
+++ b/apps/www/public/r/styles/default/hr-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport { useFocused, useSelected } from 'slate-react';\n\nexport const HrElement = withRef(\n ({ className, nodeProps, ...props }, ref) => {\n const { children } = props;\n\n const selected = useSelected();\n const focused = useFocused();\n\n return (\n \n \n
\n \n {children}\n \n );\n }\n);\n",
+ "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from './plate-element';\nimport { useFocused, useSelected } from 'slate-react';\n\nexport const HrElement = withRef(\n ({ className, nodeProps, ...props }, ref) => {\n const { children } = props;\n\n const selected = useSelected();\n const focused = useFocused();\n\n return (\n \n \n
\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/hr-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "hr-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/image-element.json b/apps/www/public/r/styles/default/image-element.json
index 305022c002..251cc06fa7 100644
--- a/apps/www/public/r/styles/default/image-element.json
+++ b/apps/www/public/r/styles/default/image-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement, withHOC } from '@udecode/plate-common/react';\nimport { Image, ImagePlugin, useMediaState } from '@udecode/plate-media/react';\nimport { ResizableProvider, useResizableStore } from '@udecode/plate-resizable';\n\nimport { Caption, CaptionTextarea } from './caption';\nimport { MediaPopover } from './media-popover';\nimport {\n Resizable,\n ResizeHandle,\n mediaResizeHandleVariants,\n} from './resizable';\n\nexport const ImageElement = withHOC(\n ResizableProvider,\n withRef(\n ({ children, className, nodeProps, ...props }, ref) => {\n const { align = 'center', focused, readOnly, selected } = useMediaState();\n\n const width = useResizableStore().get.width();\n\n return (\n \n \n \n \n \n \n \n \n\n \n \n \n \n\n {children}\n \n \n );\n }\n )\n);\n",
+ "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { withHOC } from '@udecode/plate-common/react';\nimport { Image, ImagePlugin, useMediaState } from '@udecode/plate-media/react';\nimport { ResizableProvider, useResizableStore } from '@udecode/plate-resizable';\n\nimport { Caption, CaptionTextarea } from './caption';\nimport { MediaPopover } from './media-popover';\nimport { PlateElement } from './plate-element';\nimport {\n Resizable,\n ResizeHandle,\n mediaResizeHandleVariants,\n} from './resizable';\n\nexport const ImageElement = withHOC(\n ResizableProvider,\n withRef(\n ({ children, className, nodeProps, ...props }, ref) => {\n const { align = 'center', focused, readOnly, selected } = useMediaState();\n\n const width = useResizableStore().get.width();\n\n return (\n \n \n \n \n \n \n \n \n\n \n \n \n \n\n {children}\n \n \n );\n }\n )\n);\n",
"path": "plate-ui/image-element.tsx",
"target": "",
"type": "registry:ui"
@@ -14,7 +14,8 @@
"registryDependencies": [
"media-popover",
"caption",
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/link-element.json b/apps/www/public/r/styles/default/link-element.json
index 2403a9bbb3..8f9c8ee646 100644
--- a/apps/www/public/r/styles/default/link-element.json
+++ b/apps/www/public/r/styles/default/link-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport type { TLinkElement } from '@udecode/plate-link';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement, useElement } from '@udecode/plate-common/react';\nimport { useLink } from '@udecode/plate-link/react';\n\nexport const LinkElement = withRef(\n ({ children, className, ...props }, ref) => {\n const element = useElement();\n const { props: linkProps } = useLink({ element });\n\n return (\n \n {children} \n \n );\n }\n);\n",
+ "content": "import React from 'react';\n\nimport type { TLinkElement } from '@udecode/plate-link';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { useElement } from '@udecode/plate-common/react';\nimport { useLink } from '@udecode/plate-link/react';\n\nimport { PlateElement } from './plate-element';\n\nexport const LinkElement = withRef(\n ({ children, className, ...props }, ref) => {\n const element = useElement();\n const { props: linkProps } = useLink({ element });\n\n return (\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/link-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "link-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/list-element.json b/apps/www/public/r/styles/default/list-element.json
index 8e7e5db116..d82a2ec45c 100644
--- a/apps/www/public/r/styles/default/list-element.json
+++ b/apps/www/public/r/styles/default/list-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { withRef, withVariants } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport { cva } from 'class-variance-authority';\n\nconst listVariants = cva('m-0 ps-6', {\n variants: {\n variant: {\n ol: 'list-decimal',\n ul: 'list-disc [&_ul]:list-[circle] [&_ul_ul]:list-[square]',\n },\n },\n});\n\nconst ListElementVariants = withVariants(PlateElement, listVariants, [\n 'variant',\n]);\n\nexport const ListElement = withRef(\n ({ children, variant = 'ul', ...props }, ref) => {\n const Component = variant!;\n\n return (\n \n {children} \n \n );\n }\n);\n",
+ "content": "import React from 'react';\n\nimport { withRef, withVariants } from '@udecode/cn';\nimport { cva } from 'class-variance-authority';\n\nimport { PlateElement } from './plate-element';\n\nconst listVariants = cva('m-0 ps-6', {\n variants: {\n variant: {\n ol: 'list-decimal',\n ul: 'list-disc [&_ul]:list-[circle] [&_ul_ul]:list-[square]',\n },\n },\n});\n\nconst ListElementVariants = withVariants(PlateElement, listVariants, [\n 'variant',\n]);\n\nexport const ListElement = withRef(\n ({ children, variant = 'ul', ...props }, ref) => {\n return (\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/list-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "list-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/media-embed-element.json b/apps/www/public/r/styles/default/media-embed-element.json
index 230ee02b18..8cd87c466c 100644
--- a/apps/www/public/r/styles/default/media-embed-element.json
+++ b/apps/www/public/r/styles/default/media-embed-element.json
@@ -6,7 +6,7 @@
],
"files": [
{
- "content": "import React from 'react';\nimport LiteYouTubeEmbed from 'react-lite-youtube-embed';\nimport { Tweet } from 'react-tweet';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement, withHOC } from '@udecode/plate-common/react';\nimport { parseTwitterUrl, parseVideoUrl } from '@udecode/plate-media';\nimport { MediaEmbedPlugin, useMediaState } from '@udecode/plate-media/react';\nimport { ResizableProvider, useResizableStore } from '@udecode/plate-resizable';\n\nimport { Caption, CaptionTextarea } from './caption';\nimport { MediaPopover } from './media-popover';\nimport {\n Resizable,\n ResizeHandle,\n mediaResizeHandleVariants,\n} from './resizable';\n\nexport const MediaEmbedElement = withHOC(\n ResizableProvider,\n withRef(({ children, className, ...props }, ref) => {\n const {\n align = 'center',\n embed,\n focused,\n isTweet,\n isVideo,\n isYoutube,\n readOnly,\n selected,\n } = useMediaState({\n urlParsers: [parseTwitterUrl, parseVideoUrl],\n });\n const width = useResizableStore().get.width();\n const provider = embed?.provider;\n\n return (\n \n \n \n \n \n\n {isVideo ? (\n isYoutube ? (\n _iframe]:absolute [&_>_iframe]:left-0 [&_>_iframe]:top-0 [&_>_iframe]:size-full',\n '[&_>_.lty-playbtn]:z-[1] [&_>_.lty-playbtn]:h-[46px] [&_>_.lty-playbtn]:w-[70px] [&_>_.lty-playbtn]:rounded-[14%] [&_>_.lty-playbtn]:bg-[#212121] [&_>_.lty-playbtn]:opacity-80 [&_>_.lty-playbtn]:[transition:all_0.2s_cubic-bezier(0,_0,_0.2,_1)]',\n '[&:hover_>_.lty-playbtn]:bg-[red] [&:hover_>_.lty-playbtn]:opacity-100',\n '[&_>_.lty-playbtn]:before:border-y-[11px] [&_>_.lty-playbtn]:before:border-l-[19px] [&_>_.lty-playbtn]:before:border-r-0 [&_>_.lty-playbtn]:before:border-[transparent_transparent_transparent_#fff] [&_>_.lty-playbtn]:before:content-[\"\"]',\n '[&_>_.lty-playbtn]:absolute [&_>_.lty-playbtn]:left-1/2 [&_>_.lty-playbtn]:top-1/2 [&_>_.lty-playbtn]:[transform:translate3d(-50%,-50%,0)]',\n '[&_>_.lty-playbtn]:before:absolute [&_>_.lty-playbtn]:before:left-1/2 [&_>_.lty-playbtn]:before:top-1/2 [&_>_.lty-playbtn]:before:[transform:translate3d(-50%,-50%,0)]',\n '[&.lyt-activated]:cursor-[unset]',\n '[&.lyt-activated]:before:pointer-events-none [&.lyt-activated]:before:opacity-0',\n '[&.lyt-activated_>_.lty-playbtn]:pointer-events-none [&.lyt-activated_>_.lty-playbtn]:!opacity-0'\n )}\n />\n ) : (\n \n \n
\n )\n ) : null}\n\n {isTweet && (\n \n \n
\n )}\n\n \n \n\n \n \n \n \n\n {children}\n \n \n );\n })\n);\n",
+ "content": "import React from 'react';\nimport LiteYouTubeEmbed from 'react-lite-youtube-embed';\nimport { Tweet } from 'react-tweet';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { withHOC } from '@udecode/plate-common/react';\nimport { parseTwitterUrl, parseVideoUrl } from '@udecode/plate-media';\nimport { MediaEmbedPlugin, useMediaState } from '@udecode/plate-media/react';\nimport { ResizableProvider, useResizableStore } from '@udecode/plate-resizable';\n\nimport { Caption, CaptionTextarea } from './caption';\nimport { MediaPopover } from './media-popover';\nimport { PlateElement } from './plate-element';\nimport {\n Resizable,\n ResizeHandle,\n mediaResizeHandleVariants,\n} from './resizable';\n\nexport const MediaEmbedElement = withHOC(\n ResizableProvider,\n withRef(({ children, className, ...props }, ref) => {\n const {\n align = 'center',\n embed,\n focused,\n isTweet,\n isVideo,\n isYoutube,\n readOnly,\n selected,\n } = useMediaState({\n urlParsers: [parseTwitterUrl, parseVideoUrl],\n });\n const width = useResizableStore().get.width();\n const provider = embed?.provider;\n\n return (\n \n \n \n \n \n\n {isVideo ? (\n isYoutube ? (\n _iframe]:absolute [&_>_iframe]:left-0 [&_>_iframe]:top-0 [&_>_iframe]:size-full',\n '[&_>_.lty-playbtn]:z-[1] [&_>_.lty-playbtn]:h-[46px] [&_>_.lty-playbtn]:w-[70px] [&_>_.lty-playbtn]:rounded-[14%] [&_>_.lty-playbtn]:bg-[#212121] [&_>_.lty-playbtn]:opacity-80 [&_>_.lty-playbtn]:[transition:all_0.2s_cubic-bezier(0,_0,_0.2,_1)]',\n '[&:hover_>_.lty-playbtn]:bg-[red] [&:hover_>_.lty-playbtn]:opacity-100',\n '[&_>_.lty-playbtn]:before:border-y-[11px] [&_>_.lty-playbtn]:before:border-l-[19px] [&_>_.lty-playbtn]:before:border-r-0 [&_>_.lty-playbtn]:before:border-[transparent_transparent_transparent_#fff] [&_>_.lty-playbtn]:before:content-[\"\"]',\n '[&_>_.lty-playbtn]:absolute [&_>_.lty-playbtn]:left-1/2 [&_>_.lty-playbtn]:top-1/2 [&_>_.lty-playbtn]:[transform:translate3d(-50%,-50%,0)]',\n '[&_>_.lty-playbtn]:before:absolute [&_>_.lty-playbtn]:before:left-1/2 [&_>_.lty-playbtn]:before:top-1/2 [&_>_.lty-playbtn]:before:[transform:translate3d(-50%,-50%,0)]',\n '[&.lyt-activated]:cursor-[unset]',\n '[&.lyt-activated]:before:pointer-events-none [&.lyt-activated]:before:opacity-0',\n '[&.lyt-activated_>_.lty-playbtn]:pointer-events-none [&.lyt-activated_>_.lty-playbtn]:!opacity-0'\n )}\n />\n ) : (\n \n \n
\n )\n ) : null}\n\n {isTweet && (\n \n \n
\n )}\n\n \n \n\n \n \n \n \n\n {children}\n \n \n );\n })\n);\n",
"path": "plate-ui/media-embed-element.tsx",
"target": "",
"type": "registry:ui"
@@ -16,7 +16,8 @@
"registryDependencies": [
"media-popover",
"caption",
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/mention-element.json b/apps/www/public/r/styles/default/mention-element.json
index 654419f28d..f75968cda0 100644
--- a/apps/www/public/r/styles/default/mention-element.json
+++ b/apps/www/public/r/styles/default/mention-element.json
@@ -4,13 +4,16 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport type { TMentionElement } from '@udecode/plate-mention';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { getHandler } from '@udecode/plate-common';\nimport { PlateElement, useElement } from '@udecode/plate-common/react';\nimport { useFocused, useSelected } from 'slate-react';\n\nexport const MentionElement = withRef<\n typeof PlateElement,\n {\n prefix?: string;\n renderLabel?: (mentionable: TMentionElement) => string;\n onClick?: (mentionNode: any) => void;\n }\n>(({ children, className, prefix, renderLabel, onClick, ...props }, ref) => {\n const element = useElement();\n const selected = useSelected();\n const focused = useFocused();\n\n return (\n \n {prefix}\n {renderLabel ? renderLabel(element) : element.value}\n {children}\n \n );\n});\n",
+ "content": "import React from 'react';\n\nimport type { TMentionElement } from '@udecode/plate-mention';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { getHandler } from '@udecode/plate-common';\nimport { useElement } from '@udecode/plate-common/react';\nimport { IS_APPLE } from '@udecode/utils';\nimport { useFocused, useSelected } from 'slate-react';\n\nimport { useMounted } from '@/registry/default/hooks/use-mounted';\n\nimport { PlateElement } from './plate-element';\n\nexport const MentionElement = withRef<\n typeof PlateElement,\n {\n prefix?: string;\n renderLabel?: (mentionable: TMentionElement) => string;\n onClick?: (mentionNode: any) => void;\n }\n>(({ children, className, prefix, renderLabel, onClick, ...props }, ref) => {\n const element = useElement();\n const selected = useSelected();\n const focused = useFocused();\n const mounted = useMounted();\n\n return (\n \n {mounted && IS_APPLE ? (\n // Mac OS IME https://github.com/ianstormtaylor/slate/issues/3490\n \n {children}\n {prefix}\n {renderLabel ? renderLabel(element) : element.value}\n \n ) : (\n // Others like Android https://github.com/ianstormtaylor/slate/pull/5360\n \n {prefix}\n {renderLabel ? renderLabel(element) : element.value}\n {children}\n \n )}\n \n );\n});\n",
"path": "plate-ui/mention-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "mention-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element",
+ "use-mounted"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/mention-input-element.json b/apps/www/public/r/styles/default/mention-input-element.json
index 0c7ed62d07..95320fac62 100644
--- a/apps/www/public/r/styles/default/mention-input-element.json
+++ b/apps/www/public/r/styles/default/mention-input-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React, { useState } from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport { getMentionOnSelectItem } from '@udecode/plate-mention';\n\nimport {\n InlineCombobox,\n InlineComboboxContent,\n InlineComboboxEmpty,\n InlineComboboxInput,\n InlineComboboxItem,\n} from './inline-combobox';\n\nconst onSelectItem = getMentionOnSelectItem();\n\nexport const MentionInputElement = withRef(\n ({ className, ...props }, ref) => {\n const { children, editor, element } = props;\n const [search, setSearch] = useState('');\n\n return (\n \n \n \n \n \n\n \n No results found \n\n {MENTIONABLES.map((item) => (\n onSelectItem(editor, item, search)}\n >\n {item.text}\n \n ))}\n \n \n\n {children}\n \n );\n }\n);\n\nexport const MENTIONABLES = [\n { key: '0', text: 'Aayla Secura' },\n { key: '1', text: 'Adi Gallia' },\n {\n key: '2',\n text: 'Admiral Dodd Rancit',\n },\n {\n key: '3',\n text: 'Admiral Firmus Piett',\n },\n {\n key: '4',\n text: 'Admiral Gial Ackbar',\n },\n { key: '5', text: 'Admiral Ozzel' },\n { key: '6', text: 'Admiral Raddus' },\n {\n key: '7',\n text: 'Admiral Terrinald Screed',\n },\n { key: '8', text: 'Admiral Trench' },\n {\n key: '9',\n text: 'Admiral U.O. Statura',\n },\n { key: '10', text: 'Agen Kolar' },\n { key: '11', text: 'Agent Kallus' },\n {\n key: '12',\n text: 'Aiolin and Morit Astarte',\n },\n { key: '13', text: 'Aks Moe' },\n { key: '14', text: 'Almec' },\n { key: '15', text: 'Alton Kastle' },\n { key: '16', text: 'Amee' },\n { key: '17', text: 'AP-5' },\n { key: '18', text: 'Armitage Hux' },\n { key: '19', text: 'Artoo' },\n { key: '20', text: 'Arvel Crynyd' },\n { key: '21', text: 'Asajj Ventress' },\n { key: '22', text: 'Aurra Sing' },\n { key: '23', text: 'AZI-3' },\n { key: '24', text: 'Bala-Tik' },\n { key: '25', text: 'Barada' },\n { key: '26', text: 'Bargwill Tomder' },\n { key: '27', text: 'Baron Papanoida' },\n { key: '28', text: 'Barriss Offee' },\n { key: '29', text: 'Baze Malbus' },\n { key: '30', text: 'Bazine Netal' },\n { key: '31', text: 'BB-8' },\n { key: '32', text: 'BB-9E' },\n { key: '33', text: 'Ben Quadinaros' },\n { key: '34', text: 'Berch Teller' },\n { key: '35', text: 'Beru Lars' },\n { key: '36', text: 'Bib Fortuna' },\n {\n key: '37',\n text: 'Biggs Darklighter',\n },\n { key: '38', text: 'Black Krrsantan' },\n { key: '39', text: 'Bo-Katan Kryze' },\n { key: '40', text: 'Boba Fett' },\n { key: '41', text: 'Bobbajo' },\n { key: '42', text: 'Bodhi Rook' },\n { key: '43', text: 'Borvo the Hutt' },\n { key: '44', text: 'Boss Nass' },\n { key: '45', text: 'Bossk' },\n {\n key: '46',\n text: 'Breha Antilles-Organa',\n },\n { key: '47', text: 'Bren Derlin' },\n { key: '48', text: 'Brendol Hux' },\n { key: '49', text: 'BT-1' },\n];\n",
+ "content": "import React, { useState } from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from './plate-element';\nimport { getMentionOnSelectItem } from '@udecode/plate-mention';\n\nimport {\n InlineCombobox,\n InlineComboboxContent,\n InlineComboboxEmpty,\n InlineComboboxInput,\n InlineComboboxItem,\n} from './inline-combobox';\n\nconst onSelectItem = getMentionOnSelectItem();\n\nexport const MentionInputElement = withRef(\n ({ className, ...props }, ref) => {\n const { children, editor, element } = props;\n const [search, setSearch] = useState('');\n\n return (\n \n \n \n \n \n\n \n No results found \n\n {MENTIONABLES.map((item) => (\n onSelectItem(editor, item, search)}\n >\n {item.text}\n \n ))}\n \n \n\n {children}\n \n );\n }\n);\n\nexport const MENTIONABLES = [\n { key: '0', text: 'Aayla Secura' },\n { key: '1', text: 'Adi Gallia' },\n {\n key: '2',\n text: 'Admiral Dodd Rancit',\n },\n {\n key: '3',\n text: 'Admiral Firmus Piett',\n },\n {\n key: '4',\n text: 'Admiral Gial Ackbar',\n },\n { key: '5', text: 'Admiral Ozzel' },\n { key: '6', text: 'Admiral Raddus' },\n {\n key: '7',\n text: 'Admiral Terrinald Screed',\n },\n { key: '8', text: 'Admiral Trench' },\n {\n key: '9',\n text: 'Admiral U.O. Statura',\n },\n { key: '10', text: 'Agen Kolar' },\n { key: '11', text: 'Agent Kallus' },\n {\n key: '12',\n text: 'Aiolin and Morit Astarte',\n },\n { key: '13', text: 'Aks Moe' },\n { key: '14', text: 'Almec' },\n { key: '15', text: 'Alton Kastle' },\n { key: '16', text: 'Amee' },\n { key: '17', text: 'AP-5' },\n { key: '18', text: 'Armitage Hux' },\n { key: '19', text: 'Artoo' },\n { key: '20', text: 'Arvel Crynyd' },\n { key: '21', text: 'Asajj Ventress' },\n { key: '22', text: 'Aurra Sing' },\n { key: '23', text: 'AZI-3' },\n { key: '24', text: 'Bala-Tik' },\n { key: '25', text: 'Barada' },\n { key: '26', text: 'Bargwill Tomder' },\n { key: '27', text: 'Baron Papanoida' },\n { key: '28', text: 'Barriss Offee' },\n { key: '29', text: 'Baze Malbus' },\n { key: '30', text: 'Bazine Netal' },\n { key: '31', text: 'BB-8' },\n { key: '32', text: 'BB-9E' },\n { key: '33', text: 'Ben Quadinaros' },\n { key: '34', text: 'Berch Teller' },\n { key: '35', text: 'Beru Lars' },\n { key: '36', text: 'Bib Fortuna' },\n {\n key: '37',\n text: 'Biggs Darklighter',\n },\n { key: '38', text: 'Black Krrsantan' },\n { key: '39', text: 'Bo-Katan Kryze' },\n { key: '40', text: 'Boba Fett' },\n { key: '41', text: 'Bobbajo' },\n { key: '42', text: 'Bodhi Rook' },\n { key: '43', text: 'Borvo the Hutt' },\n { key: '44', text: 'Boss Nass' },\n { key: '45', text: 'Bossk' },\n {\n key: '46',\n text: 'Breha Antilles-Organa',\n },\n { key: '47', text: 'Bren Derlin' },\n { key: '48', text: 'Brendol Hux' },\n { key: '49', text: 'BT-1' },\n];\n",
"path": "plate-ui/mention-input-element.tsx",
"target": "",
"type": "registry:ui"
@@ -12,7 +12,8 @@
],
"name": "mention-input-element",
"registryDependencies": [
- "inline-combobox"
+ "inline-combobox",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/paragraph-element.json b/apps/www/public/r/styles/default/paragraph-element.json
index 30c24b2058..753c1f8176 100644
--- a/apps/www/public/r/styles/default/paragraph-element.json
+++ b/apps/www/public/r/styles/default/paragraph-element.json
@@ -1,13 +1,15 @@
{
"files": [
{
- "content": "import { withCn } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\n\nexport const ParagraphElement = withCn(PlateElement, 'm-0 px-0 py-1');\n",
+ "content": "import { cn } from '@udecode/cn';\nimport { withRef } from '@udecode/plate-common/react';\n\nimport { PlateElement } from './plate-element';\n\nexport const ParagraphElement = withRef(\n ({ children, className, ...props }, ref) => {\n return (\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/paragraph-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "paragraph-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/plate-element.json b/apps/www/public/r/styles/default/plate-element.json
new file mode 100644
index 0000000000..2d276ff66d
--- /dev/null
+++ b/apps/www/public/r/styles/default/plate-element.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": [],
+ "files": [
+ {
+ "content": "import React from 'react';\n\nimport type { PlateElementProps } from '@udecode/plate-common/react';\n\nimport { cn } from '@udecode/cn';\nimport { PlateElement as PlateElementPrimitive } from '@udecode/plate-common/react';\nimport { useBlockSelectableStore } from '@udecode/plate-selection/react';\n\nimport { BlockSelection } from './block-selection';\n\nexport const PlateElement = React.forwardRef(\n ({ children, className, ...props }: PlateElementProps, ref) => {\n const selectable = useBlockSelectableStore().get.selectable();\n\n return (\n \n {children}\n\n {selectable && }\n \n );\n }\n);\n",
+ "path": "plate-ui/plate-element.tsx",
+ "target": "",
+ "type": "registry:ui"
+ }
+ ],
+ "name": "plate-element",
+ "registryDependencies": [
+ "block-selection"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/slash-input-element.json b/apps/www/public/r/styles/default/slash-input-element.json
index f026267f31..331ca91a7f 100644
--- a/apps/www/public/r/styles/default/slash-input-element.json
+++ b/apps/www/public/r/styles/default/slash-input-element.json
@@ -5,7 +5,7 @@
],
"files": [
{
- "content": "import React, { type ComponentType, type SVGProps } from 'react';\n\nimport { withRef } from '@udecode/cn';\nimport { type PlateEditor, PlateElement } from '@udecode/plate-common/react';\nimport { DatePlugin } from '@udecode/plate-date/react';\nimport { HEADING_KEYS } from '@udecode/plate-heading';\nimport { ListStyleType, toggleIndentList } from '@udecode/plate-indent-list';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n InlineCombobox,\n InlineComboboxContent,\n InlineComboboxEmpty,\n InlineComboboxInput,\n InlineComboboxItem,\n} from './inline-combobox';\n\ninterface SlashCommandRule {\n icon: ComponentType>;\n onSelect: (editor: PlateEditor) => void;\n value: string;\n keywords?: string[];\n}\n\nconst rules: SlashCommandRule[] = [\n {\n icon: Icons.h1,\n value: 'Heading 1',\n onSelect: (editor) => {\n editor.tf.toggle.block({ type: HEADING_KEYS.h1 });\n },\n },\n {\n icon: Icons.h2,\n value: 'Heading 2',\n onSelect: (editor) => {\n editor.tf.toggle.block({ type: HEADING_KEYS.h2 });\n },\n },\n {\n icon: Icons.h3,\n value: 'Heading 3',\n onSelect: (editor) => {\n editor.tf.toggle.block({ type: HEADING_KEYS.h3 });\n },\n },\n {\n icon: Icons.ul,\n keywords: ['ul', 'unordered list'],\n value: 'Bulleted list',\n onSelect: (editor) => {\n toggleIndentList(editor, {\n listStyleType: ListStyleType.Disc,\n });\n },\n },\n {\n icon: Icons.ol,\n keywords: ['ol', 'ordered list'],\n value: 'Numbered list',\n onSelect: (editor) => {\n toggleIndentList(editor, {\n listStyleType: ListStyleType.Decimal,\n });\n },\n },\n {\n icon: Icons.add,\n keywords: ['inline', 'date'],\n value: 'Date',\n onSelect: (editor) => {\n editor.getTransforms(DatePlugin).insert.date();\n },\n },\n];\n\nexport const SlashInputElement = withRef(\n ({ className, ...props }, ref) => {\n const { children, editor, element } = props;\n\n return (\n \n \n \n\n \n \n No matching commands found\n \n\n {rules.map(({ icon: Icon, keywords, value, onSelect }) => (\n onSelect(editor)}\n keywords={keywords}\n >\n \n {value}\n \n ))}\n \n \n\n {children}\n \n );\n }\n);\n",
+ "content": "import React, { type ComponentType, type SVGProps } from 'react';\n\nimport type { PlateEditor } from '@udecode/plate-common/react';\n\nimport { withRef } from '@udecode/cn';\nimport { DatePlugin } from '@udecode/plate-date/react';\nimport { HEADING_KEYS } from '@udecode/plate-heading';\nimport { ListStyleType, toggleIndentList } from '@udecode/plate-indent-list';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n InlineCombobox,\n InlineComboboxContent,\n InlineComboboxEmpty,\n InlineComboboxInput,\n InlineComboboxItem,\n} from './inline-combobox';\nimport { PlateElement } from './plate-element';\n\ninterface SlashCommandRule {\n icon: ComponentType>;\n onSelect: (editor: PlateEditor) => void;\n value: string;\n keywords?: string[];\n}\n\nconst rules: SlashCommandRule[] = [\n {\n icon: Icons.h1,\n value: 'Heading 1',\n onSelect: (editor) => {\n editor.tf.toggle.block({ type: HEADING_KEYS.h1 });\n },\n },\n {\n icon: Icons.h2,\n value: 'Heading 2',\n onSelect: (editor) => {\n editor.tf.toggle.block({ type: HEADING_KEYS.h2 });\n },\n },\n {\n icon: Icons.h3,\n value: 'Heading 3',\n onSelect: (editor) => {\n editor.tf.toggle.block({ type: HEADING_KEYS.h3 });\n },\n },\n {\n icon: Icons.ul,\n keywords: ['ul', 'unordered list'],\n value: 'Bulleted list',\n onSelect: (editor) => {\n toggleIndentList(editor, {\n listStyleType: ListStyleType.Disc,\n });\n },\n },\n {\n icon: Icons.ol,\n keywords: ['ol', 'ordered list'],\n value: 'Numbered list',\n onSelect: (editor) => {\n toggleIndentList(editor, {\n listStyleType: ListStyleType.Decimal,\n });\n },\n },\n {\n icon: Icons.add,\n keywords: ['inline', 'date'],\n value: 'Date',\n onSelect: (editor) => {\n editor.getTransforms(DatePlugin).insert.date();\n },\n },\n];\n\nexport const SlashInputElement = withRef(\n ({ className, ...props }, ref) => {\n const { children, editor, element } = props;\n\n return (\n \n \n \n\n \n \n No matching commands found\n \n\n {rules.map(({ icon: Icon, keywords, value, onSelect }) => (\n onSelect(editor)}\n keywords={keywords}\n >\n \n {value}\n \n ))}\n \n \n\n {children}\n \n );\n }\n);\n",
"path": "plate-ui/slash-input-element.tsx",
"target": "",
"type": "registry:ui"
@@ -13,7 +13,8 @@
],
"name": "slash-input-element",
"registryDependencies": [
- "inline-combobox"
+ "inline-combobox",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/table-cell-element.json b/apps/www/public/r/styles/default/table-cell-element.json
index a17957cf64..f5e6565552 100644
--- a/apps/www/public/r/styles/default/table-cell-element.json
+++ b/apps/www/public/r/styles/default/table-cell-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { cn, withProps, withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport {\n useTableCellElement,\n useTableCellElementResizable,\n useTableCellElementResizableState,\n useTableCellElementState,\n} from '@udecode/plate-table/react';\n\nimport { ResizeHandle } from './resizable';\n\nexport const TableCellElement = withRef<\n typeof PlateElement,\n {\n hideBorder?: boolean;\n isHeader?: boolean;\n }\n>(({ children, className, hideBorder, isHeader, style, ...props }, ref) => {\n const { element } = props;\n\n const {\n borders,\n colIndex,\n colSpan,\n hovered,\n hoveredLeft,\n isSelectingCell,\n readOnly,\n rowIndex,\n rowSize,\n selected,\n } = useTableCellElementState();\n const { props: cellProps } = useTableCellElement({ element: props.element });\n const resizableState = useTableCellElementResizableState({\n colIndex,\n colSpan,\n rowIndex,\n });\n\n const { bottomProps, hiddenLeft, leftProps, rightProps } =\n useTableCellElementResizable(resizableState);\n\n const Cell = isHeader ? 'th' : 'td';\n\n return (\n _*]:m-0',\n 'before:size-full',\n selected && 'before:z-10 before:bg-muted',\n \"before:absolute before:box-border before:select-none before:content-['']\",\n borders &&\n cn(\n borders.bottom?.size &&\n `before:border-b before:border-b-border`,\n borders.right?.size && `before:border-r before:border-r-border`,\n borders.left?.size && `before:border-l before:border-l-border`,\n borders.top?.size && `before:border-t before:border-t-border`\n )\n ),\n className\n )}\n {...cellProps}\n {...props}\n style={\n {\n '--cellBackground': element.background,\n ...style,\n } as React.CSSProperties\n }\n >\n \n \n {children}\n \n\n {!isSelectingCell && (\n \n {!readOnly && (\n <>\n \n \n {!hiddenLeft && (\n \n )}\n\n {hovered && (\n
\n )}\n {hoveredLeft && (\n
\n )}\n >\n )}\n \n )}\n | \n \n );\n});\n\nTableCellElement.displayName = 'TableCellElement';\n\nexport const TableCellHeaderElement = withProps(TableCellElement, {\n isHeader: true,\n});\n",
+ "content": "import React from 'react';\n\nimport { cn, withProps, withRef } from '@udecode/cn';\nimport {\n useTableCellElement,\n useTableCellElementResizable,\n useTableCellElementResizableState,\n useTableCellElementState,\n} from '@udecode/plate-table/react';\n\nimport { PlateElement } from './plate-element';\nimport { ResizeHandle } from './resizable';\n\nexport const TableCellElement = withRef<\n typeof PlateElement,\n {\n hideBorder?: boolean;\n isHeader?: boolean;\n }\n>(({ children, className, hideBorder, isHeader, style, ...props }, ref) => {\n const { element } = props;\n\n const {\n borders,\n colIndex,\n colSpan,\n hovered,\n hoveredLeft,\n isSelectingCell,\n readOnly,\n rowIndex,\n rowSize,\n selected,\n } = useTableCellElementState();\n const { props: cellProps } = useTableCellElement({ element: props.element });\n const resizableState = useTableCellElementResizableState({\n colIndex,\n colSpan,\n rowIndex,\n });\n\n const { bottomProps, hiddenLeft, leftProps, rightProps } =\n useTableCellElementResizable(resizableState);\n\n return (\n _*]:m-0',\n 'before:size-full',\n selected && 'before:z-10 before:bg-muted',\n \"before:absolute before:box-border before:select-none before:content-['']\",\n borders &&\n cn(\n borders.bottom?.size &&\n `before:border-b before:border-b-border`,\n borders.right?.size && `before:border-r before:border-r-border`,\n borders.left?.size && `before:border-l before:border-l-border`,\n borders.top?.size && `before:border-t before:border-t-border`\n )\n ),\n className\n )}\n {...cellProps}\n {...props}\n style={\n {\n '--cellBackground': element.background,\n ...style,\n } as React.CSSProperties\n }\n >\n \n {children}\n
\n\n {!isSelectingCell && (\n \n {!readOnly && (\n <>\n
\n
\n {!hiddenLeft && (\n
\n )}\n\n {hovered && (\n
\n )}\n {hoveredLeft && (\n
\n )}\n >\n )}\n
\n )}\n \n );\n});\n\nTableCellElement.displayName = 'TableCellElement';\n\nexport const TableCellHeaderElement = withProps(TableCellElement, {\n isHeader: true,\n});\n",
"path": "plate-ui/table-cell-element.tsx",
"target": "",
"type": "registry:ui"
@@ -12,7 +12,8 @@
],
"name": "table-cell-element",
"registryDependencies": [
- "resizable"
+ "resizable",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/table-element.json b/apps/www/public/r/styles/default/table-element.json
index abba3ca04d..4284ed0b9e 100644
--- a/apps/www/public/r/styles/default/table-element.json
+++ b/apps/www/public/r/styles/default/table-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport type * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport type { TTableElement } from '@udecode/plate-table';\n\nimport { PopoverAnchor } from '@radix-ui/react-popover';\nimport { cn, withRef } from '@udecode/cn';\nimport { isSelectionExpanded } from '@udecode/plate-common';\nimport {\n PlateElement,\n useEditorRef,\n useEditorSelector,\n useElement,\n useRemoveNodeButton,\n withHOC,\n} from '@udecode/plate-common/react';\nimport {\n TableProvider,\n mergeTableCells,\n unmergeTableCells,\n useTableBordersDropdownMenuContentState,\n useTableElement,\n useTableElementState,\n useTableMergeState,\n} from '@udecode/plate-table/react';\nimport { useReadOnly, useSelected } from 'slate-react';\n\nimport { Icons, iconVariants } from '@/components/icons';\n\nimport { Button } from './button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport { Popover, PopoverContent, popoverVariants } from './popover';\nimport { Separator } from './separator';\n\nexport const TableBordersDropdownMenuContent = withRef<\n typeof DropdownMenuPrimitive.Content\n>((props, ref) => {\n const {\n getOnSelectTableBorder,\n hasBottomBorder,\n hasLeftBorder,\n hasNoBorders,\n hasOuterBorders,\n hasRightBorder,\n hasTopBorder,\n } = useTableBordersDropdownMenuContentState();\n\n return (\n \n \n \n Bottom Border
\n \n \n \n Top Border
\n \n \n \n Left Border
\n \n \n \n Right Border
\n \n\n \n\n \n \n No Border
\n \n \n \n Outside Borders
\n \n \n );\n});\n\nexport const TableFloatingToolbar = withRef(\n ({ children, ...props }, ref) => {\n const element = useElement();\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n const selectionCollapsed = useEditorSelector(\n (editor) => !isSelectionExpanded(editor),\n []\n );\n\n const readOnly = useReadOnly();\n const selected = useSelected();\n const editor = useEditorRef();\n\n const collapsed = !readOnly && selected && selectionCollapsed;\n const open = !readOnly && selected;\n\n const { canMerge, canUnmerge } = useTableMergeState();\n\n const mergeContent = canMerge && (\n mergeTableCells(editor)}\n contentEditable={false}\n isMenu\n >\n \n Merge\n \n );\n\n const unmergeButton = canUnmerge && (\n unmergeTableCells(editor)}\n contentEditable={false}\n isMenu\n >\n \n Unmerge\n \n );\n\n const bordersContent = collapsed && (\n <>\n \n \n \n \n Borders\n \n \n\n \n \n \n \n\n \n \n Delete\n \n >\n );\n\n return (\n \n {children} \n {(canMerge || canUnmerge || collapsed) && (\n e.preventDefault()}\n {...props}\n >\n {unmergeButton}\n {mergeContent}\n {bordersContent}\n \n )}\n \n );\n }\n);\n\nexport const TableElement = withHOC(\n TableProvider,\n withRef(({ children, className, ...props }, ref) => {\n const { colSizes, isSelectingCell, marginLeft, minColumnWidth } =\n useTableElementState();\n const { colGroupProps, props: tableProps } = useTableElement();\n\n return (\n \n \n
\n \n \n {colSizes.map((width, index) => (\n \n ))}\n \n\n {children} \n
\n \n
\n \n );\n })\n);\n",
+ "content": "import React from 'react';\n\nimport type * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport type { TTableElement } from '@udecode/plate-table';\n\nimport { PopoverAnchor } from '@radix-ui/react-popover';\nimport { cn, withRef } from '@udecode/cn';\nimport { isSelectionExpanded } from '@udecode/plate-common';\nimport {\n useEditorRef,\n useEditorSelector,\n useElement,\n useRemoveNodeButton,\n withHOC,\n} from '@udecode/plate-common/react';\nimport {\n TableProvider,\n mergeTableCells,\n unmergeTableCells,\n useTableBordersDropdownMenuContentState,\n useTableElement,\n useTableElementState,\n useTableMergeState,\n} from '@udecode/plate-table/react';\nimport { useReadOnly, useSelected } from 'slate-react';\n\nimport { Icons, iconVariants } from '@/components/icons';\n\nimport { Button } from './button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport { PlateElement } from './plate-element';\nimport { Popover, PopoverContent, popoverVariants } from './popover';\nimport { Separator } from './separator';\n\nexport const TableBordersDropdownMenuContent = withRef<\n typeof DropdownMenuPrimitive.Content\n>((props, ref) => {\n const {\n getOnSelectTableBorder,\n hasBottomBorder,\n hasLeftBorder,\n hasNoBorders,\n hasOuterBorders,\n hasRightBorder,\n hasTopBorder,\n } = useTableBordersDropdownMenuContentState();\n\n return (\n \n \n \n Bottom Border
\n \n \n \n Top Border
\n \n \n \n Left Border
\n \n \n \n Right Border
\n \n\n \n\n \n \n No Border
\n \n \n \n Outside Borders
\n \n \n );\n});\n\nexport const TableFloatingToolbar = withRef(\n ({ children, ...props }, ref) => {\n const element = useElement();\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n const selectionCollapsed = useEditorSelector(\n (editor) => !isSelectionExpanded(editor),\n []\n );\n\n const readOnly = useReadOnly();\n const selected = useSelected();\n const editor = useEditorRef();\n\n const collapsed = !readOnly && selected && selectionCollapsed;\n const open = !readOnly && selected;\n\n const { canMerge, canUnmerge } = useTableMergeState();\n\n const mergeContent = canMerge && (\n mergeTableCells(editor)}\n contentEditable={false}\n isMenu\n >\n \n Merge\n \n );\n\n const unmergeButton = canUnmerge && (\n unmergeTableCells(editor)}\n contentEditable={false}\n isMenu\n >\n \n Unmerge\n \n );\n\n const bordersContent = collapsed && (\n <>\n \n \n \n \n Borders\n \n \n\n \n \n \n \n\n \n \n Delete\n \n >\n );\n\n return (\n \n {children} \n {(canMerge || canUnmerge || collapsed) && (\n e.preventDefault()}\n {...props}\n >\n {unmergeButton}\n {mergeContent}\n {bordersContent}\n \n )}\n \n );\n }\n);\n\nexport const TableElement = withHOC(\n TableProvider,\n withRef(({ children, className, ...props }, ref) => {\n const { colSizes, isSelectingCell, marginLeft, minColumnWidth } =\n useTableElementState();\n const { colGroupProps, props: tableProps } = useTableElement();\n\n return (\n \n \n
\n \n {colSizes.map((width, index) => (\n \n ))}\n \n\n {children} \n \n
\n \n );\n })\n);\n",
"path": "plate-ui/table-element.tsx",
"target": "",
"type": "registry:ui"
@@ -12,7 +12,8 @@
],
"name": "table-element",
"registryDependencies": [
- "dropdown-menu"
+ "dropdown-menu",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/table-row-element.json b/apps/www/public/r/styles/default/table-row-element.json
index d0b11642cd..db11efadb8 100644
--- a/apps/www/public/r/styles/default/table-row-element.json
+++ b/apps/www/public/r/styles/default/table-row-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\n\nexport const TableRowElement = withRef<\n typeof PlateElement,\n {\n hideBorder?: boolean;\n }\n>(({ children, hideBorder, ...props }, ref) => {\n return (\n \n {children} \n \n );\n});\n",
+ "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\n\nimport { PlateElement } from './plate-element';\n\nexport const TableRowElement = withRef<\n typeof PlateElement,\n {\n hideBorder?: boolean;\n }\n>(({ children, hideBorder, ...props }, ref) => {\n return (\n \n {children}\n \n );\n});\n",
"path": "plate-ui/table-row-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "table-row-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/todo-list-element.json b/apps/www/public/r/styles/default/todo-list-element.json
index 3bd6e5a247..e14dd33c28 100644
--- a/apps/www/public/r/styles/default/todo-list-element.json
+++ b/apps/www/public/r/styles/default/todo-list-element.json
@@ -4,7 +4,7 @@
],
"files": [
{
- "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from '@udecode/plate-common/react';\nimport {\n useTodoListElement,\n useTodoListElementState,\n} from '@udecode/plate-list/react';\n\nimport { Checkbox } from './checkbox';\n\nexport const TodoListElement = withRef(\n ({ children, className, ...props }, ref) => {\n const { element } = props;\n const state = useTodoListElementState({ element });\n const { checkboxProps } = useTodoListElement(state);\n\n return (\n \n \n \n
\n \n {children}\n \n \n );\n }\n);\n",
+ "content": "import React from 'react';\n\nimport { cn, withRef } from '@udecode/cn';\nimport { PlateElement } from './plate-element';\nimport {\n useTodoListElement,\n useTodoListElementState,\n} from '@udecode/plate-list/react';\n\nimport { Checkbox } from './checkbox';\n\nexport const TodoListElement = withRef(\n ({ children, className, ...props }, ref) => {\n const { element } = props;\n const state = useTodoListElementState({ element });\n const { checkboxProps } = useTodoListElement(state);\n\n return (\n \n \n \n
\n \n {children}\n \n \n );\n }\n);\n",
"path": "plate-ui/todo-list-element.tsx",
"target": "",
"type": "registry:ui"
@@ -12,7 +12,8 @@
],
"name": "todo-list-element",
"registryDependencies": [
- "checkbox"
+ "checkbox",
+ "plate-element"
],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/toggle-element.json b/apps/www/public/r/styles/default/toggle-element.json
index 6c583fcdef..26d6334dd5 100644
--- a/apps/www/public/r/styles/default/toggle-element.json
+++ b/apps/www/public/r/styles/default/toggle-element.json
@@ -4,13 +4,15 @@
],
"files": [
{
- "content": "import { withRef } from '@udecode/cn';\nimport { PlateElement, useElement } from '@udecode/plate-common/react';\nimport {\n useToggleButton,\n useToggleButtonState,\n} from '@udecode/plate-toggle/react';\n\nimport { Icons } from '@/components/icons';\n\nexport const ToggleElement = withRef(\n ({ children, ...props }, ref) => {\n const element = useElement();\n const state = useToggleButtonState(element.id as string);\n const { buttonProps, open } = useToggleButton(state);\n\n return (\n \n \n \n {open ? : }\n \n {children}\n
\n \n );\n }\n);\n",
+ "content": "import { cn, withRef } from '@udecode/cn';\nimport { useElement } from '@udecode/plate-common/react';\nimport {\n useToggleButton,\n useToggleButtonState,\n} from '@udecode/plate-toggle/react';\n\nimport { Icons } from '@/components/icons';\n\nimport { PlateElement } from './plate-element';\n\nexport const ToggleElement = withRef(\n ({ children, className, ...props }, ref) => {\n const element = useElement();\n const state = useToggleButtonState(element.id as string);\n const { buttonProps, open } = useToggleButton(state);\n\n return (\n \n \n {open ? : }\n \n {children}\n \n );\n }\n);\n",
"path": "plate-ui/toggle-element.tsx",
"target": "",
"type": "registry:ui"
}
],
"name": "toggle-element",
- "registryDependencies": [],
+ "registryDependencies": [
+ "plate-element"
+ ],
"type": "registry:ui"
}
\ No newline at end of file
diff --git a/apps/www/public/r/styles/default/use-mounted.json b/apps/www/public/r/styles/default/use-mounted.json
new file mode 100644
index 0000000000..700e40dfd5
--- /dev/null
+++ b/apps/www/public/r/styles/default/use-mounted.json
@@ -0,0 +1,11 @@
+{
+ "files": [
+ {
+ "content": "import * as React from 'react';\n\nexport function useMounted() {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n setMounted(true);\n }, []);\n\n return mounted;\n}\n",
+ "path": "hooks/use-mounted.ts",
+ "type": "registry:hook"
+ }
+ ],
+ "name": "use-mounted",
+ "type": "registry:hook"
+}
\ No newline at end of file
diff --git a/apps/www/scripts/build-registry.mts b/apps/www/scripts/build-registry.mts
index 25e60a44fe..353058c98b 100644
--- a/apps/www/scripts/build-registry.mts
+++ b/apps/www/scripts/build-registry.mts
@@ -779,7 +779,7 @@ try {
await buildStylesIndex()
await buildThemes()
- console.log("✅ Done!")
+ console.info("✅ Done!")
} catch (error) {
console.error(error)
process.exit(1)
diff --git a/apps/www/src/__registry__/index.tsx b/apps/www/src/__registry__/index.tsx
index 27b2f3e487..44c0115504 100644
--- a/apps/www/src/__registry__/index.tsx
+++ b/apps/www/src/__registry__/index.tsx
@@ -16,6 +16,28 @@ export const Index: Record = {
subcategory: "undefined",
chunks: []
},
+ "block-selection": {
+ name: "block-selection",
+ type: "registry:ui",
+ registryDependencies: [],
+ files: ["registry/default/plate-ui/block-selection.tsx"],
+ component: React.lazy(() => import("@/registry/default/plate-ui/block-selection.tsx")),
+ source: "",
+ category: "undefined",
+ subcategory: "undefined",
+ chunks: []
+ },
+ "plate-element": {
+ name: "plate-element",
+ type: "registry:ui",
+ registryDependencies: ["block-selection"],
+ files: ["registry/default/plate-ui/plate-element.tsx"],
+ component: React.lazy(() => import("@/registry/default/plate-ui/plate-element.tsx")),
+ source: "",
+ category: "undefined",
+ subcategory: "undefined",
+ chunks: []
+ },
"cloud": {
name: "cloud",
type: "registry:ui",
@@ -30,7 +52,7 @@ export const Index: Record = {
"code-block-element": {
name: "code-block-element",
type: "registry:ui",
- registryDependencies: ["command"],
+ registryDependencies: ["command","plate-element"],
files: ["registry/default/plate-ui/code-block-element.tsx","registry/default/plate-ui/code-block-element.css","registry/default/plate-ui/code-block-combobox.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/code-block-element.tsx")),
source: "",
@@ -41,7 +63,7 @@ export const Index: Record = {
"column-element": {
name: "column-element",
type: "registry:ui",
- registryDependencies: ["command","resizable"],
+ registryDependencies: ["command","resizable","plate-element"],
files: ["registry/default/plate-ui/column-element.tsx","registry/default/plate-ui/column-group-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/column-element.tsx")),
source: "",
@@ -96,7 +118,7 @@ export const Index: Record = {
"emoji-input-element": {
name: "emoji-input-element",
type: "registry:ui",
- registryDependencies: ["inline-combobox"],
+ registryDependencies: ["inline-combobox","plate-element","use-debounce"],
files: ["registry/default/plate-ui/emoji-input-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/emoji-input-element.tsx")),
source: "",
@@ -129,7 +151,7 @@ export const Index: Record = {
"blockquote-element": {
name: "blockquote-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/blockquote-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/blockquote-element.tsx")),
source: "",
@@ -140,7 +162,7 @@ export const Index: Record = {
"date-element": {
name: "date-element",
type: "registry:ui",
- registryDependencies: ["calendar"],
+ registryDependencies: ["calendar","plate-element"],
files: ["registry/default/plate-ui/date-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/date-element.tsx")),
source: "",
@@ -206,7 +228,7 @@ export const Index: Record = {
"code-line-element": {
name: "code-line-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/code-line-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/code-line-element.tsx")),
source: "",
@@ -294,7 +316,7 @@ export const Index: Record = {
"excalidraw-element": {
name: "excalidraw-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/excalidraw-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/excalidraw-element.tsx")),
source: "",
@@ -349,7 +371,7 @@ export const Index: Record = {
"heading-element": {
name: "heading-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/heading-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/heading-element.tsx")),
source: "",
@@ -371,7 +393,7 @@ export const Index: Record = {
"hr-element": {
name: "hr-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/hr-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/hr-element.tsx")),
source: "",
@@ -382,7 +404,7 @@ export const Index: Record = {
"image-element": {
name: "image-element",
type: "registry:ui",
- registryDependencies: ["media-popover","caption","resizable"],
+ registryDependencies: ["media-popover","caption","resizable","plate-element"],
files: ["registry/default/plate-ui/image-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/image-element.tsx")),
source: "",
@@ -470,7 +492,7 @@ export const Index: Record = {
"link-element": {
name: "link-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/link-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/link-element.tsx")),
source: "",
@@ -503,7 +525,7 @@ export const Index: Record = {
"list-element": {
name: "list-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/list-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/list-element.tsx")),
source: "",
@@ -536,7 +558,7 @@ export const Index: Record = {
"media-embed-element": {
name: "media-embed-element",
type: "registry:ui",
- registryDependencies: ["media-popover","caption","resizable"],
+ registryDependencies: ["media-popover","caption","resizable","plate-element"],
files: ["registry/default/plate-ui/media-embed-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/media-embed-element.tsx")),
source: "",
@@ -569,7 +591,7 @@ export const Index: Record = {
"mention-element": {
name: "mention-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element","use-mounted"],
files: ["registry/default/plate-ui/mention-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/mention-element.tsx")),
source: "",
@@ -580,7 +602,7 @@ export const Index: Record = {
"mention-input-element": {
name: "mention-input-element",
type: "registry:ui",
- registryDependencies: ["inline-combobox"],
+ registryDependencies: ["inline-combobox","plate-element"],
files: ["registry/default/plate-ui/mention-input-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/mention-input-element.tsx")),
source: "",
@@ -624,7 +646,7 @@ export const Index: Record = {
"paragraph-element": {
name: "paragraph-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/paragraph-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/paragraph-element.tsx")),
source: "",
@@ -679,7 +701,7 @@ export const Index: Record = {
"slash-input-element": {
name: "slash-input-element",
type: "registry:ui",
- registryDependencies: ["inline-combobox"],
+ registryDependencies: ["inline-combobox","plate-element"],
files: ["registry/default/plate-ui/slash-input-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/slash-input-element.tsx")),
source: "",
@@ -690,7 +712,7 @@ export const Index: Record = {
"table-cell-element": {
name: "table-cell-element",
type: "registry:ui",
- registryDependencies: ["resizable"],
+ registryDependencies: ["resizable","plate-element"],
files: ["registry/default/plate-ui/table-cell-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/table-cell-element.tsx")),
source: "",
@@ -712,7 +734,7 @@ export const Index: Record = {
"table-element": {
name: "table-element",
type: "registry:ui",
- registryDependencies: ["dropdown-menu"],
+ registryDependencies: ["dropdown-menu","plate-element"],
files: ["registry/default/plate-ui/table-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/table-element.tsx")),
source: "",
@@ -723,7 +745,7 @@ export const Index: Record = {
"table-row-element": {
name: "table-row-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/table-row-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/table-row-element.tsx")),
source: "",
@@ -734,7 +756,7 @@ export const Index: Record = {
"todo-list-element": {
name: "todo-list-element",
type: "registry:ui",
- registryDependencies: ["checkbox"],
+ registryDependencies: ["checkbox","plate-element"],
files: ["registry/default/plate-ui/todo-list-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/todo-list-element.tsx")),
source: "",
@@ -745,7 +767,7 @@ export const Index: Record = {
"toggle-element": {
name: "toggle-element",
type: "registry:ui",
- registryDependencies: [],
+ registryDependencies: ["plate-element"],
files: ["registry/default/plate-ui/toggle-element.tsx"],
component: React.lazy(() => import("@/registry/default/plate-ui/toggle-element.tsx")),
source: "",
@@ -1116,5 +1138,16 @@ export const Index: Record = {
subcategory: "undefined",
chunks: []
},
+ "use-mounted": {
+ name: "use-mounted",
+ type: "registry:hook",
+ registryDependencies: undefined,
+ files: ["registry/default/hooks/use-mounted.ts"],
+ component: React.lazy(() => import("@/registry/default/hooks/use-mounted.ts")),
+ source: "",
+ category: "undefined",
+ subcategory: "undefined",
+ chunks: []
+ },
},
}
diff --git a/apps/www/src/app/_components/installation-tab.tsx b/apps/www/src/app/_components/installation-tab.tsx
index 1a0b9c692c..e2f8973994 100644
--- a/apps/www/src/app/_components/installation-tab.tsx
+++ b/apps/www/src/app/_components/installation-tab.tsx
@@ -23,7 +23,7 @@ import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { customizerItems } from '@/config/customizer-items';
import { allPlugins, orderedPluginKeys } from '@/config/customizer-list';
-import { useMounted } from '@/hooks/use-mounted';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
import { InstallationCode } from './installation-code';
diff --git a/apps/www/src/components/context/check-plugin.tsx b/apps/www/src/components/context/check-plugin.tsx
index 0a3d7297df..55b8add34f 100644
--- a/apps/www/src/components/context/check-plugin.tsx
+++ b/apps/www/src/components/context/check-plugin.tsx
@@ -35,10 +35,6 @@ export const CheckPlugin = ({
// }
// enable if plugin is enabled
if (plugin && !editor?.plugins[plugin.key]) {
- if (plugin.key === 'bold') {
- console.log('bold', editor?.plugins[plugin.key]);
- }
-
isEnabled = false;
}
if (!isEnabled) {
diff --git a/apps/www/src/components/customizer-drawer.tsx b/apps/www/src/components/customizer-drawer.tsx
index 23c4277c8b..d7e7b25507 100644
--- a/apps/www/src/components/customizer-drawer.tsx
+++ b/apps/www/src/components/customizer-drawer.tsx
@@ -6,8 +6,8 @@ import * as React from 'react';
import * as SheetPrimitive from '@radix-ui/react-dialog';
import { ChevronsRight } from 'lucide-react';
-import { useMounted } from '@/hooks/use-mounted';
import { useViewport } from '@/hooks/use-viewport';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
import { Button } from '@/registry/default/plate-ui/button';
import { settingsStore } from './context/settings-store';
diff --git a/apps/www/src/components/theme-customizer.tsx b/apps/www/src/components/theme-customizer.tsx
index f440f25c71..3da530cc09 100644
--- a/apps/www/src/components/theme-customizer.tsx
+++ b/apps/www/src/components/theme-customizer.tsx
@@ -12,9 +12,9 @@ import { cn } from '@udecode/cn';
import { useTheme } from 'next-themes';
import { useConfig } from '@/hooks/use-config';
-import { useMounted } from '@/hooks/use-mounted';
import { useThemesConfig } from '@/hooks/use-themes-config';
import { THEMES } from '@/lib/themes';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
import { Button } from '@/registry/default/plate-ui/button';
import {
Popover,
diff --git a/apps/www/src/components/themes-selector-mini.tsx b/apps/www/src/components/themes-selector-mini.tsx
index f120f9d550..a6e076a648 100644
--- a/apps/www/src/components/themes-selector-mini.tsx
+++ b/apps/www/src/components/themes-selector-mini.tsx
@@ -4,9 +4,9 @@ import * as React from 'react';
import { useTheme } from 'next-themes';
-import { useMounted } from '@/hooks/use-mounted';
import { useThemesConfig } from '@/hooks/use-themes-config';
import { type Theme, THEME_LIST, THEMES } from '@/lib/themes';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
import { cn } from '@/registry/default/lib/utils';
import {
Tooltip,
diff --git a/apps/www/src/components/themes-selector.tsx b/apps/www/src/components/themes-selector.tsx
index d7edd3b1a1..c1e43333cd 100644
--- a/apps/www/src/components/themes-selector.tsx
+++ b/apps/www/src/components/themes-selector.tsx
@@ -5,9 +5,9 @@ import * as React from 'react';
import { useTheme } from 'next-themes';
import { useMediaQuery } from '@/hooks/use-media-query';
-import { useMounted } from '@/hooks/use-mounted';
import { useThemesConfig } from '@/hooks/use-themes-config';
import { type Theme, THEME_LIST } from '@/lib/themes';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
import { cn } from '@/registry/default/lib/utils';
import {
Tooltip,
diff --git a/apps/www/src/components/themes-styles.tsx b/apps/www/src/components/themes-styles.tsx
index 8e34c67b7d..32f39cc4e0 100644
--- a/apps/www/src/components/themes-styles.tsx
+++ b/apps/www/src/components/themes-styles.tsx
@@ -1,8 +1,8 @@
'use client';
import { useConfig } from '@/hooks/use-config';
-import { useMounted } from '@/hooks/use-mounted';
import { useThemesConfig } from '@/hooks/use-themes-config';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
export function ThemesStyle() {
const [config] = useConfig();
diff --git a/apps/www/src/lib/themes.ts b/apps/www/src/lib/themes.ts
index 9e145ac4f9..b1244c4080 100644
--- a/apps/www/src/lib/themes.ts
+++ b/apps/www/src/lib/themes.ts
@@ -6,11 +6,13 @@ const _THEMES = {
accentForeground: '0 0% 100%', // #FFFFFF
background: '38 100% 99%', // #FAFAFA
border: '44 17% 88%', // #E7E8E9
+ brand: '35 100% 50%', // #FF9940
card: '38 100% 99%', // #FAFAFA
cardForeground: '0 0% 9%', // #171717
destructive: '0 100% 67%', // #FF3333
destructiveForeground: '0 0% 100%', // #FFFFFF
foreground: '0 0% 9%', // #171717
+ highlight: '50 100% 60%', // #FFD740
input: '44 17% 88%', // #E7E8E9
muted: '44 17% 88%', // #E7E8E9
mutedForeground: '0 0% 45%', // #737373
@@ -27,11 +29,13 @@ const _THEMES = {
accentForeground: '0 0% 100%', // #FFFFFF
background: '220 27% 18%', // #1F2430
border: '220 13% 26%', // #33415E
+ brand: '35 100% 50%', // #FF9940
card: '220 27% 18%', // #1F2430
cardForeground: '0 0% 100%', // #FFFFFF
destructive: '0 100% 67%', // #FF3333
destructiveForeground: '0 0% 100%', // #FFFFFF
foreground: '0 0% 100%', // #FFFFFF
+ highlight: '50 100% 60%', // #FFD740
input: '220 13% 26%', // #33415E
muted: '220 13% 26%', // #33415E
mutedForeground: '220 13% 65%', // #8A9199
@@ -63,11 +67,13 @@ const _THEMES = {
accentForeground: '220 23% 20%',
background: '220 23% 95%',
border: '220 13% 90%',
+ brand: '266 85% 58%', // Same as primary
card: '220 23% 93%',
cardForeground: '234 16% 30%',
destructive: '3 87% 37%',
destructiveForeground: '3 87% 97%',
foreground: '234 16% 35%',
+ highlight: '266 30% 75%', // Same as secondary
input: '220 13% 87%',
muted: '220 12% 90%',
mutedForeground: '220 12% 30%',
@@ -85,11 +91,13 @@ const _THEMES = {
'accent-foreground': '240 21% 90%',
background: '240 21% 15%',
border: '240 11% 20%',
+ brand: '267 84% 81%', // Same as primary
card: '240 21% 13%',
'card-foreground': '226 64% 93%',
destructive: '8 96% 56%',
destructiveForeground: '0 0% 100%',
foreground: '226 64% 88%',
+ highlight: '267 30% 25%', // Same as secondary
input: '240 11% 23%',
muted: '240 12% 19%',
'muted-foreground': '240 12% 69%',
@@ -121,11 +129,13 @@ const _THEMES = {
'accent-foreground': '240 5.9% 10%',
background: '0 0% 100%',
border: '240 5.9% 90%',
+ brand: '240 5.9% 10%', // Same as primary
card: '0 0% 100%',
'card-foreground': '240 10% 3.9%',
destructive: '0 84.2% 60.2%',
'destructive-foreground': '0 0% 98%',
foreground: '240 10% 3.9%',
+ highlight: '240 4.8% 95.9%', // Same as secondary
input: '240 5.9% 90%',
muted: '240 4.8% 95.9%',
'muted-foreground': '240 3.8% 46.1%',
@@ -142,11 +152,13 @@ const _THEMES = {
'accent-foreground': '0 0% 98%',
background: '240 10% 3.9%',
border: '240 3.7% 15.9%',
+ brand: '0 0% 98%', // Same as primary
card: '240 10% 3.9%',
'card-foreground': '0 0% 98%',
destructive: '0 62.8% 30.6%',
'destructive-foreground': '0 0% 98%',
foreground: '0 0% 98%',
+ highlight: '240 3.7% 15.9%', // Same as secondary
input: '240 3.7% 15.9%',
muted: '240 3.7% 15.9%',
'muted-foreground': '240 5% 64.9%',
@@ -178,11 +190,13 @@ const _THEMES = {
'accent-foreground': '240 5.9% 10%',
background: '0 0% 100%',
border: '240 5.9% 90%',
+ brand: '217.2 91.2% 59.8%',
card: '0 0% 100%',
'card-foreground': '240 10% 3.9%',
destructive: '0 84.2% 60.2%',
'destructive-foreground': '0 0% 98%',
foreground: '240 10% 3.9%',
+ highlight: '47.9 95.8% 53.1%',
input: '240 5.9% 90%',
muted: '240 4.8% 95.9%',
'muted-foreground': '240 3.8% 46.1%',
@@ -199,11 +213,13 @@ const _THEMES = {
'accent-foreground': '0 0% 98%',
background: '240 10% 3.9%',
border: '240 3.7% 15.9%',
+ brand: '213.3 93.9% 67.8%',
card: '240 10% 3.9%',
'card-foreground': '0 0% 98%',
destructive: '0 62.8% 30.6%',
'destructive-foreground': '0 0% 98%',
foreground: '0 0% 98%',
+ highlight: '48 96% 53%',
input: '240 3.7% 15.9%',
muted: '240 3.7% 15.9%',
'muted-foreground': '240 5% 64.9%',
@@ -235,11 +251,13 @@ const _THEMES = {
accentForeground: '36 45% 25%',
background: '43 47% 92%',
border: '43 27% 84%',
+ brand: '39 14% 22%', // #3D3A34
card: '43 47% 92%',
cardForeground: '39 14% 22%',
destructive: '0 84% 33%',
destructiveForeground: '0 0% 100%',
foreground: '39 14% 22%',
+ highlight: '36 33% 75%', // #C9B99B
input: '43 27% 84%',
muted: '43 27% 84%',
mutedForeground: '39 14% 46%',
@@ -256,11 +274,13 @@ const _THEMES = {
accentForeground: '36 45% 75%',
background: '39 14% 12%',
border: '43 27% 16%',
+ brand: '43 47% 88%', // #EBE6D5
card: '39 14% 14%',
cardForeground: '43 47% 88%',
destructive: '0 84% 60%',
destructiveForeground: '0 0% 100%',
foreground: '43 47% 88%',
+ highlight: '36 33% 25%', // #564F3F
input: '43 27% 16%',
muted: '43 27% 16%',
mutedForeground: '39 14% 64%',
@@ -291,11 +311,13 @@ const _THEMES = {
accentForeground: '44 96% 98%', // #fdf6e3
background: '44 96% 98%', // #fdf6e3
border: '44 24% 83%', // #e0dcc7
+ brand: '142 40% 46%', // #8DA101
card: '44 96% 98%', // #fdf6e3
cardForeground: '151 17% 39%', // #5c6a72
destructive: '3 89% 65%', // #f85552
destructiveForeground: '44 96% 98%', // #fdf6e3
foreground: '151 17% 39%', // #5c6a72
+ highlight: '88 23% 63%', // #A7C080
input: '44 24% 83%', // #e0dcc7
muted: '44 24% 95%', // #f4f0d9
mutedForeground: '151 9% 63%', // #939f91
@@ -312,11 +334,13 @@ const _THEMES = {
'accent-foreground': '220 17% 20%',
background: '220 17% 20%',
border: '210 9% 33%',
+ brand: '88 23% 63%', // #A7C080
card: '220 17% 24%',
'card-foreground': '39 14% 74%',
destructive: '0 43% 70%',
'destructive-foreground': '39 14% 74%',
foreground: '39 14% 74%',
+ highlight: '142 40% 46%', // #8DA101
input: '210 9% 33%',
muted: '210 9% 33%',
'muted-foreground': '95 8% 53%',
@@ -348,11 +372,13 @@ const _THEMES = {
accentForeground: '0 0% 100%',
background: '0 0% 100%',
border: '210 18% 87%',
+ brand: '215 69% 43%', // #2F81F7
card: '0 0% 100%',
cardForeground: '215 14% 34%',
destructive: '0 72% 51%',
destructiveForeground: '0 0% 100%',
foreground: '215 14% 34%',
+ highlight: '212 92% 45%', // #1F6FEB
input: '210 18% 87%',
muted: '210 18% 96%',
mutedForeground: '215 14% 45%',
@@ -369,11 +395,13 @@ const _THEMES = {
accentForeground: '210 14% 93%',
background: '215 28% 17%',
border: '215 14% 25%',
+ brand: '212 92% 45%', // #1F6FEB
card: '215 28% 17%',
cardForeground: '210 14% 93%',
destructive: '0 72% 51%',
destructiveForeground: '210 14% 93%',
foreground: '210 14% 93%',
+ highlight: '215 69% 43%', // #2F81F7
input: '215 14% 25%',
muted: '215 14% 25%',
mutedForeground: '217 10% 64%',
@@ -405,11 +433,13 @@ const _THEMES = {
accentForeground: '345 6% 30%', // #52484e
background: '345 6% 95%', // #fdf0ed
border: '345 6% 85%', // #e4d8d4
+ brand: '345 80% 70%', // #F075B5
card: '345 6% 93%', // #f9e8e4
cardForeground: '345 6% 30%', // #52484e
destructive: '0 72% 51%', // #e33400
destructiveForeground: '345 6% 95%', // #fdf0ed
foreground: '345 6% 30%', // #52484e
+ highlight: '344 96% 92%', // #FCEAE5
input: '345 6% 85%', // #e4d8d4
muted: '345 6% 90%', // #eee0dc
mutedForeground: '345 6% 50%', // #8b7b82
@@ -426,11 +456,13 @@ const _THEMES = {
accentForeground: '345 6% 30%', // #52484e
background: '345 6% 15%', // #1c1e26
border: '345 6% 25%', // #3d3741
+ brand: '345 80% 70%', // #F075B5
card: '345 6% 17%', // #232530
cardForeground: '345 6% 80%', // #d5d0d2
destructive: '0 72% 51%', // #e33400
destructiveForeground: '345 6% 95%', // #fdf0ed
foreground: '345 6% 80%', // #d5d0d2
+ highlight: '344 96% 92%', // #FCEAE5
input: '345 6% 25%', // #3d3741
muted: '345 6% 20%', // #2e3037
mutedForeground: '345 6% 60%', // #a39fa1
@@ -462,11 +494,13 @@ const _THEMES = {
'accent-foreground': '0 0% 98%', // #FBFBFB
background: '0 0% 98%', // #FBFBFB
border: '220 9% 93%', // #edeef1
+ brand: '220 13% 86%', // #E1E3E8
card: '220 13% 95%', // #f2f3f5
'card-foreground': '216 14% 43%', // #5d6a7e
destructive: '0 80% 60%', // #ef4343
'destructive-foreground': '0 0% 98%', // #FBFBFB
foreground: '216 14% 43%', // #5d6a7e
+ highlight: '220 13% 93%', // #F1F2F4
input: '220 13% 91%', // #e8eaee
muted: '220 13% 91%', // #e8eaee
'muted-foreground': '215 13% 65%', // #8b96a9
@@ -484,11 +518,13 @@ const _THEMES = {
'accent-foreground': '220 5% 77%', // #c1c3c8
background: '220 7% 13%', // #1f2023
border: '225 6% 19%', // #2e2f33
+ brand: '220 13% 86%', // #E1E3E8
card: '225 5% 17%', // #292a2e
'card-foreground': '220 5% 77%', // #c1c3c8
destructive: '0 72% 63%', // #eb5757
'destructive-foreground': '220 5% 77%', // #c1c3c8
foreground: '220 5% 77%', // #c1c3c8
+ highlight: '220 13% 93%', // #F1F2F4
input: '225 7% 21%', // #323439
muted: '225 7% 21%', // #323439
'muted-foreground': '220 5% 57%', // #8b8e98
@@ -520,11 +556,13 @@ const _THEMES = {
'accent-foreground': '220 13% 93%',
background: '220 13% 18%',
border: '220 3% 23%',
+ brand: '220 13% 86%', // #E1E3E8
card: '220 13% 16%',
'card-foreground': '219 14% 76%',
destructive: '6 97% 49%',
'destructive-foreground': '0 0% 100%',
foreground: '219 14% 71%',
+ highlight: '220 13% 93%', // #F1F2F4
input: '220 3% 26%',
muted: '220 12% 22%',
'muted-foreground': '220 12% 72%',
@@ -541,11 +579,13 @@ const _THEMES = {
'accent-foreground': '220 13% 93%',
background: '220 13% 18%',
border: '220 3% 23%',
+ brand: '220 13% 86%', // #E1E3E8
card: '220 13% 16%',
'card-foreground': '219 14% 76%',
destructive: '6 97% 49%',
'destructive-foreground': '0 0% 100%',
foreground: '219 14% 71%',
+ highlight: '220 13% 93%', // #F1F2F4
input: '220 3% 26%',
muted: '220 12% 22%',
'muted-foreground': '220 12% 72%',
@@ -570,7 +610,7 @@ const _THEMES = {
name: 'One Dark Pro',
radius: 0.5,
},
-} as const;
+};
Object.entries(_THEMES).forEach(([key, theme]) => {
(_THEMES as any)[key] = {
diff --git a/apps/www/src/registry/default/example/playground-demo.tsx b/apps/www/src/registry/default/example/playground-demo.tsx
index 02f9813445..ed43d1c3c0 100644
--- a/apps/www/src/registry/default/example/playground-demo.tsx
+++ b/apps/www/src/registry/default/example/playground-demo.tsx
@@ -366,7 +366,7 @@ export default function PlaygroundDemo({
className={cn(
'relative flex max-h-[800px] w-full overflow-x-auto',
// block selection area
- '[&_.slate-selected]:!bg-primary/20 [&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10',
+ '[&_.slate-selection-area]:border [&_.slate-selection-area]:border-brand/25 [&_.slate-selection-area]:bg-brand/15',
className
)}
data-plate-selectable
diff --git a/apps/www/src/hooks/use-mounted.ts b/apps/www/src/registry/default/hooks/use-mounted.ts
similarity index 100%
rename from apps/www/src/hooks/use-mounted.ts
rename to apps/www/src/registry/default/hooks/use-mounted.ts
diff --git a/apps/www/src/registry/default/plate-ui/block-selection.tsx b/apps/www/src/registry/default/plate-ui/block-selection.tsx
new file mode 100644
index 0000000000..a9d1b20359
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/block-selection.tsx
@@ -0,0 +1,37 @@
+import { useBlockSelected } from '@udecode/plate-selection/react';
+import { type VariantProps, cva } from 'class-variance-authority';
+
+const blockSelectionVariants = cva(
+ 'pointer-events-none absolute inset-0 z-[1] bg-brand/[.13] transition-opacity',
+ {
+ defaultVariants: {
+ active: false,
+ },
+ variants: {
+ active: {
+ false: 'opacity-0',
+ true: 'opacity-100',
+ },
+ },
+ }
+);
+
+export function BlockSelection({
+ className,
+ ...props
+}: React.HTMLAttributes &
+ VariantProps) {
+ const isBlockSelected = useBlockSelected();
+
+ if (!isBlockSelected) return null;
+
+ return (
+
+ );
+}
diff --git a/apps/www/src/registry/default/plate-ui/blockquote-element.tsx b/apps/www/src/registry/default/plate-ui/blockquote-element.tsx
index 8c85b5303d..f6fa8a208e 100644
--- a/apps/www/src/registry/default/plate-ui/blockquote-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/blockquote-element.tsx
@@ -3,18 +3,19 @@
import React from 'react';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+
+import { PlateElement } from './plate-element';
export const BlockquoteElement = withRef(
({ children, className, ...props }, ref) => {
return (
- {children}
+ {children}
);
}
diff --git a/apps/www/src/registry/default/plate-ui/code-block-element.tsx b/apps/www/src/registry/default/plate-ui/code-block-element.tsx
index fbb17b1c84..afc18a529e 100644
--- a/apps/www/src/registry/default/plate-ui/code-block-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/code-block-element.tsx
@@ -4,9 +4,9 @@ import React from 'react';
import { cn, withRef } from '@udecode/cn';
import { useCodeBlockElementState } from '@udecode/plate-code-block/react';
-import { PlateElement } from '@udecode/plate-common/react';
import { CodeBlockCombobox } from './code-block-combobox';
+import { PlateElement } from './plate-element';
import './code-block-element.css';
diff --git a/apps/www/src/registry/default/plate-ui/code-line-element.tsx b/apps/www/src/registry/default/plate-ui/code-line-element.tsx
index 061b8375c0..f07b89c191 100644
--- a/apps/www/src/registry/default/plate-ui/code-line-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/code-line-element.tsx
@@ -3,7 +3,7 @@
import React from 'react';
import { withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
export const CodeLineElement = withRef((props, ref) => (
diff --git a/apps/www/src/registry/default/plate-ui/column-element.tsx b/apps/www/src/registry/default/plate-ui/column-element.tsx
index 591a3f5235..cfe7a1dbe9 100644
--- a/apps/www/src/registry/default/plate-ui/column-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/column-element.tsx
@@ -3,10 +3,12 @@ import React from 'react';
import type { TColumnElement } from '@udecode/plate-layout';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement, useElement, withHOC } from '@udecode/plate-common/react';
+import { useElement, withHOC } from '@udecode/plate-common/react';
import { ResizableProvider } from '@udecode/plate-resizable';
import { useReadOnly } from 'slate-react';
+import { PlateElement } from './plate-element';
+
export const ColumnElement = withHOC(
ResizableProvider,
withRef(({ children, className, ...props }, ref) => {
diff --git a/apps/www/src/registry/default/plate-ui/column-group-element.tsx b/apps/www/src/registry/default/plate-ui/column-group-element.tsx
index f150672086..484f9383a9 100644
--- a/apps/www/src/registry/default/plate-ui/column-group-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/column-group-element.tsx
@@ -3,11 +3,7 @@ import React from 'react';
import type { TColumnElement } from '@udecode/plate-layout';
import { cn, withRef } from '@udecode/cn';
-import {
- PlateElement,
- useElement,
- useRemoveNodeButton,
-} from '@udecode/plate-common/react';
+import { useElement, useRemoveNodeButton } from '@udecode/plate-common/react';
import {
ColumnItemPlugin,
useColumnState,
@@ -18,6 +14,7 @@ import { useReadOnly } from 'slate-react';
import { Icons } from '@/components/icons';
import { Button } from './button';
+import { PlateElement } from './plate-element';
import { Popover, PopoverAnchor, PopoverContent } from './popover';
import { Separator } from './separator';
diff --git a/apps/www/src/registry/default/plate-ui/comment-leaf.tsx b/apps/www/src/registry/default/plate-ui/comment-leaf.tsx
index 2420a20a2f..0751d01dac 100644
--- a/apps/www/src/registry/default/plate-ui/comment-leaf.tsx
+++ b/apps/www/src/registry/default/plate-ui/comment-leaf.tsx
@@ -26,7 +26,7 @@ export function CommentLeaf({
if (!state.isActive) {
for (let i = 1; i < state.commentCount; i++) {
- aboveChildren = {aboveChildren} ;
+ aboveChildren = {aboveChildren} ;
}
}
@@ -34,8 +34,8 @@ export function CommentLeaf({
(
diff --git a/apps/www/src/registry/default/plate-ui/draggable.tsx b/apps/www/src/registry/default/plate-ui/draggable.tsx
index e5bd1f2296..1a5438a8ee 100644
--- a/apps/www/src/registry/default/plate-ui/draggable.tsx
+++ b/apps/www/src/registry/default/plate-ui/draggable.tsx
@@ -1,19 +1,26 @@
+/* eslint-disable tailwindcss/no-custom-classname */
'use client';
import React from 'react';
-import type { ClassNames, TEditor } from '@udecode/plate-common';
+import type { TEditor } from '@udecode/plate-common';
import type { DropTargetMonitor } from 'react-dnd';
import { cn, withRef } from '@udecode/cn';
import {
type PlateElementProps,
+ MemoizedChildren,
+ useEditorPlugin,
useEditorRef,
+ withHOC,
} from '@udecode/plate-common/react';
import {
type DragItemNode,
+ DraggableProvider,
useDraggable,
+ useDraggableGutter,
useDraggableState,
+ useDropLine,
} from '@udecode/plate-dnd';
import { BlockSelectionPlugin } from '@udecode/plate-selection/react';
@@ -27,38 +34,7 @@ import {
TooltipTrigger,
} from './tooltip';
-export interface DraggableProps
- extends PlateElementProps,
- ClassNames<{
- /** Block. */
- block: string;
-
- /** Block and gutter. */
- blockAndGutter: string;
-
- /** Block toolbar in the gutter. */
- blockToolbar: string;
-
- /**
- * Block toolbar wrapper in the gutter left. It has the height of a line
- * of the block.
- */
- blockToolbarWrapper: string;
-
- blockWrapper: string;
-
- /** Button to dnd the block, in the block toolbar. */
- dragHandle: string;
-
- /** Icon of the drag button, in the drag icon. */
- dragIcon: string;
-
- /** Show a dropline above or below the block when dragging a block. */
- dropLine: string;
-
- /** Gutter at the left side of the editor. It has the height of the block */
- gutterLeft: string;
- }> {
+export interface DraggableProps extends PlateElementProps {
/**
* Intercepts the drop handling. If `false` is returned, the default drop
* behavior is called after. If `true` is returned, the default behavior is
@@ -75,7 +51,82 @@ export interface DraggableProps
) => boolean;
}
-const DragHandle = () => {
+export const Draggable = withHOC(
+ DraggableProvider,
+ withRef<'div', DraggableProps>(
+ ({ className, onDropHandler, ...props }, ref) => {
+ const { children, element } = props;
+
+ const state = useDraggableState({ element, onDropHandler });
+ const { isDragging } = state;
+ const { previewRef, handleRef } = useDraggable(state);
+
+ return (
+
+
+
+
+
+
+ {children}
+
+
+
+
+ );
+ }
+ )
+);
+
+const Gutter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ children, className, ...props }, ref) => {
+ const { useOption } = useEditorPlugin(BlockSelectionPlugin);
+ const isSelectionAreaVisible = useOption('isSelectionAreaVisible');
+ const gutter = useDraggableGutter();
+
+ return (
+
+ {children}
+
+ );
+});
+
+const DragHandle = React.memo(() => {
const editor = useEditorRef();
return (
@@ -87,16 +138,11 @@ const DragHandle = () => {
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
-
- // if (element.id) {
- // editor.getApi(BlockSelectionPlugin).blockSelection.addSelectedRow(element.id as string);
- // api.blockContextMenu.show(editor.id, event as any);
- // }
}}
onMouseDown={() => {
editor
.getApi(BlockSelectionPlugin)
- .blockSelection.resetSelectedIds();
+ .blockSelection?.resetSelectedIds();
}}
/>
@@ -106,75 +152,32 @@ const DragHandle = () => {
);
-};
-
-export const Draggable = withRef<'div', DraggableProps>(
- ({ className, classNames = {}, onDropHandler, ...props }, ref) => {
- const { children, element } = props;
-
- const state = useDraggableState({ element, onDropHandler });
- const { dropLine, isDragging, isHovered } = state;
- const {
- droplineProps,
- groupProps,
- gutterLeftProps,
- previewRef,
- handleRef,
- } = useDraggable(state);
-
- return (
-
+});
+
+const DropLine = React.memo(
+ React.forwardRef
>(
+ ({ children, className, ...props }, ref) => {
+ const state = useDropLine();
+
+ if (!state.dropLine) return null;
+
+ return (
-
-
{children}
-
- {!!dropLine && (
-
- )}
-
- );
- }
+ );
+ }
+ )
);
diff --git a/apps/www/src/registry/default/plate-ui/emoji-input-element.tsx b/apps/www/src/registry/default/plate-ui/emoji-input-element.tsx
index e170a8f48a..96f43b3dcd 100644
--- a/apps/www/src/registry/default/plate-ui/emoji-input-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/emoji-input-element.tsx
@@ -1,7 +1,7 @@
import React, { useMemo, useState } from 'react';
import { withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
import { EmojiInlineIndexSearch, insertEmoji } from '@udecode/plate-emoji';
import { useDebounce } from '@/registry/default/hooks/use-debounce';
diff --git a/apps/www/src/registry/default/plate-ui/excalidraw-element.tsx b/apps/www/src/registry/default/plate-ui/excalidraw-element.tsx
index edae36299a..f686afc786 100644
--- a/apps/www/src/registry/default/plate-ui/excalidraw-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/excalidraw-element.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
import { useExcalidrawElement } from '@udecode/plate-excalidraw/react';
export const ExcalidrawElement = withRef(
diff --git a/apps/www/src/registry/default/plate-ui/heading-element.tsx b/apps/www/src/registry/default/plate-ui/heading-element.tsx
index 982b24bff2..66349fdc58 100644
--- a/apps/www/src/registry/default/plate-ui/heading-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/heading-element.tsx
@@ -1,9 +1,10 @@
import React from 'react';
import { withRef, withVariants } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
import { cva } from 'class-variance-authority';
+import { PlateElement } from './plate-element';
+
const headingVariants = cva('relative mb-1', {
variants: {
variant: {
@@ -36,17 +37,15 @@ export const HeadingElement = withRef(
({ children, isFirstBlock, variant = 'h1', ...props }, ref) => {
const { editor, element } = props;
- const Element = variant!;
-
return (
- {children}
+ {children}
);
}
diff --git a/apps/www/src/registry/default/plate-ui/highlight-leaf.tsx b/apps/www/src/registry/default/plate-ui/highlight-leaf.tsx
index c66ca113a6..3e7508ce77 100644
--- a/apps/www/src/registry/default/plate-ui/highlight-leaf.tsx
+++ b/apps/www/src/registry/default/plate-ui/highlight-leaf.tsx
@@ -8,7 +8,7 @@ export const HighlightLeaf = withRef(
{children}
diff --git a/apps/www/src/registry/default/plate-ui/hr-element.tsx b/apps/www/src/registry/default/plate-ui/hr-element.tsx
index 99d57c3a61..f4213f75b3 100644
--- a/apps/www/src/registry/default/plate-ui/hr-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/hr-element.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
import { useFocused, useSelected } from 'slate-react';
export const HrElement = withRef(
diff --git a/apps/www/src/registry/default/plate-ui/image-element.tsx b/apps/www/src/registry/default/plate-ui/image-element.tsx
index ab35dce7b4..80bafdaaad 100644
--- a/apps/www/src/registry/default/plate-ui/image-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/image-element.tsx
@@ -1,12 +1,13 @@
import React from 'react';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement, withHOC } from '@udecode/plate-common/react';
+import { withHOC } from '@udecode/plate-common/react';
import { Image, ImagePlugin, useMediaState } from '@udecode/plate-media/react';
import { ResizableProvider, useResizableStore } from '@udecode/plate-resizable';
import { Caption, CaptionTextarea } from './caption';
import { MediaPopover } from './media-popover';
+import { PlateElement } from './plate-element';
import {
Resizable,
ResizeHandle,
diff --git a/apps/www/src/registry/default/plate-ui/link-element.tsx b/apps/www/src/registry/default/plate-ui/link-element.tsx
index f2188bfad3..069156489d 100644
--- a/apps/www/src/registry/default/plate-ui/link-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/link-element.tsx
@@ -3,9 +3,11 @@ import React from 'react';
import type { TLinkElement } from '@udecode/plate-link';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement, useElement } from '@udecode/plate-common/react';
+import { useElement } from '@udecode/plate-common/react';
import { useLink } from '@udecode/plate-link/react';
+import { PlateElement } from './plate-element';
+
export const LinkElement = withRef(
({ children, className, ...props }, ref) => {
const element = useElement();
@@ -14,7 +16,7 @@ export const LinkElement = withRef(
return (
(
{...(linkProps as any)}
{...props}
>
- {children}
+ {children}
);
}
diff --git a/apps/www/src/registry/default/plate-ui/list-element.tsx b/apps/www/src/registry/default/plate-ui/list-element.tsx
index 5f0811f678..0dae58a39f 100644
--- a/apps/www/src/registry/default/plate-ui/list-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/list-element.tsx
@@ -1,9 +1,10 @@
import React from 'react';
import { withRef, withVariants } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
import { cva } from 'class-variance-authority';
+import { PlateElement } from './plate-element';
+
const listVariants = cva('m-0 ps-6', {
variants: {
variant: {
@@ -19,11 +20,9 @@ const ListElementVariants = withVariants(PlateElement, listVariants, [
export const ListElement = withRef(
({ children, variant = 'ul', ...props }, ref) => {
- const Component = variant!;
-
return (
-
- {children}
+
+ {children}
);
}
diff --git a/apps/www/src/registry/default/plate-ui/media-embed-element.tsx b/apps/www/src/registry/default/plate-ui/media-embed-element.tsx
index 20e5b899b9..0c185ab56d 100644
--- a/apps/www/src/registry/default/plate-ui/media-embed-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/media-embed-element.tsx
@@ -3,13 +3,14 @@ import LiteYouTubeEmbed from 'react-lite-youtube-embed';
import { Tweet } from 'react-tweet';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement, withHOC } from '@udecode/plate-common/react';
+import { withHOC } from '@udecode/plate-common/react';
import { parseTwitterUrl, parseVideoUrl } from '@udecode/plate-media';
import { MediaEmbedPlugin, useMediaState } from '@udecode/plate-media/react';
import { ResizableProvider, useResizableStore } from '@udecode/plate-resizable';
import { Caption, CaptionTextarea } from './caption';
import { MediaPopover } from './media-popover';
+import { PlateElement } from './plate-element';
import {
Resizable,
ResizeHandle,
diff --git a/apps/www/src/registry/default/plate-ui/mention-element.tsx b/apps/www/src/registry/default/plate-ui/mention-element.tsx
index 724e2af49e..2c5e78fe16 100644
--- a/apps/www/src/registry/default/plate-ui/mention-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/mention-element.tsx
@@ -4,11 +4,13 @@ import type { TMentionElement } from '@udecode/plate-mention';
import { cn, withRef } from '@udecode/cn';
import { getHandler } from '@udecode/plate-common';
-import { PlateElement, useElement } from '@udecode/plate-common/react';
+import { useElement } from '@udecode/plate-common/react';
import { IS_APPLE } from '@udecode/utils';
import { useFocused, useSelected } from 'slate-react';
-import { useMounted } from '@/hooks/use-mounted';
+import { useMounted } from '@/registry/default/hooks/use-mounted';
+
+import { PlateElement } from './plate-element';
export const MentionElement = withRef<
typeof PlateElement,
diff --git a/apps/www/src/registry/default/plate-ui/mention-input-element.tsx b/apps/www/src/registry/default/plate-ui/mention-input-element.tsx
index f9fabd6308..51c93fad80 100644
--- a/apps/www/src/registry/default/plate-ui/mention-input-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/mention-input-element.tsx
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
import { getMentionOnSelectItem } from '@udecode/plate-mention';
import {
diff --git a/apps/www/src/registry/default/plate-ui/paragraph-element.tsx b/apps/www/src/registry/default/plate-ui/paragraph-element.tsx
index 9948c0df75..fc127101f4 100644
--- a/apps/www/src/registry/default/plate-ui/paragraph-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/paragraph-element.tsx
@@ -1,4 +1,20 @@
-import { withCn } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import React from 'react';
-export const ParagraphElement = withCn(PlateElement, 'm-0 px-0 py-1');
+import { cn } from '@udecode/cn';
+import { withRef } from '@udecode/plate-common/react';
+
+import { PlateElement } from './plate-element';
+
+export const ParagraphElement = withRef(
+ ({ children, className, ...props }, ref) => {
+ return (
+
+ {children}
+
+ );
+ }
+);
diff --git a/apps/www/src/registry/default/plate-ui/plate-element.tsx b/apps/www/src/registry/default/plate-ui/plate-element.tsx
new file mode 100644
index 0000000000..9782256a1a
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/plate-element.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+
+import type { PlateElementProps } from '@udecode/plate-common/react';
+
+import { cn } from '@udecode/cn';
+import { PlateElement as PlateElementPrimitive } from '@udecode/plate-common/react';
+import { useBlockSelectableStore } from '@udecode/plate-selection/react';
+
+import { BlockSelection } from './block-selection';
+
+export const PlateElement = React.forwardRef(
+ ({ children, className, ...props }: PlateElementProps, ref) => {
+ const selectable = useBlockSelectableStore().get.selectable();
+
+ return (
+
+ {children}
+
+ {selectable && }
+
+ );
+ }
+);
diff --git a/apps/www/src/registry/default/plate-ui/slash-input-element.tsx b/apps/www/src/registry/default/plate-ui/slash-input-element.tsx
index c3cd26cebb..04bf234a3b 100644
--- a/apps/www/src/registry/default/plate-ui/slash-input-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/slash-input-element.tsx
@@ -1,7 +1,8 @@
import React, { type ComponentType, type SVGProps } from 'react';
+import type { PlateEditor } from '@udecode/plate-common/react';
+
import { withRef } from '@udecode/cn';
-import { type PlateEditor, PlateElement } from '@udecode/plate-common/react';
import { DatePlugin } from '@udecode/plate-date/react';
import { HEADING_KEYS } from '@udecode/plate-heading';
import { ListStyleType, toggleIndentList } from '@udecode/plate-indent-list';
@@ -15,6 +16,7 @@ import {
InlineComboboxInput,
InlineComboboxItem,
} from './inline-combobox';
+import { PlateElement } from './plate-element';
interface SlashCommandRule {
icon: ComponentType>;
diff --git a/apps/www/src/registry/default/plate-ui/table-cell-element.tsx b/apps/www/src/registry/default/plate-ui/table-cell-element.tsx
index 4561c1d909..b04062d379 100644
--- a/apps/www/src/registry/default/plate-ui/table-cell-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/table-cell-element.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { cn, withProps, withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
import {
useTableCellElement,
useTableCellElementResizable,
@@ -9,6 +8,7 @@ import {
useTableCellElementState,
} from '@udecode/plate-table/react';
+import { PlateElement } from './plate-element';
import { ResizeHandle } from './resizable';
export const TableCellElement = withRef<
@@ -42,12 +42,10 @@ export const TableCellElement = withRef<
const { bottomProps, hiddenLeft, leftProps, rightProps } =
useTableCellElementResizable(resizableState);
- const Cell = isHeader ? 'th' : 'td';
-
return (
-
+
+ {children}
+
+
+ {!isSelectingCell && (
- {children}
-
-
- {!isSelectingCell && (
-
- {!readOnly && (
- <>
-
+ {!readOnly && (
+ <>
+
+
+ {!hiddenLeft && (
- {!hiddenLeft && (
-
- )}
+ )}
- {hovered && (
-
- )}
- {hoveredLeft && (
-
- )}
- >
- )}
-
- )}
- |
+ {hovered && (
+
+ )}
+ {hoveredLeft && (
+
+ )}
+ >
+ )}
+
+ )}
);
});
diff --git a/apps/www/src/registry/default/plate-ui/table-element.tsx b/apps/www/src/registry/default/plate-ui/table-element.tsx
index dcf850348b..5c27c6ce05 100644
--- a/apps/www/src/registry/default/plate-ui/table-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/table-element.tsx
@@ -7,7 +7,6 @@ import { PopoverAnchor } from '@radix-ui/react-popover';
import { cn, withRef } from '@udecode/cn';
import { isSelectionExpanded } from '@udecode/plate-common';
import {
- PlateElement,
useEditorRef,
useEditorSelector,
useElement,
@@ -35,6 +34,7 @@ import {
DropdownMenuPortal,
DropdownMenuTrigger,
} from './dropdown-menu';
+import { PlateElement } from './plate-element';
import { Popover, PopoverContent, popoverVariants } from './popover';
import { Separator } from './separator';
@@ -209,7 +209,7 @@ export const TableElement = withHOC(
-
-
- {colSizes.map((width, index) => (
-
- ))}
-
-
- {children}
-
+
+ {colSizes.map((width, index) => (
+
+ ))}
+
+
+ {children}
diff --git a/apps/www/src/registry/default/plate-ui/table-row-element.tsx b/apps/www/src/registry/default/plate-ui/table-row-element.tsx
index f28b267a95..b737be7b1d 100644
--- a/apps/www/src/registry/default/plate-ui/table-row-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/table-row-element.tsx
@@ -1,7 +1,8 @@
import React from 'react';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+
+import { PlateElement } from './plate-element';
export const TableRowElement = withRef<
typeof PlateElement,
@@ -12,11 +13,11 @@ export const TableRowElement = withRef<
return (
- {children}
+ {children}
);
});
diff --git a/apps/www/src/registry/default/plate-ui/toc-element.tsx b/apps/www/src/registry/default/plate-ui/toc-element.tsx
index b5d454bb44..922074de18 100644
--- a/apps/www/src/registry/default/plate-ui/toc-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/toc-element.tsx
@@ -1,5 +1,5 @@
import { cn } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
import {
useTocElement,
useTocElementState,
diff --git a/apps/www/src/registry/default/plate-ui/todo-list-element.tsx b/apps/www/src/registry/default/plate-ui/todo-list-element.tsx
index 66b155c0fa..caaa94099a 100644
--- a/apps/www/src/registry/default/plate-ui/todo-list-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/todo-list-element.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { cn, withRef } from '@udecode/cn';
-import { PlateElement } from '@udecode/plate-common/react';
+import { PlateElement } from './plate-element';
import {
useTodoListElement,
useTodoListElementState,
diff --git a/apps/www/src/registry/default/plate-ui/toggle-element.tsx b/apps/www/src/registry/default/plate-ui/toggle-element.tsx
index e9a78c8846..55363b0736 100644
--- a/apps/www/src/registry/default/plate-ui/toggle-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/toggle-element.tsx
@@ -1,5 +1,5 @@
-import { withRef } from '@udecode/cn';
-import { PlateElement, useElement } from '@udecode/plate-common/react';
+import { cn, withRef } from '@udecode/cn';
+import { useElement } from '@udecode/plate-common/react';
import {
useToggleButton,
useToggleButtonState,
@@ -7,24 +7,28 @@ import {
import { Icons } from '@/components/icons';
+import { PlateElement } from './plate-element';
+
export const ToggleElement = withRef(
- ({ children, ...props }, ref) => {
+ ({ children, className, ...props }, ref) => {
const element = useElement();
const state = useToggleButtonState(element.id as string);
const { buttonProps, open } = useToggleButton(state);
return (
-
-
-
- {open ? : }
-
- {children}
-
+
+
+ {open ? : }
+
+ {children}
);
}
diff --git a/apps/www/src/registry/default/plate-ui/with-draggables.tsx b/apps/www/src/registry/default/plate-ui/with-draggables.tsx
index f6994f7612..e374a36797 100644
--- a/apps/www/src/registry/default/plate-ui/with-draggables.tsx
+++ b/apps/www/src/registry/default/plate-ui/with-draggables.tsx
@@ -50,125 +50,104 @@ export const withDraggables = (components: any) => {
{
key: HEADING_KEYS.h1,
draggableProps: {
- classNames: {
- blockToolbarWrapper: 'h-[1.3em]',
- gutterLeft: 'px-0 pb-1 text-[1.875em]',
- },
+ className:
+ '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-1 [&_.slate-gutterLeft]:text-[1.875em]',
},
},
{
key: HEADING_KEYS.h2,
draggableProps: {
- classNames: {
- blockToolbarWrapper: 'h-[1.3em]',
- gutterLeft: 'px-0 pb-1 text-[1.5em]',
- },
+ className:
+ '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-1 [&_.slate-gutterLeft]:text-[1.5em]',
},
},
{
key: HEADING_KEYS.h3,
draggableProps: {
- classNames: {
- blockToolbarWrapper: 'h-[1.3em]',
- gutterLeft: 'pt-[2px] px-0 pb-1 text-[1.25em]',
- },
+ className:
+ '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:pt-[2px] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-1 [&_.slate-gutterLeft]:text-[1.25em]',
},
},
{
keys: [HEADING_KEYS.h4, HEADING_KEYS.h5],
draggableProps: {
- classNames: {
- blockToolbarWrapper: 'h-[1.3em]',
- gutterLeft: 'pt-[3px] px-0 pb-0 text-[1.1em]',
- },
+ className:
+ '[&_.slate-blockToolbarWrapper]:h-[1.3em] [&_.slate-gutterLeft]:pt-[3px] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0 [&_.slate-gutterLeft]:text-[1.1em]',
},
},
{
keys: [ParagraphPlugin.key],
draggableProps: {
- classNames: {
- gutterLeft: 'pt-[3px] px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-[3px] [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
keys: [HEADING_KEYS.h6, BulletedListPlugin.key, NumberedListPlugin.key],
draggableProps: {
- classNames: {
- gutterLeft: 'px-0 pb-0',
- },
+ className: '[&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: BlockquotePlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'px-0 pb-0',
- },
+ className: '[&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: CodeBlockPlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-6 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-6 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: ImagePlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-0 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: MediaEmbedPlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-0 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: ExcalidrawPlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-0 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: TogglePlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-0 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: ColumnPlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-0 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-0 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: PlaceholderPlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-3 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-3 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
{
key: TablePlugin.key,
draggableProps: {
- classNames: {
- gutterLeft: 'pt-3 px-0 pb-0',
- },
+ className:
+ '[&_.slate-gutterLeft]:pt-3 [&_.slate-gutterLeft]:px-0 [&_.slate-gutterLeft]:pb-0',
},
},
]);
diff --git a/apps/www/src/registry/registry-hooks.ts b/apps/www/src/registry/registry-hooks.ts
index e3ddb1c49e..52e856a3b2 100644
--- a/apps/www/src/registry/registry-hooks.ts
+++ b/apps/www/src/registry/registry-hooks.ts
@@ -11,4 +11,14 @@ export const hooks: Registry = [
name: 'use-debounce',
type: 'registry:hook',
},
+ {
+ files: [
+ {
+ path: 'hooks/use-mounted.ts',
+ type: 'registry:hook',
+ },
+ ],
+ name: 'use-mounted',
+ type: 'registry:hook',
+ },
];
diff --git a/apps/www/src/registry/registry-ui.ts b/apps/www/src/registry/registry-ui.ts
index 8c70727748..8cec2a27fd 100644
--- a/apps/www/src/registry/registry-ui.ts
+++ b/apps/www/src/registry/registry-ui.ts
@@ -8,6 +8,20 @@ export const ui: Registry = [
registryDependencies: [],
type: 'registry:ui',
},
+ {
+ dependencies: ['@udecode/plate-selection'],
+ files: ['plate-ui/block-selection.tsx'],
+ name: 'block-selection',
+ registryDependencies: [],
+ type: 'registry:ui',
+ },
+ {
+ dependencies: [],
+ files: ['plate-ui/plate-element.tsx'],
+ name: 'plate-element',
+ registryDependencies: ['block-selection'],
+ type: 'registry:ui',
+ },
{
dependencies: ['@udecode/plate-cloud'],
files: [
@@ -30,14 +44,14 @@ export const ui: Registry = [
'plate-ui/code-block-combobox.tsx',
],
name: 'code-block-element',
- registryDependencies: ['command'],
+ registryDependencies: ['command', 'plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-layout'],
files: ['plate-ui/column-element.tsx', 'plate-ui/column-group-element.tsx'],
name: 'column-element',
- registryDependencies: ['command', 'resizable'],
+ registryDependencies: ['command', 'resizable', 'plate-element'],
type: 'registry:ui',
},
{
@@ -79,6 +93,7 @@ export const ui: Registry = [
{
dependencies: [
'@udecode/plate-dnd',
+ '@udecode/plate-selection',
'react-dnd',
'react-dnd-html5-backend',
],
@@ -109,7 +124,7 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-emoji'],
files: ['plate-ui/emoji-input-element.tsx'],
name: 'emoji-input-element',
- registryDependencies: ['inline-combobox'],
+ registryDependencies: ['inline-combobox', 'plate-element', 'use-debounce'],
type: 'registry:ui',
},
{
@@ -130,14 +145,14 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-block-quote'],
files: ['plate-ui/blockquote-element.tsx'],
name: 'blockquote-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-date'],
files: ['plate-ui/date-element.tsx'],
name: 'date-element',
- registryDependencies: ['calendar'],
+ registryDependencies: ['calendar', 'plate-element'],
type: 'registry:ui',
},
{
@@ -179,7 +194,7 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-code-block'],
files: ['plate-ui/code-line-element.tsx'],
name: 'code-line-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
@@ -236,7 +251,7 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-excalidraw'],
files: ['plate-ui/excalidraw-element.tsx'],
name: 'excalidraw-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
@@ -281,7 +296,7 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-heading'],
files: ['plate-ui/heading-element.tsx'],
name: 'heading-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
@@ -295,14 +310,19 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-horizontal-rule'],
files: ['plate-ui/hr-element.tsx'],
name: 'hr-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-media'],
files: ['plate-ui/image-element.tsx'],
name: 'image-element',
- registryDependencies: ['media-popover', 'caption', 'resizable'],
+ registryDependencies: [
+ 'media-popover',
+ 'caption',
+ 'resizable',
+ 'plate-element',
+ ],
type: 'registry:ui',
},
{
@@ -358,7 +378,7 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-link'],
files: ['plate-ui/link-element.tsx'],
name: 'link-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
@@ -379,7 +399,7 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-list'],
files: ['plate-ui/list-element.tsx'],
name: 'list-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
@@ -404,7 +424,12 @@ export const ui: Registry = [
],
files: ['plate-ui/media-embed-element.tsx'],
name: 'media-embed-element',
- registryDependencies: ['media-popover', 'caption', 'resizable'],
+ registryDependencies: [
+ 'media-popover',
+ 'caption',
+ 'resizable',
+ 'plate-element',
+ ],
type: 'registry:ui',
},
{
@@ -425,14 +450,14 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-mention'],
files: ['plate-ui/mention-element.tsx'],
name: 'mention-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element', 'use-mounted'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-mention'],
files: ['plate-ui/mention-input-element.tsx'],
name: 'mention-input-element',
- registryDependencies: ['inline-combobox'],
+ registryDependencies: ['inline-combobox', 'plate-element'],
type: 'registry:ui',
},
{
@@ -459,7 +484,7 @@ export const ui: Registry = [
{
files: ['plate-ui/paragraph-element.tsx'],
name: 'paragraph-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
@@ -494,14 +519,14 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-heading', '@udecode/plate-indent-list'],
files: ['plate-ui/slash-input-element.tsx'],
name: 'slash-input-element',
- registryDependencies: ['inline-combobox'],
+ registryDependencies: ['inline-combobox', 'plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-table'],
files: ['plate-ui/table-cell-element.tsx'],
name: 'table-cell-element',
- registryDependencies: ['resizable'],
+ registryDependencies: ['resizable', 'plate-element'],
type: 'registry:ui',
},
{
@@ -516,28 +541,28 @@ export const ui: Registry = [
dependencies: ['@udecode/plate-table'],
files: ['plate-ui/table-element.tsx'],
name: 'table-element',
- registryDependencies: ['dropdown-menu'],
+ registryDependencies: ['dropdown-menu', 'plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-table'],
files: ['plate-ui/table-row-element.tsx'],
name: 'table-row-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-list'],
files: ['plate-ui/todo-list-element.tsx'],
name: 'todo-list-element',
- registryDependencies: ['checkbox'],
+ registryDependencies: ['checkbox', 'plate-element'],
type: 'registry:ui',
},
{
dependencies: ['@udecode/plate-toggle'],
files: ['plate-ui/toggle-element.tsx'],
name: 'toggle-element',
- registryDependencies: [],
+ registryDependencies: ['plate-element'],
type: 'registry:ui',
},
{
diff --git a/apps/www/src/styles/globals.css b/apps/www/src/styles/globals.css
index 974ee93243..5392c22921 100644
--- a/apps/www/src/styles/globals.css
+++ b/apps/www/src/styles/globals.css
@@ -24,6 +24,9 @@
--input: 240 5.9% 90%;
--ring: 240 5% 64.9%;
--radius: 0.5rem;
+
+ --brand: 217.2 91.2% 59.8%;
+ --highlight: 47.9 95.8% 53.1%;
}
.dark {
@@ -46,6 +49,9 @@
--border: 240 3.7% 25%;
--input: 240 3.7% 25%;
--ring: 240 3.7% 25%;
+
+ --brand: 213.3 93.9% 67.8%;
+ --highlight: 48 96% 53%;
}
}
diff --git a/config/eslint/bases/react.cjs b/config/eslint/bases/react.cjs
index 5d432fc66c..fa001d9dd2 100644
--- a/config/eslint/bases/react.cjs
+++ b/config/eslint/bases/react.cjs
@@ -61,13 +61,14 @@ module.exports = {
'jsx-a11y/no-static-element-interactions': 'off',
'mdx/no-unescaped-entities': 'off',
'mdx/no-unused-expressions': 'off',
-
'react/button-has-type': [
'error',
{
reset: true,
},
],
+
+ 'react/display-name': 'off',
'react/jsx-curly-brace-presence': [
'warn',
{ children: 'never', props: 'never' },
diff --git a/packages/core/src/react/editor/withPlate.ts b/packages/core/src/react/editor/withPlate.ts
index 02e53ec1af..3983138899 100644
--- a/packages/core/src/react/editor/withPlate.ts
+++ b/packages/core/src/react/editor/withPlate.ts
@@ -62,10 +62,12 @@ export const withPlate = <
const store = editor.getOptionsStore(plugin);
if (!store) {
- editor.api.debug.error(
+ editor.api.debug.warn(
`editor.useOptions: ${plugin.key} plugin is missing`,
'PLUGIN_MISSING'
);
+
+ return {};
}
return store.useStore(selector, equalityFn);
@@ -75,10 +77,12 @@ export const withPlate = <
const store = editor.getOptionsStore(plugin);
if (!store) {
- editor.api.debug.error(
+ editor.api.debug.warn(
`editor.useOption: ${plugin.key} plugin is missing`,
'PLUGIN_MISSING'
);
+
+ return;
}
const useState = (store as any)?.use[key];
diff --git a/packages/dnd/src/components/useDraggable.ts b/packages/dnd/src/components/useDraggable.ts
index 5ac0247d92..42212e39fc 100644
--- a/packages/dnd/src/components/useDraggable.ts
+++ b/packages/dnd/src/components/useDraggable.ts
@@ -3,17 +3,23 @@ import React from 'react';
import type { TEditor, TElement } from '@udecode/plate-common';
import type { DropTargetMonitor } from 'react-dnd';
+import { createAtomStore } from '@udecode/plate-common/react';
+
import { type DragItemNode, type DropLineDirection, useDndBlock } from '..';
+export const { DraggableProvider, useDraggableStore } = createAtomStore(
+ {
+ dropLine: '' as DropLineDirection,
+ },
+ { name: 'draggable' }
+);
+
export type DraggableState = {
dragRef: (
elementOrNode: Element | React.ReactElement | React.RefObject | null
) => void;
- dropLine: DropLineDirection;
isDragging: boolean;
- isHovered: boolean;
nodeRef: React.RefObject;
- setIsHovered: (isHovered: boolean) => void;
};
export const useDraggableState = (props: {
@@ -31,8 +37,7 @@ export const useDraggableState = (props: {
const { element, onDropHandler } = props;
const nodeRef = React.useRef(null);
- const [isHovered, setIsHovered] = React.useState(false);
- const { dragRef, dropLine, isDragging } = useDndBlock({
+ const { dragRef, isDragging } = useDndBlock({
id: element.id as string,
nodeRef,
onDropHandler,
@@ -40,27 +45,33 @@ export const useDraggableState = (props: {
return {
dragRef,
- dropLine,
isDragging,
- isHovered,
nodeRef,
- setIsHovered,
};
};
export const useDraggable = (state: DraggableState) => {
return {
- droplineProps: {
+ previewRef: state.nodeRef,
+ handleRef: state.dragRef,
+ };
+};
+
+export const useDraggableGutter = () => {
+ return {
+ props: {
contentEditable: false,
},
- groupProps: {
- onPointerEnter: () => state.setIsHovered(true),
- onPointerLeave: () => state.setIsHovered(false),
- },
- gutterLeftProps: {
+ };
+};
+
+export const useDropLine = () => {
+ const dropLine = useDraggableStore().get.dropLine();
+
+ return {
+ dropLine,
+ props: {
contentEditable: false,
},
- previewRef: state.nodeRef,
- handleRef: state.dragRef,
};
};
diff --git a/packages/dnd/src/hooks/useDndNode.ts b/packages/dnd/src/hooks/useDndNode.ts
index 1c2f1937df..d652a70637 100644
--- a/packages/dnd/src/hooks/useDndNode.ts
+++ b/packages/dnd/src/hooks/useDndNode.ts
@@ -1,12 +1,12 @@
-import React from 'react';
import { getEmptyImage } from 'react-dnd-html5-backend';
import type { DropTargetMonitor } from 'react-dnd';
import { type PlateEditor, useEditorRef } from '@udecode/plate-common/react';
-import type { DragItemNode, DropLineDirection } from '../types';
+import type { DragItemNode } from '../types';
+import { useDraggableStore } from '../components/useDraggable';
import { type UseDragNodeOptions, useDragNode } from './useDragNode';
import { type UseDropNodeOptions, useDropNode } from './useDropNode';
@@ -49,7 +49,7 @@ export const useDndNode = ({
}: UseDndNodeOptions) => {
const editor = useEditorRef();
- const [dropLine, setDropLine] = React.useState('');
+ const [dropLine, setDropLine] = useDraggableStore().use.dropLine();
const [{ isDragging }, dragRef, preview] = useDragNode(editor, {
id,
@@ -81,7 +81,6 @@ export const useDndNode = ({
return {
dragRef,
- dropLine,
isDragging,
isOver,
};
diff --git a/packages/react-utils/package.json b/packages/react-utils/package.json
index 8fd1c4c6bd..8ad5353e31 100644
--- a/packages/react-utils/package.json
+++ b/packages/react-utils/package.json
@@ -2,22 +2,19 @@
"name": "@udecode/react-utils",
"version": "38.0.1",
"description": "Udecode React utils",
- "license": "MIT",
+ "keywords": [
+ "utils"
+ ],
+ "bugs": {
+ "url": "https://github.com/udecode/plate/issues"
+ },
"repository": {
"type": "git",
"url": "https://github.com/udecode/plate.git",
"directory": "packages/react-utils"
},
- "bugs": {
- "url": "https://github.com/udecode/plate/issues"
- },
+ "license": "MIT",
"sideEffects": false,
- "main": "dist/index.js",
- "module": "dist/index.mjs",
- "types": "dist/index.d.ts",
- "files": [
- "dist/**/*"
- ],
"exports": {
".": {
"types": "./dist/index.d.ts",
@@ -26,10 +23,16 @@
"require": "./dist/index.js"
}
},
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist/**/*"
+ ],
"scripts": {
+ "brl": "yarn p:brl",
"build": "yarn p:build",
"build:watch": "yarn p:build:watch",
- "brl": "yarn p:brl",
"clean": "yarn p:clean",
"lint": "yarn p:lint",
"lint:fix": "yarn p:lint:fix",
@@ -46,9 +49,6 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
},
- "keywords": [
- "utils"
- ],
"publishConfig": {
"access": "public"
}
diff --git a/packages/react-utils/src/MemoizedChildren.tsx b/packages/react-utils/src/MemoizedChildren.tsx
new file mode 100644
index 0000000000..8205bf4c22
--- /dev/null
+++ b/packages/react-utils/src/MemoizedChildren.tsx
@@ -0,0 +1,7 @@
+import React from 'react';
+
+export const MemoizedChildren = React.memo(
+ ({ children }: { children: React.ReactNode }) => {
+ return <>{children}>;
+ }
+);
diff --git a/packages/react-utils/src/index.ts b/packages/react-utils/src/index.ts
index f223c04585..f32b143810 100644
--- a/packages/react-utils/src/index.ts
+++ b/packages/react-utils/src/index.ts
@@ -5,6 +5,7 @@
export * from './Box';
export * from './PortalBody';
export * from './Text';
+export * from './MemoizedChildren';
export * from './composeEventHandlers';
export * from './createPrimitiveComponent';
export * from './createPrimitiveElement';
diff --git a/packages/selection/src/react/BlockSelectionAfterEditable.tsx b/packages/selection/src/react/BlockSelectionAfterEditable.tsx
new file mode 100644
index 0000000000..f9c84c2e88
--- /dev/null
+++ b/packages/selection/src/react/BlockSelectionAfterEditable.tsx
@@ -0,0 +1,198 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import {
+ findNode,
+ getEndPoint,
+ getNextNode,
+ getPreviousNode,
+ isHotkey,
+ removeNodes,
+} from '@udecode/plate-common';
+import {
+ type EditableSiblingComponent,
+ focusEditor,
+ isEditorReadOnly,
+ useEditorPlugin,
+ useEditorRef,
+} from '@udecode/plate-common/react';
+
+import { BlockContextMenuPlugin } from './BlockContextMenuPlugin';
+import {
+ type BlockSelectionConfig,
+ BlockSelectionPlugin,
+} from './BlockSelectionPlugin';
+import { useSelectionArea } from './useSelectionArea';
+import {
+ copySelectedBlocks,
+ pasteSelectedBlocks,
+ selectInsertedBlocks,
+} from './utils';
+
+export const BlockSelectionAfterEditable: EditableSiblingComponent = () => {
+ const editor = useEditorRef();
+ const { api, getOption, getOptions, useOption } =
+ useEditorPlugin(BlockSelectionPlugin);
+ const isSelecting = useOption('isSelecting');
+ const selectedIds = useOption('selectedIds');
+ const blockContextMenu = useEditorPlugin(BlockContextMenuPlugin);
+ const isOpen = blockContextMenu.useOption('isOpen', editor.id);
+
+ useSelectionArea();
+
+ const inputRef = React.useRef(null);
+ const [isMounted, setIsMounted] = React.useState(false);
+
+ React.useEffect(() => {
+ setIsMounted(true);
+
+ return () => {
+ setIsMounted(false);
+ };
+ }, []);
+
+ React.useEffect(() => {
+ if (isSelecting && !isOpen && inputRef.current) {
+ inputRef.current.focus();
+ } else if (inputRef.current) {
+ inputRef.current.blur();
+ }
+ }, [isSelecting, isOpen]);
+
+ const handleKeyDown = React.useCallback(
+ (e: React.KeyboardEvent) => {
+ const isReadonly = isEditorReadOnly(editor);
+ getOptions().onKeyDownSelecting?.(e.nativeEvent);
+
+ // selecting commands
+ if (!getOptions().isSelecting) return;
+ if (isHotkey('escape')(e)) {
+ api.blockSelection.unselect();
+ }
+ if (isHotkey('mod+z')(e)) {
+ editor.undo();
+ selectInsertedBlocks(editor);
+ }
+ if (isHotkey('mod+shift+z')(e)) {
+ editor.redo();
+ selectInsertedBlocks(editor);
+ }
+ // selecting some commands
+ if (!getOption('isSelectingSome')) return;
+ if (isHotkey('enter')(e)) {
+ // get the first block in the selection
+ const entry = findNode(editor, {
+ at: [],
+ match: (n) => selectedIds!.has(n.id),
+ });
+
+ if (entry) {
+ const [, path] = entry;
+
+ // focus the end of that block
+ focusEditor(editor, getEndPoint(editor, path));
+ e.preventDefault();
+ }
+ }
+ if (isHotkey(['backspace', 'delete'])(e) && !isReadonly) {
+ removeNodes(editor, {
+ at: [],
+ match: (n) => selectedIds!.has(n.id),
+ });
+ }
+ // TODO: skip toggle child
+ if (isHotkey('up')(e)) {
+ const firstId = [...selectedIds!][0];
+ const node = findNode(editor, {
+ at: [],
+ match: (n) => n.id === firstId,
+ });
+ const prev = getPreviousNode(editor, {
+ at: node?.[1],
+ });
+
+ const prevId = prev?.[0].id;
+ api.blockSelection.addSelectedRow(prevId);
+ }
+ if (isHotkey('down')(e)) {
+ const lastId = [...selectedIds!].pop();
+ const node = findNode(editor, {
+ at: [],
+ match: (n) => n.id === lastId,
+ });
+ const next = getNextNode(editor, {
+ at: node?.[1],
+ });
+ const nextId = next?.[0].id;
+ api.blockSelection.addSelectedRow(nextId);
+ }
+ },
+ [editor, selectedIds, api, getOptions, getOption]
+ );
+
+ const handleCopy = React.useCallback(
+ (e: React.ClipboardEvent) => {
+ e.preventDefault();
+
+ if (getOption('isSelectingSome')) {
+ copySelectedBlocks(editor);
+ }
+ },
+ [editor, getOption]
+ );
+
+ const handleCut = React.useCallback(
+ (e: React.ClipboardEvent) => {
+ e.preventDefault();
+
+ if (getOption('isSelectingSome')) {
+ copySelectedBlocks(editor);
+
+ if (!isEditorReadOnly(editor)) {
+ removeNodes(editor, {
+ at: [],
+ match: (n) => selectedIds!.has(n.id),
+ });
+
+ focusEditor(editor);
+ }
+ }
+ },
+ [editor, selectedIds, getOption]
+ );
+
+ const handlePaste = React.useCallback(
+ (e: React.ClipboardEvent) => {
+ e.preventDefault();
+
+ if (!isEditorReadOnly(editor)) {
+ pasteSelectedBlocks(editor, e.nativeEvent);
+ }
+ },
+ [editor]
+ );
+
+ if (!isMounted || typeof window === 'undefined') {
+ return null;
+ }
+
+ return ReactDOM.createPortal(
+ ,
+ document.body
+ );
+};
diff --git a/packages/selection/src/react/BlockSelectionPlugin.tsx b/packages/selection/src/react/BlockSelectionPlugin.tsx
index 4f533e4039..624be10d7d 100644
--- a/packages/selection/src/react/BlockSelectionPlugin.tsx
+++ b/packages/selection/src/react/BlockSelectionPlugin.tsx
@@ -13,9 +13,9 @@ import type { ChangedElements, PartialSelectionOptions } from '../internal';
import { getAllSelectableDomNode, getSelectedDomNode } from '../lib';
import { extractSelectableIds } from '../lib/extractSelectableIds';
import { BlockContextMenuPlugin } from './BlockContextMenuPlugin';
+import { BlockSelectionAfterEditable } from './BlockSelectionAfterEditable';
import { BlockSelectable } from './components/BlockSelectable';
import { onKeyDownSelection } from './onKeyDownSelection';
-import { useHooksBlockSelection } from './useHooksBlockSelection';
import { onChangeBlockSelection } from './utils';
export type BlockSelectionConfig = PluginConfig<
@@ -25,6 +25,7 @@ export type BlockSelectionConfig = PluginConfig<
editorPaddingRight?: CSSProperties['width'];
enableContextMenu?: boolean;
isSelecting?: boolean;
+ isSelectionAreaVisible?: boolean;
query?: QueryNodeOptions;
rightSelectionAreaClassName?: string;
selectedIds?: Set;
@@ -71,6 +72,7 @@ export const BlockSelectionPlugin = createTPlatePlugin({
},
enableContextMenu: false,
isSelecting: false,
+ isSelectionAreaVisible: false,
query: {
maxLevel: 1,
},
@@ -87,8 +89,8 @@ export const BlockSelectionPlugin = createTPlatePlugin({
element,
},
}),
+ afterEditable: BlockSelectionAfterEditable,
},
- useHooks: useHooksBlockSelection,
handlers: {
onChange: onChangeBlockSelection,
onKeyDown: onKeyDownSelection,
diff --git a/packages/selection/src/react/components/BlockSelectable.tsx b/packages/selection/src/react/components/BlockSelectable.tsx
index 5c51c68d4f..93f2a28fb2 100644
--- a/packages/selection/src/react/components/BlockSelectable.tsx
+++ b/packages/selection/src/react/components/BlockSelectable.tsx
@@ -7,11 +7,23 @@ import {
isVoid,
queryNode,
} from '@udecode/plate-common';
-import { findNodePath, useEditorPlugin } from '@udecode/plate-common/react';
+import {
+ createAtomStore,
+ findNodePath,
+ useEditorPlugin,
+} from '@udecode/plate-common/react';
import { Path } from 'slate';
import { BlockSelectionPlugin } from '../BlockSelectionPlugin';
+export const { BlockSelectableProvider, useBlockSelectableStore } =
+ createAtomStore(
+ {
+ selectable: false,
+ },
+ { name: 'blockSelectable' }
+ );
+
export interface BlockSelectableOptions {
element: TElement;
active?: boolean;
@@ -53,30 +65,24 @@ export const useBlockSelectableState = ({
};
export const useBlockSelectable = ({
+ active,
element,
path,
ref,
}: ReturnType) => {
- const { api, editor, getOption, getOptions, useOption } =
+ const { api, editor, getOption, getOptions } =
useEditorPlugin(BlockSelectionPlugin);
const id = element?.id as string | undefined;
- const isSelected = useOption('isSelected', id);
-
- const data = {
- 'data-key': id,
- };
+ const data = { 'data-key': id };
return {
props: {
- key: id,
- className: isSelected
- ? 'slate-selected slate-selectable'
- : 'slate-selectable',
+ className: 'slate-selectable',
ref,
onContextMenu: (event: React.MouseEvent) => {
- if (!element) return;
+ if (!element || !active) return;
const { enableContextMenu } = getOptions();
@@ -108,11 +114,6 @@ export const useBlockSelectable = ({
});
}
},
- // style: isSelected
- // ? {
- // backgroundColor: selectedColor,
- // }
- // : undefined,
...data,
},
};
@@ -124,13 +125,16 @@ export function BlockSelectable({
...props
}: { options: BlockSelectableOptions } & React.HTMLAttributes) {
const state = useBlockSelectableState(options);
- const { props: rootProps } = useBlockSelectable(state);
+ const blockSelectable = useBlockSelectable(state);
- if (!state.active) return <>{children}>;
+ if (!state.active)
+ return {children} ;
return (
-
- {children}
-
+
+
+ {children}
+
+
);
}
diff --git a/packages/selection/src/react/index.ts b/packages/selection/src/react/index.ts
index 716cec46e5..00d2054404 100644
--- a/packages/selection/src/react/index.ts
+++ b/packages/selection/src/react/index.ts
@@ -5,8 +5,9 @@
export * from './BlockContextMenuPlugin';
export * from './BlockSelectionPlugin';
export * from './onKeyDownSelection';
-export * from './useHooksBlockSelection';
+export * from './BlockSelectionAfterEditable';
export * from './useSelectionArea';
export * from './components/index';
export * from './context-menu/index';
+export * from './useBlockSelected';
export * from './utils/index';
diff --git a/packages/selection/src/react/useBlockSelected.ts b/packages/selection/src/react/useBlockSelected.ts
new file mode 100644
index 0000000000..abefd290cf
--- /dev/null
+++ b/packages/selection/src/react/useBlockSelected.ts
@@ -0,0 +1,12 @@
+import { useEditorPlugin, useElement } from '@udecode/plate-common/react';
+
+import { BlockSelectionPlugin } from './BlockSelectionPlugin';
+
+export const useBlockSelected = (_id?: string) => {
+ const { useOption } = useEditorPlugin(BlockSelectionPlugin);
+ const { id } = useElement();
+
+ const isBlockSelected = useOption('isSelected', id as string);
+
+ return isBlockSelected;
+};
diff --git a/packages/selection/src/react/useHooksBlockSelection.ts b/packages/selection/src/react/useHooksBlockSelection.ts
deleted file mode 100644
index f1d20ec0cb..0000000000
--- a/packages/selection/src/react/useHooksBlockSelection.ts
+++ /dev/null
@@ -1,163 +0,0 @@
-import React from 'react';
-
-import {
- findNode,
- getEndPoint,
- getNextNode,
- getPreviousNode,
- isHotkey,
- removeNodes,
-} from '@udecode/plate-common';
-import {
- type UseHooks,
- focusEditor,
- isEditorReadOnly,
- useEditorPlugin,
-} from '@udecode/plate-common/react';
-
-import type { BlockSelectionConfig } from './BlockSelectionPlugin';
-
-import { BlockContextMenuPlugin } from './BlockContextMenuPlugin';
-import { useSelectionArea } from './useSelectionArea';
-import { selectInsertedBlocks } from './utils';
-import { copySelectedBlocks } from './utils/copySelectedBlocks';
-import { pasteSelectedBlocks } from './utils/pasteSelectedBlocks';
-
-export const useHooksBlockSelection: UseHooks = ({
- api,
- editor,
- getOption,
- getOptions,
- useOption,
-}) => {
- const isSelecting = useOption('isSelecting');
- const selectedIds = useOption('selectedIds');
- const blockContextMenu = useEditorPlugin(BlockContextMenuPlugin);
- const isOpen = blockContextMenu.useOption('isOpen', editor.id);
-
- useSelectionArea();
-
- // TODO: test
- React.useEffect(() => {
- const el = document.querySelector('#slate-shadow-input');
-
- if (el) {
- el.remove();
- }
-
- const isReadonly = isEditorReadOnly(editor);
-
- if (isSelecting) {
- const input = document.createElement('input');
- input.setAttribute('id', 'slate-shadow-input');
- // no scrolling on focus
- input.style.position = 'fixed';
- input.style.zIndex = '999';
- // hide
- input.style.top = '-300px';
- input.style.left = '-300px';
- input.style.opacity = '0';
-
- input.addEventListener('keydown', (e) => {
- getOptions().onKeyDownSelecting?.(e);
-
- // selecting commands
- if (!getOptions().isSelecting) return;
- if (isHotkey('escape')(e)) {
- api.blockSelection.unselect();
- }
- if (isHotkey('mod+z')(e)) {
- editor.undo();
- selectInsertedBlocks(editor);
- }
- if (isHotkey('mod+shift+z')(e)) {
- editor.redo();
- selectInsertedBlocks(editor);
- }
- // selecting some commands
- if (!getOption('isSelectingSome')) return;
- if (isHotkey('enter')(e)) {
- // get the first block in the selection
- const entry = findNode(editor, {
- at: [],
- match: (n) => selectedIds!.has(n.id),
- });
-
- if (entry) {
- const [, path] = entry;
-
- // focus the end of that block
- focusEditor(editor, getEndPoint(editor, path));
- e.preventDefault();
- }
- }
- if (isHotkey(['backspace', 'delete'])(e) && !isReadonly) {
- removeNodes(editor, {
- at: [],
- match: (n) => selectedIds!.has(n.id),
- });
- }
- // TODO: skip toggle child
- if (isHotkey('up')(e)) {
- const firstId = [...selectedIds!][0];
- const node = findNode(editor, {
- at: [],
- match: (n) => n.id === firstId,
- });
- const prev = getPreviousNode(editor, {
- at: node?.[1],
- });
-
- const prevId = prev?.[0].id;
- api.blockSelection.addSelectedRow(prevId);
- }
- if (isHotkey('down')(e)) {
- const lastId = [...selectedIds!].pop();
- const node = findNode(editor, {
- at: [],
- match: (n) => n.id === lastId,
- });
- const next = getNextNode(editor, {
- at: node?.[1],
- });
- const nextId = next?.[0].id;
- api.blockSelection.addSelectedRow(nextId);
- }
- });
-
- // TODO: paste + select blocks if selecting editor
- input.addEventListener('copy', (e) => {
- e.preventDefault();
-
- if (getOption('isSelectingSome')) {
- copySelectedBlocks(editor);
- }
- });
- input.addEventListener('cut', (e) => {
- e.preventDefault();
-
- if (getOption('isSelectingSome')) {
- copySelectedBlocks(editor);
-
- if (!isReadonly) {
- removeNodes(editor, {
- at: [],
- match: (n) => selectedIds!.has(n.id),
- });
-
- focusEditor(editor);
- }
- }
- });
- input.addEventListener('paste', (e) => {
- e.preventDefault();
-
- if (!isReadonly) {
- pasteSelectedBlocks(editor, e);
- }
- });
- document.body.append(input);
- input.focus();
- }
- }, [editor, isSelecting, selectedIds, isOpen, api, getOptions, getOption]);
-};
diff --git a/packages/selection/src/react/useSelectionArea.ts b/packages/selection/src/react/useSelectionArea.ts
index f19a7aeb92..023d2ccc0f 100644
--- a/packages/selection/src/react/useSelectionArea.ts
+++ b/packages/selection/src/react/useSelectionArea.ts
@@ -6,7 +6,8 @@ import { SelectionArea } from '../internal';
import { BlockSelectionPlugin } from './BlockSelectionPlugin';
export const useSelectionArea = () => {
- const { api, editor, getOptions } = useEditorPlugin(BlockSelectionPlugin);
+ const { api, editor, getOptions, setOption } =
+ useEditorPlugin(BlockSelectionPlugin);
const { areaOptions } = getOptions();
@@ -15,8 +16,9 @@ export const useSelectionArea = () => {
document: window.document,
...areaOptions,
})
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- .on('start', ({ event, store }) => {
+ .on('start', ({ event }) => {
+ setOption('isSelectionAreaVisible', true);
+
deselectEditor(editor);
if (!event?.shiftKey) {
@@ -25,17 +27,15 @@ export const useSelectionArea = () => {
}
})
.on('move', ({ store: { changed } }) => {
- if (changed.added.length === 0 && changed.removed.length === 0) return;
-
- for (const el of changed.added) {
- el.classList.add('selected');
- }
-
- for (const el of changed.removed) {
- el.classList.remove('selected');
+ if (!getOptions().isSelectionAreaVisible) {
+ setOption('isSelectionAreaVisible', true);
}
+ if (changed.added.length === 0 && changed.removed.length === 0) return;
api.blockSelection.setSelectedIds(changed);
+ })
+ .on('stop', () => {
+ setOption('isSelectionAreaVisible', false);
});
return () => selection.destroy();
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
index e56f29d15f..1aaf7d7b94 100644
--- a/tailwind.config.cjs
+++ b/tailwind.config.cjs
@@ -38,6 +38,10 @@ module.exports = {
},
background: 'hsl(var(--background))',
border: 'hsl(var(--border))',
+ brand: {
+ DEFAULT: 'hsl(var(--brand))',
+ foreground: 'hsl(var(--brand-foreground))',
+ },
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
@@ -47,6 +51,10 @@ module.exports = {
foreground: 'hsl(var(--destructive-foreground) / )',
},
foreground: 'hsl(var(--foreground))',
+ highlight: {
+ DEFAULT: 'hsl(var(--highlight))',
+ foreground: 'hsl(var(--highlight-foreground))',
+ },
input: 'hsl(var(--input))',
muted: {
DEFAULT: 'hsl(var(--muted))',
diff --git a/yarn.lock b/yarn.lock
index 931eeeb610..5e59565ddb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3145,7 +3145,7 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-compose-refs@npm:1.1.0":
+"@radix-ui/react-compose-refs@npm:1.1.0, @radix-ui/react-compose-refs@npm:^1.1.0":
version: 1.1.0
resolution: "@radix-ui/react-compose-refs@npm:1.1.0"
peerDependencies:
@@ -6525,7 +6525,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@udecode/plate-markdown@npm:38.0.1, @udecode/plate-markdown@workspace:^, @udecode/plate-markdown@workspace:packages/markdown":
+"@udecode/plate-markdown@npm:38.0.13, @udecode/plate-markdown@workspace:^, @udecode/plate-markdown@workspace:packages/markdown":
version: 0.0.0-use.local
resolution: "@udecode/plate-markdown@workspace:packages/markdown"
dependencies:
@@ -6928,7 +6928,7 @@ __metadata:
"@udecode/plate-line-height": "npm:38.0.1"
"@udecode/plate-link": "npm:38.0.6"
"@udecode/plate-list": "npm:38.0.1"
- "@udecode/plate-markdown": "npm:38.0.1"
+ "@udecode/plate-markdown": "npm:38.0.13"
"@udecode/plate-media": "npm:38.0.6"
"@udecode/plate-mention": "npm:38.0.1"
"@udecode/plate-node-id": "npm:38.0.1"
@@ -6966,6 +6966,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@udecode/react-utils@workspace:packages/react-utils"
dependencies:
+ "@radix-ui/react-compose-refs": "npm:^1.1.0"
"@radix-ui/react-slot": "npm:^1.1.0"
"@udecode/utils": "npm:37.0.0"
clsx: "npm:^2.1.1"