diff --git a/.changeset/base.md b/.changeset/base.md new file mode 100644 index 0000000000..0e33f334c2 --- /dev/null +++ b/.changeset/base.md @@ -0,0 +1,6 @@ +--- +'@udecode/plate-table': patch +'@udecode/plate-link': patch +--- + +Move `node.props` plugin attributes from `/react` to `/` diff --git a/.changeset/core-minor.md b/.changeset/core-minor.md new file mode 100644 index 0000000000..22bbd75a62 --- /dev/null +++ b/.changeset/core-minor.md @@ -0,0 +1,13 @@ +--- +'@udecode/plate-core': minor +--- + +## @udecode/plate-core@40.1.0 + +### Minor Changes + +- [#3744](https://github.com/udecode/plate/pull/3744) by [@zbeyens](https://github.com/zbeyens) – + - Add `PlateStatic`, `SlateElement`, `SlateLeaf` components for static rendering and server-side HTML serialization + - Add `serializeHtml` function to serialize editor content to HTML. Deprecating `@udecode/plate-html` in favor of core serialization. + - Move from `PlatePlugin` (`/react`) to `BasePlugin` (`/`): `node.component`, `render.aboveEditable`, `render.aboveSlate`, `render.node` + - Add to `SlatePlugin`: `node.props`, `render.aboveNodes`, `render.belowNodes`, `render.afterEditable`, `render.beforeEditable`, `render.node` diff --git a/.changeset/findNodePath.md b/.changeset/findNodePath.md new file mode 100644 index 0000000000..7d258abf31 --- /dev/null +++ b/.changeset/findNodePath.md @@ -0,0 +1,16 @@ +--- +'@udecode/plate-indent-list': patch +'@udecode/plate-utils': patch +'@udecode/plate-code-block': patch +'@udecode/plate-resizable': patch +'@udecode/plate-selection': patch +'@udecode/plate-combobox': patch +'@udecode/plate-tabbable': patch +'@udecode/plate-caption': patch +'@udecode/plate-layout': patch +'@udecode/plate-table': patch +'@udecode/plate-list': patch +'@udecode/plate-dnd': patch +--- + +Replace `findNodePath` with `findPath` diff --git a/.changeset/link.md b/.changeset/link.md new file mode 100644 index 0000000000..c4fd20ee5b --- /dev/null +++ b/.changeset/link.md @@ -0,0 +1,5 @@ +--- +'@udecode/plate-link': patch +--- + +- Fix floating link url input being focused when focusing the placeholder input diff --git a/.changeset/list-major.md b/.changeset/list-major.md new file mode 100644 index 0000000000..1ca8cdb1df --- /dev/null +++ b/.changeset/list-major.md @@ -0,0 +1,6 @@ +--- +'@udecode/plate-indent-list': major +--- + +- Move `render.belowNodes` from `IndentListPlugin` to `BaseIndentListPlugin`. Props type for `listStyleTypes.liComponent` and `listStyleTypes.markerComponent` options is now `SlateRenderElementProps` instead of `PlateRenderElementProps` +- Move `someIndentList`, `someIndentTodo` from `@udecode/plate-indent-list/react` to `@udecode/plate-indent-list` diff --git a/.changeset/slate-react major.md b/.changeset/slate-react major.md new file mode 100644 index 0000000000..bcf288cd76 --- /dev/null +++ b/.changeset/slate-react major.md @@ -0,0 +1,12 @@ +--- +'@udecode/slate-react': major +--- + +Rename `findNodePath` to `findPath` since the addition of `findNodePath` in the headless lib. + +We recommend using `findPath` mostly when subscribing to its value (e.g. in a React component) as it has O(path.length) complexity, compared to O(n) for the traversal-based `findNodePath`. This optimization is particularly important in: + +- Render functions of Plate components where using `findNodePath` would increase the initial render time by O(n²) +- Key press handlers where using `findNodePath` would increase the handling time by O(n) + +where n is the number of nodes in the editor. diff --git a/.changeset/slate-react.md b/.changeset/slate-react.md new file mode 100644 index 0000000000..756b598010 --- /dev/null +++ b/.changeset/slate-react.md @@ -0,0 +1,5 @@ +--- +'@udecode/slate-react': patch +--- + +Update `TRenderElementProps`, `TRenderLeafProps` types diff --git a/.changeset/slate.md b/.changeset/slate.md new file mode 100644 index 0000000000..395aca53fa --- /dev/null +++ b/.changeset/slate.md @@ -0,0 +1,9 @@ +--- +'@udecode/slate': minor +--- + +Add `findNodePath` - a traversal-based node path finder with O(n) complexity. This is the headless alternative to `findPath` from `@udecode/slate-react`, recommended for: + +- Non-React contexts +- Plugin logic that doesn't require React dependencies +- Non-performance-critical paths where O(n) traversal is acceptable diff --git a/.changeset/table-major.md b/.changeset/table-major.md new file mode 100644 index 0000000000..7d552d02ad --- /dev/null +++ b/.changeset/table-major.md @@ -0,0 +1,27 @@ +--- +'@udecode/plate-table': major +--- + +Move from `@udecode/plate-table/react` to `@udecode/plate-table`: + +- `deleteColumn` +- `deleteColumnWhenExpanded` +- `deleteRow` +- `deleteRowWhenExpanded` +- `getTableColumn` +- `getTableGridAbove` +- `getTableGridByRange` +- `getTableRow` +- `insertTable` +- `mergeTableCells` +- `moveSelectionFromCell` +- `overrideSelectionFromCell` +- `unmergeTableCells` +- `withDeleteTable` +- `withGetFragmentlable` +- `withInsertFragmentTable` +- `withInsertTextTable` +- `withMarkTable` +- `withSelectionTable` +- `withSetFragmentDataTable` +- `withTable` diff --git a/.github/workflows/registry.yml b/.github/workflows/registry.yml index 3ea60d0ed5..fe79a578f3 100644 --- a/.github/workflows/registry.yml +++ b/.github/workflows/registry.yml @@ -37,7 +37,7 @@ jobs: key: packages-cache-${{ runner.os }}-${{ hashFiles('yarn.lock') }} - name: 🏗 Build Registry - run: yarn build:registry + run: yarn build:registry && yarn build:tw - name: ◻️ Create Pull Request uses: peter-evans/create-pull-request@v4 diff --git a/.gitignore b/.gitignore index e5a9c9e88b..d78c881327 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ !.yarn/releases !.yarn/sdks !.yarn/versions +.repo_ignore **/traceDir diff --git a/apps/www/content/docs/api/slate-react.mdx b/apps/www/content/docs/api/slate-react.mdx index b3ef616505..e194f9b0f3 100644 --- a/apps/www/content/docs/api/slate-react.mdx +++ b/apps/www/content/docs/api/slate-react.mdx @@ -21,7 +21,7 @@ Find the corresponding documentation in the [Slate React docs](https://docs.slat ### `findNodeKey` -### `findNodePath` +### `findPath` ### `focusEditor` diff --git a/apps/www/content/docs/components/changelog.mdx b/apps/www/content/docs/components/changelog.mdx index e84f2377bf..fa2590eb44 100644 --- a/apps/www/content/docs/components/changelog.mdx +++ b/apps/www/content/docs/components/changelog.mdx @@ -11,6 +11,18 @@ Use the [CLI](https://platejs.org/docs/components/cli) to install the latest ver ## December 2024 #17 +### December 19 #17.2 + +Plate 41 + +- New RSC components for element and leaf components, filename ending with `-static.tsx`. Those are now added along with the default client components. +- `editor`: add `select-text` to `editorVariants` +- `date-element`: remove popover when read-only +- `indent-todo-marker`: use `SlateRenderElementProps` type instead of `PlateRenderElementProps` +- `hr-element`, `media-audio-element`, `media-embed-element`, `mention-element`: improve cursor styling +- `media-file-element`: use `` instead of `div` + `onClick` +- all element and leaf components: `className` prop is now placed before inline prop. + ### December 16 #17.1 - `column-element`: diff --git a/apps/www/content/docs/examples/iframe.mdx b/apps/www/content/docs/examples/iframe.mdx deleted file mode 100644 index 762614c993..0000000000 --- a/apps/www/content/docs/examples/iframe.mdx +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: IFrame ---- - - diff --git a/apps/www/content/docs/html.mdx b/apps/www/content/docs/html.mdx index b2b1949642..88693009e6 100644 --- a/apps/www/content/docs/html.mdx +++ b/apps/www/content/docs/html.mdx @@ -4,11 +4,190 @@ title: Serializing HTML - + + **Note**: Round-tripping is not yet supported: the HTML serializer will not + preserve all information from the Slate value when converting to HTML and + back. + + +## Slate -> HTML + +[Server-side example](/docs/examples/slate-to-html) + +### Usage + +```tsx +// ... +import { createSlateEditor, serializeHtml } from '@udecode/plate-common'; +import { EditorStatic } from '@/components/plate-ui/editor-static'; + +// Create an editor and configure all the plugins you need +const editor = createSlateEditor({ + // ... your plugins ... +}); + +// Provide the components that map Slate nodes to HTML elements +const components = { + // [ParagraphPlugin.key]: ParagraphElementStatic, + // [HeadingPlugin.key]: HeadingElementStatic, + // ... +}; + +// You can also pass a custom editor component and props +// For example, EditorStatic is a styled version of PlateStatic. +const html = await serializeHtml(editor, { + components, + editorComponent: EditorStatic, // defaults to PlateStatic if not provided + props: { variant: 'none', className: 'p-2' }, +}); +``` + +If you use a custom component, like [EditorStatic](/docs/components/editor), you must also ensure that all required styles and classes are included in your final HTML file. Since serialize only returns the inner editor HTML, you may need to wrap it in a full HTML document with any external CSS, scripts, or ` + + + + + + + + ${editorHtml} + +`; +} diff --git a/apps/www/src/registry/default/plate-ui/ai-leaf.tsx b/apps/www/src/registry/default/plate-ui/ai-leaf.tsx index 0080ac459c..e91cc14379 100644 --- a/apps/www/src/registry/default/plate-ui/ai-leaf.tsx +++ b/apps/www/src/registry/default/plate-ui/ai-leaf.tsx @@ -11,9 +11,9 @@ export const AILeaf = withRef( diff --git a/apps/www/src/registry/default/plate-ui/blockquote-element-static.tsx b/apps/www/src/registry/default/plate-ui/blockquote-element-static.tsx new file mode 100644 index 0000000000..a7e1e1ef0d --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/blockquote-element-static.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export const BlockquoteElementStatic = ({ + children, + className, + ...props +}: SlateElementProps) => { + return ( + + {children} + + ); +}; 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 f6fa8a208e..147873821a 100644 --- a/apps/www/src/registry/default/plate-ui/blockquote-element.tsx +++ b/apps/www/src/registry/default/plate-ui/blockquote-element.tsx @@ -12,7 +12,7 @@ export const BlockquoteElement = withRef( {children} diff --git a/apps/www/src/registry/default/plate-ui/checkbox-static.tsx b/apps/www/src/registry/default/plate-ui/checkbox-static.tsx new file mode 100644 index 0000000000..0b1ae0ab01 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/checkbox-static.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; + +import { cn } from '@udecode/cn'; +import { Check } from 'lucide-react'; + +export function CheckboxStatic({ + className, + ...props +}: { + checked: boolean; + className?: string; + style?: React.CSSProperties; +}) { + return ( + + ); +} diff --git a/apps/www/src/registry/default/plate-ui/code-block-element-static.tsx b/apps/www/src/registry/default/plate-ui/code-block-element-static.tsx new file mode 100644 index 0000000000..70b0a36fb4 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/code-block-element-static.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +import type { TCodeBlockElement } from '@udecode/plate-code-block'; +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export const CodeBlockElementStatic = ({ + children, + className, + ...props +}: SlateElementProps) => { + const { element } = props; + + const codeClassName = element?.lang + ? `${element.lang} language-${element.lang}` + : ''; + + return ( + +
+        {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 afc18a529e..2f584ce6e7 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 @@ -13,12 +13,13 @@ import './code-block-element.css'; export const CodeBlockElement = withRef( ({ children, className, ...props }, ref) => { const { element } = props; + const state = useCodeBlockElementState({ element }); return (
diff --git a/apps/www/src/registry/default/plate-ui/code-leaf-static.tsx b/apps/www/src/registry/default/plate-ui/code-leaf-static.tsx
new file mode 100644
index 0000000000..0db873e90b
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/code-leaf-static.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+
+import type { SlateLeafProps } from '@udecode/plate-common';
+
+import { cn } from '@udecode/cn';
+import { SlateLeaf } from '@udecode/plate-common';
+
+export const CodeLeafStatic = ({
+  children,
+  className,
+  ...props
+}: SlateLeafProps) => {
+  return (
+    
+      {children}
+    
+  );
+};
diff --git a/apps/www/src/registry/default/plate-ui/code-leaf.tsx b/apps/www/src/registry/default/plate-ui/code-leaf.tsx
index dd0c48a2fd..15587774b4 100644
--- a/apps/www/src/registry/default/plate-ui/code-leaf.tsx
+++ b/apps/www/src/registry/default/plate-ui/code-leaf.tsx
@@ -10,14 +10,14 @@ export const CodeLeaf = withRef(
     return (
       
-        {children}
+        {children}
       
     );
   }
diff --git a/apps/www/src/registry/default/plate-ui/code-line-element-static.tsx b/apps/www/src/registry/default/plate-ui/code-line-element-static.tsx
new file mode 100644
index 0000000000..7b3465580e
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/code-line-element-static.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+
+import type { SlateElementProps } from '@udecode/plate-common';
+
+import { SlateElement } from '@udecode/plate-common';
+
+export const CodeLineElementStatic = ({
+  children,
+  ...props
+}: SlateElementProps) => {
+  return {children};
+};
diff --git a/apps/www/src/registry/default/plate-ui/code-syntax-leaf-static.tsx b/apps/www/src/registry/default/plate-ui/code-syntax-leaf-static.tsx
new file mode 100644
index 0000000000..b6bad8e948
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/code-syntax-leaf-static.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+
+import type { SlateLeafProps } from '@udecode/plate-common';
+
+import { cn } from '@udecode/cn';
+import { SlateLeaf } from '@udecode/plate-common';
+
+export function CodeSyntaxLeafStatic({
+  children,
+  className,
+  ...props
+}: SlateLeafProps) {
+  const syntaxClassName = `prism-token token ${props.leaf.tokenType}`;
+
+  return (
+    
+      {children}
+    
+  );
+}
diff --git a/apps/www/src/registry/default/plate-ui/column-element-static.tsx b/apps/www/src/registry/default/plate-ui/column-element-static.tsx
new file mode 100644
index 0000000000..8b411f54e3
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/column-element-static.tsx
@@ -0,0 +1,25 @@
+import React from 'react';
+
+import type { SlateElementProps } from '@udecode/plate-common';
+import type { TColumnElement } from '@udecode/plate-layout';
+
+import { cn } from '@udecode/cn';
+import { SlateElement } from '@udecode/plate-common';
+
+export function ColumnElementStatic({
+  children,
+  className,
+  ...props
+}: SlateElementProps) {
+  const { width } = props.element as TColumnElement;
+
+  return (
+    
+      {children}
+    
+  );
+}
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 8f4a663748..1e5caf7369 100644
--- a/apps/www/src/registry/default/plate-ui/column-element.tsx
+++ b/apps/www/src/registry/default/plate-ui/column-element.tsx
@@ -67,8 +67,8 @@ export const ColumnElement = withHOC(
         >
           
diff --git a/apps/www/src/registry/default/plate-ui/column-group-element-static.tsx b/apps/www/src/registry/default/plate-ui/column-group-element-static.tsx new file mode 100644 index 0000000000..7c726f1794 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/column-group-element-static.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export function ColumnGroupElementStatic({ + children, + className, + ...props +}: SlateElementProps) { + return ( + +
{children}
+
+ ); +} diff --git a/apps/www/src/registry/default/plate-ui/comment-leaf-static.tsx b/apps/www/src/registry/default/plate-ui/comment-leaf-static.tsx new file mode 100644 index 0000000000..04c5e4ecce --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/comment-leaf-static.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +import type { TCommentText } from '@udecode/plate-comments'; +import type { SlateLeafProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateLeaf } from '@udecode/plate-common'; + +export function CommentLeafStatic({ + children, + className, + ...props +}: SlateLeafProps) { + return ( + + <>{children} + + ); +} 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 0751d01dac..3e2ec1ccd1 100644 --- a/apps/www/src/registry/default/plate-ui/comment-leaf.tsx +++ b/apps/www/src/registry/default/plate-ui/comment-leaf.tsx @@ -34,9 +34,9 @@ export function CommentLeaf({ + + {element.date ? ( + (() => { + const today = new Date(); + const elementDate = new Date(element.date as string); + const isToday = + elementDate.getDate() === today.getDate() && + elementDate.getMonth() === today.getMonth() && + elementDate.getFullYear() === today.getFullYear(); + + const isYesterday = + new Date(today.setDate(today.getDate() - 1)).toDateString() === + elementDate.toDateString(); + const isTomorrow = + new Date(today.setDate(today.getDate() + 2)).toDateString() === + elementDate.toDateString(); + + if (isToday) return 'Today'; + if (isYesterday) return 'Yesterday'; + if (isTomorrow) return 'Tomorrow'; + + return elementDate.toLocaleDateString(undefined, { + day: 'numeric', + month: 'long', + year: 'numeric', + }); + })() + ) : ( + Pick a date + )} + + {children} + + ); +} diff --git a/apps/www/src/registry/default/plate-ui/date-element.tsx b/apps/www/src/registry/default/plate-ui/date-element.tsx index a9b12737fb..f914ec68b7 100644 --- a/apps/www/src/registry/default/plate-ui/date-element.tsx +++ b/apps/www/src/registry/default/plate-ui/date-element.tsx @@ -2,7 +2,8 @@ import { cn, withRef } from '@udecode/cn'; import { setNodes } from '@udecode/plate-common'; -import { findNodePath } from '@udecode/plate-common/react'; +import { findPath } from '@udecode/plate-common/react'; +import { useReadOnly } from 'slate-react'; import { Calendar } from './calendar'; import { PlateElement } from './plate-element'; @@ -12,55 +13,61 @@ export const DateElement = withRef( ({ children, className, ...props }, ref) => { const { editor, element } = props; + const readOnly = useReadOnly(); + + const trigger = ( + + {element.date ? ( + (() => { + const today = new Date(); + const elementDate = new Date(element.date as string); + const isToday = + elementDate.getDate() === today.getDate() && + elementDate.getMonth() === today.getMonth() && + elementDate.getFullYear() === today.getFullYear(); + + const isYesterday = + new Date(today.setDate(today.getDate() - 1)).toDateString() === + elementDate.toDateString(); + const isTomorrow = + new Date(today.setDate(today.getDate() + 2)).toDateString() === + elementDate.toDateString(); + + if (isToday) return 'Today'; + if (isYesterday) return 'Yesterday'; + if (isTomorrow) return 'Tomorrow'; + + return elementDate.toLocaleDateString(undefined, { + day: 'numeric', + month: 'long', + year: 'numeric', + }); + })() + ) : ( + Pick a date + )} + + ); + + if (readOnly) { + return trigger; + } + return ( - - - {element.date ? ( - (() => { - const today = new Date(); - const elementDate = new Date(element.date as string); - const isToday = - elementDate.getDate() === today.getDate() && - elementDate.getMonth() === today.getMonth() && - elementDate.getFullYear() === today.getFullYear(); - - const isYesterday = - new Date( - today.setDate(today.getDate() - 1) - ).toDateString() === elementDate.toDateString(); - const isTomorrow = - new Date( - today.setDate(today.getDate() + 2) - ).toDateString() === elementDate.toDateString(); - - if (isToday) return 'Today'; - if (isYesterday) return 'Yesterday'; - if (isTomorrow) return 'Tomorrow'; - - return elementDate.toLocaleDateString(undefined, { - day: 'numeric', - month: 'long', - year: 'numeric', - }); - })() - ) : ( - Pick a date - )} - - + {trigger} ( setNodes( editor, { date: date.toDateString() }, - { at: findNodePath(editor, element) } + { at: findPath(editor, element) } ); }} mode="single" diff --git a/apps/www/src/registry/default/plate-ui/editor-static.tsx b/apps/www/src/registry/default/plate-ui/editor-static.tsx new file mode 100644 index 0000000000..f383031c41 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/editor-static.tsx @@ -0,0 +1,55 @@ +import React from 'react'; + +import type { VariantProps } from 'class-variance-authority'; + +import { cn } from '@udecode/cn'; +import { type PlateStaticProps, PlateStatic } from '@udecode/plate-common'; +import { cva } from 'class-variance-authority'; + +export const editorVariants = cva( + cn( + 'group/editor', + 'relative w-full cursor-text select-text overflow-x-hidden whitespace-pre-wrap break-words', + 'rounded-md ring-offset-background focus-visible:outline-none', + 'placeholder:text-muted-foreground/80 [&_[data-slate-placeholder]]:top-[auto_!important] [&_[data-slate-placeholder]]:text-muted-foreground/80 [&_[data-slate-placeholder]]:!opacity-100', + '[&_strong]:font-bold' + ), + { + defaultVariants: { + variant: 'none', + }, + variants: { + disabled: { + true: 'cursor-not-allowed opacity-50', + }, + focused: { + true: 'ring-2 ring-ring ring-offset-2', + }, + variant: { + ai: 'w-full px-0 text-base md:text-sm', + aiChat: + 'max-h-[min(70vh,320px)] w-full max-w-[700px] overflow-y-auto px-3 py-2 text-base md:text-sm', + default: + 'size-full px-16 pb-72 pt-4 text-base sm:px-[max(64px,calc(50%-350px))]', + demo: 'size-full px-16 pb-72 pt-4 text-base sm:px-[max(64px,calc(50%-350px))]', + fullWidth: 'size-full px-16 pb-72 pt-4 text-base sm:px-24', + none: '', + select: 'px-3 py-2 text-base data-[readonly]:w-fit', + }, + }, + } +); + +export function EditorStatic({ + children, + className, + variant, + ...props +}: PlateStaticProps & VariantProps) { + return ( + + ); +} diff --git a/apps/www/src/registry/default/plate-ui/editor.tsx b/apps/www/src/registry/default/plate-ui/editor.tsx index f89f0a26ea..396a278ab7 100644 --- a/apps/www/src/registry/default/plate-ui/editor.tsx +++ b/apps/www/src/registry/default/plate-ui/editor.tsx @@ -14,7 +14,7 @@ import { import { cva } from 'class-variance-authority'; const editorContainerVariants = cva( - 'relative w-full cursor-text overflow-y-auto caret-primary selection:bg-brand/25 focus-visible:outline-none [&_.slate-selection-area]:border [&_.slate-selection-area]:border-brand/25 [&_.slate-selection-area]:bg-brand/15', + 'relative w-full cursor-text select-text overflow-y-auto caret-primary selection:bg-brand/25 focus-visible:outline-none [&_.slate-selection-area]:border [&_.slate-selection-area]:border-brand/25 [&_.slate-selection-area]:bg-brand/15', { defaultVariants: { variant: 'default', @@ -60,10 +60,9 @@ EditorContainer.displayName = 'EditorContainer'; const editorVariants = cva( cn( 'group/editor', - 'relative w-full overflow-x-hidden whitespace-pre-wrap break-words', - 'rounded-md ring-offset-background placeholder:text-muted-foreground/80 focus-visible:outline-none', - '[&_[data-slate-placeholder]]:text-muted-foreground/80 [&_[data-slate-placeholder]]:!opacity-100', - '[&_[data-slate-placeholder]]:top-[auto_!important]', + 'relative w-full cursor-text select-text overflow-x-hidden whitespace-pre-wrap break-words', + 'rounded-md ring-offset-background focus-visible:outline-none', + 'placeholder:text-muted-foreground/80 [&_[data-slate-placeholder]]:top-[auto_!important] [&_[data-slate-placeholder]]:text-muted-foreground/80 [&_[data-slate-placeholder]]:!opacity-100', '[&_strong]:font-bold' ), { 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 4731522745..f0c435a745 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 @@ -36,6 +36,7 @@ export const EmojiInputElement = withRef( 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 1f6275a0ed..5712c8f507 100644 --- a/apps/www/src/registry/default/plate-ui/excalidraw-element.tsx +++ b/apps/www/src/registry/default/plate-ui/excalidraw-element.tsx @@ -1,4 +1,5 @@ 'use client'; + import React from 'react'; import { withRef } from '@udecode/cn'; diff --git a/apps/www/src/registry/default/plate-ui/heading-element-static.tsx b/apps/www/src/registry/default/plate-ui/heading-element-static.tsx new file mode 100644 index 0000000000..77c92e0a5f --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/heading-element-static.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; +import { cva } from 'class-variance-authority'; + +interface HeadingElementViewProps extends SlateElementProps { + variant?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; +} + +const headingVariants = cva('relative mb-1', { + variants: { + variant: { + h1: 'mt-[1.6em] pb-1 font-heading text-4xl font-bold', + h2: 'mt-[1.4em] pb-px font-heading text-2xl font-semibold tracking-tight', + h3: 'mt-[1em] pb-px font-heading text-xl font-semibold tracking-tight', + h4: 'mt-[0.75em] font-heading text-lg font-semibold tracking-tight', + h5: 'mt-[0.75em] text-lg font-semibold tracking-tight', + h6: 'mt-[0.75em] text-base font-semibold tracking-tight', + }, + }, +}); + +export const HeadingElementStatic = ({ + children, + className, + variant = 'h1', + ...props +}: HeadingElementViewProps) => { + return ( + + {children} + + ); +}; diff --git a/apps/www/src/registry/default/plate-ui/highlight-leaf-static.tsx b/apps/www/src/registry/default/plate-ui/highlight-leaf-static.tsx new file mode 100644 index 0000000000..417ef73975 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/highlight-leaf-static.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +import type { SlateLeafProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateLeaf } from '@udecode/plate-common'; + +export function HighlightLeafStatic({ + children, + className, + ...props +}: SlateLeafProps) { + return ( + + {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 09f7f2d70e..0d1801c5ee 100644 --- a/apps/www/src/registry/default/plate-ui/highlight-leaf.tsx +++ b/apps/www/src/registry/default/plate-ui/highlight-leaf.tsx @@ -9,11 +9,11 @@ export const HighlightLeaf = withRef( ({ children, className, ...props }, ref) => ( - {children} + {children} ) ); diff --git a/apps/www/src/registry/default/plate-ui/hr-element-static.tsx b/apps/www/src/registry/default/plate-ui/hr-element-static.tsx new file mode 100644 index 0000000000..d3bc75c9dc --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/hr-element-static.tsx @@ -0,0 +1,27 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export function HrElementStatic({ + children, + className, + nodeProps, + ...props +}: SlateElementProps) { + return ( + +
+
+
+ {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 ea60a650a0..70ea7236b3 100644 --- a/apps/www/src/registry/default/plate-ui/hr-element.tsx +++ b/apps/www/src/registry/default/plate-ui/hr-element.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { cn, withRef } from '@udecode/cn'; -import { useFocused, useSelected } from 'slate-react'; +import { useFocused, useReadOnly, useSelected } from 'slate-react'; import { PlateElement } from './plate-element'; @@ -11,6 +11,7 @@ export const HrElement = withRef( ({ className, nodeProps, ...props }, ref) => { const { children } = props; + const readOnly = useReadOnly(); const selected = useSelected(); const focused = useFocused(); @@ -20,8 +21,9 @@ export const HrElement = withRef(
diff --git a/apps/www/src/registry/default/plate-ui/image-element-static.tsx b/apps/www/src/registry/default/plate-ui/image-element-static.tsx new file mode 100644 index 0000000000..e606262d6a --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/image-element-static.tsx @@ -0,0 +1,52 @@ +import React from 'react'; + +import type { TCaptionElement } from '@udecode/plate-caption'; +import type { SlateElementProps } from '@udecode/plate-common'; +import type { TImageElement } from '@udecode/plate-media'; + +import { cn } from '@udecode/cn'; +import { SlateElement, getNodeString } from '@udecode/plate-common'; + +export function ImageElementStatic({ + children, + className, + nodeProps, + ...props +}: SlateElementProps) { + const { + align = 'center', + caption, + url, + width, + } = props.element as TImageElement & + TCaptionElement & { + width: number; + }; + + return ( + +
+
+ + {caption && ( +
+ {getNodeString(caption[0])} +
+ )} +
+
+ {children} +
+ ); +} 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 248bd2b905..e05ea38aa3 100644 --- a/apps/www/src/registry/default/plate-ui/image-element.tsx +++ b/apps/www/src/registry/default/plate-ui/image-element.tsx @@ -38,7 +38,7 @@ export const ImageElement = withHOC(
diff --git a/apps/www/src/registry/default/plate-ui/indent-fire-marker.tsx b/apps/www/src/registry/default/plate-ui/indent-fire-marker.tsx index 5887dcd5ac..35dbc5c9d5 100644 --- a/apps/www/src/registry/default/plate-ui/indent-fire-marker.tsx +++ b/apps/www/src/registry/default/plate-ui/indent-fire-marker.tsx @@ -1,8 +1,10 @@ -import type { PlateRenderElementProps } from '@udecode/plate-common/react'; +import React from 'react'; + +import type { SlateRenderElementProps } from '@udecode/plate-core'; import type { TIndentElement } from '@udecode/plate-indent'; export const FireMarker = ( - props: Omit + props: Omit ) => { const { element } = props; @@ -15,7 +17,7 @@ export const FireMarker = ( ); }; -export const FireLiComponent = (props: PlateRenderElementProps) => { +export const FireLiComponent = (props: SlateRenderElementProps) => { const { children } = props; return {children}; diff --git a/apps/www/src/registry/default/plate-ui/indent-todo-marker-static.tsx b/apps/www/src/registry/default/plate-ui/indent-todo-marker-static.tsx new file mode 100644 index 0000000000..4bc0071ed7 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/indent-todo-marker-static.tsx @@ -0,0 +1,35 @@ +import React from 'react'; + +import type { SlateRenderElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; + +import { CheckboxStatic } from './checkbox-static'; + +export const TodoMarkerStatic = ({ + element, +}: Omit) => { + return ( +
+ +
+ ); +}; + +export const TodoLiStatic = ({ + children, + element, +}: SlateRenderElementProps) => { + return ( + + {children} + + ); +}; diff --git a/apps/www/src/registry/default/plate-ui/indent-todo-marker.tsx b/apps/www/src/registry/default/plate-ui/indent-todo-marker.tsx index 9d441367b1..48643b21aa 100644 --- a/apps/www/src/registry/default/plate-ui/indent-todo-marker.tsx +++ b/apps/www/src/registry/default/plate-ui/indent-todo-marker.tsx @@ -1,32 +1,37 @@ 'use client'; -import type { PlateRenderElementProps } from '@udecode/plate-common/react'; +import type { SlateRenderElementProps } from '@udecode/plate-common'; import { cn } from '@udecode/cn'; import { useIndentTodoListElement, useIndentTodoListElementState, } from '@udecode/plate-indent-list/react'; +import { useReadOnly } from 'slate-react'; import { Checkbox } from './checkbox'; export const TodoMarker = ({ element, -}: Omit) => { +}: Omit) => { const state = useIndentTodoListElementState({ element }); const { checkboxProps } = useIndentTodoListElement(state); + const readOnly = useReadOnly(); return (
); }; -export const TodoLi = (props: PlateRenderElementProps) => { +export const TodoLi = (props: SlateRenderElementProps) => { const { children, element } = props; return ( diff --git a/apps/www/src/registry/default/plate-ui/inline-combobox.tsx b/apps/www/src/registry/default/plate-ui/inline-combobox.tsx index 601ec14e7d..253e9a39a1 100644 --- a/apps/www/src/registry/default/plate-ui/inline-combobox.tsx +++ b/apps/www/src/registry/default/plate-ui/inline-combobox.tsx @@ -44,7 +44,7 @@ import { moveSelection, } from '@udecode/plate-common'; import { - findNodePath, + findPath, useComposedRef, useEditorRef, } from '@udecode/plate-common/react'; @@ -129,7 +129,7 @@ const InlineCombobox = ({ const [insertPoint, setInsertPoint] = useState(null); useEffect(() => { - const path = findNodePath(editor, element); + const path = findPath(editor, element); if (!path) return; diff --git a/apps/www/src/registry/default/plate-ui/input.tsx b/apps/www/src/registry/default/plate-ui/input.tsx index ce7a709586..b388b685c0 100644 --- a/apps/www/src/registry/default/plate-ui/input.tsx +++ b/apps/www/src/registry/default/plate-ui/input.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { cn, withVariants } from '@udecode/cn'; +import { withVariants } from '@udecode/cn'; import { type VariantProps, cva } from 'class-variance-authority'; export const inputVariants = cva( @@ -47,7 +47,7 @@ export function FloatingInput({ > {label} - + ); } diff --git a/apps/www/src/registry/default/plate-ui/kbd-leaf-static.tsx b/apps/www/src/registry/default/plate-ui/kbd-leaf-static.tsx new file mode 100644 index 0000000000..fac606d3df --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/kbd-leaf-static.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +import type { SlateLeafProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateLeaf } from '@udecode/plate-common'; + +export function KbdLeafStatic({ + children, + className, + ...props +}: SlateLeafProps) { + return ( + + {children} + + ); +} diff --git a/apps/www/src/registry/default/plate-ui/kbd-leaf.tsx b/apps/www/src/registry/default/plate-ui/kbd-leaf.tsx index e0187c19cf..4d83ad6b8a 100644 --- a/apps/www/src/registry/default/plate-ui/kbd-leaf.tsx +++ b/apps/www/src/registry/default/plate-ui/kbd-leaf.tsx @@ -9,14 +9,14 @@ export const KbdLeaf = withRef( ({ children, className, ...props }, ref) => ( - {children} + {children} ) ); diff --git a/apps/www/src/registry/default/plate-ui/link-element-static.tsx b/apps/www/src/registry/default/plate-ui/link-element-static.tsx new file mode 100644 index 0000000000..42867d7732 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/link-element-static.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export const LinkElementStatic = ({ + children, + className, + ...props +}: SlateElementProps) => { + return ( + + {children} + + ); +}; 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 9ca6503295..7c6c4433fb 100644 --- a/apps/www/src/registry/default/plate-ui/link-element.tsx +++ b/apps/www/src/registry/default/plate-ui/link-element.tsx @@ -20,8 +20,8 @@ export const LinkElement = withRef( ref={ref} as="a" className={cn( - 'font-medium text-primary underline decoration-primary underline-offset-4', - className + className, + 'font-medium text-primary underline decoration-primary underline-offset-4' )} {...(linkProps as any)} {...props} diff --git a/apps/www/src/registry/default/plate-ui/media-audio-element-static.tsx b/apps/www/src/registry/default/plate-ui/media-audio-element-static.tsx new file mode 100644 index 0000000000..281e4fd667 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/media-audio-element-static.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; +import type { TAudioElement } from '@udecode/plate-media'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export function MediaAudioElementStatic({ + children, + className, + ...props +}: SlateElementProps) { + const { url } = props.element as TAudioElement; + + return ( + +
+
+
+
+ {children} +
+ ); +} diff --git a/apps/www/src/registry/default/plate-ui/media-audio-element.tsx b/apps/www/src/registry/default/plate-ui/media-audio-element.tsx index c3000126da..ec0c84263d 100644 --- a/apps/www/src/registry/default/plate-ui/media-audio-element.tsx +++ b/apps/www/src/registry/default/plate-ui/media-audio-element.tsx @@ -19,10 +19,13 @@ export const MediaAudioElement = withHOC( return ( -
+
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 90243af87b..d6c5af72a0 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 @@ -41,10 +41,13 @@ export const MediaEmbedElement = withHOC( -
+
{ + const { name, url } = props.element as TFileElement; + + return ( + + +
+ + +
{name}
+
+ + {/* + + */} +
+ + {children} + + ); +}; diff --git a/apps/www/src/registry/default/plate-ui/media-file-element.tsx b/apps/www/src/registry/default/plate-ui/media-file-element.tsx index 85e50e0c2b..765d6698ee 100644 --- a/apps/www/src/registry/default/plate-ui/media-file-element.tsx +++ b/apps/www/src/registry/default/plate-ui/media-file-element.tsx @@ -20,21 +20,20 @@ export const MediaFileElement = withHOC( const { name, unsafeUrl } = useMediaState(); - const onDownload = () => { - window.open(unsafeUrl); - }; - return ( -
@@ -52,7 +51,7 @@ export const MediaFileElement = withHOC( placeholder="Write a caption..." /> -
+ {children} ); diff --git a/apps/www/src/registry/default/plate-ui/media-placeholder-element.tsx b/apps/www/src/registry/default/plate-ui/media-placeholder-element.tsx index 1d7afa8d96..0c5ddf5715 100644 --- a/apps/www/src/registry/default/plate-ui/media-placeholder-element.tsx +++ b/apps/www/src/registry/default/plate-ui/media-placeholder-element.tsx @@ -12,7 +12,7 @@ import { withoutSavingHistory, } from '@udecode/plate-common'; import { - findNodePath, + findPath, useEditorPlugin, withHOC, withRef, @@ -67,7 +67,8 @@ const CONTENT: Record< export const MediaPlaceholderElement = withHOC( PlaceholderProvider, withRef( - ({ children, className, editor, nodeProps, ...props }, ref) => { + ({ children, className, nodeProps, ...props }, ref) => { + const editor = props.editor; const element = props.element as TPlaceholderElement; const { api } = useEditorPlugin(PlaceholderPlugin); @@ -107,7 +108,7 @@ export const MediaPlaceholderElement = withHOC( useEffect(() => { if (!uploadedFile) return; - const path = findNodePath(editor, element); + const path = findPath(editor, element); withoutSavingHistory(editor, () => { removeNodes(editor, { at: path }); @@ -154,8 +155,7 @@ export const MediaPlaceholderElement = withHOC( return ( {(!loading || !isImage) && ( diff --git a/apps/www/src/registry/default/plate-ui/media-video-element-static.tsx b/apps/www/src/registry/default/plate-ui/media-video-element-static.tsx new file mode 100644 index 0000000000..91cdbf3cba --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/media-video-element-static.tsx @@ -0,0 +1,43 @@ +import React from 'react'; + +import type { TCaptionElement } from '@udecode/plate-caption'; +import type { SlateElementProps } from '@udecode/plate-common'; +import type { TVideoElement } from '@udecode/plate-media'; + +import { cn } from '@udecode/cn'; +import { SlateElement, getNodeString } from '@udecode/plate-common'; + +export function MediaVideoElementStatic({ + children, + className, + ...props +}: SlateElementProps) { + const { + align = 'center', + caption, + url, + width, + } = props.element as TVideoElement & + TCaptionElement & { + width: number; + }; + + return ( + +
+
+
+
+ {children} +
+ ); +} diff --git a/apps/www/src/registry/default/plate-ui/media-video-element.tsx b/apps/www/src/registry/default/plate-ui/media-video-element.tsx index 6108bacecb..571da9a527 100644 --- a/apps/www/src/registry/default/plate-ui/media-video-element.tsx +++ b/apps/www/src/registry/default/plate-ui/media-video-element.tsx @@ -46,7 +46,7 @@ export const MediaVideoElement = withHOC( return (
+ {IS_APPLE ? ( + // Mac OS IME https://github.com/ianstormtaylor/slate/issues/3490 + + {children} + {prefix} + {element.value} + + ) : ( + // Others like Android https://github.com/ianstormtaylor/slate/pull/5360 + + {prefix} + {element.value} + {children} + + )} + + ); +} 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 038b2d7c1e..0fa56f4311 100644 --- a/apps/www/src/registry/default/plate-ui/mention-element.tsx +++ b/apps/www/src/registry/default/plate-ui/mention-element.tsx @@ -7,7 +7,7 @@ import type { TMentionElement } from '@udecode/plate-mention'; import { cn, withRef } from '@udecode/cn'; import { IS_APPLE, getHandler } from '@udecode/plate-common'; import { useElement } from '@udecode/plate-common/react'; -import { useFocused, useSelected } from 'slate-react'; +import { useFocused, useReadOnly, useSelected } from 'slate-react'; import { useMounted } from '@/registry/default/hooks/use-mounted'; @@ -17,25 +17,26 @@ export const MentionElement = withRef< typeof PlateElement, { prefix?: string; - renderLabel?: (mentionable: TMentionElement) => string; onClick?: (mentionNode: any) => void; } ->(({ children, className, prefix, renderLabel, onClick, ...props }, ref) => { +>(({ children, className, prefix, onClick, ...props }, ref) => { const element = useElement(); const selected = useSelected(); const focused = useFocused(); const mounted = useMounted(); + const readOnly = useReadOnly(); return ( {children} {prefix} - {renderLabel ? renderLabel(element) : element.value} + {element.value} ) : ( // Others like Android https://github.com/ianstormtaylor/slate/pull/5360 {prefix} - {renderLabel ? renderLabel(element) : element.value} + {element.value} {children} )} 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 e9bb671d8a..835a06d88b 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 @@ -2,7 +2,7 @@ import React, { useState } from 'react'; -import { cn, withRef } from '@udecode/cn'; +import { withRef } from '@udecode/cn'; import { getMentionOnSelectItem } from '@udecode/plate-mention'; import { @@ -26,6 +26,7 @@ export const MentionInputElement = withRef( @@ -36,12 +37,7 @@ export const MentionInputElement = withRef( showTrigger={false} trigger="@" > - + diff --git a/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx index 58f02a06d6..7cd039bc71 100644 --- a/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/more-dropdown-menu.tsx @@ -1,4 +1,5 @@ 'use client'; + import React from 'react'; import type { DropdownMenuProps } from '@radix-ui/react-dropdown-menu'; diff --git a/apps/www/src/registry/default/plate-ui/paragraph-element-static.tsx b/apps/www/src/registry/default/plate-ui/paragraph-element-static.tsx new file mode 100644 index 0000000000..0c6f1bbfc5 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/paragraph-element-static.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export const ParagraphElementStatic = ({ + children, + className, + ...props +}: SlateElementProps) => { + return ( + + {children} + + ); +}; 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 a9388efb0c..118db0ea36 100644 --- a/apps/www/src/registry/default/plate-ui/paragraph-element.tsx +++ b/apps/www/src/registry/default/plate-ui/paragraph-element.tsx @@ -12,7 +12,7 @@ export const ParagraphElement = withRef( 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 index d3db18f8f7..b99ae77164 100644 --- a/apps/www/src/registry/default/plate-ui/plate-element.tsx +++ b/apps/www/src/registry/default/plate-ui/plate-element.tsx @@ -14,7 +14,7 @@ export const PlateElement = React.forwardRef( return ( {children} 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 eaf91f83dc..343f04799f 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 @@ -201,6 +201,7 @@ export const SlashInputElement = withRef( diff --git a/apps/www/src/registry/default/plate-ui/table-cell-element-static.tsx b/apps/www/src/registry/default/plate-ui/table-cell-element-static.tsx new file mode 100644 index 0000000000..0040d0b9fa --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/table-cell-element-static.tsx @@ -0,0 +1,73 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { + SlateElement, + findNode, + getParentNode, + isElement, +} from '@udecode/plate-common'; +import { getTableCellBorders } from '@udecode/plate-table'; + +export function TableCellElementStatic({ + children, + className, + isHeader, + style, + ...props +}: SlateElementProps & { + isHeader?: boolean; +}) { + const { editor, element } = props; + + const cellPath = findNode(editor!, { + match: (n) => isElement(n) && n === element, + })![1]; + + const rowPath = getParentNode(editor!, cellPath)![1]; + + const borders = getTableCellBorders(element, { + isFirstCell: cellPath.at(-1) === 0, + isFirstRow: rowPath.at(-1) === 0, + }); + + return ( + _*]:m-0', + 'before:size-full', + "before:absolute before:box-border before:select-none before:content-['']", + borders && + cn( + borders.bottom?.size && `before:border-b before:border-b-border`, + borders.right?.size && `before:border-r before:border-r-border`, + borders.left?.size && `before:border-l before:border-l-border`, + borders.top?.size && `before:border-t before:border-t-border` + ) + ) + )} + style={ + { + '--cellBackground': element.background, + ...style, + } as React.CSSProperties + } + {...props} + > +
+ {children} +
+
+ ); +} + +export function TableCellHeaderStaticElement(props: SlateElementProps) { + return ; +} 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 b4f247d33b..b0bacd0987 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 @@ -56,6 +56,7 @@ export const TableCellElement = withRef< ref={ref} as={isHeader ? 'th' : 'td'} className={cn( + className, 'relative h-full overflow-visible border-none bg-background p-0', hideBorder && 'before:border-none', element.background ? 'bg-[--cellBackground]' : 'bg-background', @@ -73,8 +74,7 @@ export const TableCellElement = withRef< borders.left?.size && `before:border-l before:border-l-border`, borders.top?.size && `before:border-t before:border-t-border` ) - ), - className + ) )} {...cellProps} {...props} diff --git a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx index 5f28689b4c..a6833cb833 100644 --- a/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx +++ b/apps/www/src/registry/default/plate-ui/table-dropdown-menu.tsx @@ -10,13 +10,14 @@ import { useEditorPlugin, useEditorSelector, } from '@udecode/plate-common/react'; -import { deleteTable, insertTableRow } from '@udecode/plate-table'; import { - TablePlugin, deleteColumn, deleteRow, + deleteTable, insertTable, -} from '@udecode/plate-table/react'; + insertTableRow, +} from '@udecode/plate-table'; +import { TablePlugin } from '@udecode/plate-table/react'; import { Minus, Plus, diff --git a/apps/www/src/registry/default/plate-ui/table-element-static.tsx b/apps/www/src/registry/default/plate-ui/table-element-static.tsx new file mode 100644 index 0000000000..42aa43f64f --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/table-element-static.tsx @@ -0,0 +1,38 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; +import type { TTableElement } from '@udecode/plate-table'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export const TableElementStatic = ({ + children, + className, + ...props +}: SlateElementProps) => { + const { colSizes } = props.element as TTableElement; + + return ( + + + + {colSizes?.map((width, index) => ( + + ))} + + + {children} +
+
+ ); +}; 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 14bacd94fb..277c289252 100644 --- a/apps/www/src/registry/default/plate-ui/table-element.tsx +++ b/apps/www/src/registry/default/plate-ui/table-element.tsx @@ -3,7 +3,6 @@ import React from 'react'; import type * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; -import type { TTableElement } from '@udecode/plate-table'; import { PopoverAnchor } from '@radix-ui/react-popover'; import { cn, withRef } from '@udecode/cn'; @@ -16,9 +15,12 @@ import { withHOC, } from '@udecode/plate-common/react'; import { - TableProvider, + type TTableElement, mergeTableCells, unmergeTableCells, +} from '@udecode/plate-table'; +import { + TableProvider, useTableBordersDropdownMenuContentState, useTableElement, useTableElementState, @@ -207,7 +209,7 @@ export const TableElement = withHOC( return ( diff --git a/apps/www/src/registry/default/plate-ui/table-row-element-static.tsx b/apps/www/src/registry/default/plate-ui/table-row-element-static.tsx new file mode 100644 index 0000000000..1d605a2e39 --- /dev/null +++ b/apps/www/src/registry/default/plate-ui/table-row-element-static.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +import type { SlateElementProps } from '@udecode/plate-common'; + +import { cn } from '@udecode/cn'; +import { SlateElement } from '@udecode/plate-common'; + +export function TableRowElementStatic({ + children, + className, + ...props +}: SlateElementProps) { + return ( + + {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 d437383b8f..d281d08530 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 @@ -10,12 +10,12 @@ export const TableRowElement = withRef< { hideBorder?: boolean; } ->(({ children, hideBorder, ...props }, ref) => { +>(({ children, className, hideBorder, ...props }, ref) => { return ( {children} diff --git a/apps/www/src/registry/default/plate-ui/tag-element.tsx b/apps/www/src/registry/default/plate-ui/tag-element.tsx index 7f4b26595a..56393ea75d 100644 --- a/apps/www/src/registry/default/plate-ui/tag-element.tsx +++ b/apps/www/src/registry/default/plate-ui/tag-element.tsx @@ -36,8 +36,8 @@ export const TagElement = withRef( +
+ {headingList.length > 0 ? ( + headingList.map((item) => ( + + )) + ) : ( +
+ Create a heading to display the table of contents. +
+ )} +
+ {children} + + ); +} + +const headingDepth: Record = { + [HEADING_KEYS.h1]: 1, + [HEADING_KEYS.h2]: 2, + [HEADING_KEYS.h3]: 3, + [HEADING_KEYS.h4]: 4, + [HEADING_KEYS.h5]: 5, + [HEADING_KEYS.h6]: 6, +}; + +const getHeadingList = (editor?: SlateEditor) => { + if (!editor) return []; + + const options = editor.getOptions(BaseTocPlugin); + + if (options.queryHeading) { + return options.queryHeading(editor); + } + + const headingList: Heading[] = []; + + const values = getNodeEntries(editor, { + at: [], + match: (n) => isHeading(n), + }); + + if (!values) return []; + + Array.from(values, ([node, path]) => { + const { type } = node as TElement; + const title = getNodeString(node); + const depth = headingDepth[type]; + const id = node.id; + title && headingList.push({ id, depth, path, title, type }); + }); + + return headingList; +}; 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 a282c8d5b3..4d09f3c052 100644 --- a/apps/www/src/registry/default/plate-ui/toc-element.tsx +++ b/apps/www/src/registry/default/plate-ui/toc-element.tsx @@ -34,7 +34,7 @@ export const TocElement = withRef( return (
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 e26dc5e4ed..2d83b99240 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 @@ -20,7 +20,7 @@ export const TodoListElement = withRef( return (
+
+ +
+ {children} + + ); +} 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 42366f3b8c..44d1b7ee91 100644 --- a/apps/www/src/registry/default/plate-ui/toggle-element.tsx +++ b/apps/www/src/registry/default/plate-ui/toggle-element.tsx @@ -20,7 +20,7 @@ export const ToggleElement = withRef( return (