import('./_components/home-tabs'));
const CustomizerDrawer = dynamic(
() => import('@/components/customizer-drawer')
);
-
export default function IndexPage() {
return (
diff --git a/apps/www/src/components/icons.tsx b/apps/www/src/components/icons.tsx
index d6a02c9b11..d5cda79e04 100644
--- a/apps/www/src/components/icons.tsx
+++ b/apps/www/src/components/icons.tsx
@@ -255,7 +255,129 @@ const yarn = (props: LucideProps) => (
);
+export const DoubleColumnOutlined = (props: LucideProps) => (
+
+);
+
+export const ThreeColumnOutlined = (props: LucideProps) => (
+
+);
+
+export const RightSideDoubleColumnOutlined = (props: LucideProps) => (
+
+);
+
+export const LeftSideDoubleColumnOutlined = (props: LucideProps) => (
+
+);
+
+export const DoubleSideDoubleColumnOutlined = (props: LucideProps) => (
+
+);
+
+const LayoutIcon = (props: LucideProps) => (
+
+);
+
export const Icons = {
+ doubleColumn: DoubleColumnOutlined,
+ threeColumn: ThreeColumnOutlined,
+ rightSideDoubleColumn: RightSideDoubleColumnOutlined,
+ leftSideDoubleColumn: LeftSideDoubleColumnOutlined,
+ doubleSideDoubleColumn: DoubleSideDoubleColumnOutlined,
+ LayoutIcon,
todo: Square,
add: Plus,
alignCenter: AlignCenter,
diff --git a/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx b/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx
index 4febf26437..4cfe482d52 100644
--- a/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx
+++ b/apps/www/src/components/plate-ui/playground-insert-dropdown-menu.tsx
@@ -26,6 +26,7 @@ import {
KEY_LIST_STYLE_TYPE,
toggleIndentList,
} from '@udecode/plate-indent-list';
+import { ELEMENT_COLUMN_GROUP, insertColumnGroup } from '@udecode/plate-layout';
import { ELEMENT_LINK, triggerFloatingLink } from '@udecode/plate-link';
import { toggleList } from '@udecode/plate-list';
import {
@@ -125,6 +126,12 @@ const items = [
description: 'Divider (---)',
icon: Icons.hr,
},
+ {
+ value: ELEMENT_COLUMN_GROUP,
+ label: 'Columns',
+ description: 'Columns',
+ icon: Icons.LayoutIcon,
+ },
],
},
{
@@ -197,6 +204,11 @@ export function PlaygroundInsertDropdownMenu(props: DropdownMenuProps) {
className="min-w-[180px]"
onSelect={async () => {
switch (type) {
+ case ELEMENT_COLUMN_GROUP: {
+ insertColumnGroup(editor);
+ break;
+ }
+
case ELEMENT_CODE_BLOCK: {
insertEmptyCodeBlock(editor);
diff --git a/apps/www/src/components/settings-combobox.tsx b/apps/www/src/components/settings-combobox.tsx
index c43bd206be..f21d4d311b 100644
--- a/apps/www/src/components/settings-combobox.tsx
+++ b/apps/www/src/components/settings-combobox.tsx
@@ -40,6 +40,7 @@ const categories = [
customizerPlugins.blockselection,
customizerPlugins.comment,
customizerPlugins.cursoroverlay,
+ customizerPlugins.column,
customizerPlugins.deserializecsv,
customizerPlugins.deserializedocx,
customizerPlugins.deserializehtml,
diff --git a/apps/www/src/config/customizer-components.ts b/apps/www/src/config/customizer-components.ts
index 650bc961aa..f258c4a6ae 100644
--- a/apps/www/src/config/customizer-components.ts
+++ b/apps/www/src/config/customizer-components.ts
@@ -242,7 +242,17 @@ export const customizerComponents = {
},
toggleElement: {
title: 'Toggle',
- href: '/docs/components/toggle',
+ href: '/docs/components/toggle-element',
+ },
+ columnGroupElement: {
+ title: 'Column Group',
+ href: '/docs/components/column-group-element',
+ label: 'Element',
+ },
+ columnElement: {
+ title: 'Column',
+ href: '/docs/components/column-element',
+ label: 'Element',
},
toggleToolbarButton: {
title: 'Toggle Toolbar Button',
diff --git a/apps/www/src/config/customizer-items.ts b/apps/www/src/config/customizer-items.ts
index ce10b3ff19..704ff0898b 100644
--- a/apps/www/src/config/customizer-items.ts
+++ b/apps/www/src/config/customizer-items.ts
@@ -273,6 +273,30 @@ export const customizerItems: Record
= {
},
],
},
+ column: {
+ id: 'column',
+ npmPackage: '@udecode/plate-layout',
+ pluginFactory: 'createColumnPlugin',
+ label: 'Column',
+ badges: [customizerBadges.element],
+ route: customizerPlugins.column.route,
+ components: [
+ {
+ id: 'column-group-element',
+ label: 'ColumnGroupElement',
+ pluginKey: 'ELEMENT_COLUMN_GROUP',
+ usage: 'ColumnGroupElement',
+ route: customizerComponents.columnGroupElement.href,
+ },
+ {
+ id: 'column-element',
+ label: 'ColumnElement',
+ pluginKey: 'ELEMENT_COLUMN',
+ usage: 'ColumnElement',
+ route: customizerComponents.columnElement.href,
+ },
+ ],
+ },
heading: {
id: 'heading',
npmPackage: '@udecode/plate-heading',
diff --git a/apps/www/src/config/customizer-list.ts b/apps/www/src/config/customizer-list.ts
index 36202b0d31..86e03813a0 100644
--- a/apps/www/src/config/customizer-list.ts
+++ b/apps/www/src/config/customizer-list.ts
@@ -64,6 +64,7 @@ export const customizerList = [
customizerItems[ELEMENT_IMAGE],
customizerItems[ELEMENT_LINK],
customizerItems[ELEMENT_TOGGLE],
+ customizerItems.column,
customizerItems.heading,
customizerItems.list,
customizerItems[ELEMENT_MEDIA_EMBED],
diff --git a/apps/www/src/config/customizer-plugins.ts b/apps/www/src/config/customizer-plugins.ts
index 9a3178b82a..e8c1becae4 100644
--- a/apps/www/src/config/customizer-plugins.ts
+++ b/apps/www/src/config/customizer-plugins.ts
@@ -51,6 +51,7 @@ import { ELEMENT_HR } from '@udecode/plate-horizontal-rule';
import { KEY_INDENT } from '@udecode/plate-indent';
import { KEY_LIST_STYLE_TYPE } from '@udecode/plate-indent-list';
import { MARK_KBD } from '@udecode/plate-kbd';
+import { ELEMENT_COLUMN_GROUP } from '@udecode/plate-layout';
import { KEY_LINE_HEIGHT } from '@udecode/plate-line-height';
import { ELEMENT_LINK } from '@udecode/plate-link';
import { ELEMENT_TODO_LI } from '@udecode/plate-list';
@@ -68,6 +69,8 @@ import { ELEMENT_TABLE } from '@udecode/plate-table';
import { ELEMENT_TOGGLE } from '@udecode/plate-toggle';
import { KEY_TRAILING_BLOCK } from '@udecode/plate-trailing-block';
+import { columnValue } from '@/lib/plate/demo/values/columnValue';
+
export type ValueId = keyof typeof customizerPlugins | 'tableMerge';
// cmdk needs lowercase
@@ -340,6 +343,13 @@ export const customizerPlugins = {
route: '/docs/toggle',
plugins: [ELEMENT_TOGGLE],
},
+ column: {
+ id: 'column',
+ label: 'Column',
+ value: columnValue,
+ route: '/docs/column',
+ plugins: [ELEMENT_COLUMN_GROUP],
+ },
trailingblock: {
id: 'trailingblock',
label: 'Trailing Block',
diff --git a/apps/www/src/config/descriptions.ts b/apps/www/src/config/descriptions.ts
index 2307290af0..24f3fe7a79 100644
--- a/apps/www/src/config/descriptions.ts
+++ b/apps/www/src/config/descriptions.ts
@@ -56,6 +56,7 @@ export const descriptions: Record = {
[ELEMENT_IMAGE]: 'Embed images into your document.',
[ELEMENT_LINK]: 'Insert and manage hyperlinks.',
[ELEMENT_TOGGLE]: 'Add toggles to your document.',
+ column: 'Add column plugins',
heading: 'Organize your document with up to 6 headings.',
list: 'Organize nestable items in a bulleted or numbered list.',
[ELEMENT_MEDIA_EMBED]:
diff --git a/apps/www/src/config/doc-to-package.ts b/apps/www/src/config/doc-to-package.ts
index 054b65823f..246dd1904b 100644
--- a/apps/www/src/config/doc-to-package.ts
+++ b/apps/www/src/config/doc-to-package.ts
@@ -9,6 +9,7 @@ const plateOverrides = {
collaboration: 'plate-yjs',
combobox: 'plate-combobox',
comments: 'plate-comments',
+ column: 'plate-column',
dnd: 'plate-dnd',
emoji: 'plate-emoji',
excalidraw: 'plate-excalidraw',
diff --git a/apps/www/src/config/docs.ts b/apps/www/src/config/docs.ts
index 39ac11e5f7..c530e1a7ee 100644
--- a/apps/www/src/config/docs.ts
+++ b/apps/www/src/config/docs.ts
@@ -120,6 +120,11 @@ export const docsConfig: DocsConfig = {
href: '/docs/comments',
label: 'Leaf',
},
+ {
+ title: 'Column',
+ href: '/docs/column',
+ label: 'Element',
+ },
{
title: 'Drag & Drop',
href: '/docs/dnd',
@@ -735,6 +740,8 @@ export const docsConfig: DocsConfig = {
customizerComponents.commentToolbarButton,
customizerComponents.commentsPopover,
customizerComponents.cursorOverlay,
+ customizerComponents.columnGroupElement,
+ customizerComponents.columnElement,
customizerComponents.dialog,
customizerComponents.draggable,
customizerComponents.dropdownMenu,
diff --git a/apps/www/src/lib/plate/create-plate-ui.ts b/apps/www/src/lib/plate/create-plate-ui.ts
index 400c1b1a55..ed21cd78ec 100644
--- a/apps/www/src/lib/plate/create-plate-ui.ts
+++ b/apps/www/src/lib/plate/create-plate-ui.ts
@@ -33,6 +33,7 @@ import {
import { MARK_HIGHLIGHT } from '@udecode/plate-highlight';
import { ELEMENT_HR } from '@udecode/plate-horizontal-rule';
import { MARK_KBD } from '@udecode/plate-kbd';
+import { ELEMENT_COLUMN, ELEMENT_COLUMN_GROUP } from '@udecode/plate-layout';
import { ELEMENT_LINK } from '@udecode/plate-link';
import {
ELEMENT_LI,
@@ -56,6 +57,8 @@ import { CodeBlockElement } from '@/registry/default/plate-ui/code-block-element
import { CodeLeaf } from '@/registry/default/plate-ui/code-leaf';
import { CodeLineElement } from '@/registry/default/plate-ui/code-line-element';
import { CodeSyntaxLeaf } from '@/registry/default/plate-ui/code-syntax-leaf';
+import { ColumnElement } from '@/registry/default/plate-ui/column-element';
+import { ColumnGroupElement } from '@/registry/default/plate-ui/column-group-element';
import { CommentLeaf } from '@/registry/default/plate-ui/comment-leaf';
import { ExcalidrawElement } from '@/registry/default/plate-ui/excalidraw-element';
import { HeadingElement } from '@/registry/default/plate-ui/heading-element';
@@ -116,6 +119,8 @@ export const createPlateUI = (
[ELEMENT_TOGGLE]: ToggleElement,
[ELEMENT_TR]: TableRowElement,
[ELEMENT_EXCALIDRAW]: ExcalidrawElement,
+ [ELEMENT_COLUMN_GROUP]: ColumnGroupElement,
+ [ELEMENT_COLUMN]: ColumnElement,
[MARK_BOLD]: withProps(PlateLeaf, { as: 'strong' }),
[MARK_CODE]: CodeLeaf,
[MARK_HIGHLIGHT]: HighlightLeaf,
diff --git a/apps/www/src/lib/plate/demo/values/columnValue.tsx b/apps/www/src/lib/plate/demo/values/columnValue.tsx
new file mode 100644
index 0000000000..b280d0dca7
--- /dev/null
+++ b/apps/www/src/lib/plate/demo/values/columnValue.tsx
@@ -0,0 +1,16 @@
+/** @jsxRuntime classic */
+/** @jsx jsx */
+import { jsx } from '@udecode/plate-test-utils';
+
+jsx;
+
+export const columnValue: any = (
+
+ 🌻 Column
+ Create column and the border will hidden when viewing
+
+ left
+ right
+
+
+);
diff --git a/apps/www/src/lib/plate/demo/values/toggleValue.tsx b/apps/www/src/lib/plate/demo/values/toggleValue.tsx
index 17e73b5380..1ab02118a5 100644
--- a/apps/www/src/lib/plate/demo/values/toggleValue.tsx
+++ b/apps/www/src/lib/plate/demo/values/toggleValue.tsx
@@ -6,7 +6,7 @@ jsx;
export const toggleValue: any = (
- Toggle
+ 🦚 Toggle
Create toggles with multiple levels of indentation
Level 1 toggle
Inside level 1 toggle
diff --git a/apps/www/src/lib/plate/demo/values/usePlaygroundValue.ts b/apps/www/src/lib/plate/demo/values/usePlaygroundValue.ts
index 486df4d1ec..7678db4b61 100644
--- a/apps/www/src/lib/plate/demo/values/usePlaygroundValue.ts
+++ b/apps/www/src/lib/plate/demo/values/usePlaygroundValue.ts
@@ -9,6 +9,7 @@ import { alignValue } from './alignValue';
import { autoformatValue } from './autoformatValue';
import { basicElementsValue } from './basicElementsValue';
import { basicMarksValue } from './basicMarksValue';
+import { columnValue } from './columnValue';
import { commentsValue } from './commentsValue';
import { cursorOverlayValue } from './cursorOverlayValue';
import { deserializeCsvValue } from './deserializeCsvValue';
@@ -76,6 +77,7 @@ export const usePlaygroundValue = (id?: ValueId) => {
if (enabled.list) value.push(...listValue);
if (enabled.img || enabled.media_embed) value.push(...mediaValue);
if (enabled.table) value.push(...tableValue);
+ if (enabled.column) value.push(...columnValue);
if (enabled.toggle) value.push(...toggleValue);
// Functionalities
@@ -129,6 +131,7 @@ export const usePlaygroundValue = (id?: ValueId) => {
enabled.table,
enabled.toggle,
enabled.trailingBlock,
+ enabled.column,
valueId,
]);
};
diff --git a/apps/www/src/registry/default/example/playground-demo.tsx b/apps/www/src/registry/default/example/playground-demo.tsx
index 05913d24cb..63ddbd822c 100644
--- a/apps/www/src/registry/default/example/playground-demo.tsx
+++ b/apps/www/src/registry/default/example/playground-demo.tsx
@@ -79,6 +79,7 @@ import { createIndentPlugin } from '@udecode/plate-indent';
import { createIndentListPlugin } from '@udecode/plate-indent-list';
import { createJuicePlugin } from '@udecode/plate-juice';
import { createKbdPlugin } from '@udecode/plate-kbd';
+import { createColumnPlugin } from '@udecode/plate-layout';
import { createLineHeightPlugin } from '@udecode/plate-line-height';
import { createLinkPlugin } from '@udecode/plate-link';
import { createListPlugin, createTodoListPlugin } from '@udecode/plate-list';
@@ -324,6 +325,7 @@ export const usePlaygroundPlugins = ({
createDeserializeDocxPlugin({ enabled: !!enabled.deserializeDocx }),
createDeserializeMdPlugin({ enabled: !!enabled.deserializeMd }),
createJuicePlugin({ enabled: !!enabled.juice }),
+ createColumnPlugin({ enabled: !!enabled.column }),
],
{
components,
diff --git a/apps/www/src/registry/default/plate-ui/column-element.tsx b/apps/www/src/registry/default/plate-ui/column-element.tsx
new file mode 100644
index 0000000000..00c50a1fd9
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/column-element.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { cn, withRef } from '@udecode/cn';
+import { PlateElement, useElement, withHOC } from '@udecode/plate-common';
+import { TColumnElement } from '@udecode/plate-layout';
+import { ResizableProvider } from '@udecode/plate-resizable';
+import { useReadOnly } from 'slate-react';
+
+export const ColumnElement = withHOC(
+ ResizableProvider,
+ withRef(({ className, children, ...props }, ref) => {
+ const readOnly = useReadOnly();
+ const { width } = useElement();
+
+ return (
+
+ {children}
+
+ );
+ })
+);
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
new file mode 100644
index 0000000000..4a3ce5837e
--- /dev/null
+++ b/apps/www/src/registry/default/plate-ui/column-group-element.tsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import { cn, withRef } from '@udecode/cn';
+import {
+ PlateElement,
+ useElement,
+ useRemoveNodeButton,
+} from '@udecode/plate-common';
+import {
+ ELEMENT_COLUMN,
+ TColumnElement,
+ useColumnState,
+ useDebouncePopoverOpen,
+} from '@udecode/plate-layout';
+import { useReadOnly } from 'slate-react';
+
+import { Icons } from '@/components/icons';
+
+import { Button } from './button';
+import { Popover, PopoverAnchor, PopoverContent } from './popover';
+import { Separator } from './separator';
+
+export const ColumnGroupElement = withRef(
+ ({ className, children, ...props }, ref) => {
+ return (
+
+
+ {children}
+
+
+ );
+ }
+);
+
+export function ColumnFloatingToolbar({ children }: React.PropsWithChildren) {
+ const readOnly = useReadOnly();
+
+ const {
+ setDoubleColumn,
+ setDoubleSideDoubleColumn,
+ setLeftSideDoubleColumn,
+ setRightSideDoubleColumn,
+ setThreeColumn,
+ } = useColumnState();
+
+ const element = useElement(ELEMENT_COLUMN);
+
+ const { props: buttonProps } = useRemoveNodeButton({ element });
+
+ const isOpen = useDebouncePopoverOpen();
+
+ if (readOnly) return <>{children}>;
+
+ return (
+
+ {children}
+ e.preventDefault()}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/www/src/registry/registry.ts b/apps/www/src/registry/registry.ts
index 9367d5dbb1..c3856cf493 100644
--- a/apps/www/src/registry/registry.ts
+++ b/apps/www/src/registry/registry.ts
@@ -33,6 +33,13 @@ const ui: Registry = [
'plate-ui/code-block-combobox.tsx',
],
},
+ {
+ name: 'column-element',
+ type: 'components:plate-ui',
+ dependencies: ['@udecode/plate-layout'],
+ registryDependencies: ['command', 'resizable'],
+ files: ['plate-ui/column-element.tsx', 'plate-ui/column-group-element.tsx'],
+ },
{
name: 'color-dropdown-menu',
type: 'components:plate-ui',
diff --git a/package.json b/package.json
index 75973d78d2..7d86f87bd9 100644
--- a/package.json
+++ b/package.json
@@ -49,8 +49,8 @@
"g:typecheck:apps": "turbo --filter=www typecheck --no-daemon",
"install:playwright": "yarn playwright install --with-deps",
"nuke:node_modules": "rimraf '**/node_modules'",
- "p:brl": "cd $INIT_CWD && barrelsby -d $INIT_CWD/src -D -l all -q -e '.*(fixture|template|spec|internal).*'",
- "p:brl:below": "cd $INIT_CWD && barrelsby -d $INIT_CWD/src -D -l below -q -e '.*(fixture|template|spec|internal).*'",
+ "p:brl": "cd $INIT_CWD && barrelsby -d $INIT_CWD/src -D -l all -q -e '.*__tests__.*|(.*(fixture|template|spec|internal).*)|server.ts'",
+ "p:brl:below": "cd $INIT_CWD && barrelsby -d $INIT_CWD/src -D -l below -q -e '.*__tests__.*|(.*(fixture|template|spec|internal).*)|server.ts'",
"p:build": "cd $INIT_CWD && yarn p:tsup",
"p:build:watch": "cd $INIT_CWD && yarn p:tsup --watch",
"p:clean": "cd $INIT_CWD && rimraf dist && jest --clear-cache",
diff --git a/packages/emoji/src/utils/index.ts b/packages/emoji/src/utils/index.ts
index f8e1d5114d..220ede92cd 100644
--- a/packages/emoji/src/utils/index.ts
+++ b/packages/emoji/src/utils/index.ts
@@ -2,7 +2,6 @@
* @file Automatically generated by barrelsby.
*/
-export * from './EmojiObserver';
export * from './EmojiTriggeringController';
export * from './EmojiLibrary/index';
export * from './EmojiPicker/index';
diff --git a/packages/indent-list/src/delete-backward/index.ts b/packages/indent-list/src/delete-backward/index.ts
new file mode 100644
index 0000000000..426bcad2e0
--- /dev/null
+++ b/packages/indent-list/src/delete-backward/index.ts
@@ -0,0 +1,5 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './deleteBackwardIndentList';
diff --git a/packages/indent-list/src/hooks/index.ts b/packages/indent-list/src/hooks/index.ts
index 21baa61d39..7bad491849 100644
--- a/packages/indent-list/src/hooks/index.ts
+++ b/packages/indent-list/src/hooks/index.ts
@@ -3,5 +3,6 @@
*/
export * from './someIndentList';
+export * from './someIndentTodo';
export * from './useIndentListToolbarButton';
export * from './useIndentTodoToolbarButton';
diff --git a/packages/indent-list/src/index.ts b/packages/indent-list/src/index.ts
index 6124021f44..1dd3510163 100644
--- a/packages/indent-list/src/index.ts
+++ b/packages/indent-list/src/index.ts
@@ -8,6 +8,7 @@ export * from './normalizeIndentList';
export * from './onKeyDownIndentList';
export * from './types';
export * from './withIndentList';
+export * from './delete-backward/index';
export * from './hooks/index';
export * from './normalizers/index';
export * from './queries/index';
diff --git a/packages/layout/.npmignore b/packages/layout/.npmignore
new file mode 100644
index 0000000000..7d3b305b17
--- /dev/null
+++ b/packages/layout/.npmignore
@@ -0,0 +1,3 @@
+__tests__
+__test-utils__
+__mocks__
diff --git a/packages/layout/README.md b/packages/layout/README.md
new file mode 100644
index 0000000000..e4809c5358
--- /dev/null
+++ b/packages/layout/README.md
@@ -0,0 +1 @@
+# Plate Column plugin
diff --git a/packages/layout/package.json b/packages/layout/package.json
new file mode 100644
index 0000000000..a89431a4de
--- /dev/null
+++ b/packages/layout/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "@udecode/plate-layout",
+ "version": "31.0.0",
+ "description": "Layout plugin for Plate",
+ "license": "MIT",
+ "homepage": "https://platejs.org",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/udecode/plate.git",
+ "directory": "packages/layout"
+ },
+ "bugs": {
+ "url": "https://github.com/udecode/plate/issues"
+ },
+ "sideEffects": false,
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist/**/*"
+ ],
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.mjs",
+ "module": "./dist/index.mjs",
+ "require": "./dist/index.js"
+ }
+ },
+ "scripts": {
+ "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",
+ "test": "yarn p:test",
+ "test:watch": "yarn p:test:watch",
+ "typecheck": "yarn p:typecheck"
+ },
+ "devDependencies": {
+ "@udecode/plate-common": "workspace:^"
+ },
+ "peerDependencies": {
+ "@udecode/plate-common": ">=31.3.2",
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0",
+ "slate": ">=0.94.0",
+ "slate-history": ">=0.93.0",
+ "slate-hyperscript": ">=0.66.0",
+ "slate-react": ">=0.99.0"
+ },
+ "keywords": [
+ "plate",
+ "plugin",
+ "slate"
+ ],
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/layout/src/column-store.ts b/packages/layout/src/column-store.ts
new file mode 100644
index 0000000000..aae37cedab
--- /dev/null
+++ b/packages/layout/src/column-store.ts
@@ -0,0 +1,46 @@
+import {
+ findNodePath,
+ setNodes,
+ useEditorRef,
+ useElement,
+} from '@udecode/plate-common';
+
+import { ELEMENT_COLUMN_GROUP } from './createColumnPlugin';
+import { TColumnGroupElement } from './types';
+
+export const useColumnState = () => {
+ const editor = useEditorRef();
+
+ const columnGroupElement =
+ useElement(ELEMENT_COLUMN_GROUP);
+
+ const columnPath = findNodePath(editor, columnGroupElement);
+
+ const setDoubleColumn = () => {
+ setNodes(editor, { layout: [50, 50] }, { at: columnPath });
+ };
+
+ const setThreeColumn = () => {
+ setNodes(editor, { layout: [33, 33, 33] }, { at: columnPath });
+ };
+
+ const setRightSideDoubleColumn = () => {
+ setNodes(editor, { layout: [70, 30] }, { at: columnPath });
+ };
+
+ const setLeftSideDoubleColumn = () => {
+ setNodes(editor, { layout: [30, 70] }, { at: columnPath });
+ };
+
+ const setDoubleSideDoubleColumn = () => {
+ setNodes(editor, { layout: [25, 50, 25] }, { at: columnPath });
+ };
+
+ return {
+ setDoubleColumn,
+ setDoubleSideDoubleColumn,
+ setLeftSideDoubleColumn,
+ setRightSideDoubleColumn,
+ setThreeColumn,
+ };
+};
diff --git a/packages/layout/src/createColumnPlugin.ts b/packages/layout/src/createColumnPlugin.ts
new file mode 100644
index 0000000000..bc932b2f82
--- /dev/null
+++ b/packages/layout/src/createColumnPlugin.ts
@@ -0,0 +1,23 @@
+import { createPluginFactory, HotkeyPlugin } from '@udecode/plate-common';
+
+import { onKeyDownColumn } from './onKeyDownColumn';
+import { withColumn } from './withColumn';
+
+export const ELEMENT_COLUMN_GROUP = 'column_group';
+export const ELEMENT_COLUMN = 'column';
+
+export const createColumnPlugin = createPluginFactory({
+ key: ELEMENT_COLUMN_GROUP,
+ isElement: true,
+ options: {},
+ handlers: {
+ onKeyDown: onKeyDownColumn,
+ },
+ plugins: [
+ {
+ key: ELEMENT_COLUMN,
+ isElement: true,
+ withOverrides: withColumn,
+ },
+ ],
+});
diff --git a/packages/layout/src/hooks/index.ts b/packages/layout/src/hooks/index.ts
new file mode 100644
index 0000000000..ab852a73b1
--- /dev/null
+++ b/packages/layout/src/hooks/index.ts
@@ -0,0 +1,5 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './useDebouncePopoverOpen';
diff --git a/packages/layout/src/hooks/useDebouncePopoverOpen.ts b/packages/layout/src/hooks/useDebouncePopoverOpen.ts
new file mode 100644
index 0000000000..db746353f0
--- /dev/null
+++ b/packages/layout/src/hooks/useDebouncePopoverOpen.ts
@@ -0,0 +1,15 @@
+import { isCollapsed, useEditorSelector } from '@udecode/plate-common';
+import { useReadOnly, useSelected } from 'slate-react';
+
+export const useDebouncePopoverOpen = () => {
+ const readOnly = useReadOnly();
+ const selected = useSelected();
+
+ const selectionCollapsed = useEditorSelector(
+ (editor) => isCollapsed(editor.selection),
+ []
+ );
+
+ // TODO:should add debounce
+ return !readOnly && selected && selectionCollapsed;
+};
diff --git a/packages/layout/src/index.ts b/packages/layout/src/index.ts
new file mode 100644
index 0000000000..1369e1efa9
--- /dev/null
+++ b/packages/layout/src/index.ts
@@ -0,0 +1,12 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './column-store';
+export * from './createColumnPlugin';
+export * from './onKeyDownColumn';
+export * from './types';
+export * from './withColumn';
+export * from './hooks/index';
+export * from './normalizers/index';
+export * from './transforms/index';
diff --git a/packages/layout/src/normalizers/index.ts b/packages/layout/src/normalizers/index.ts
new file mode 100644
index 0000000000..2a2de7fc1d
--- /dev/null
+++ b/packages/layout/src/normalizers/index.ts
@@ -0,0 +1,5 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './normalizedColumn';
diff --git a/packages/layout/src/normalizers/normalizedColumn.ts b/packages/layout/src/normalizers/normalizedColumn.ts
new file mode 100644
index 0000000000..d59897227f
--- /dev/null
+++ b/packages/layout/src/normalizers/normalizedColumn.ts
@@ -0,0 +1,66 @@
+import {
+ createPathRef,
+ getLastChildPath,
+ isElement,
+ PlateEditor,
+ TNode,
+ TNodeEntry,
+ Value,
+} from '@udecode/plate-common';
+
+import { ELEMENT_COLUMN_GROUP } from '../createColumnPlugin';
+import { moveMiddleColumn } from '../transforms';
+import { insertEmptyColumn } from '../transforms/insertEmptyColumn';
+import { setColumnWidth } from '../transforms/setColumnWidth';
+import { TColumnGroupElement } from '../types';
+
+export const normalizeColumn = (
+ editor: PlateEditor
+) => {
+ const { normalizeNode } = editor;
+
+ return function (entry: TNodeEntry) {
+ if (isElement(entry[0]) && entry[0].type === ELEMENT_COLUMN_GROUP) {
+ normalizeColumnHelper(
+ editor,
+ entry as unknown as TNodeEntry
+ );
+ }
+
+ normalizeNode(entry);
+ };
+};
+
+const normalizeColumnHelper = (
+ editor: PlateEditor,
+ entry: TNodeEntry
+) => {
+ const [node, path] = entry;
+
+ const prevChildrenCnt = node.children.length;
+ const currentLayout = node.layout;
+ if (!currentLayout) return;
+
+ const currentChildrenCnt = currentLayout.length;
+
+ const groupPathRef = createPathRef(editor, path);
+
+ if (prevChildrenCnt === 2 && currentChildrenCnt === 3) {
+ const lastChildPath = getLastChildPath(entry);
+
+ insertEmptyColumn(editor, {
+ at: lastChildPath,
+ });
+
+ setColumnWidth(editor, groupPathRef, currentLayout);
+ }
+
+ if (prevChildrenCnt === 3 && currentChildrenCnt === 2) {
+ moveMiddleColumn(editor, entry, { direction: 'left' });
+ setColumnWidth(editor, groupPathRef, currentLayout);
+ }
+
+ if (prevChildrenCnt === currentChildrenCnt) {
+ setColumnWidth(editor, groupPathRef, currentLayout);
+ }
+};
diff --git a/packages/layout/src/onKeyDownColumn.ts b/packages/layout/src/onKeyDownColumn.ts
new file mode 100644
index 0000000000..2613126594
--- /dev/null
+++ b/packages/layout/src/onKeyDownColumn.ts
@@ -0,0 +1,30 @@
+import {
+ getParentNode,
+ isHotkey,
+ KeyboardHandlerReturnType,
+ PlateEditor,
+ select,
+ Value,
+} from '@udecode/plate-common';
+
+export const onKeyDownColumn =
+ = PlateEditor>(
+ editor: E
+ ): KeyboardHandlerReturnType =>
+ (e) => {
+ if (e.defaultPrevented) return;
+
+ const at = editor.selection;
+
+ if (isHotkey('mod+a', e) && at) {
+ const selectionParent = getParentNode(editor, at);
+ if (!selectionParent) return;
+ const [, parentPath] = selectionParent;
+ parentPath.pop();
+
+ select(editor, parentPath);
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ };
diff --git a/packages/layout/src/transforms/index.ts b/packages/layout/src/transforms/index.ts
new file mode 100644
index 0000000000..4431b96ccb
--- /dev/null
+++ b/packages/layout/src/transforms/index.ts
@@ -0,0 +1,8 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './insertColumnGroup';
+export * from './insertEmptyColumn';
+export * from './moveMiddleColumn';
+export * from './setColumnWidth';
diff --git a/packages/layout/src/transforms/insertColumnGroup.ts b/packages/layout/src/transforms/insertColumnGroup.ts
new file mode 100644
index 0000000000..e44cc58f44
--- /dev/null
+++ b/packages/layout/src/transforms/insertColumnGroup.ts
@@ -0,0 +1,31 @@
+import {
+ ELEMENT_DEFAULT,
+ insertNodes,
+ PlateEditor,
+ Value,
+ withoutNormalizing,
+} from '@udecode/plate-common';
+
+import { ELEMENT_COLUMN, ELEMENT_COLUMN_GROUP } from '../createColumnPlugin';
+import { TColumnGroupElement } from '../types';
+
+export const insertColumnGroup = (editor: PlateEditor) => {
+ withoutNormalizing(editor, () => {
+ insertNodes(editor, {
+ type: ELEMENT_COLUMN_GROUP,
+ layout: [50, 50],
+ children: [
+ {
+ type: ELEMENT_COLUMN,
+ width: '50%',
+ children: [{ type: ELEMENT_DEFAULT, children: [{ text: '' }] }],
+ },
+ {
+ type: ELEMENT_COLUMN,
+ width: '50%',
+ children: [{ type: ELEMENT_DEFAULT, children: [{ text: '' }] }],
+ },
+ ],
+ });
+ });
+};
diff --git a/packages/layout/src/transforms/insertEmptyColumn.ts b/packages/layout/src/transforms/insertEmptyColumn.ts
new file mode 100644
index 0000000000..4972437098
--- /dev/null
+++ b/packages/layout/src/transforms/insertEmptyColumn.ts
@@ -0,0 +1,28 @@
+import {
+ ELEMENT_DEFAULT,
+ getQueryOptions,
+ insertNodes,
+ InsertNodesOptions,
+ PlateEditor,
+ Value,
+} from '@udecode/plate-common';
+
+import { ELEMENT_COLUMN } from '../createColumnPlugin';
+import { TColumnElement } from '../types';
+
+export const insertEmptyColumn = (
+ editor: PlateEditor,
+ options?: InsertNodesOptions & { width?: string }
+) => {
+ const width = options?.width || '33%';
+
+ insertNodes(
+ editor,
+ {
+ type: ELEMENT_COLUMN,
+ children: [{ type: ELEMENT_DEFAULT, children: [{ text: '' }] }],
+ width,
+ },
+ getQueryOptions(editor, options)
+ );
+};
diff --git a/packages/layout/src/transforms/moveMiddleColumn.ts b/packages/layout/src/transforms/moveMiddleColumn.ts
new file mode 100644
index 0000000000..77106f3bbc
--- /dev/null
+++ b/packages/layout/src/transforms/moveMiddleColumn.ts
@@ -0,0 +1,47 @@
+import {
+ moveNodes,
+ PlateEditor,
+ removeNodes,
+ TNode,
+ TNodeEntry,
+ unwrapNodes,
+ Value,
+} from '@udecode/plate-common';
+import { Node } from 'slate';
+
+import { TColumnElement } from '../types';
+
+/**
+ * @description move the middle column to the left of right by options.direction. if the middle node is empty return false and remove it.
+ */
+export const moveMiddleColumn = (
+ editor: PlateEditor,
+ [node, path]: TNodeEntry,
+ options?: {
+ direction: 'left' | 'right';
+ }
+) => {
+ const direction = options?.direction || 'left';
+
+ if (direction === 'left') {
+ const DESCENDANT_PATH = [1];
+
+ const middleChildNode = Node.get(node, DESCENDANT_PATH);
+ const isEmpty = editor.isEmpty(middleChildNode as any);
+
+ const middleChildPathRef = editor.pathRef(path.concat(DESCENDANT_PATH));
+
+ if (isEmpty) {
+ removeNodes(editor, { at: middleChildPathRef.current! });
+ return false;
+ }
+
+ const firstNode = Node.descendant(node, [0]) as TColumnElement;
+
+ const firstLast = path.concat([0, firstNode.children.length]);
+
+ moveNodes(editor, { at: middleChildPathRef.current!, to: firstLast });
+ unwrapNodes(editor, { at: middleChildPathRef.current! });
+ middleChildPathRef.unref();
+ }
+};
diff --git a/packages/layout/src/transforms/setColumnWidth.ts b/packages/layout/src/transforms/setColumnWidth.ts
new file mode 100644
index 0000000000..90b5bf18b3
--- /dev/null
+++ b/packages/layout/src/transforms/setColumnWidth.ts
@@ -0,0 +1,41 @@
+import {
+ getChildren,
+ getNodeEntry,
+ isElement,
+ PlateEditor,
+ setNodes,
+ Value,
+} from '@udecode/plate-common';
+import { PathRef } from 'slate';
+
+import { ELEMENT_COLUMN } from '../createColumnPlugin';
+import { TColumnElement, TColumnGroupElement } from '../types';
+
+export const setColumnWidth = (
+ editor: PlateEditor,
+ groupPathRef: PathRef,
+ layout: Required['layout']
+) => {
+ const path = groupPathRef.unref()!;
+
+ const columnGroup = getNodeEntry(editor, path);
+
+ if (!columnGroup) throw new Error(`can not find the column group in ${path}`);
+
+ const children = getChildren(columnGroup);
+
+ const childPaths = Array.from(children, (item) => item[1]);
+
+ childPaths.forEach((item, index) => {
+ const width = layout[index] + '%';
+ if (!width) return;
+ setNodes(
+ editor,
+ { width: width },
+ {
+ at: item,
+ match: (n) => isElement(n) && n.type === ELEMENT_COLUMN,
+ }
+ );
+ });
+};
diff --git a/packages/layout/src/types.ts b/packages/layout/src/types.ts
new file mode 100644
index 0000000000..c2074f89cf
--- /dev/null
+++ b/packages/layout/src/types.ts
@@ -0,0 +1,14 @@
+import { TElement } from '@udecode/plate-common';
+
+export interface TColumnElement extends TElement {
+ id?: string;
+ type: 'column';
+ width: string;
+}
+
+export interface TColumnGroupElement extends TElement {
+ id?: string;
+ type: 'column_group';
+ layout?: number[];
+ children: TColumnElement[];
+}
diff --git a/packages/layout/src/withColumn.ts b/packages/layout/src/withColumn.ts
new file mode 100644
index 0000000000..e1af6f1624
--- /dev/null
+++ b/packages/layout/src/withColumn.ts
@@ -0,0 +1,48 @@
+import {
+ getAboveNode,
+ isCollapsed,
+ isElement,
+ isStartPoint,
+ PlateEditor,
+ Value,
+} from '@udecode/plate-common';
+
+import { ELEMENT_COLUMN } from './createColumnPlugin';
+import { normalizeColumn } from './normalizers/normalizedColumn';
+
+export const withColumn = <
+ V extends Value = Value,
+ E extends PlateEditor = PlateEditor,
+>(
+ editor: E
+) => {
+ const { deleteBackward, isEmpty } = editor;
+
+ editor.normalizeNode = normalizeColumn(editor);
+
+ editor.deleteBackward = (unit) => {
+ if (isCollapsed(editor.selection)) {
+ const entry = getAboveNode(editor, {
+ match: (n) => isElement(n) && n.type === ELEMENT_COLUMN,
+ });
+
+ if (entry) {
+ const [node, path] = entry;
+
+ if (node.children.length > 1) return deleteBackward(unit);
+ const isStart = isStartPoint(editor, editor.selection?.anchor, path);
+ if (isStart) return;
+ }
+ }
+ deleteBackward(unit);
+ };
+
+ editor.isEmpty = (element: any) => {
+ if (element && element.type && element.type === ELEMENT_COLUMN) {
+ return element.children.length === 1 && isEmpty(element.children[0]);
+ }
+ return isEmpty(element);
+ };
+
+ return editor;
+};
diff --git a/packages/layout/tsconfig.json b/packages/layout/tsconfig.json
new file mode 100644
index 0000000000..425481e027
--- /dev/null
+++ b/packages/layout/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../config/tsconfig.build.json",
+ "compilerOptions": {
+ "declarationDir": "./dist",
+ "outDir": "./dist"
+ },
+ "include": ["src"]
+}
diff --git a/packages/serializer-md/src/serializer/data.ts b/packages/serializer-md/src/serializer/__tests__/data.ts
similarity index 100%
rename from packages/serializer-md/src/serializer/data.ts
rename to packages/serializer-md/src/serializer/__tests__/data.ts
diff --git a/packages/serializer-md/src/serializer/index.ts b/packages/serializer-md/src/serializer/index.ts
index abd2e7b867..78ad4b1d73 100644
--- a/packages/serializer-md/src/serializer/index.ts
+++ b/packages/serializer-md/src/serializer/index.ts
@@ -1 +1,7 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './serialize';
export * from './serializeMd';
+export * from './types';
diff --git a/packages/serializer-md/src/serializer/serializeMd.spec.tsx b/packages/serializer-md/src/serializer/serializeMd.spec.tsx
index 5093bdbc98..5a669a8bd3 100644
--- a/packages/serializer-md/src/serializer/serializeMd.spec.tsx
+++ b/packages/serializer-md/src/serializer/serializeMd.spec.tsx
@@ -30,7 +30,7 @@ import {
} from '@udecode/plate-paragraph';
import { jsx } from '@udecode/plate-test-utils';
-import { editorValueMock } from './data';
+import { editorValueMock } from './__tests__/data';
import { serializeMd } from './serializeMd';
jsx;
diff --git a/packages/table/src/index.ts b/packages/table/src/index.ts
index 8704b7e1ac..f649b52bc6 100644
--- a/packages/table/src/index.ts
+++ b/packages/table/src/index.ts
@@ -10,6 +10,7 @@ export * from './withDeleteTable';
export * from './withGetFragmentTable';
export * from './withInsertFragmentTable';
export * from './withInsertTextTable';
+export * from './withMarkTable';
export * from './withNormalizeTable';
export * from './withSelectionTable';
export * from './withSetFragmentDataTable';
diff --git a/packages/table/src/merge/index.ts b/packages/table/src/merge/index.ts
index ac17e9d34c..2a3c20532a 100644
--- a/packages/table/src/merge/index.ts
+++ b/packages/table/src/merge/index.ts
@@ -5,12 +5,16 @@
export * from './computeCellIndices';
export * from './createEmptyCell';
export * from './deleteColumn';
+export * from './deleteColumnWhenExpanded';
export * from './deleteRow';
+export * from './deleteRowWhenExpanded';
export * from './findCellByIndexes';
export * from './getCellIndices';
export * from './getCellIndicesWithSpans';
export * from './getCellPath';
+export * from './getSelectionWidth';
export * from './getTableGridByRange';
+export * from './getTableMergedColumnCount';
export * from './insertTableColumn';
export * from './insertTableRow';
export * from './isTableRectangular';
diff --git a/packages/table/src/utils/index.ts b/packages/table/src/utils/index.ts
index 7b8476464d..521e585d75 100644
--- a/packages/table/src/utils/index.ts
+++ b/packages/table/src/utils/index.ts
@@ -2,6 +2,7 @@
* @file Automatically generated by barrelsby.
*/
+export * from './getCellRowIndexByPath';
export * from './getCellType';
export * from './getEmptyCellNode';
export * from './getEmptyRowNode';
diff --git a/packages/test-utils/src/jsx.ts b/packages/test-utils/src/jsx.ts
index 6bd79ebb2b..98aa01353f 100644
--- a/packages/test-utils/src/jsx.ts
+++ b/packages/test-utils/src/jsx.ts
@@ -1,8 +1,12 @@
/* eslint-disable prettier/prettier */
// @ts-ignore
-import { createHyperscript, createText as createTestText } from "slate-hyperscript";
-import { HyperscriptShorthands } from "slate-hyperscript/dist/hyperscript";
-import { createText } from "./hyperscript/creators";
+import {
+ createHyperscript,
+ createText as createTestText,
+} from 'slate-hyperscript';
+import { HyperscriptShorthands } from 'slate-hyperscript/dist/hyperscript';
+
+import { createText } from './hyperscript/creators';
declare global {
namespace JSX {
@@ -62,6 +66,8 @@ const ELEMENT_TODO_LI = 'action_item';
const ELEMENT_TOGGLE = 'toggle';
const ELEMENT_TR = 'tr';
const ELEMENT_UL = 'ul';
+const ELEMENT_COLUMN_GROUP = 'column_group';
+const ELEMENT_COLUMN = 'column';
const elements: HyperscriptShorthands = {
ha: { type: ELEMENT_LINK },
@@ -92,6 +98,8 @@ const elements: HyperscriptShorthands = {
htoggle: { type: ELEMENT_TOGGLE },
htr: { type: ELEMENT_TR },
hul: { type: ELEMENT_UL },
+ hcolumngroup: { type: ELEMENT_COLUMN_GROUP },
+ hcolumn: { type: ELEMENT_COLUMN },
};
export const jsx = createHyperscript({
diff --git a/packages/toggle/src/hooks/index.ts b/packages/toggle/src/hooks/index.ts
index e91ef60524..15150b5431 100644
--- a/packages/toggle/src/hooks/index.ts
+++ b/packages/toggle/src/hooks/index.ts
@@ -2,6 +2,6 @@
* @file Automatically generated by barrelsby.
*/
+export * from './useHooksToggle';
export * from './useToggleButton';
export * from './useToggleToolbarButton';
-export * from './useHooksToggle';
diff --git a/packages/toggle/src/index.ts b/packages/toggle/src/index.ts
index 0ee44da450..89dcbb9076 100644
--- a/packages/toggle/src/index.ts
+++ b/packages/toggle/src/index.ts
@@ -3,9 +3,10 @@
*/
export * from './createTogglePlugin';
+export * from './injectToggle';
+export * from './toggle-controller-store';
export * from './types';
export * from './withToggle';
export * from './hooks/index';
export * from './queries/index';
export * from './transforms/index';
-export * from './toggle-controller-store';
diff --git a/turbo.json b/turbo.json
index ecf2656f1e..15ba64161d 100644
--- a/turbo.json
+++ b/turbo.json
@@ -22,7 +22,8 @@
"persistent": true
},
"brl": {
- "outputs": []
+ "outputs": [],
+ "cache": false
},
"clean": {
"cache": false,
diff --git a/yarn.lock b/yarn.lock
index b1e91ad528..625bff2894 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5969,6 +5969,22 @@ __metadata:
languageName: unknown
linkType: soft
+"@udecode/plate-layout@workspace:^, @udecode/plate-layout@workspace:packages/layout":
+ version: 0.0.0-use.local
+ resolution: "@udecode/plate-layout@workspace:packages/layout"
+ dependencies:
+ "@udecode/plate-common": "workspace:^"
+ peerDependencies:
+ "@udecode/plate-common": ">=31.3.2"
+ react: ">=16.8.0"
+ react-dom: ">=16.8.0"
+ slate: ">=0.94.0"
+ slate-history: ">=0.93.0"
+ slate-hyperscript: ">=0.66.0"
+ slate-react: ">=0.99.0"
+ languageName: unknown
+ linkType: soft
+
"@udecode/plate-line-height@npm:31.0.0, @udecode/plate-line-height@workspace:^, @udecode/plate-line-height@workspace:packages/line-height":
version: 0.0.0-use.local
resolution: "@udecode/plate-line-height@workspace:packages/line-height"
@@ -21320,6 +21336,7 @@ __metadata:
"@udecode/plate-indent-list": "workspace:^"
"@udecode/plate-juice": "workspace:^"
"@udecode/plate-kbd": "workspace:^"
+ "@udecode/plate-layout": "workspace:^"
"@udecode/plate-line-height": "workspace:^"
"@udecode/plate-link": "workspace:^"
"@udecode/plate-list": "workspace:^"