;
}
) => {
- const {
- inject: { targetPlugins },
- } = editor.getPlugin(BaseAlignPlugin);
const { defaultNodeValue, nodeKey } = editor.getInjectProps(BaseAlignPlugin);
- const match: TNodeMatch = (n) => {
- return (
- isBlock(editor, n) &&
- !!targetPlugins &&
- targetPlugins.includes(getKeyByType(editor, n.type as string))
- );
- };
+ const match = getInjectMatch(editor, editor.getPlugin(BaseAlignPlugin));
if (value === defaultNodeValue) {
unsetNodes(editor, nodeKey!, {
diff --git a/packages/autoformat/package.json b/packages/autoformat/package.json
index d848bb94ac..4e4042b083 100644
--- a/packages/autoformat/package.json
+++ b/packages/autoformat/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/autoformat/src/lib/index.ts b/packages/autoformat/src/lib/index.ts
index b008771c04..2ab9f24640 100644
--- a/packages/autoformat/src/lib/index.ts
+++ b/packages/autoformat/src/lib/index.ts
@@ -3,7 +3,7 @@
*/
export * from './BaseAutoformatPlugin';
-export type * from './types';
+export * from './types';
export * from './withAutoformat';
export * from './rules/index';
export * from './transforms/index';
diff --git a/packages/basic-elements/package.json b/packages/basic-elements/package.json
index 60bd03f4b7..4ed5486216 100644
--- a/packages/basic-elements/package.json
+++ b/packages/basic-elements/package.json
@@ -62,9 +62,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/basic-marks/package.json b/packages/basic-marks/package.json
index 5c0dd7c112..c78c97fa31 100644
--- a/packages/basic-marks/package.json
+++ b/packages/basic-marks/package.json
@@ -56,9 +56,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/block-quote/package.json b/packages/block-quote/package.json
index de415ea3b5..80c72e6b7d 100644
--- a/packages/block-quote/package.json
+++ b/packages/block-quote/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/break/package.json b/packages/break/package.json
index 6f88bce244..7962dd4167 100644
--- a/packages/break/package.json
+++ b/packages/break/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/break/src/lib/exit-break/index.ts b/packages/break/src/lib/exit-break/index.ts
index cff467c677..a9b9b7750a 100644
--- a/packages/break/src/lib/exit-break/index.ts
+++ b/packages/break/src/lib/exit-break/index.ts
@@ -3,6 +3,6 @@
*/
export * from './BaseExitBreakPlugin';
-export type * from './types';
+export * from './types';
export * from './queries/index';
export * from './transforms/index';
diff --git a/packages/callout/package.json b/packages/callout/package.json
index 44616ad55d..632b6ddbfe 100644
--- a/packages/callout/package.json
+++ b/packages/callout/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/caption/package.json b/packages/caption/package.json
index 5cb6083f59..b1940844f7 100644
--- a/packages/caption/package.json
+++ b/packages/caption/package.json
@@ -59,9 +59,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/caption/src/lib/index.ts b/packages/caption/src/lib/index.ts
index 0277290caa..b6de0213e5 100644
--- a/packages/caption/src/lib/index.ts
+++ b/packages/caption/src/lib/index.ts
@@ -3,5 +3,5 @@
*/
export * from './BaseCaptionPlugin';
-export type * from './TCaptionElement';
+export * from './TCaptionElement';
export * from './withCaption';
diff --git a/packages/cloud/package.json b/packages/cloud/package.json
index 702d7823d1..ab90fdf038 100644
--- a/packages/cloud/package.json
+++ b/packages/cloud/package.json
@@ -56,9 +56,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/cloud/src/attachment/index.ts b/packages/cloud/src/attachment/index.ts
index f9b7f3c8ed..d7c0321522 100644
--- a/packages/cloud/src/attachment/index.ts
+++ b/packages/cloud/src/attachment/index.ts
@@ -3,5 +3,5 @@
*/
export * from './CloudAttachmentPlugin';
-export type * from './types';
+export * from './types';
export * from './useCloudAttachmentElementState';
diff --git a/packages/cloud/src/cloud/index.ts b/packages/cloud/src/cloud/index.ts
index 2a85330cfe..91adcf0f3a 100644
--- a/packages/cloud/src/cloud/index.ts
+++ b/packages/cloud/src/cloud/index.ts
@@ -8,5 +8,5 @@ export * from './generateSrcAndSrcSet';
export * from './getInProgressUploads';
export * from './getSaveValue';
export * from './handlers';
-export type * from './types';
+export * from './types';
export * from './uploadFiles';
diff --git a/packages/cloud/src/image/index.ts b/packages/cloud/src/image/index.ts
index 05126c84ed..eb7648ae10 100644
--- a/packages/cloud/src/image/index.ts
+++ b/packages/cloud/src/image/index.ts
@@ -3,5 +3,5 @@
*/
export * from './CloudImagePlugin';
-export type * from './types';
+export * from './types';
export * from './useCloudImageElementState';
diff --git a/packages/cloud/src/upload/index.ts b/packages/cloud/src/upload/index.ts
index f17439c296..624540102e 100644
--- a/packages/cloud/src/upload/index.ts
+++ b/packages/cloud/src/upload/index.ts
@@ -3,5 +3,5 @@
*/
export * from './createUploadStore';
-export type * from './types';
+export * from './types';
export * from './useUpload';
diff --git a/packages/code-block/package.json b/packages/code-block/package.json
index 3bc3ac0211..2fa904883a 100644
--- a/packages/code-block/package.json
+++ b/packages/code-block/package.json
@@ -58,9 +58,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/code-block/src/lib/index.ts b/packages/code-block/src/lib/index.ts
index 00486713a3..5300c0d7f0 100644
--- a/packages/code-block/src/lib/index.ts
+++ b/packages/code-block/src/lib/index.ts
@@ -6,7 +6,7 @@ export * from './BaseCodeBlockPlugin';
export * from './decorateCodeLine';
export * from './htmlDeserializerCodeBlock';
export * from './insertFragmentCodeBlock';
-export type * from './types';
+export * from './types';
export * from './withCodeBlock';
export * from './normalizers/index';
export * from './queries/index';
diff --git a/packages/combobox/package.json b/packages/combobox/package.json
index 3a93528090..59768fb131 100644
--- a/packages/combobox/package.json
+++ b/packages/combobox/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/combobox/src/lib/index.ts b/packages/combobox/src/lib/index.ts
index 63e0bda2f8..a5241d3ca4 100644
--- a/packages/combobox/src/lib/index.ts
+++ b/packages/combobox/src/lib/index.ts
@@ -2,6 +2,6 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './types';
+export * from './types';
export * from './withTriggerCombobox';
export * from './utils/index';
diff --git a/packages/comments/package.json b/packages/comments/package.json
index 7afb82b586..69d98bb860 100644
--- a/packages/comments/package.json
+++ b/packages/comments/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/comments/src/lib/index.ts b/packages/comments/src/lib/index.ts
index 2dc9f48b5e..0b7d639770 100644
--- a/packages/comments/src/lib/index.ts
+++ b/packages/comments/src/lib/index.ts
@@ -3,7 +3,7 @@
*/
export * from './BaseCommentsPlugin';
-export type * from './types';
+export * from './types';
export * from './withComments';
export * from './queries/index';
export * from './transforms/index';
diff --git a/packages/common/package.json b/packages/common/package.json
index 7dceb1a601..b1459081d1 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -63,9 +63,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/core/package.json b/packages/core/package.json
index b8eff7f0d4..5be3843599 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -78,9 +78,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/core/src/internal/usePlateInstancesWarn.ts b/packages/core/src/internal/usePlateInstancesWarn.ts
new file mode 100644
index 0000000000..3bef15a11f
--- /dev/null
+++ b/packages/core/src/internal/usePlateInstancesWarn.ts
@@ -0,0 +1,32 @@
+import React from 'react';
+
+declare global {
+ interface Global {
+ __PLATE_INSTANCES__?: number;
+ }
+}
+
+function checkPlateInstances() {
+ (globalThis as any).__PLATE_INSTANCES__ =
+ ((globalThis as any).__PLATE_INSTANCES__ || 0) + 1;
+}
+
+checkPlateInstances();
+
+export function usePlateInstancesWarn(disabled?: boolean) {
+ React.useEffect(() => {
+ if (
+ !disabled &&
+ (globalThis as any).__PLATE_INSTANCES__ &&
+ (globalThis as any).__PLATE_INSTANCES__ > 1
+ ) {
+ console.warn(
+ 'Detected multiple @udecode/plate-core instances!\n' +
+ 'Choose only one of these packages in your dependencies:\n' +
+ '- @udecode/plate\n' +
+ '- @udecode/plate-core\n' +
+ '- @udecode/plate-common\n\n'
+ );
+ }
+ }, [disabled]);
+}
diff --git a/packages/core/src/lib/editor/index.ts b/packages/core/src/lib/editor/index.ts
index d6e5d67f41..568871215b 100644
--- a/packages/core/src/lib/editor/index.ts
+++ b/packages/core/src/lib/editor/index.ts
@@ -2,5 +2,5 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './SlateEditor';
+export * from './SlateEditor';
export * from './withSlate';
diff --git a/packages/core/src/lib/editor/withSlate.ts b/packages/core/src/lib/editor/withSlate.ts
index bd29912119..869f39d3ae 100644
--- a/packages/core/src/lib/editor/withSlate.ts
+++ b/packages/core/src/lib/editor/withSlate.ts
@@ -8,6 +8,7 @@ import {
normalizeEditor,
select,
} from '@udecode/slate';
+import { nanoid } from 'nanoid';
import type { AnyPluginConfig } from '../plugin/BasePlugin';
import type { AnySlatePlugin } from '../plugin/SlatePlugin';
@@ -19,10 +20,7 @@ import { type CorePlugin, getCorePlugins } from '../plugins/getCorePlugins';
import { pipeNormalizeInitialValue } from '../utils/pipeNormalizeInitialValue';
import { resolvePlugins } from '../utils/resolvePlugins';
-export type BaseWithSlateOptions<
- V extends Value = Value,
- P extends AnyPluginConfig = CorePlugin,
-> = {
+export type BaseWithSlateOptions = {
id?: any;
/**
@@ -51,14 +49,12 @@ export type BaseWithSlateOptions<
* @default false
*/
shouldNormalizeEditor?: boolean;
-
- value?: V | string;
};
export type WithSlateOptions<
V extends Value = Value,
P extends AnyPluginConfig = CorePlugin,
-> = BaseWithSlateOptions &
+> = BaseWithSlateOptions &
Pick<
Partial,
| 'api'
@@ -72,6 +68,8 @@ export type WithSlateOptions<
> & {
/** Function to configure the root plugin */
rootPlugin?: (plugin: AnySlatePlugin) => AnySlatePlugin;
+
+ value?: ((editor: SlateEditor) => V) | V | string;
};
/**
@@ -106,7 +104,7 @@ export const withSlate = <
// Override incremental id generated by slate
editor.id = id ?? editor.id;
- editor.key = editor.key ?? Math.random();
+ editor.key = editor.key ?? nanoid();
editor.isFallback = false;
editor.getApi = () => editor.api as any;
@@ -192,10 +190,12 @@ export const withSlate = <
if (typeof value === 'string') {
editor.children = editor.api.html.deserialize({ element: value }) as Value;
+ } else if (typeof value === 'function') {
+ editor.children = value(editor);
} else if (value) {
editor.children = value;
}
- if (editor.children?.length === 0) {
+ if (!editor.children || editor.children?.length === 0) {
editor.children = editor.api.create.value();
}
if (selection) {
@@ -206,7 +206,7 @@ export const withSlate = <
edge === 'start' ? getStartPoint(editor, []) : getEndPoint(editor, []);
select(editor, target);
}
- if (value) {
+ if (editor.children.length > 0) {
pipeNormalizeInitialValue(editor);
}
if (shouldNormalizeEditor) {
diff --git a/packages/core/src/lib/index.ts b/packages/core/src/lib/index.ts
index a14d707ab5..03abca7e8f 100644
--- a/packages/core/src/lib/index.ts
+++ b/packages/core/src/lib/index.ts
@@ -7,5 +7,5 @@ export * from './libs/index';
export * from './plugin/index';
export * from './plugins/index';
export * from './transforms/index';
-export type * from './types/index';
+export * from './types/index';
export * from './utils/index';
diff --git a/packages/core/src/lib/plugin/BasePlugin.ts b/packages/core/src/lib/plugin/BasePlugin.ts
index 343ee4af55..754ae64a13 100644
--- a/packages/core/src/lib/plugin/BasePlugin.ts
+++ b/packages/core/src/lib/plugin/BasePlugin.ts
@@ -1,14 +1,32 @@
+import type { TElement, TText } from '@udecode/slate';
import type { AnyObject } from '@udecode/utils';
import type { SetImmerState, StoreApi } from 'zustand-x';
import type { Nullable } from '../types';
-import type { GetInjectNodePropsOptions } from '../utils';
export type BasePlugin = {
/** Unique identifier for this plugin. */
key: C['key'];
inject: Nullable<{
+ /** Plugin keys of elements to exclude the children from */
+ excludeBelowPlugins?: string[];
+
+ /** Plugin keys of elements to exclude */
+ excludePlugins?: string[];
+
+ /** Whether to filter blocks */
+ isBlock?: boolean;
+
+ /** Whether to filter elements */
+ isElement?: boolean;
+
+ /** Whether to filter leaves */
+ isLeaf?: boolean;
+
+ /** Filter nodes with path above this level. */
+ maxLevel?: number;
+
/**
* Plugin keys used by {@link InjectNodeProps} and the targetPluginToInject
* function. For plugin injection by key, use the inject.plugins property.
@@ -232,6 +250,25 @@ export type BaseInjectProps = {
validNodeValues?: any[];
};
+export interface GetInjectNodePropsOptions {
+ /** Existing className. */
+ className?: string;
+
+ /** Style value or className key. */
+ element?: TElement;
+
+ /** Existing style. */
+ style?: CSSStyleDeclaration;
+
+ /** Style value or className key. */
+ text?: TText;
+}
+
+export interface GetInjectNodePropsReturnType extends AnyObject {
+ className?: string;
+ style?: CSSStyleDeclaration;
+}
+
export type BaseTransformOptions = GetInjectNodePropsOptions & {
nodeValue?: any;
value?: any;
diff --git a/packages/core/src/lib/plugin/SlatePlugin.ts b/packages/core/src/lib/plugin/SlatePlugin.ts
index fb715586b6..4f4ab13a7d 100644
--- a/packages/core/src/lib/plugin/SlatePlugin.ts
+++ b/packages/core/src/lib/plugin/SlatePlugin.ts
@@ -4,10 +4,6 @@ import type { Range } from 'slate';
import type { SlateEditor } from '../editor';
import type { Nullable } from '../types/misc';
-import type {
- GetInjectNodePropsOptions,
- GetInjectNodePropsReturnType,
-} from '../utils';
import type {
AnyPluginConfig,
BaseDeserializer,
@@ -17,6 +13,8 @@ import type {
BasePluginContext,
BaseSerializer,
BaseTransformOptions,
+ GetInjectNodePropsOptions,
+ GetInjectNodePropsReturnType,
InferApi,
InferOptions,
InferTransforms,
diff --git a/packages/core/src/lib/plugin/index.ts b/packages/core/src/lib/plugin/index.ts
index 63a7c956ca..b9220d4bbd 100644
--- a/packages/core/src/lib/plugin/index.ts
+++ b/packages/core/src/lib/plugin/index.ts
@@ -2,9 +2,9 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './BasePlugin';
-export type * from './HandlerReturnType';
-export type * from './SlatePlugin';
+export * from './BasePlugin';
+export * from './HandlerReturnType';
+export * from './SlatePlugin';
export * from './createSlatePlugin';
export * from './getEditorPlugin';
export * from './getSlatePlugin';
diff --git a/packages/core/src/lib/plugins/html/index.ts b/packages/core/src/lib/plugins/html/index.ts
index 5b7ddcf43e..1ba6018e57 100644
--- a/packages/core/src/lib/plugins/html/index.ts
+++ b/packages/core/src/lib/plugins/html/index.ts
@@ -4,5 +4,5 @@
export * from './HtmlPlugin';
export * from './constants';
-export type * from './types';
+export * from './types';
export * from './utils/index';
diff --git a/packages/core/src/lib/plugins/html/utils/collapse-white-space/index.ts b/packages/core/src/lib/plugins/html/utils/collapse-white-space/index.ts
index 8f3f757af3..ff88e2e843 100644
--- a/packages/core/src/lib/plugins/html/utils/collapse-white-space/index.ts
+++ b/packages/core/src/lib/plugins/html/utils/collapse-white-space/index.ts
@@ -11,4 +11,4 @@ export * from './collapseWhiteSpaceText';
export * from './inferWhiteSpaceRule';
export * from './isLastNonEmptyTextOfInlineFormattingContext';
export * from './stateTransforms';
-export type * from './types';
+export * from './types';
diff --git a/packages/core/src/lib/types/index.ts b/packages/core/src/lib/types/index.ts
index d27732771d..51e76c0743 100644
--- a/packages/core/src/lib/types/index.ts
+++ b/packages/core/src/lib/types/index.ts
@@ -2,4 +2,4 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './misc/index';
+export * from './misc/index';
diff --git a/packages/core/src/lib/types/misc/index.ts b/packages/core/src/lib/types/misc/index.ts
index 67309b6e8a..6374abc891 100644
--- a/packages/core/src/lib/types/misc/index.ts
+++ b/packages/core/src/lib/types/misc/index.ts
@@ -2,6 +2,6 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './NoInfer';
-export type * from './Nullable';
-export type * from './types';
+export * from './NoInfer';
+export * from './Nullable';
+export * from './types';
diff --git a/packages/core/src/lib/utils/getInjectMatch.ts b/packages/core/src/lib/utils/getInjectMatch.ts
new file mode 100644
index 0000000000..5496017558
--- /dev/null
+++ b/packages/core/src/lib/utils/getInjectMatch.ts
@@ -0,0 +1,63 @@
+import type { Path } from 'slate';
+
+import { type TNode, getAboveNode, isBlock, isElement } from '@udecode/slate';
+
+import type { SlateEditor } from '../editor';
+import type { EditorPlugin } from '../plugin';
+
+import { getKeyByType, getKeysByTypes } from './getKeysByTypes';
+
+export const getInjectMatch = (
+ editor: E,
+ plugin: EditorPlugin
+) => {
+ return (node: TNode, path: Path) => {
+ const {
+ inject: {
+ excludeBelowPlugins,
+ excludePlugins,
+ isBlock: _isBlock,
+ isElement: _isElement,
+ isLeaf,
+ maxLevel,
+ targetPlugins,
+ },
+ } = plugin;
+
+ const element = isElement(node) ? node : undefined;
+
+ if (_isElement && element) return false;
+ if (_isBlock && (!element || !isBlock(editor, element))) return false;
+ if (isLeaf && element) return false;
+ if (element?.type) {
+ // Exclude plugins
+ if (excludePlugins?.includes(getKeyByType(editor, element.type))) {
+ return false;
+ }
+ // Target plugins
+ if (
+ targetPlugins &&
+ !targetPlugins.includes(getKeyByType(editor, element.type))
+ ) {
+ return false;
+ }
+ }
+ // Exclude below plugins
+ if (excludeBelowPlugins || maxLevel) {
+ if (maxLevel && path.length > maxLevel) {
+ return false;
+ }
+ if (excludeBelowPlugins) {
+ const excludeTypes = getKeysByTypes(editor, excludeBelowPlugins);
+ const isBelow = getAboveNode(editor, {
+ at: path,
+ match: (n) => isElement(n) && excludeTypes.includes(n.type),
+ });
+
+ if (isBelow) return false;
+ }
+ }
+
+ return true;
+ };
+};
diff --git a/packages/core/src/lib/utils/index.ts b/packages/core/src/lib/utils/index.ts
index 53e02e8088..146909dcc2 100644
--- a/packages/core/src/lib/utils/index.ts
+++ b/packages/core/src/lib/utils/index.ts
@@ -3,19 +3,18 @@
*/
export * from './applyDeepToNodes';
+export * from './getInjectMatch';
export * from './getInjectedPlugins';
export * from './getKeysByTypes';
export * from './hotkeys';
export * from './mergeDeepToNodes';
export * from './normalizeDescendantsToDocumentFragment';
export * from './overridePluginsByKey';
-export * from './pipeInjectNodeProps';
export * from './pipeInsertDataQuery';
export * from './pipeInsertFragment';
export * from './pipeNormalizeInitialValue';
export * from './pipeTransformData';
export * from './pipeTransformFragment';
-export * from './pluginInjectNodeProps';
export * from './resolveCreatePluginTest';
export * from './resolvePlugin';
export * from './resolvePlugins';
diff --git a/packages/core/src/lib/utils/misc/getSlateClass.ts b/packages/core/src/lib/utils/misc/getSlateClass.ts
index 48aa07406c..639e7907f0 100644
--- a/packages/core/src/lib/utils/misc/getSlateClass.ts
+++ b/packages/core/src/lib/utils/misc/getSlateClass.ts
@@ -1,2 +1,2 @@
/** Get slate class name: slate- */
-export const getSlateClass = (type: string) => `slate-${type}`;
+export const getSlateClass = (type?: string) => (type ? `slate-${type}` : '');
diff --git a/packages/core/src/lib/utils/pipeInjectNodeProps.tsx b/packages/core/src/lib/utils/pipeInjectNodeProps.tsx
deleted file mode 100644
index acd3fd6527..0000000000
--- a/packages/core/src/lib/utils/pipeInjectNodeProps.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { SlateEditor } from '../editor';
-
-import { pluginInjectNodeProps } from './pluginInjectNodeProps';
-
-/** Inject plugin props, editor. */
-export const pipeInjectNodeProps = (editor: SlateEditor, nodeProps: any) => {
- editor.pluginList.forEach((plugin) => {
- if (plugin.inject.nodeProps) {
- const props = pluginInjectNodeProps(editor, plugin, nodeProps);
-
- if (props) {
- nodeProps = {
- ...nodeProps,
- ...props,
- };
- }
- }
- });
-
- return { ...nodeProps, editor };
-};
diff --git a/packages/core/src/lib/utils/pipeNormalizeInitialValue.spec.tsx b/packages/core/src/lib/utils/pipeNormalizeInitialValue.spec.tsx
index ac1a197914..dadb8894da 100644
--- a/packages/core/src/lib/utils/pipeNormalizeInitialValue.spec.tsx
+++ b/packages/core/src/lib/utils/pipeNormalizeInitialValue.spec.tsx
@@ -81,24 +81,6 @@ describe('pipeNormalizeInitialValue', () => {
});
});
- describe('when no initial value is provided', () => {
- it('should not normalize', () => {
- const editor = createPlateEditor({
- plugins,
- });
-
- const wrapper = ({ children }: any) => (
- {children}
- );
-
- const { result } = renderHook(() => useEditorValue(), {
- wrapper,
- });
-
- expect(result.current).toEqual([{ children: [{ text: '' }], type: 'p' }]);
- });
- });
-
describe('withPlate', () => {
describe('children handling', () => {
it('should use provided children', () => {
diff --git a/packages/core/src/lib/utils/pipeNormalizeInitialValue.ts b/packages/core/src/lib/utils/pipeNormalizeInitialValue.ts
index 054dc5311d..1d416dc73a 100644
--- a/packages/core/src/lib/utils/pipeNormalizeInitialValue.ts
+++ b/packages/core/src/lib/utils/pipeNormalizeInitialValue.ts
@@ -1,27 +1,17 @@
-import cloneDeep from 'lodash/cloneDeep.js';
-import isEqual from 'lodash/isEqual.js';
-
import type { SlateEditor } from '../editor';
import { getEditorPlugin } from '../plugin';
/** Normalize initial value from editor plugins. Set into plate store if diff. */
export const pipeNormalizeInitialValue = (editor: SlateEditor) => {
- const value = editor.children;
- let normalizedValue = cloneDeep(value);
-
editor.pluginList.forEach((p) => {
- const _normalizedValue = p.normalizeInitialValue?.({
+ const normalizedValue = p.normalizeInitialValue?.({
...getEditorPlugin(editor, p),
- value: normalizedValue,
+ value: editor.children,
} as any);
- if (_normalizedValue) {
- normalizedValue = _normalizedValue;
+ if (normalizedValue) {
+ editor.children = normalizedValue;
}
});
-
- if (!isEqual(value, normalizedValue) && normalizedValue) {
- editor.children = normalizedValue;
- }
};
diff --git a/packages/core/src/react/components/Plate.spec.tsx b/packages/core/src/react/components/Plate.spec.tsx
index c324485bc7..68cd5205de 100644
--- a/packages/core/src/react/components/Plate.spec.tsx
+++ b/packages/core/src/react/components/Plate.spec.tsx
@@ -453,6 +453,8 @@ describe('Plate', () => {
const TestComponent = ({ dep }: { dep: number }) => {
const editor = usePlateEditor({ id: 'test' }, [dep]);
+ editor.key = dep;
+
return (
diff --git a/packages/core/src/react/components/Plate.tsx b/packages/core/src/react/components/Plate.tsx
index 411253b21e..92382fbc39 100644
--- a/packages/core/src/react/components/Plate.tsx
+++ b/packages/core/src/react/components/Plate.tsx
@@ -1,9 +1,10 @@
-import React from 'react';
+import React, { useId } from 'react';
import type { TEditableProps } from '@udecode/slate-react';
import type { PlateEditor } from '../editor/PlateEditor';
+import { usePlateInstancesWarn } from '../../internal/usePlateInstancesWarn';
import { type PlateStoreState, PlateStoreProvider } from '../stores';
export interface PlateProps
@@ -25,10 +26,13 @@ export interface PlateProps
renderElement?: TEditableProps['renderElement'];
renderLeaf?: TEditableProps['renderLeaf'];
+
+ suppressInstanceWarning?: boolean;
}
function PlateInner({
children,
+ containerRef,
decorate,
editor,
primary,
@@ -38,13 +42,14 @@ function PlateInner({
onChange,
onSelectionChange,
onValueChange,
-}: PlateProps) {
+}: PlateProps & { containerRef: React.RefObject }) {
return (
(
props: PlateProps
) {
+ const id = useId();
+
+ const containerRef = React.useRef(null);
+
+ usePlateInstancesWarn(props.suppressInstanceWarning);
+
if (!props.editor) return null;
- return ;
+ props.editor.uid = 'e-' + id.replace(/:/g, '');
+
+ return (
+
+ );
}
diff --git a/packages/core/src/react/editor/PlateEditor.ts b/packages/core/src/react/editor/PlateEditor.ts
index 164d25849f..fc5663300b 100644
--- a/packages/core/src/react/editor/PlateEditor.ts
+++ b/packages/core/src/react/editor/PlateEditor.ts
@@ -72,6 +72,8 @@ export type PlateEditor = {
tf: PlateEditor['transforms'];
transforms: UnionToIntersection>;
+
+ uid?: string;
} & BaseEditor;
export type TPlateEditor<
diff --git a/packages/core/src/react/editor/index.ts b/packages/core/src/react/editor/index.ts
index b2621824d7..b065bba1b2 100644
--- a/packages/core/src/react/editor/index.ts
+++ b/packages/core/src/react/editor/index.ts
@@ -2,7 +2,7 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './PlateEditor';
+export * from './PlateEditor';
export * from './getPlateCorePlugins';
export * from './usePlateEditor';
export * from './withPlate';
diff --git a/packages/core/src/react/editor/withPlate.ts b/packages/core/src/react/editor/withPlate.ts
index 9d651febd1..544f624d35 100644
--- a/packages/core/src/react/editor/withPlate.ts
+++ b/packages/core/src/react/editor/withPlate.ts
@@ -3,7 +3,7 @@ import { type TEditor, type Value, createTEditor } from '@udecode/slate';
import type { AnyPlatePlugin } from '../plugin';
import type { PlateApiPlugin } from '../plugins';
-import type { TPlateEditor } from './PlateEditor';
+import type { PlateEditor, TPlateEditor } from './PlateEditor';
import {
type AnyPluginConfig,
@@ -19,7 +19,7 @@ export type PlateCorePlugin = CorePlugin | typeof PlateApiPlugin;
export type WithPlateOptions<
V extends Value = Value,
P extends AnyPluginConfig = PlateCorePlugin,
-> = BaseWithSlateOptions &
+> = BaseWithSlateOptions &
Pick<
Partial,
| 'api'
@@ -37,6 +37,7 @@ export type WithPlateOptions<
| 'useHooks'
> & {
rootPlugin?: (plugin: AnyPlatePlugin) => AnyPlatePlugin;
+ value?: ((editor: PlateEditor) => V) | V | string;
};
/**
diff --git a/packages/core/src/react/plugin/index.ts b/packages/core/src/react/plugin/index.ts
index 4bbd9f4e04..11a8a06a8a 100644
--- a/packages/core/src/react/plugin/index.ts
+++ b/packages/core/src/react/plugin/index.ts
@@ -2,12 +2,12 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './DOMHandlers';
-export type * from './KeyboardHandler';
-export type * from './PlatePlugin';
-export type * from './PlateRenderElementProps';
-export type * from './PlateRenderLeafProps';
-export type * from './PlateRenderNodeProps';
+export * from './DOMHandlers';
+export * from './KeyboardHandler';
+export * from './PlatePlugin';
+export * from './PlateRenderElementProps';
+export * from './PlateRenderLeafProps';
+export * from './PlateRenderNodeProps';
export * from './createPlatePlugin';
export * from './getEditorPlugin';
export * from './getPlugin';
diff --git a/packages/core/src/react/stores/plate/PlateStore.ts b/packages/core/src/react/stores/plate/PlateStore.ts
index 6d12a7e8b6..da0c5a3c7e 100644
--- a/packages/core/src/react/stores/plate/PlateStore.ts
+++ b/packages/core/src/react/stores/plate/PlateStore.ts
@@ -60,6 +60,9 @@ export type PlateStoreState = Nullable<{
*/
id: string;
+ /** A reference to the editor container element. */
+ containerRef: React.RefObject;
+
/**
* Slate editor reference.
*
diff --git a/packages/core/src/react/stores/plate/createPlateStore.ts b/packages/core/src/react/stores/plate/createPlateStore.ts
index 444c626173..23869e298b 100644
--- a/packages/core/src/react/stores/plate/createPlateStore.ts
+++ b/packages/core/src/react/stores/plate/createPlateStore.ts
@@ -19,6 +19,7 @@ export const GLOBAL_PLATE_SCOPE = Symbol('global-plate');
export const createPlateStore = ({
id,
+ containerRef = { current: null },
decorate = null,
editor,
isMounted = false,
@@ -37,6 +38,7 @@ export const createPlateStore = ({
}: Partial> = {}) =>
createAtomStore(
{
+ containerRef,
decorate,
editor,
isMounted,
diff --git a/packages/core/src/react/stores/plate/selectors/index.ts b/packages/core/src/react/stores/plate/selectors/index.ts
index 90355534ed..b996afbec6 100644
--- a/packages/core/src/react/stores/plate/selectors/index.ts
+++ b/packages/core/src/react/stores/plate/selectors/index.ts
@@ -2,6 +2,7 @@
* @file Automatically generated by barrelsby.
*/
+export * from './useEditorContainerRef';
export * from './useEditorId';
export * from './useEditorMounted';
export * from './useEditorPlugin';
diff --git a/packages/core/src/react/stores/plate/selectors/useEditorContainerRef.ts b/packages/core/src/react/stores/plate/selectors/useEditorContainerRef.ts
new file mode 100644
index 0000000000..870052020d
--- /dev/null
+++ b/packages/core/src/react/stores/plate/selectors/useEditorContainerRef.ts
@@ -0,0 +1,7 @@
+import { usePlateSelectors } from '../createPlateStore';
+
+export const useEditorContainerRef = (id?: string) => {
+ return usePlateSelectors(id, {
+ debugHookName: 'useEditorContainerRef',
+ }).containerRef();
+};
diff --git a/packages/core/src/react/utils/getRenderNodeProps.ts b/packages/core/src/react/utils/getRenderNodeProps.ts
index 63e43d8a0d..08f3395df6 100644
--- a/packages/core/src/react/utils/getRenderNodeProps.ts
+++ b/packages/core/src/react/utils/getRenderNodeProps.ts
@@ -9,6 +9,7 @@ import type { PlateRenderNodeProps } from '../plugin/PlateRenderNodeProps';
import { getSlateClass } from '../../lib';
import { getEditorPlugin } from '../plugin';
+import { pipeInjectNodeProps } from './pipeInjectNodeProps';
/**
* Override node props with plugin props. Allowed properties in
@@ -22,19 +23,19 @@ export const getRenderNodeProps = ({
props,
}: {
editor: PlateEditor;
- plugin: AnyEditorPlatePlugin;
props: PlateRenderNodeProps;
attributes?: AnyObject;
+ plugin?: AnyEditorPlatePlugin;
}): PlateRenderNodeProps => {
let newProps: AnyObject = {};
- if (plugin.node.props) {
+ if (plugin?.node.props) {
newProps =
(typeof plugin.node.props === 'function'
? plugin.node.props(props as any)
: plugin.node.props) ?? {};
}
- if (!newProps.nodeProps && attributes) {
+ if (!newProps.nodeProps && attributes && plugin) {
/**
* WARNING: Improper use of `dangerouslyAllowAttributes` WILL make your
* application vulnerable to cross-site scripting (XSS) or information
@@ -61,9 +62,17 @@ export const getRenderNodeProps = ({
const { className } = props;
- return {
+ let nodeProps = {
...props,
- className: clsx(getSlateClass(plugin.node.type), className),
- ...(getEditorPlugin(editor, plugin) as any),
+ ...(plugin ? (getEditorPlugin(editor, plugin) as any) : {}),
+ className: clsx(getSlateClass(plugin?.node.type), className),
};
+
+ nodeProps = pipeInjectNodeProps(editor, nodeProps) as PlateRenderNodeProps;
+
+ if (nodeProps.style && Object.keys(nodeProps.style).length === 0) {
+ delete nodeProps.style;
+ }
+
+ return nodeProps;
};
diff --git a/packages/core/src/react/utils/index.ts b/packages/core/src/react/utils/index.ts
index 015da58d3c..076fb0b416 100644
--- a/packages/core/src/react/utils/index.ts
+++ b/packages/core/src/react/utils/index.ts
@@ -8,8 +8,10 @@ export * from './getRenderNodeProps';
export * from './hotkeys';
export * from './pipeDecorate';
export * from './pipeHandler';
+export * from './pipeInjectNodeProps';
export * from './pipeOnChange';
export * from './pipeRenderElement';
export * from './pipeRenderLeaf';
+export * from './pluginInjectNodeProps';
export * from './pluginRenderElement';
export * from './pluginRenderLeaf';
diff --git a/packages/core/src/react/utils/pipeInjectNodeProps.tsx b/packages/core/src/react/utils/pipeInjectNodeProps.tsx
new file mode 100644
index 0000000000..db763e67a9
--- /dev/null
+++ b/packages/core/src/react/utils/pipeInjectNodeProps.tsx
@@ -0,0 +1,28 @@
+import clsx from 'clsx';
+
+import type { SlateEditor } from '../../lib/editor';
+
+import { pluginInjectNodeProps } from './pluginInjectNodeProps';
+
+/** Inject plugin props, editor. */
+export const pipeInjectNodeProps = (editor: SlateEditor, nodeProps: any) => {
+ editor.pluginList.forEach((plugin) => {
+ if (plugin.inject.nodeProps) {
+ const newProps = pluginInjectNodeProps(editor, plugin, nodeProps);
+
+ if (!newProps) return;
+
+ nodeProps = {
+ ...nodeProps,
+ ...newProps,
+ className: clsx(nodeProps.className, newProps.className),
+ style: {
+ ...nodeProps.style,
+ ...newProps.style,
+ },
+ };
+ }
+ });
+
+ return nodeProps;
+};
diff --git a/packages/core/src/react/utils/pipeRenderElement.tsx b/packages/core/src/react/utils/pipeRenderElement.tsx
index 4f0bf622e3..8a0da24e8b 100644
--- a/packages/core/src/react/utils/pipeRenderElement.tsx
+++ b/packages/core/src/react/utils/pipeRenderElement.tsx
@@ -6,7 +6,6 @@ import { DefaultElement } from 'slate-react';
import type { PlateEditor } from '../editor/PlateEditor';
-import { pipeInjectNodeProps } from '../../lib';
import { type RenderElement, pluginRenderElement } from './pluginRenderElement';
/** @see {@link RenderElement} */
@@ -22,9 +21,7 @@ export const pipeRenderElement = (
}
});
- return function render(nodeProps) {
- const props = pipeInjectNodeProps(editor, nodeProps);
-
+ return function render(props) {
let element;
renderElements.some((renderElement) => {
diff --git a/packages/core/src/react/utils/pipeRenderLeaf.tsx b/packages/core/src/react/utils/pipeRenderLeaf.tsx
index c204595cdb..cfb6f614ae 100644
--- a/packages/core/src/react/utils/pipeRenderLeaf.tsx
+++ b/packages/core/src/react/utils/pipeRenderLeaf.tsx
@@ -3,10 +3,9 @@ import React from 'react';
import type { TEditableProps } from '@udecode/slate-react';
import type { PlateEditor } from '../editor/PlateEditor';
-import type { PlateRenderLeafProps } from '../plugin/PlateRenderLeafProps';
-import { pipeInjectNodeProps } from '../../lib';
import { DefaultLeaf } from '../components';
+import { getRenderNodeProps } from './getRenderNodeProps';
import { type RenderLeaf, pluginRenderLeaf } from './pluginRenderLeaf';
/** @see {@link RenderLeaf} */
@@ -22,12 +21,7 @@ export const pipeRenderLeaf = (
}
});
- return function render(nodeProps) {
- const props = pipeInjectNodeProps(
- editor,
- nodeProps
- ) as PlateRenderLeafProps;
-
+ return function render(props) {
renderLeafs.forEach((renderLeaf) => {
const newChildren = renderLeaf(props as any);
@@ -40,6 +34,12 @@ export const pipeRenderLeaf = (
return renderLeafProp(props);
}
- return ;
+ const ctxProps = getRenderNodeProps({
+ attributes: props.attributes as any,
+ editor,
+ props: props as any,
+ }) as any;
+
+ return ;
};
};
diff --git a/packages/core/src/lib/utils/pluginInjectNodeProps.ts b/packages/core/src/react/utils/pluginInjectNodeProps.ts
similarity index 55%
rename from packages/core/src/lib/utils/pluginInjectNodeProps.ts
rename to packages/core/src/react/utils/pluginInjectNodeProps.ts
index f1e894f813..392bc56a35 100644
--- a/packages/core/src/lib/utils/pluginInjectNodeProps.ts
+++ b/packages/core/src/react/utils/pluginInjectNodeProps.ts
@@ -1,31 +1,18 @@
-import { type TElement, type TText, isElement } from '@udecode/slate';
-import { type AnyObject, isDefined } from '@udecode/utils';
-import { clsx } from 'clsx';
-
-import type { SlateEditor } from '../editor';
-import type { EditorPlugin, TransformOptions } from '../plugin/SlatePlugin';
-
-import { getEditorPlugin } from '../plugin';
-import { getKeyByType } from './getKeysByTypes';
-
-export interface GetInjectNodePropsOptions {
- /** Existing className. */
- className?: string;
-
- /** Style value or className key. */
- element?: TElement;
-
- /** Existing style. */
- style?: CSSStyleDeclaration;
-
- /** Style value or className key. */
- text?: TText;
-}
-
-export interface GetInjectNodePropsReturnType extends AnyObject {
- className?: string;
- style?: CSSStyleDeclaration;
-}
+import { findNodePath } from '@udecode/slate-react';
+import { isDefined } from '@udecode/utils';
+
+import type { SlateEditor } from '../../lib/editor';
+import type {
+ EditorPlugin,
+ TransformOptions,
+} from '../../lib/plugin/SlatePlugin';
+
+import {
+ type GetInjectNodePropsOptions,
+ type GetInjectNodePropsReturnType,
+ getEditorPlugin,
+} from '../../lib/plugin';
+import { getInjectMatch } from '../../lib/utils/getInjectMatch';
/**
* Return if `element`, `text`, `nodeKey` is defined. Return if `node.type` is
@@ -41,10 +28,10 @@ export const pluginInjectNodeProps = (
): GetInjectNodePropsReturnType | undefined => {
const {
key,
- inject: { nodeProps: injectNodeProps, targetPlugins },
+ inject: { nodeProps: injectNodeProps },
} = plugin;
- const { className, element, style, text } = nodeProps;
+ const { element, text } = nodeProps;
const node = element ?? text;
@@ -64,19 +51,17 @@ export const pluginInjectNodeProps = (
validNodeValues,
} = injectNodeProps;
+ const injectMatch = getInjectMatch(editor, plugin);
+
+ if (!injectMatch(node, findNodePath(editor, node)!)) return;
+
const queryResult = query?.({
...injectNodeProps,
...(getEditorPlugin(editor, plugin) as any),
nodeProps,
});
- if (
- !queryResult &&
- targetPlugins &&
- isElement(node) &&
- node.type &&
- !targetPlugins.includes(getKeyByType(editor, node.type))
- ) {
+ if (query && !queryResult) {
return;
}
@@ -84,7 +69,7 @@ export const pluginInjectNodeProps = (
// early return if there is no reason to inject props
if (
- !queryResult &&
+ !transformProps &&
(!isDefined(nodeValue) ||
(validNodeValues && !validNodeValues.includes(nodeValue)) ||
nodeValue === defaultNodeValue)
@@ -100,27 +85,26 @@ export const pluginInjectNodeProps = (
const value = transformNodeValue?.(transformOptions) ?? nodeValue;
transformOptions.value = value;
- let res: GetInjectNodePropsReturnType = {};
+ let newProps: GetInjectNodePropsReturnType = {};
- if (element) {
- res.className = clsx(className, `slate-${nodeKey}-${nodeValue}`);
+ if (element && nodeKey) {
+ newProps.className = `slate-${nodeKey}-${nodeValue}`;
}
if (classNames?.[nodeValue] || transformClassName) {
- res.className =
- transformClassName?.(transformOptions) ??
- clsx(className, classNames?.[value]);
+ newProps.className =
+ transformClassName?.(transformOptions) ?? classNames?.[value];
}
if (styleKey) {
- res.style =
+ newProps.style =
transformStyle?.(transformOptions) ??
({
- ...style,
[styleKey as string]: value,
} as any);
}
if (transformProps) {
- res = transformProps({ ...transformOptions, props: res }) ?? res;
+ newProps =
+ transformProps({ ...transformOptions, props: newProps }) ?? newProps;
}
- return res;
+ return newProps;
};
diff --git a/packages/core/src/react/utils/pluginRenderElement.tsx b/packages/core/src/react/utils/pluginRenderElement.tsx
index 2fd4dc0166..40e510caef 100644
--- a/packages/core/src/react/utils/pluginRenderElement.tsx
+++ b/packages/core/src/react/utils/pluginRenderElement.tsx
@@ -6,6 +6,7 @@ import type { PlateEditor } from '../editor/PlateEditor';
import type { AnyEditorPlatePlugin } from '../plugin/PlatePlugin';
import type { PlateRenderElementProps } from '../plugin/PlateRenderElementProps';
+import { useElement } from '../stores';
import { ElementProvider } from '../stores/element/useElementStore';
import { getRenderNodeProps } from './getRenderNodeProps';
@@ -18,6 +19,58 @@ export type RenderElement = (
props: PlateRenderElementProps
) => React.ReactElement | undefined;
+function ElementContent({
+ editor,
+ nodeProps,
+ plugin,
+}: {
+ editor: PlateEditor;
+ nodeProps: PlateRenderElementProps;
+ plugin: AnyEditorPlatePlugin;
+}) {
+ const element = useElement();
+
+ const { children: _children } = nodeProps;
+ const key = plugin.key;
+ const Element = plugin.render?.node ?? (DefaultElement as any);
+
+ const aboveNodes = editor.pluginList.flatMap(
+ (o) => o.render?.aboveNodes ?? []
+ );
+ const belowNodes = editor.pluginList.flatMap(
+ (o) => o.render?.belowNodes ?? []
+ );
+
+ nodeProps = getRenderNodeProps({
+ attributes: element.attributes as any,
+ editor,
+ plugin,
+ props: nodeProps as any,
+ }) as any;
+
+ let children = _children;
+
+ belowNodes.forEach((withHOC) => {
+ const hoc = withHOC({ ...nodeProps, key } as any);
+
+ if (hoc) {
+ children = hoc({ ...nodeProps, children } as any);
+ }
+ });
+
+ let component: React.ReactNode = {children} ;
+
+ aboveNodes.forEach((withHOC) => {
+ const hoc = withHOC({ ...nodeProps, key } as any);
+
+ if (hoc) {
+ component = hoc({ ...nodeProps, children: component } as any);
+ }
+ });
+
+ return component;
+}
+
/**
* Get a `Editable.renderElement` handler for `plugin.node.type`. If the type is
* equals to the slate element type, render `plugin.render.node`. Else, return
@@ -28,54 +81,16 @@ export const pluginRenderElement = (
plugin: AnyEditorPlatePlugin
): RenderElement =>
function render(nodeProps) {
- const {
- key,
- render: { node },
- } = plugin;
- const { children: _children, element } = nodeProps;
+ const { element } = nodeProps;
if (element.type === plugin.node.type) {
- const Element = node ?? DefaultElement;
-
- const aboveNodes = editor.pluginList.flatMap(
- (o) => o.render?.aboveNodes ?? []
- );
- const belowNodes = editor.pluginList.flatMap(
- (o) => o.render?.belowNodes ?? []
- );
-
- nodeProps = getRenderNodeProps({
- attributes: element.attributes as any,
- editor,
- plugin,
- props: nodeProps as any,
- }) as any;
-
- let children = _children;
-
- belowNodes.forEach((withHOC) => {
- const hoc = withHOC({ ...nodeProps, key } as any);
-
- if (hoc) {
- children = hoc({ ...nodeProps, children } as any);
- }
- });
-
- let component: React.ReactNode = (
- {children}
- );
-
- aboveNodes.forEach((withHOC) => {
- const hoc = withHOC({ ...nodeProps, key } as any);
-
- if (hoc) {
- component = hoc({ ...nodeProps, children: component } as any);
- }
- });
-
return (
-
- {component}
+
+
);
}
diff --git a/packages/csv/package.json b/packages/csv/package.json
index 1c58ec12a5..40e469d387 100644
--- a/packages/csv/package.json
+++ b/packages/csv/package.json
@@ -58,9 +58,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/cursor/package.json b/packages/cursor/package.json
index 4df4a1f7ef..bf28e04e47 100644
--- a/packages/cursor/package.json
+++ b/packages/cursor/package.json
@@ -51,9 +51,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/cursor/src/components/CursorOverlay.tsx b/packages/cursor/src/components/CursorOverlay.tsx
index 97b91ff10b..e2ed3cf600 100644
--- a/packages/cursor/src/components/CursorOverlay.tsx
+++ b/packages/cursor/src/components/CursorOverlay.tsx
@@ -19,6 +19,8 @@ export interface CursorProps
caret: string;
selectionRect: string;
}> {
+ id: string;
+
/**
* Custom caret component. For example, you could display a label next to the
* caret.
@@ -99,7 +101,12 @@ export function CursorOverlayContent<
return (
<>
{cursors.map((cursor) => (
-
+
))}
>
);
diff --git a/packages/cursor/src/index.ts b/packages/cursor/src/index.ts
index 8fd42a75b2..d05c35a07e 100644
--- a/packages/cursor/src/index.ts
+++ b/packages/cursor/src/index.ts
@@ -2,7 +2,7 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './types';
+export * from './types';
export * from './components/index';
export * from './hooks/index';
export * from './queries/index';
diff --git a/packages/diff/package.json b/packages/diff/package.json
index ffa5e09675..547ae21db7 100644
--- a/packages/diff/package.json
+++ b/packages/diff/package.json
@@ -54,9 +54,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/diff/src/lib/index.ts b/packages/diff/src/lib/index.ts
index 6314404d8c..c5b1fec6f5 100644
--- a/packages/diff/src/lib/index.ts
+++ b/packages/diff/src/lib/index.ts
@@ -3,5 +3,5 @@
*/
export * from './computeDiff';
-export type * from './types';
+export * from './types';
export * from './withGetFragmentExcludeDiff';
diff --git a/packages/dnd/package.json b/packages/dnd/package.json
index 934ff96b7a..a255b35f05 100644
--- a/packages/dnd/package.json
+++ b/packages/dnd/package.json
@@ -57,9 +57,10 @@
"react-dnd-html5-backend": ">=14.0.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/dnd/src/DndPlugin.tsx b/packages/dnd/src/DndPlugin.tsx
index 82753138c4..563fe0d8d2 100644
--- a/packages/dnd/src/DndPlugin.tsx
+++ b/packages/dnd/src/DndPlugin.tsx
@@ -42,7 +42,15 @@ export const DndPlugin = createTPlatePlugin({
editor.setOption(plugin, 'isDragging', false);
},
onDragStart: ({ editor, event, plugin }) => {
- const id = (event.target as HTMLDivElement).dataset.key ?? null;
+ const target = event.target as HTMLElement;
+
+ const dataTransfer = (event as React.DragEvent).dataTransfer!;
+ dataTransfer.effectAllowed = 'move';
+ dataTransfer.dropEffect = 'move';
+
+ const id = target.dataset.blockId;
+
+ if (!id) return;
editor.setOption(plugin, 'draggingId', id);
editor.setOption(plugin, 'isDragging', true);
diff --git a/packages/dnd/src/index.ts b/packages/dnd/src/index.ts
index 9fa9ba99c9..2ca23d422d 100644
--- a/packages/dnd/src/index.ts
+++ b/packages/dnd/src/index.ts
@@ -3,7 +3,7 @@
*/
export * from './DndPlugin';
-export type * from './types';
+export * from './types';
export * from './components/index';
export * from './hooks/index';
export * from './queries/index';
diff --git a/packages/docx/package.json b/packages/docx/package.json
index abf7b43fab..ee6270e63f 100644
--- a/packages/docx/package.json
+++ b/packages/docx/package.json
@@ -61,9 +61,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/docx/src/lib/docx-cleaner/index.ts b/packages/docx/src/lib/docx-cleaner/index.ts
index 3c8f7845b9..e3451d12da 100644
--- a/packages/docx/src/lib/docx-cleaner/index.ts
+++ b/packages/docx/src/lib/docx-cleaner/index.ts
@@ -3,5 +3,5 @@
*/
export * from './cleanDocx';
-export type * from './types';
+export * from './types';
export * from './utils/index';
diff --git a/packages/emoji/package.json b/packages/emoji/package.json
index 92de289230..e94ad9528d 100644
--- a/packages/emoji/package.json
+++ b/packages/emoji/package.json
@@ -61,9 +61,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/emoji/src/lib/utils/EmojiLibrary/index.ts b/packages/emoji/src/lib/utils/EmojiLibrary/index.ts
index 465dbae643..ac338756cc 100644
--- a/packages/emoji/src/lib/utils/EmojiLibrary/index.ts
+++ b/packages/emoji/src/lib/utils/EmojiLibrary/index.ts
@@ -3,4 +3,4 @@
*/
export * from './EmojiInlineLibrary';
-export type * from './EmojiLibrary.types';
+export * from './EmojiLibrary.types';
diff --git a/packages/emoji/src/lib/utils/Grid/index.ts b/packages/emoji/src/lib/utils/Grid/index.ts
index 549debd9b2..9206474f96 100644
--- a/packages/emoji/src/lib/utils/Grid/index.ts
+++ b/packages/emoji/src/lib/utils/Grid/index.ts
@@ -3,5 +3,5 @@
*/
export * from './Grid';
-export type * from './Grid.types';
+export * from './Grid.types';
export * from './GridSection';
diff --git a/packages/emoji/src/react/utils/EmojiLibrary/index.ts b/packages/emoji/src/react/utils/EmojiLibrary/index.ts
index 61490f88a2..9ea76b72d8 100644
--- a/packages/emoji/src/react/utils/EmojiLibrary/index.ts
+++ b/packages/emoji/src/react/utils/EmojiLibrary/index.ts
@@ -5,4 +5,4 @@
export * from './EmojiFloatingGrid';
export * from './EmojiFloatingGridBuilder';
export * from './EmojiFloatingLibrary';
-export type * from './EmojiFloatingLibrary.types';
+export * from './EmojiFloatingLibrary.types';
diff --git a/packages/excalidraw/package.json b/packages/excalidraw/package.json
index 4dc86c4e0b..dd3b9a8d69 100644
--- a/packages/excalidraw/package.json
+++ b/packages/excalidraw/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/excalidraw/src/lib/index.ts b/packages/excalidraw/src/lib/index.ts
index 625a5044cb..ef3ba1e557 100644
--- a/packages/excalidraw/src/lib/index.ts
+++ b/packages/excalidraw/src/lib/index.ts
@@ -3,5 +3,5 @@
*/
export * from './BaseExcalidrawPlugin';
-export type * from './types';
+export * from './types';
export * from './transforms/index';
diff --git a/packages/excalidraw/src/react/index.ts b/packages/excalidraw/src/react/index.ts
index 58868025ca..a0ed9785af 100644
--- a/packages/excalidraw/src/react/index.ts
+++ b/packages/excalidraw/src/react/index.ts
@@ -3,5 +3,5 @@
*/
export * from './ExcalidrawPlugin';
-export type * from './types';
+export * from './types';
export * from './hooks/index';
diff --git a/packages/find-replace/package.json b/packages/find-replace/package.json
index 082e185cba..3757e19228 100644
--- a/packages/find-replace/package.json
+++ b/packages/find-replace/package.json
@@ -51,9 +51,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/floating/package.json b/packages/floating/package.json
index d9ddc97a40..452859fddc 100644
--- a/packages/floating/package.json
+++ b/packages/floating/package.json
@@ -55,9 +55,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/font/package.json b/packages/font/package.json
index 26cf556633..13655dbfbe 100644
--- a/packages/font/package.json
+++ b/packages/font/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/heading/package.json b/packages/heading/package.json
index c5580502be..a0be475cd0 100644
--- a/packages/heading/package.json
+++ b/packages/heading/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/heading/src/lib/BaseTocPlugin.ts b/packages/heading/src/lib/BaseTocPlugin.ts
index f33ec14141..84d1fcda93 100644
--- a/packages/heading/src/lib/BaseTocPlugin.ts
+++ b/packages/heading/src/lib/BaseTocPlugin.ts
@@ -12,7 +12,6 @@ export type TocConfig = PluginConfig<
isScroll: boolean;
topOffset: number;
queryHeading?: (editor: SlateEditor) => Heading[];
- scrollContainerSelector?: string;
}
>;
@@ -21,7 +20,6 @@ export const BaseTocPlugin = createTSlatePlugin({
node: { isElement: true, isVoid: true },
options: {
isScroll: true,
- scrollContainerSelector: '#scroll_container',
topOffset: 80,
},
});
diff --git a/packages/heading/src/lib/index.ts b/packages/heading/src/lib/index.ts
index 6a22be035c..efbf79736d 100644
--- a/packages/heading/src/lib/index.ts
+++ b/packages/heading/src/lib/index.ts
@@ -5,6 +5,6 @@
export * from './BaseHeadingPlugin';
export * from './BaseTocPlugin';
export * from './constants';
-export type * from './types';
+export * from './types';
export * from './transforms/index';
export * from './utils/index';
diff --git a/packages/heading/src/react/hooks/useTocElement.ts b/packages/heading/src/react/hooks/useTocElement.ts
index aa96a361e4..4ef0e3bed2 100644
--- a/packages/heading/src/react/hooks/useTocElement.ts
+++ b/packages/heading/src/react/hooks/useTocElement.ts
@@ -1,8 +1,9 @@
-import React, { useEffect } from 'react';
+import React from 'react';
import { getNode } from '@udecode/plate-common';
import {
toDOMNode,
+ useEditorContainerRef,
useEditorPlugin,
useEditorSelector,
} from '@udecode/plate-common/react';
@@ -15,26 +16,11 @@ import { heightToTop } from '../utils';
export const useTocElementState = () => {
const { editor, getOptions } = useEditorPlugin(TocPlugin);
- const { isScroll, scrollContainerSelector, topOffset } = getOptions();
+ const { isScroll, topOffset } = getOptions();
const headingList = useEditorSelector(getHeadingList, []);
- const containerRef = React.useRef(null);
-
- useEffect(() => {
- const container = scrollContainerSelector
- ? document.querySelector(scrollContainerSelector)
- : toDOMNode(editor, editor)!;
-
- if (!container) return;
-
- containerRef.current = container as HTMLElement;
-
- return () => {
- containerRef.current = null;
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ const containerRef = useEditorContainerRef();
const onContentScroll = React.useCallback(
(el: HTMLElement, id: string, behavior: ScrollBehavior = 'instant') => {
diff --git a/packages/heading/src/react/hooks/useTocSideBar.ts b/packages/heading/src/react/hooks/useTocSideBar.ts
index f788e20345..df275ca483 100644
--- a/packages/heading/src/react/hooks/useTocSideBar.ts
+++ b/packages/heading/src/react/hooks/useTocSideBar.ts
@@ -3,6 +3,7 @@ import React from 'react';
import { getNode } from '@udecode/plate-common';
import {
toDOMNode,
+ useEditorContainerRef,
useEditorPlugin,
useEditorSelector,
} from '@udecode/plate-common/react';
@@ -20,17 +21,9 @@ export const useTocSideBarState = ({
rootMargin = '0px 0px 0px 0px',
topOffset = 0,
}: TocSideBarProps) => {
- const { editor, getOptions } = useEditorPlugin(TocPlugin);
- const { scrollContainerSelector } = getOptions();
+ const { editor } = useEditorPlugin(TocPlugin);
const headingList = useEditorSelector(getHeadingList, []);
- const scrollContainerRef = React.useRef(null);
-
- React.useEffect(() => {
- scrollContainerRef.current = document.querySelector(
- scrollContainerSelector ?? '#scroll_container'
- )!;
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ const containerRef = useEditorContainerRef();
const tocRef = React.useRef(null);
@@ -39,7 +32,7 @@ export const useTocSideBarState = ({
const [isObserve, setIsObserve] = React.useState(open);
const { activeContentId, onContentScroll } = useContentController({
- containerRef: scrollContainerRef,
+ containerRef,
isObserve,
rootMargin,
topOffset,
diff --git a/packages/heading/src/react/index.ts b/packages/heading/src/react/index.ts
index 90ff956a3a..0883517d43 100644
--- a/packages/heading/src/react/index.ts
+++ b/packages/heading/src/react/index.ts
@@ -4,6 +4,6 @@
export * from './HeadingPlugin';
export * from './TocPlugin';
-export type * from './types';
+export * from './types';
export * from './hooks/index';
export * from './utils/index';
diff --git a/packages/highlight/package.json b/packages/highlight/package.json
index e558d081a2..9a707488e6 100644
--- a/packages/highlight/package.json
+++ b/packages/highlight/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/horizontal-rule/package.json b/packages/horizontal-rule/package.json
index 033cad1b29..26cfcb410e 100644
--- a/packages/horizontal-rule/package.json
+++ b/packages/horizontal-rule/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/html/package.json b/packages/html/package.json
index cc29d5f2d7..8ace0a8e98 100644
--- a/packages/html/package.json
+++ b/packages/html/package.json
@@ -63,9 +63,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/html/src/react/elementToHtml.ts b/packages/html/src/react/elementToHtml.ts
index 53b46de3ee..dd9d94420f 100644
--- a/packages/html/src/react/elementToHtml.ts
+++ b/packages/html/src/react/elementToHtml.ts
@@ -2,7 +2,7 @@ import type React from 'react';
import type { TRenderElementProps } from '@udecode/slate-react';
-import { getEditorPlugin, pipeInjectNodeProps } from '@udecode/plate-common';
+import { getEditorPlugin } from '@udecode/plate-common';
import {
type PlateEditor,
type PlateProps,
@@ -35,8 +35,6 @@ export const elementToHtml = (
return html;
}
- props = pipeInjectNodeProps(editor, props);
-
// Search for matching plugin based on element type
editor.pluginList.some((plugin) => {
const serializer = plugin.parsers.htmlReact?.serializer;
diff --git a/packages/html/src/react/leafToHtml.ts b/packages/html/src/react/leafToHtml.ts
index 8dca35f23d..1837e25400 100644
--- a/packages/html/src/react/leafToHtml.ts
+++ b/packages/html/src/react/leafToHtml.ts
@@ -1,6 +1,6 @@
import type { TRenderLeafProps } from '@udecode/slate-react';
-import { getEditorPlugin, pipeInjectNodeProps } from '@udecode/plate-common';
+import { getEditorPlugin } from '@udecode/plate-common';
import {
type PlateEditor,
type PlateProps,
@@ -30,7 +30,7 @@ export const leafToHtml = (
if (!plugin.node.isLeaf) return result;
props = {
- ...pipeInjectNodeProps(editor, props),
+ ...props,
children: result,
...getEditorPlugin(editor, plugin),
};
diff --git a/packages/indent-list/package.json b/packages/indent-list/package.json
index 8640d7e4d6..ef4fedeb7d 100644
--- a/packages/indent-list/package.json
+++ b/packages/indent-list/package.json
@@ -62,9 +62,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/indent/package.json b/packages/indent/package.json
index c5321dfc56..b258a1103c 100644
--- a/packages/indent/package.json
+++ b/packages/indent/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/indent/src/lib/BaseIndentPlugin.ts b/packages/indent/src/lib/BaseIndentPlugin.ts
index afb63b58bf..7b98a6120a 100644
--- a/packages/indent/src/lib/BaseIndentPlugin.ts
+++ b/packages/indent/src/lib/BaseIndentPlugin.ts
@@ -37,6 +37,7 @@ export const BaseIndentPlugin = createTSlatePlugin({
key: 'indent',
extendEditor: withIndent,
inject: {
+ isBlock: true,
nodeProps: {
nodeKey: 'indent',
styleKey: 'marginLeft',
diff --git a/packages/indent/src/lib/BaseTextIndentPlugin.ts b/packages/indent/src/lib/BaseTextIndentPlugin.ts
index a7c225499a..436773efeb 100644
--- a/packages/indent/src/lib/BaseTextIndentPlugin.ts
+++ b/packages/indent/src/lib/BaseTextIndentPlugin.ts
@@ -14,6 +14,7 @@ export type TextIndentConfig = PluginConfig<
export const BaseTextIndentPlugin = createTSlatePlugin({
key: 'textIndent',
inject: {
+ isBlock: true,
nodeProps: {
nodeKey: 'textIndent',
styleKey: 'textIndent',
diff --git a/packages/indent/src/lib/withIndent.ts b/packages/indent/src/lib/withIndent.ts
index 0523343461..f97c1fe96c 100644
--- a/packages/indent/src/lib/withIndent.ts
+++ b/packages/indent/src/lib/withIndent.ts
@@ -1,4 +1,4 @@
-import { getKeyByType } from '@udecode/plate-common';
+import { getInjectMatch } from '@udecode/plate-common';
import {
type ExtendEditor,
setElements,
@@ -14,9 +14,7 @@ import type { IndentConfig, TIndentElement } from './BaseIndentPlugin';
export const withIndent: ExtendEditor = ({
editor,
getOptions,
- plugin: {
- inject: { targetPlugins },
- },
+ plugin,
}) => {
const { normalizeNode } = editor;
@@ -26,8 +24,10 @@ export const withIndent: ExtendEditor = ({
const element = node as TIndentElement;
const { type } = element;
+ const match = getInjectMatch(editor, plugin);
+
if (type) {
- if (targetPlugins!.includes(getKeyByType(editor, type))) {
+ if (match(element, path)) {
if (indentMax && element.indent && element.indent > indentMax) {
setElements(editor, { indent: indentMax }, { at: path });
diff --git a/packages/juice/package.json b/packages/juice/package.json
index e3a1c6272a..ef5b644275 100644
--- a/packages/juice/package.json
+++ b/packages/juice/package.json
@@ -54,9 +54,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/kbd/package.json b/packages/kbd/package.json
index de4cf9f244..d87a2a8945 100644
--- a/packages/kbd/package.json
+++ b/packages/kbd/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/layout/package.json b/packages/layout/package.json
index 06d4d67e80..e8f62dc922 100644
--- a/packages/layout/package.json
+++ b/packages/layout/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/layout/src/lib/index.ts b/packages/layout/src/lib/index.ts
index e399aab845..34b1e779d8 100644
--- a/packages/layout/src/lib/index.ts
+++ b/packages/layout/src/lib/index.ts
@@ -3,7 +3,6 @@
*/
export * from './BaseColumnPlugin';
-export type * from './types';
+export * from './types';
export * from './withColumn';
-export * from './normalizers/index';
export * from './transforms/index';
diff --git a/packages/layout/src/lib/normalizers/index.ts b/packages/layout/src/lib/normalizers/index.ts
deleted file mode 100644
index 2a2de7fc1d..0000000000
--- a/packages/layout/src/lib/normalizers/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * @file Automatically generated by barrelsby.
- */
-
-export * from './normalizedColumn';
diff --git a/packages/layout/src/lib/normalizers/normalizedColumn.ts b/packages/layout/src/lib/normalizers/normalizedColumn.ts
deleted file mode 100644
index 09c5bb9f6f..0000000000
--- a/packages/layout/src/lib/normalizers/normalizedColumn.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import {
- type SlateEditor,
- type TNode,
- type TNodeEntry,
- createPathRef,
- getLastChildPath,
- isElement,
-} from '@udecode/plate-common';
-
-import type { TColumnGroupElement } from '../types';
-
-import { BaseColumnPlugin } from '../BaseColumnPlugin';
-import { moveMiddleColumn } from '../transforms';
-import { insertEmptyColumn } from '../transforms/insertEmptyColumn';
-import { setColumnWidth } from '../transforms/setColumnWidth';
-
-export const normalizeColumn = (editor: SlateEditor) => {
- const { normalizeNode } = editor;
-
- return function (entry: TNodeEntry) {
- if (isElement(entry[0]) && entry[0].type === BaseColumnPlugin.key) {
- return normalizeColumnHelper(
- editor,
- entry as unknown as TNodeEntry
- );
- }
-
- return normalizeNode(entry);
- };
-};
-
-const normalizeColumnHelper = (
- editor: SlateEditor,
- 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/lib/transforms/index.ts b/packages/layout/src/lib/transforms/index.ts
index cde427139e..5075b4c4a2 100644
--- a/packages/layout/src/lib/transforms/index.ts
+++ b/packages/layout/src/lib/transforms/index.ts
@@ -2,8 +2,8 @@
* @file Automatically generated by barrelsby.
*/
+export * from './insertColumn';
export * from './insertColumnGroup';
-export * from './insertEmptyColumn';
export * from './moveMiddleColumn';
export * from './setColumnWidth';
-export * from './toggleColumns';
+export * from './toggleColumnGroup';
diff --git a/packages/layout/src/lib/transforms/insertEmptyColumn.ts b/packages/layout/src/lib/transforms/insertColumn.ts
similarity index 52%
rename from packages/layout/src/lib/transforms/insertEmptyColumn.ts
rename to packages/layout/src/lib/transforms/insertColumn.ts
index 103d214d19..84ba1a1560 100644
--- a/packages/layout/src/lib/transforms/insertEmptyColumn.ts
+++ b/packages/layout/src/lib/transforms/insertColumn.ts
@@ -1,8 +1,6 @@
import {
type InsertNodesOptions,
type SlateEditor,
- BaseParagraphPlugin,
- getQueryOptions,
insertNodes,
} from '@udecode/plate-common';
@@ -10,19 +8,17 @@ import type { TColumnElement } from '../types';
import { BaseColumnItemPlugin } from '../BaseColumnPlugin';
-export const insertEmptyColumn = (
+export const insertColumn = (
editor: E,
- options?: { width?: string } & InsertNodesOptions
+ { width = '33%', ...options }: { width?: string } & InsertNodesOptions = {}
) => {
- const width = options?.width || '33%';
-
insertNodes(
editor,
{
- children: [{ children: [{ text: '' }], type: BaseParagraphPlugin.key }],
+ children: [editor.api.create.block()],
type: BaseColumnItemPlugin.key,
width,
},
- getQueryOptions(editor, options)
+ options as any
);
};
diff --git a/packages/layout/src/lib/transforms/insertColumnGroup.ts b/packages/layout/src/lib/transforms/insertColumnGroup.ts
index 19e972cc93..8f108769c2 100644
--- a/packages/layout/src/lib/transforms/insertColumnGroup.ts
+++ b/packages/layout/src/lib/transforms/insertColumnGroup.ts
@@ -1,7 +1,9 @@
import {
+ type InsertNodesOptions,
type SlateEditor,
- BaseParagraphPlugin,
+ findNode,
insertNodes,
+ select,
withoutNormalizing,
} from '@udecode/plate-common';
@@ -9,27 +11,44 @@ import type { TColumnGroupElement } from '../types';
import { BaseColumnItemPlugin, BaseColumnPlugin } from '../BaseColumnPlugin';
-export const insertColumnGroup = (editor: SlateEditor) => {
+export const insertColumnGroup = (
+ editor: SlateEditor,
+ {
+ layout = 2,
+ select: selectProp,
+ ...options
+ }: InsertNodesOptions & {
+ layout?: number[] | number;
+ } = {}
+) => {
+ const columnLayout = Array.isArray(layout)
+ ? layout
+ : Array(layout).fill(Math.floor(100 / layout));
+
withoutNormalizing(editor, () => {
- insertNodes(editor, {
- children: [
- {
- children: [
- { children: [{ text: '' }], type: BaseParagraphPlugin.key },
- ],
- type: BaseColumnItemPlugin.key,
- width: '50%',
- },
- {
- children: [
- { children: [{ text: '' }], type: BaseParagraphPlugin.key },
- ],
+ insertNodes(
+ editor,
+ {
+ children: columnLayout.map((width) => ({
+ children: [editor.api.create.block()],
type: BaseColumnItemPlugin.key,
- width: '50%',
- },
- ],
- layout: [50, 50],
- type: BaseColumnPlugin.key,
- });
+ width: `${width}%`,
+ })),
+ layout: columnLayout,
+ type: BaseColumnPlugin.key,
+ },
+ options
+ );
+
+ if (selectProp) {
+ const entry = findNode(editor, {
+ at: options.at,
+ match: { type: editor.getType(BaseColumnPlugin) },
+ });
+
+ if (!entry) return;
+
+ select(editor, entry[1].concat([0]));
+ }
});
};
diff --git a/packages/layout/src/lib/transforms/toggleColumnGroup.ts b/packages/layout/src/lib/transforms/toggleColumnGroup.ts
new file mode 100644
index 0000000000..671cbfc85f
--- /dev/null
+++ b/packages/layout/src/lib/transforms/toggleColumnGroup.ts
@@ -0,0 +1,48 @@
+import {
+ type ReplaceNodeChildrenOptions,
+ type SlateEditor,
+ type TElement,
+ getBlockAbove,
+ getStartPoint,
+ replaceNode,
+ select,
+} from '@udecode/plate-common';
+
+import { BaseColumnItemPlugin, BaseColumnPlugin } from '../BaseColumnPlugin';
+
+export const toggleColumnGroup = (
+ editor: SlateEditor,
+ {
+ at,
+ layout = 2,
+ }: Partial, 'nodes'>> & {
+ layout?: number[] | number;
+ } = {}
+) => {
+ const entry = getBlockAbove(editor, { at });
+
+ if (!entry) return;
+
+ const [node] = entry;
+
+ const columnLayout = Array.isArray(layout)
+ ? layout
+ : Array(layout).fill(Math.floor(100 / layout));
+
+ const nodes = {
+ children: columnLayout.map((width, index) => ({
+ children: [index === 0 ? node : editor.api.create.block()],
+ type: BaseColumnItemPlugin.key,
+ width: `${width}%`,
+ })),
+ layout: columnLayout,
+ type: BaseColumnPlugin.key,
+ } as TElement;
+
+ replaceNode(editor, {
+ at: entry[1],
+ nodes,
+ });
+
+ select(editor, getStartPoint(editor, entry[1].concat([0])));
+};
diff --git a/packages/layout/src/lib/transforms/toggleColumns.ts b/packages/layout/src/lib/transforms/toggleColumns.ts
deleted file mode 100644
index f8a237a399..0000000000
--- a/packages/layout/src/lib/transforms/toggleColumns.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import {
- type SlateEditor,
- type TElement,
- type TNodeEntry,
- replaceNode,
-} from '@udecode/plate-common';
-
-import { BaseColumnItemPlugin, BaseColumnPlugin } from '../BaseColumnPlugin';
-
-export const toggleColumns = (editor: SlateEditor, nodeEntry: TNodeEntry) => {
- const nodes = {
- children: [
- {
- children: [nodeEntry[0]],
- type: BaseColumnItemPlugin.key,
- width: '33.33%',
- },
- {
- children: [{ text: '' }],
- type: BaseColumnItemPlugin.key,
- width: '33.33%',
- },
- {
- children: [{ text: '' }],
- type: BaseColumnItemPlugin.key,
- width: '33.33%',
- },
- ],
- type: BaseColumnPlugin.key,
- } as TElement;
-
- replaceNode(editor, {
- at: nodeEntry[1],
- nodes,
- });
-};
diff --git a/packages/layout/src/lib/withColumn.ts b/packages/layout/src/lib/withColumn.ts
index 619dfa929a..1c864e56d8 100644
--- a/packages/layout/src/lib/withColumn.ts
+++ b/packages/layout/src/lib/withColumn.ts
@@ -1,18 +1,93 @@
import {
type ExtendEditor,
+ createPathRef,
getAboveNode,
+ getLastChildPath,
isCollapsed,
isElement,
isStartPoint,
+ removeNodes,
+ unwrapNodes,
} from '@udecode/plate-common';
-import { BaseColumnItemPlugin } from './BaseColumnPlugin';
-import { normalizeColumn } from './normalizers/normalizedColumn';
+import type { TColumnElement, TColumnGroupElement } from './types';
+
+import { BaseColumnItemPlugin, BaseColumnPlugin } from './BaseColumnPlugin';
+import { insertColumn, moveMiddleColumn, setColumnWidth } from './transforms';
export const withColumn: ExtendEditor = ({ editor }) => {
- const { deleteBackward, isEmpty } = editor;
+ const { deleteBackward, isEmpty, normalizeNode } = editor;
+
+ editor.normalizeNode = (entry) => {
+ const [n, path] = entry;
+
+ if (isElement(n) && n.type === BaseColumnPlugin.key) {
+ const node = n as TColumnGroupElement;
+
+ if (
+ !node.children.some(
+ (child) =>
+ isElement(child) &&
+ child.type === editor.getType(BaseColumnItemPlugin)
+ )
+ ) {
+ removeNodes(editor, { at: path });
+
+ return;
+ }
+ if (node.children.length < 2) {
+ editor.withoutNormalizing(() => {
+ unwrapNodes(editor, { at: path });
+ unwrapNodes(editor, { at: path });
+ });
+
+ return;
+ }
+
+ const prevChildrenCnt = node.children.length;
+ const currentLayout = node.layout;
+
+ if (currentLayout) {
+ const currentChildrenCnt = currentLayout.length;
+
+ const groupPathRef = createPathRef(editor, path);
+
+ if (prevChildrenCnt === 2 && currentChildrenCnt === 3) {
+ const lastChildPath = getLastChildPath(entry);
- editor.normalizeNode = normalizeColumn(editor);
+ insertColumn(editor, {
+ at: lastChildPath,
+ });
+
+ setColumnWidth(editor, groupPathRef, currentLayout);
+
+ return;
+ }
+ if (prevChildrenCnt === 3 && currentChildrenCnt === 2) {
+ moveMiddleColumn(editor, entry, { direction: 'left' });
+ setColumnWidth(editor, groupPathRef, currentLayout);
+
+ return;
+ }
+ if (prevChildrenCnt === currentChildrenCnt) {
+ setColumnWidth(editor, groupPathRef, currentLayout);
+
+ return;
+ }
+ }
+ }
+ if (isElement(n) && n.type === BaseColumnItemPlugin.key) {
+ const node = n as TColumnElement;
+
+ if (node.children.length === 0) {
+ removeNodes(editor, { at: path });
+
+ return;
+ }
+ }
+
+ return normalizeNode(entry);
+ };
editor.deleteBackward = (unit) => {
if (isCollapsed(editor.selection)) {
diff --git a/packages/line-height/package.json b/packages/line-height/package.json
index 4aecb95752..a5707142ab 100644
--- a/packages/line-height/package.json
+++ b/packages/line-height/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/line-height/src/lib/BaseLineHeightPlugin.ts b/packages/line-height/src/lib/BaseLineHeightPlugin.ts
index 0b446cc6cc..f891154266 100644
--- a/packages/line-height/src/lib/BaseLineHeightPlugin.ts
+++ b/packages/line-height/src/lib/BaseLineHeightPlugin.ts
@@ -7,6 +7,7 @@ import { BaseParagraphPlugin, createSlatePlugin } from '@udecode/plate-common';
export const BaseLineHeightPlugin = createSlatePlugin({
key: 'lineHeight',
inject: {
+ isBlock: true,
nodeProps: {
defaultNodeValue: 1.5,
nodeKey: 'lineHeight',
diff --git a/packages/line-height/src/lib/transforms/setLineHeight.ts b/packages/line-height/src/lib/transforms/setLineHeight.ts
index f31b0c2238..95a159423d 100644
--- a/packages/line-height/src/lib/transforms/setLineHeight.ts
+++ b/packages/line-height/src/lib/transforms/setLineHeight.ts
@@ -1,9 +1,7 @@
import {
type SetNodesOptions,
type SlateEditor,
- type TNodeMatch,
- getKeyByType,
- isBlock,
+ getInjectMatch,
setElements,
unsetNodes,
} from '@udecode/plate-common';
@@ -17,16 +15,10 @@ export const setLineHeight = (
value,
}: { value: number; setNodesOptions?: SetNodesOptions }
): void => {
- const {
- inject: { targetPlugins },
- } = editor.getPlugin(BaseLineHeightPlugin);
const { defaultNodeValue, nodeKey } =
editor.getInjectProps(BaseLineHeightPlugin);
- const match: TNodeMatch = (n) =>
- isBlock(editor, n) &&
- !!targetPlugins &&
- targetPlugins.includes(getKeyByType(editor, n.type as string));
+ const match = getInjectMatch(editor, editor.getPlugin(BaseLineHeightPlugin));
if (value === defaultNodeValue) {
unsetNodes(editor, nodeKey!, {
diff --git a/packages/link/package.json b/packages/link/package.json
index b573854c98..4ff061a0b2 100644
--- a/packages/link/package.json
+++ b/packages/link/package.json
@@ -61,9 +61,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/link/src/lib/index.ts b/packages/link/src/lib/index.ts
index 9bb4b45fe4..eb64b1e646 100644
--- a/packages/link/src/lib/index.ts
+++ b/packages/link/src/lib/index.ts
@@ -3,7 +3,7 @@
*/
export * from './BaseLinkPlugin';
-export type * from './types';
+export * from './types';
export * from './withLink';
export * from './transforms/index';
export * from './utils/index';
diff --git a/packages/list/package.json b/packages/list/package.json
index c42aaaea13..2d16d4f0f2 100644
--- a/packages/list/package.json
+++ b/packages/list/package.json
@@ -61,9 +61,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/markdown/package.json b/packages/markdown/package.json
index c1833d0e32..fe4be6ca06 100644
--- a/packages/markdown/package.json
+++ b/packages/markdown/package.json
@@ -48,6 +48,7 @@
},
"dependencies": {
"lodash": "^4.17.21",
+ "remark-gfm": "4.0.0",
"remark-parse": "^9.0.0",
"unified": "^11.0.5"
},
@@ -59,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx b/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx
index 596c3418f5..eda5de53f4 100644
--- a/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx
+++ b/packages/markdown/src/lib/deserializer/utils/deserializeMd.spec.tsx
@@ -14,6 +14,21 @@ describe('deserializeMd', () => {
plugins: [MarkdownPlugin],
});
+ // TODO
+ // it('should deserialize strikethrough', () => {
+ // const input = 'This is ~~strikethrough~~.';
+
+ // const output = (
+ //
+ //
+ // This is strikethrough .
+ //
+ //
+ // );
+
+ // expect(deserializeMd(editor, input)).toEqual(output);
+ // });
+
it('should deserialize >>> to blockquote', () => {
const input = '>>>a';
diff --git a/packages/markdown/src/lib/deserializer/utils/deserializeMd.ts b/packages/markdown/src/lib/deserializer/utils/deserializeMd.ts
index 1ac66c9eb8..8cdec51114 100644
--- a/packages/markdown/src/lib/deserializer/utils/deserializeMd.ts
+++ b/packages/markdown/src/lib/deserializer/utils/deserializeMd.ts
@@ -1,7 +1,7 @@
import type { SlateEditor } from '@udecode/plate-common';
-import markdown from 'remark-parse';
-import { unified } from 'unified';
+import remarkParse from 'remark-parse';
+import { type Processor, unified } from 'unified';
import { MarkdownPlugin } from '../../MarkdownPlugin';
import {
@@ -12,40 +12,52 @@ import {
} from '../../remark-slate';
/** Deserialize content from Markdown format to Slate format. */
-export const deserializeMd = (editor: SlateEditor, data: string) => {
+export const deserializeMd = (
+ editor: SlateEditor,
+ data: string,
+ {
+ processor,
+ }: {
+ processor?: (processor: Processor) => Processor;
+ } = {}
+) => {
const elementRules: RemarkElementRules = {};
const textRules: RemarkTextRules = {};
- // Collect rules from plugins
- // editor.plugins.forEach((plugin: SlatePlugin) => {
- // if (plugin.parsers?.markdown?.deserialize) {
- // const { elementRules: pluginElementRules, textRules: pluginTextRules } =
- // plugin.parsers.markdown.deserialize as MarkdownDeserializer;
- //
- // if (pluginElementRules) {
- // Object.assign(elementRules, pluginElementRules);
- // }
- // if (pluginTextRules) {
- // Object.assign(textRules, pluginTextRules);
- // }
- // }
- // });
-
const options = editor.getOptions(MarkdownPlugin);
Object.assign(elementRules, options.elementRules);
Object.assign(textRules, options.textRules);
- const tree: any = unified()
- .use(markdown as any)
+ let tree: any = unified().use(remarkParse);
+
+ if (processor) {
+ tree = processor(tree);
+ }
+
+ tree = tree
.use(remarkPlugin, {
editor,
elementRules,
indentList: options.indentList,
- // || !editor.plugins.list,
textRules,
} as unknown as RemarkPluginOptions)
.processSync(data);
return tree.result;
};
+
+// TODO: Collect rules from plugins
+// editor.plugins.forEach((plugin: SlatePlugin) => {
+// if (plugin.parsers?.markdown?.deserialize) {
+// const { elementRules: pluginElementRules, textRules: pluginTextRules } =
+// plugin.parsers.markdown.deserialize as MarkdownDeserializer;
+//
+// if (pluginElementRules) {
+// Object.assign(elementRules, pluginElementRules);
+// }
+// if (pluginTextRules) {
+// Object.assign(textRules, pluginTextRules);
+// }
+// }
+// });
diff --git a/packages/markdown/src/lib/remark-slate/index.ts b/packages/markdown/src/lib/remark-slate/index.ts
index 98e677fb9b..7fde5b2e0f 100644
--- a/packages/markdown/src/lib/remark-slate/index.ts
+++ b/packages/markdown/src/lib/remark-slate/index.ts
@@ -10,4 +10,4 @@ export * from './remarkTransformElement';
export * from './remarkTransformElementChildren';
export * from './remarkTransformNode';
export * from './remarkTransformText';
-export type * from './types';
+export * from './types';
diff --git a/packages/markdown/src/lib/remark-slate/remarkDefaultTextRules.ts b/packages/markdown/src/lib/remark-slate/remarkDefaultTextRules.ts
index 13be8ae71a..eb9a7c14c0 100644
--- a/packages/markdown/src/lib/remark-slate/remarkDefaultTextRules.ts
+++ b/packages/markdown/src/lib/remark-slate/remarkDefaultTextRules.ts
@@ -1,6 +1,7 @@
import type { RemarkTextRules } from './types';
export const remarkDefaultTextRules: RemarkTextRules = {
+ delete: { mark: ({ editor }) => editor.getType({ key: 'strikethrough' }) },
emphasis: { mark: ({ editor }) => editor.getType({ key: 'italic' }) },
html: { transform: (text: string) => text.replaceAll(' ', '\n') },
inlineCode: { mark: ({ editor }) => editor.getType({ key: 'code' }) },
diff --git a/packages/markdown/src/lib/serializer/index.ts b/packages/markdown/src/lib/serializer/index.ts
index 54ab9dddb1..6544ee1c6d 100644
--- a/packages/markdown/src/lib/serializer/index.ts
+++ b/packages/markdown/src/lib/serializer/index.ts
@@ -7,4 +7,4 @@ export * from './serializeInlineMd';
export * from './serializeMd';
export * from './serializeMdNode';
export * from './serializeMdNodes';
-export type * from './types';
+export * from './types';
diff --git a/packages/math/package.json b/packages/math/package.json
index d02649a1b2..5622d98ffb 100644
--- a/packages/math/package.json
+++ b/packages/math/package.json
@@ -61,9 +61,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/media/package.json b/packages/media/package.json
index f70f62bbe0..702a97f2ee 100644
--- a/packages/media/package.json
+++ b/packages/media/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/media/src/lib/media/index.ts b/packages/media/src/lib/media/index.ts
index 7f9a061e57..4a95d1b952 100644
--- a/packages/media/src/lib/media/index.ts
+++ b/packages/media/src/lib/media/index.ts
@@ -4,4 +4,4 @@
export * from './insertMedia';
export * from './parseMediaUrl';
-export type * from './types';
+export * from './types';
diff --git a/packages/mention/package.json b/packages/mention/package.json
index 240b3eb67f..9283ac17ef 100644
--- a/packages/mention/package.json
+++ b/packages/mention/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/mention/src/lib/index.ts b/packages/mention/src/lib/index.ts
index 0573ffe868..0ba1d16034 100644
--- a/packages/mention/src/lib/index.ts
+++ b/packages/mention/src/lib/index.ts
@@ -4,4 +4,4 @@
export * from './BaseMentionPlugin';
export * from './getMentionOnSelectItem';
-export type * from './types';
+export * from './types';
diff --git a/packages/node-id/package.json b/packages/node-id/package.json
index 26eac4eee6..30fa31135b 100644
--- a/packages/node-id/package.json
+++ b/packages/node-id/package.json
@@ -54,9 +54,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/node-id/src/lib/NodeIdPlugin.spec.tsx b/packages/node-id/src/lib/NodeIdPlugin.spec.tsx
index 727cf3d4c7..8369ee97c9 100644
--- a/packages/node-id/src/lib/NodeIdPlugin.spec.tsx
+++ b/packages/node-id/src/lib/NodeIdPlugin.spec.tsx
@@ -8,6 +8,7 @@ import {
splitNodes,
} from '@udecode/plate-common';
import { ParagraphPlugin } from '@udecode/plate-common/react';
+import { LinkPlugin } from '@udecode/plate-link/react';
import { BulletedListPlugin, ListItemPlugin } from '@udecode/plate-list/react';
import { jsx } from '@udecode/plate-test-utils';
@@ -21,6 +22,130 @@ const getIdFactory = () => {
return () => id++;
};
+describe('when normalizing initial value', () => {
+ it('should not add id to inline nodes', () => {
+ const input = (
+
+
+ test1
+ link
+ test2
+
+
+ link2
+
+
+ ) as any as SlateEditor;
+
+ const editor = createSlateEditor({
+ plugins: [
+ NodeIdPlugin.configure({
+ options: {
+ idCreator: getIdFactory(),
+ },
+ }),
+ LinkPlugin,
+ ],
+ value: input.children,
+ });
+
+ // Block elements should have IDs
+ expect(editor.children[0].id).toBe(1);
+ expect(editor.children[1].id).toBe(2);
+
+ // Inline elements should not have IDs
+ expect((editor.children[0] as any).children[1].id).toBeUndefined();
+ expect((editor.children[1] as any).children[0].id).toBeUndefined();
+ });
+
+ it('should add id to inline nodes', () => {
+ const input = (
+
+
+ test1
+ link
+ test2
+
+
+ link2
+
+
+ ) as any as SlateEditor;
+
+ const editor = createSlateEditor({
+ plugins: [
+ NodeIdPlugin.configure({
+ options: {
+ filterInline: false,
+ idCreator: getIdFactory(),
+ },
+ }),
+ LinkPlugin,
+ ],
+ value: input.children,
+ });
+
+ // Block elements should have IDs
+ expect(editor.children[0].id).toBe(1);
+ expect(editor.children[1].id).toBe(3);
+
+ // Inline elements should have IDs
+ expect((editor.children[0] as any).children[1].id).toBe(2);
+ expect((editor.children[1] as any).children[0].id).toBe(4);
+ });
+
+ it('should add ids to all nodes when normalizeInitialValue is true', () => {
+ const input = (
+
+ test1
+ test2
+
+ test3
+
+
+ ) as any as SlateEditor;
+
+ const editor = createSlateEditor({
+ plugins: [
+ NodeIdPlugin.configure({
+ options: {
+ idCreator: getIdFactory(),
+ normalizeInitialValue: true,
+ },
+ }),
+ ],
+ value: input.children,
+ });
+
+ // All nodes should have sequential IDs
+ expect(editor.children[1].id).toBe(1);
+ });
+
+ it('should only add ids to first and last nodes when normalizeInitialValue is false', () => {
+ const input = (
+
+ test1
+ test2
+ test3
+
+ ) as any as SlateEditor;
+
+ const editor = createSlateEditor({
+ plugins: [
+ NodeIdPlugin.configure({
+ options: {
+ idCreator: getIdFactory(),
+ },
+ }),
+ ],
+ value: input.children,
+ });
+
+ // Only first and last nodes should have IeDs
+ expect(editor.children[0].id).toBe(1);
+ });
+});
+
describe('when inserting nodes', () => {
describe('when allow is p, inserting li and p', () => {
it('should add an id to the inserted p but not li', () => {
diff --git a/packages/node-id/src/lib/NodeIdPlugin.ts b/packages/node-id/src/lib/NodeIdPlugin.ts
index 2882c36106..eabe92bcb0 100644
--- a/packages/node-id/src/lib/NodeIdPlugin.ts
+++ b/packages/node-id/src/lib/NodeIdPlugin.ts
@@ -1,7 +1,13 @@
import {
type PluginConfig,
type QueryNodeOptions,
+ type TDescendant,
+ type Value,
createTSlatePlugin,
+ isBlock,
+ isElement,
+ nanoid,
+ queryNode,
} from '@udecode/plate-common';
import { withNodeId } from './withNodeId';
@@ -16,6 +22,13 @@ export type NodeIdConfig = PluginConfig<
*/
disableInsertOverrides?: boolean;
+ /**
+ * Filter inline `Element` nodes.
+ *
+ * @default true
+ */
+ filterInline?: boolean;
+
/**
* Filter `Text` nodes.
*
@@ -37,6 +50,15 @@ export type NodeIdConfig = PluginConfig<
*/
idKey?: string;
+ /**
+ * Normalize initial value. If false, normalize only the first and last node
+ * are missing id. To disable this behavior, use `NodeIdPlugin.configure({
+ * normalizeInitialValue: null })`.
+ *
+ * @default false
+ */
+ normalizeInitialValue?: boolean;
+
/**
* Reuse ids on undo/redo and copy/pasting if not existing in the document.
* This is disabled by default to avoid duplicate ids across documents.
@@ -51,10 +73,73 @@ export type NodeIdConfig = PluginConfig<
export const NodeIdPlugin = createTSlatePlugin({
key: 'nodeId',
extendEditor: withNodeId,
+ normalizeInitialValue: ({ editor, getOptions }) => {
+ const {
+ allow,
+ exclude,
+ filter,
+ filterInline,
+ filterText,
+ idKey,
+ normalizeInitialValue,
+ } = getOptions();
+
+ // Perf: check if normalization is needed by looking at the first node and last node
+ if (!normalizeInitialValue) {
+ const firstNode = editor.children[0];
+ const lastNode = editor.children.at(-1);
+
+ if (firstNode?.id && lastNode?.id) {
+ return editor.children as Value;
+ }
+ }
+
+ const addNodeId = (entry: [TDescendant, number[]]) => {
+ const [node, path] = entry;
+ const newNode = { ...node };
+
+ if (
+ !newNode[idKey!] &&
+ queryNode([node, path], {
+ allow,
+ exclude,
+ filter: (entry) => {
+ const [node] = entry;
+
+ if (filterText && !isElement(node)) {
+ return false;
+ }
+ if (filterInline && isElement(node) && !isBlock(editor, node)) {
+ return false;
+ }
+
+ return filter!(entry);
+ },
+ })
+ ) {
+ newNode[idKey!] = getOptions().idCreator!();
+ }
+ // Recursively process children if they exist
+ if ((newNode.children as any)?.length > 0) {
+ newNode.children = (newNode.children as any).map(
+ (child: any, index: number) => addNodeId([child, [...path, index]])
+ );
+ }
+
+ return newNode;
+ };
+
+ // Process top-level nodes
+ return editor.children.map((node, index) =>
+ addNodeId([node, [index]])
+ ) as Value;
+ },
options: {
filter: () => true,
+ filterInline: true,
filterText: true,
- idCreator: () => Math.random().toString(36).slice(2, 7),
+ idCreator: () => nanoid(10),
idKey: 'id',
+ normalizeInitialValue: false,
},
});
diff --git a/packages/normalizers/package.json b/packages/normalizers/package.json
index 51110f48cf..c621dbe1e6 100644
--- a/packages/normalizers/package.json
+++ b/packages/normalizers/package.json
@@ -54,9 +54,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/plate-utils/src/lib/index.ts b/packages/plate-utils/src/lib/index.ts
index d130f1328e..9b8cf54e9f 100644
--- a/packages/plate-utils/src/lib/index.ts
+++ b/packages/plate-utils/src/lib/index.ts
@@ -5,4 +5,4 @@
export * from './defaultsDeepToNodes';
export * from './isType';
export * from './moveSelectionByOffset';
-export type * from './types/index';
+export * from './types/index';
diff --git a/packages/plate-utils/src/lib/types/index.ts b/packages/plate-utils/src/lib/types/index.ts
index 98a2beda1e..e51f64b6e0 100644
--- a/packages/plate-utils/src/lib/types/index.ts
+++ b/packages/plate-utils/src/lib/types/index.ts
@@ -2,5 +2,5 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './ClassNames';
-export type * from './ErrorHandler';
+export * from './ClassNames';
+export * from './ErrorHandler';
diff --git a/packages/plate-utils/src/react/PlateElement.tsx b/packages/plate-utils/src/react/PlateElement.tsx
index 9febad88b2..4f1f0b418e 100644
--- a/packages/plate-utils/src/react/PlateElement.tsx
+++ b/packages/plate-utils/src/react/PlateElement.tsx
@@ -1,13 +1,13 @@
import React from 'react';
-import type { TElement } from '@udecode/slate';
-
import {
type AnyPlatePlugin,
type PlateRenderElementProps,
omitPluginContext,
+ usePlateStore,
} from '@udecode/plate-core/react';
import { type BoxProps, Box, useComposedRef } from '@udecode/react-utils';
+import { type TElement, isBlock } from '@udecode/slate';
import { clsx } from 'clsx';
export type PlateElementProps<
@@ -22,6 +22,12 @@ export type PlateElementProps<
export const usePlateElement = (props: PlateElementProps) => {
const { attributes, element, elementToAttributes, nodeProps, ...rootProps } =
omitPluginContext(props);
+ const mounted = usePlateStore().get.isMounted();
+
+ const block = React.useMemo(
+ () => mounted && !!element.id && isBlock(props.editor, element),
+ [element, props.editor, mounted]
+ );
return {
props: {
@@ -30,6 +36,7 @@ export const usePlateElement = (props: PlateElementProps) => {
...nodeProps,
...elementToAttributes?.(element),
className: clsx(props.className, nodeProps?.className),
+ 'data-block-id': block ? element.id : undefined,
},
ref: useComposedRef(props.ref, attributes.ref),
};
@@ -42,8 +49,9 @@ const PlateElement = React.forwardRef(
...props,
ref,
});
+ const { ...rest } = rootProps;
- return ;
+ return ;
}
) as (<
N extends TElement = TElement,
diff --git a/packages/plate/package.json b/packages/plate/package.json
index 286a071ffa..2ee71e78c2 100644
--- a/packages/plate/package.json
+++ b/packages/plate/package.json
@@ -103,9 +103,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/playwright/package.json b/packages/playwright/package.json
index c660aef018..2246dee175 100644
--- a/packages/playwright/package.json
+++ b/packages/playwright/package.json
@@ -50,9 +50,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts
index c217648d26..b1e8cc550c 100644
--- a/packages/playwright/src/index.ts
+++ b/packages/playwright/src/index.ts
@@ -11,5 +11,5 @@ export * from './getNodeByPath';
export * from './getSelection';
export * from './getTypeAtPath';
export * from './setSelection';
-export type * from './types';
+export * from './types';
export * from './usePlaywrightAdapter';
diff --git a/packages/reset-node/package.json b/packages/reset-node/package.json
index b543550dcc..a3709d31cc 100644
--- a/packages/reset-node/package.json
+++ b/packages/reset-node/package.json
@@ -57,9 +57,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/reset-node/src/lib/index.ts b/packages/reset-node/src/lib/index.ts
index 25de0fee0c..5f0e634af6 100644
--- a/packages/reset-node/src/lib/index.ts
+++ b/packages/reset-node/src/lib/index.ts
@@ -3,4 +3,4 @@
*/
export * from './BaseResetNodePlugin';
-export type * from './types';
+export * from './types';
diff --git a/packages/resizable/package.json b/packages/resizable/package.json
index d3cb3c17c6..8abf43c2a4 100644
--- a/packages/resizable/package.json
+++ b/packages/resizable/package.json
@@ -50,9 +50,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/resizable/src/components/index.ts b/packages/resizable/src/components/index.ts
index d57b81054b..9045f0c550 100644
--- a/packages/resizable/src/components/index.ts
+++ b/packages/resizable/src/components/index.ts
@@ -4,5 +4,5 @@
export * from './Resizable';
export * from './ResizeHandle';
-export type * from './TResizableElement';
+export * from './TResizableElement';
export * from './useResizableStore';
diff --git a/packages/resizable/src/index.ts b/packages/resizable/src/index.ts
index 25aa5c128e..2985a3c676 100644
--- a/packages/resizable/src/index.ts
+++ b/packages/resizable/src/index.ts
@@ -2,6 +2,6 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './types';
+export * from './types';
export * from './components/index';
export * from './utils/index';
diff --git a/packages/select/package.json b/packages/select/package.json
index c53eebf310..83eadb230c 100644
--- a/packages/select/package.json
+++ b/packages/select/package.json
@@ -51,9 +51,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/selection/package.json b/packages/selection/package.json
index be0a0fa712..9831950d64 100644
--- a/packages/selection/package.json
+++ b/packages/selection/package.json
@@ -1,7 +1,7 @@
{
"name": "@udecode/plate-selection",
"version": "39.3.7",
- "description": "Plate React plugin to add a visual way of selecting blocks",
+ "description": "Plate selection plugins",
"keywords": [
"plate",
"plugin",
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/selection/src/internal/SelectionArea.ts b/packages/selection/src/internal/SelectionArea.ts
index 5fa3920eb0..6441644b0f 100644
--- a/packages/selection/src/internal/SelectionArea.ts
+++ b/packages/selection/src/internal/SelectionArea.ts
@@ -499,6 +499,7 @@ export class SelectionArea extends EventTarget {
this._container = selectAll(container, document)[0];
+ if (!this._container) return;
if (
this._container.contains(target) &&
target.dataset.slateEditor !== 'true' &&
diff --git a/packages/selection/src/lib/extractSelectableIds.ts b/packages/selection/src/lib/extractSelectableIds.ts
index fd8b6c5b82..1c13cfb1e8 100644
--- a/packages/selection/src/lib/extractSelectableIds.ts
+++ b/packages/selection/src/lib/extractSelectableIds.ts
@@ -1,6 +1,6 @@
export const extractSelectableIds = (els: Element[]): any[] => {
- return els.map((v) => (v as HTMLElement).dataset.key);
+ return els.map((v) => (v as HTMLElement).dataset.blockId);
};
export const extractSelectableId = (el: Element) =>
- (el as HTMLElement).dataset.key;
+ (el as HTMLElement).dataset.blockId;
diff --git a/packages/selection/src/lib/getAboveDomNode.ts b/packages/selection/src/lib/getAboveDomNode.ts
index 668bda9838..c08f6e8ac9 100644
--- a/packages/selection/src/lib/getAboveDomNode.ts
+++ b/packages/selection/src/lib/getAboveDomNode.ts
@@ -1,5 +1,5 @@
export const getSelectedDomNode = (id: string) => {
- return document.querySelector(`.slate-selectable[data-key="${id}"]`);
+ return document.querySelector(`.slate-selectable[data-block-id="${id}"]`);
};
export const getAllSelectableDomNode = () => {
diff --git a/packages/selection/src/react/BlockSelectionPlugin.tsx b/packages/selection/src/react/BlockSelectionPlugin.tsx
index c57fb71a8c..4994580959 100644
--- a/packages/selection/src/react/BlockSelectionPlugin.tsx
+++ b/packages/selection/src/react/BlockSelectionPlugin.tsx
@@ -1,39 +1,22 @@
import type { CSSProperties } from 'react';
-import React from 'react';
-import ReactDOM from 'react-dom';
+import type React from 'react';
import {
type PluginConfig,
- type QueryNodeOptions,
type TElement,
type TNodeEntry,
bindFirst,
getNodeEntries,
} from '@udecode/plate-common';
-import {
- findNode,
- getEndPoint,
- getNextNode,
- getPreviousNode,
- isHotkey,
- removeNodes,
-} from '@udecode/plate-common';
import { createTPlatePlugin } from '@udecode/plate-common/react';
-import {
- type EditableSiblingComponent,
- focusEditor,
- isEditorReadOnly,
- useEditorPlugin,
- useEditorRef,
-} from '@udecode/plate-common/react';
import type { ChangedElements, PartialSelectionOptions } from '../internal';
import { getAllSelectableDomNode, getSelectedDomNode } from '../lib';
import { extractSelectableIds } from '../lib/extractSelectableIds';
import { BlockMenuPlugin } from './BlockMenuPlugin';
-import { BlockSelectable } from './components/BlockSelectable';
-import { useSelectionArea } from './hooks/useSelectionArea';
+import { BlockSelectionAfterEditable } from './components/BlockSelectionAfterEditable';
+import { useBlockSelectable } from './hooks/useBlockSelectable';
import { onKeyDownSelection } from './onKeyDownSelection';
import { duplicateBlockSelectionNodes } from './transforms/duplicateBlockSelectionNodes';
import { insertBlocksAndSelect } from './transforms/insertBlocksAndSelect';
@@ -44,11 +27,6 @@ import {
setBlockSelectionNodes,
setBlockSelectionTexts,
} from './transforms/setBlockSelectionNodes';
-import {
- copySelectedBlocks,
- pasteSelectedBlocks,
- selectInsertedBlocks,
-} from './utils';
export type BlockSelectionConfig = PluginConfig<
'blockSelection',
@@ -58,7 +36,6 @@ export type BlockSelectionConfig = PluginConfig<
enableContextMenu?: boolean;
isSelecting?: boolean;
isSelectionAreaVisible?: boolean;
- query?: QueryNodeOptions;
rightSelectionAreaClassName?: string;
selectedIds?: Set;
shadowInputRef?: React.RefObject;
@@ -75,13 +52,10 @@ export type BlockSelectionSelectors = {
};
export type BlockSelectionApi = {
- addSelectedRow: (
- id: string,
- options?: { aboveHtmlNode?: HTMLDivElement; clear?: boolean }
- ) => void;
setSelectedIds: (
options: Partial & { ids?: string[] }
) => void;
+ addSelectedRow: (id: string, options?: { clear?: boolean }) => void;
focus: () => void;
getNodes: () => TNodeEntry[];
resetSelectedIds: () => void;
@@ -89,173 +63,6 @@ export type BlockSelectionApi = {
unselect: () => void;
};
-export const BlockSelectionAfterEditable: EditableSiblingComponent = () => {
- const editor = useEditorRef();
- const { api, getOption, getOptions, setOption, useOption } =
- useEditorPlugin({ key: 'blockSelection' });
- const isSelecting = useOption('isSelecting');
- const selectedIds = useOption('selectedIds');
-
- useSelectionArea();
-
- const inputRef = React.useRef(null);
- const [isMounted, setIsMounted] = React.useState(false);
-
- React.useEffect(() => {
- setIsMounted(true);
- setOption('shadowInputRef', inputRef);
-
- return () => {
- setIsMounted(false);
- };
- }, [setOption]);
-
- React.useEffect(() => {
- if (isSelecting && inputRef.current) {
- inputRef.current.focus({ preventScroll: true });
- } else if (inputRef.current) {
- inputRef.current.blur();
- }
- }, [isSelecting]);
-
- const handleKeyDown = React.useCallback(
- (e: React.KeyboardEvent) => {
- const isReadonly = isEditorReadOnly(editor);
- getOptions().onKeyDownSelecting?.(e.nativeEvent);
-
- // selecting commands
- if (!getOptions().isSelecting) return;
- if (isHotkey('escape')(e)) {
- api.blockSelection.unselect();
- }
- if (isHotkey('mod+z')(e)) {
- editor.undo();
- selectInsertedBlocks(editor);
- }
- if (isHotkey('mod+shift+z')(e)) {
- editor.redo();
- selectInsertedBlocks(editor);
- }
- // selecting some commands
- if (!getOption('isSelectingSome')) return;
- if (isHotkey('enter')(e)) {
- // get the first block in the selection
- const entry = findNode(editor, {
- at: [],
- match: (n) => selectedIds!.has(n.id),
- });
-
- if (entry) {
- const [, path] = entry;
-
- // focus the end of that block
- focusEditor(editor, getEndPoint(editor, path));
- e.preventDefault();
- }
- }
- if (isHotkey(['backspace', 'delete'])(e) && !isReadonly) {
- removeNodes(editor, {
- at: [],
- match: (n) => selectedIds!.has(n.id),
- });
- }
- // TODO: skip toggle child
- if (isHotkey('up')(e)) {
- const firstId = [...selectedIds!][0];
- const node = findNode(editor, {
- at: [],
- match: (n) => n.id === firstId,
- });
- const prev = getPreviousNode(editor, {
- at: node?.[1],
- });
-
- const prevId = prev?.[0].id;
- api.blockSelection.addSelectedRow(prevId);
- }
- if (isHotkey('down')(e)) {
- const lastId = [...selectedIds!].pop();
- const node = findNode(editor, {
- at: [],
- match: (n) => n.id === lastId,
- });
- const next = getNextNode(editor, {
- at: node?.[1],
- });
- const nextId = next?.[0].id;
- api.blockSelection.addSelectedRow(nextId);
- }
- },
- [editor, selectedIds, api, getOptions, getOption]
- );
-
- const handleCopy = React.useCallback(
- (e: React.ClipboardEvent) => {
- e.preventDefault();
-
- if (getOption('isSelectingSome')) {
- copySelectedBlocks(editor);
- }
- },
- [editor, getOption]
- );
-
- const handleCut = React.useCallback(
- (e: React.ClipboardEvent) => {
- e.preventDefault();
-
- if (getOption('isSelectingSome')) {
- copySelectedBlocks(editor);
-
- if (!isEditorReadOnly(editor)) {
- removeNodes(editor, {
- at: [],
- match: (n) => selectedIds!.has(n.id),
- });
-
- focusEditor(editor);
- }
- }
- },
- [editor, selectedIds, getOption]
- );
-
- const handlePaste = React.useCallback(
- (e: React.ClipboardEvent) => {
- e.preventDefault();
-
- if (!isEditorReadOnly(editor)) {
- pasteSelectedBlocks(editor, e.nativeEvent);
- }
- },
- [editor]
- );
-
- if (!isMounted || typeof window === 'undefined') {
- return null;
- }
-
- return ReactDOM.createPortal(
- ,
- document.body
- );
-};
-
export const BlockSelectionPlugin = createTPlatePlugin({
key: 'blockSelection',
extendEditor: ({ api, editor, getOptions }) => {
@@ -274,6 +81,15 @@ export const BlockSelectionPlugin = createTPlatePlugin({
return editor;
},
+ inject: {
+ isBlock: true,
+ nodeProps: {
+ transformProps: () => {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ return useBlockSelectable().props;
+ },
+ },
+ },
options: {
areaOptions: {
behaviour: {
@@ -292,23 +108,11 @@ export const BlockSelectionPlugin = createTPlatePlugin({
enableContextMenu: false,
isSelecting: false,
isSelectionAreaVisible: false,
- query: {
- maxLevel: 1,
- },
selectedIds: new Set(),
shadowInputRef: { current: null },
},
plugins: [BlockMenuPlugin],
render: {
- aboveNodes:
- () =>
- ({ children, element }) =>
- BlockSelectable({
- children,
- options: {
- element,
- },
- }),
afterEditable: BlockSelectionAfterEditable,
},
handlers: {
@@ -327,6 +131,9 @@ export const BlockSelectionPlugin = createTPlatePlugin({
},
},
})
+ .extend(() => ({
+ inject: {},
+ }))
.extendOptions(({ getOptions }) => ({
isSelected: (id?: string) => !!id && getOptions().selectedIds!.has(id),
isSelectingSome: () => getOptions().selectedIds!.size > 0,
@@ -381,9 +188,9 @@ export const BlockSelectionPlugin = createTPlatePlugin({
)
.extendApi>(({ api, getOptions, setOption }) => ({
addSelectedRow: (id, options = {}) => {
- const { aboveHtmlNode, clear = true } = options;
+ const { clear = true } = options;
- const element = aboveHtmlNode ?? getSelectedDomNode(id);
+ const element = getSelectedDomNode(id);
if (!element) return;
if (!getOptions().selectedIds!.has(id) && clear) {
diff --git a/packages/selection/src/react/CursorOverlayPlugin.tsx b/packages/selection/src/react/CursorOverlayPlugin.tsx
new file mode 100644
index 0000000000..6e8d4539e7
--- /dev/null
+++ b/packages/selection/src/react/CursorOverlayPlugin.tsx
@@ -0,0 +1,127 @@
+import { useEffect } from 'react';
+
+import type { PluginConfig } from '@udecode/plate-common';
+
+import {
+ type DOMHandler,
+ createTPlatePlugin,
+ findEventRange,
+ useEditorPlugin,
+} from '@udecode/plate-common/react';
+
+import type { CursorData, CursorState } from './types';
+
+import { BlockSelectionPlugin } from './BlockSelectionPlugin';
+
+export type CursorOverlayConfig = PluginConfig<
+ 'cursorOverlay',
+ {
+ cursors: Record>;
+ },
+ {
+ cursorOverlay: CursorOverlayApi;
+ }
+>;
+
+type CursorOverlayApi = {
+ addCursor: (id: string, cursor: Omit, 'id'>) => void;
+ removeCursor: (id: (string & {}) | 'drag' | 'selection') => void;
+};
+
+const getRemoveCursorHandler =
+ (id: string): DOMHandler =>
+ ({ api }) => {
+ api.cursorOverlay.removeCursor(id);
+ };
+
+export const CursorOverlayPlugin = createTPlatePlugin({
+ key: 'cursorOverlay',
+ options: { cursors: {} },
+})
+ .extendApi(({ editor, plugin }) => ({
+ addCursor: (id, cursor) => {
+ const newCursors = { ...editor.getOptions(plugin).cursors };
+ newCursors[id] = {
+ id,
+ ...cursor,
+ };
+ editor.setOption(plugin, 'cursors', newCursors);
+ },
+ removeCursor: (id) => {
+ const newCursors = { ...editor.getOptions(plugin).cursors };
+
+ if (!newCursors[id]) return;
+
+ delete newCursors[id];
+ editor.setOption(plugin, 'cursors', newCursors);
+ },
+ }))
+ .extend(() => ({
+ extendEditor: ({ api, editor, getOptions }) => {
+ const { setSelection } = editor;
+
+ editor.setSelection = (...args) => {
+ if (getOptions().cursors?.selection) {
+ setTimeout(() => {
+ api.cursorOverlay.addCursor('selection', {
+ selection: editor.selection,
+ });
+ }, 0);
+ }
+
+ setSelection(...args);
+ };
+
+ return editor;
+ },
+ useHooks: ({ api, setOption }) => {
+ const { editor } = useEditorPlugin(BlockSelectionPlugin);
+ const isSelecting = editor.useOption(BlockSelectionPlugin, 'isSelecting');
+
+ useEffect(() => {
+ if (isSelecting) {
+ setTimeout(() => {
+ api.cursorOverlay.removeCursor('selection');
+ }, 0);
+ }
+ }, [isSelecting, setOption, api.cursorOverlay]);
+ },
+ handlers: {
+ onBlur: ({ api, editor, event }) => {
+ if (!editor.selection) return;
+
+ const relatedTarget = event.relatedTarget as HTMLElement;
+ const enabled = relatedTarget?.dataset?.plateFocus === 'true';
+
+ if (!enabled) return;
+
+ api.cursorOverlay.addCursor('selection', {
+ selection: editor.selection,
+ });
+ },
+ onDragEnd: getRemoveCursorHandler('drag') as any,
+ onDragLeave: getRemoveCursorHandler('drag') as any,
+ onDragOver: ({ api, editor, event }) => {
+ if (
+ !editor.plugins.dnd ||
+ editor.getOptions({ key: 'dnd' }).isDragging
+ ) {
+ return;
+ }
+
+ const types = event.dataTransfer?.types || [];
+
+ if (types.some((type) => type.startsWith('Files'))) return;
+
+ const range = findEventRange(editor, event);
+
+ if (!range) return;
+
+ api.cursorOverlay.addCursor('drag', {
+ selection: range,
+ });
+ },
+ onDrop: getRemoveCursorHandler('drag') as any,
+ onFocus: getRemoveCursorHandler('selection') as any,
+ },
+ }));
diff --git a/packages/selection/src/react/components/BlockSelectable.tsx b/packages/selection/src/react/components/BlockSelectable.tsx
deleted file mode 100644
index 78fc2bee3d..0000000000
--- a/packages/selection/src/react/components/BlockSelectable.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import React, { useEffect, useRef, useState } from 'react';
-
-import {
- type TElement,
- getAboveNode,
- isInline,
- isVoid,
- queryNode,
-} from '@udecode/plate-common';
-import {
- createAtomStore,
- findNodePath,
- useEditorPlugin,
-} from '@udecode/plate-common/react';
-import { Path } from 'slate';
-
-import { BlockSelectionPlugin } from '../BlockSelectionPlugin';
-
-export const { BlockSelectableProvider, useBlockSelectableStore } =
- createAtomStore(
- {
- selectable: false,
- },
- { name: 'blockSelectable' }
- );
-
-export interface BlockSelectableOptions {
- element: TElement;
- active?: boolean;
-}
-
-export const useBlockSelectableState = ({
- active,
- element,
-}: BlockSelectableOptions) => {
- const { editor, getOptions } = useEditorPlugin(BlockSelectionPlugin);
-
- const ref = useRef(null);
-
- const path = React.useMemo(
- () => findNodePath(editor, element),
- [editor, element]
- );
-
- if (!path || isInline(editor, element)) {
- return {
- active: active ?? false,
- };
- }
-
- const { query } = getOptions();
-
- if (query && !queryNode([element, path], query)) {
- return {
- active: active ?? false,
- };
- }
-
- return {
- active: active ?? true,
- element,
- path,
- ref,
- };
-};
-
-export const useBlockSelectable = ({
- active,
- element,
- path,
- ref,
-}: ReturnType) => {
- const { api, editor, getOption, getOptions } =
- useEditorPlugin(BlockSelectionPlugin);
-
- const [mounted, setMounted] = useState(false);
-
- useEffect(() => {
- setMounted(true);
- }, []);
-
- const id = element?.id as string | undefined;
-
- const data = mounted ? { 'data-key': id } : {};
-
- return {
- props: {
- className: 'slate-selectable',
- ref,
- onContextMenu: (event: React.MouseEvent) => {
- if (!element || !active) return;
-
- const { enableContextMenu } = getOptions();
-
- if (!enableContextMenu) return;
- if (editor.selection?.focus) {
- const nodeEntry = getAboveNode(editor);
-
- if (nodeEntry && Path.isCommon(path, nodeEntry[1])) {
- const id = nodeEntry[0].id as string | undefined;
- const isSelected = getOption('isSelected', id);
- const isOpenAlways =
- (event.target as HTMLElement).dataset?.plateOpenContextMenu ===
- 'true';
-
- /**
- * When "block selected or is void or has openContextMenu props",
- * right click can always open the context menu.
- */
- if (!isSelected && !isVoid(editor, nodeEntry[0]) && !isOpenAlways)
- return event.stopPropagation();
- }
- }
-
- const aboveHtmlNode = ref.current;
-
- if (id && aboveHtmlNode) {
- api.blockSelection.addSelectedRow(id, {
- aboveHtmlNode,
- clear: !event?.shiftKey,
- });
- }
- },
- ...data,
- },
- };
-};
-
-export function BlockSelectable({
- children,
- options,
- ...props
-}: { options: BlockSelectableOptions } & React.HTMLAttributes) {
- const state = useBlockSelectableState(options);
- const blockSelectable = useBlockSelectable(state);
-
- if (!state.active)
- return {children} ;
-
- return (
-
-
- {children}
-
-
- );
-}
diff --git a/packages/selection/src/react/components/BlockSelectionAfterEditable.tsx b/packages/selection/src/react/components/BlockSelectionAfterEditable.tsx
new file mode 100644
index 0000000000..1870ba1e44
--- /dev/null
+++ b/packages/selection/src/react/components/BlockSelectionAfterEditable.tsx
@@ -0,0 +1,194 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import {
+ findNode,
+ getEndPoint,
+ getNextNode,
+ getPreviousNode,
+ isHotkey,
+ removeNodes,
+} from '@udecode/plate-common';
+import {
+ type EditableSiblingComponent,
+ focusEditor,
+ isEditorReadOnly,
+ useEditorPlugin,
+ useEditorRef,
+} from '@udecode/plate-common/react';
+
+import type { BlockSelectionConfig } from '../BlockSelectionPlugin';
+
+import { useSelectionArea } from '../hooks';
+import {
+ copySelectedBlocks,
+ pasteSelectedBlocks,
+ selectInsertedBlocks,
+} from '../utils';
+
+export const BlockSelectionAfterEditable: EditableSiblingComponent = () => {
+ const editor = useEditorRef();
+ const { api, getOption, getOptions, setOption, useOption } =
+ useEditorPlugin({ key: 'blockSelection' });
+ const isSelecting = useOption('isSelecting');
+ const selectedIds = useOption('selectedIds');
+
+ useSelectionArea();
+
+ const inputRef = React.useRef(null);
+ const [isMounted, setIsMounted] = React.useState(false);
+
+ React.useEffect(() => {
+ setIsMounted(true);
+ setOption('shadowInputRef', inputRef);
+
+ return () => {
+ setIsMounted(false);
+ };
+ }, [setOption]);
+
+ React.useEffect(() => {
+ if (isSelecting && inputRef.current) {
+ inputRef.current.focus({ preventScroll: true });
+ } else if (inputRef.current) {
+ inputRef.current.blur();
+ }
+ }, [isSelecting]);
+
+ const handleKeyDown = React.useCallback(
+ (e: React.KeyboardEvent) => {
+ const isReadonly = isEditorReadOnly(editor);
+ getOptions().onKeyDownSelecting?.(e.nativeEvent);
+
+ // selecting commands
+ if (!getOptions().isSelecting) return;
+ if (isHotkey('escape')(e)) {
+ api.blockSelection.unselect();
+ }
+ if (isHotkey('mod+z')(e)) {
+ editor.undo();
+ selectInsertedBlocks(editor);
+ }
+ if (isHotkey('mod+shift+z')(e)) {
+ editor.redo();
+ selectInsertedBlocks(editor);
+ }
+ // selecting some commands
+ if (!getOption('isSelectingSome')) return;
+ if (isHotkey('enter')(e)) {
+ // get the first block in the selection
+ const entry = findNode(editor, {
+ at: [],
+ match: (n) => n.id && selectedIds!.has(n.id),
+ });
+
+ if (entry) {
+ const [, path] = entry;
+
+ // focus the end of that block
+ focusEditor(editor, getEndPoint(editor, path));
+ e.preventDefault();
+ }
+ }
+ if (isHotkey(['backspace', 'delete'])(e) && !isReadonly) {
+ removeNodes(editor, {
+ at: [],
+ match: (n) => !!n.id && selectedIds!.has(n.id),
+ });
+ }
+ // TODO: skip toggle child
+ if (isHotkey('up')(e)) {
+ const firstId = [...selectedIds!][0];
+ const node = findNode(editor, {
+ at: [],
+ match: (n) => n.id && n.id === firstId,
+ });
+ const prev = getPreviousNode(editor, {
+ at: node?.[1],
+ });
+
+ const prevId = prev?.[0].id;
+ api.blockSelection.addSelectedRow(prevId);
+ }
+ if (isHotkey('down')(e)) {
+ const lastId = [...selectedIds!].pop();
+ const node = findNode(editor, {
+ at: [],
+ match: (n) => n.id && n.id === lastId,
+ });
+ const next = getNextNode(editor, {
+ at: node?.[1],
+ });
+ const nextId = next?.[0].id;
+ api.blockSelection.addSelectedRow(nextId);
+ }
+ },
+ [editor, selectedIds, api, getOptions, getOption]
+ );
+
+ const handleCopy = React.useCallback(
+ (e: React.ClipboardEvent) => {
+ e.preventDefault();
+
+ if (getOption('isSelectingSome')) {
+ copySelectedBlocks(editor);
+ }
+ },
+ [editor, getOption]
+ );
+
+ const handleCut = React.useCallback(
+ (e: React.ClipboardEvent) => {
+ e.preventDefault();
+
+ if (getOption('isSelectingSome')) {
+ copySelectedBlocks(editor);
+
+ if (!isEditorReadOnly(editor)) {
+ removeNodes(editor, {
+ at: [],
+ match: (n) => selectedIds!.has(n.id),
+ });
+
+ focusEditor(editor);
+ }
+ }
+ },
+ [editor, selectedIds, getOption]
+ );
+
+ const handlePaste = React.useCallback(
+ (e: React.ClipboardEvent) => {
+ e.preventDefault();
+
+ if (!isEditorReadOnly(editor)) {
+ pasteSelectedBlocks(editor, e.nativeEvent);
+ }
+ },
+ [editor]
+ );
+
+ if (!isMounted || typeof window === 'undefined') {
+ return null;
+ }
+
+ return ReactDOM.createPortal(
+ ,
+ document.body
+ );
+};
diff --git a/packages/selection/src/react/components/index.ts b/packages/selection/src/react/components/index.ts
index b34c8e115d..1db7b2435f 100644
--- a/packages/selection/src/react/components/index.ts
+++ b/packages/selection/src/react/components/index.ts
@@ -2,4 +2,4 @@
* @file Automatically generated by barrelsby.
*/
-export * from './BlockSelectable';
+export * from './BlockSelectionAfterEditable';
diff --git a/packages/selection/src/react/hooks/index.ts b/packages/selection/src/react/hooks/index.ts
index 3d9c2f8267..3b70f82645 100644
--- a/packages/selection/src/react/hooks/index.ts
+++ b/packages/selection/src/react/hooks/index.ts
@@ -2,7 +2,11 @@
* @file Automatically generated by barrelsby.
*/
+export * from './useBlockSelectable';
export * from './useBlockSelected';
export * from './useBlockSelectionNodes';
+export * from './useCursorOverlay';
export * from './useIsSelecting';
+export * from './useRefreshOnResize';
+export * from './useRequestReRender';
export * from './useSelectionArea';
diff --git a/packages/selection/src/react/hooks/useBlockSelectable.ts b/packages/selection/src/react/hooks/useBlockSelectable.ts
new file mode 100644
index 0000000000..82eb03d16f
--- /dev/null
+++ b/packages/selection/src/react/hooks/useBlockSelectable.ts
@@ -0,0 +1,60 @@
+import React from 'react';
+
+import { getAboveNode, isVoid } from '@udecode/plate-common';
+import {
+ findNodePath,
+ useEditorPlugin,
+ useElement,
+} from '@udecode/plate-common/react';
+import { Path } from 'slate';
+
+import { BlockSelectionPlugin } from '../BlockSelectionPlugin';
+
+export const useBlockSelectable = () => {
+ const element = useElement();
+ const { api, editor, getOption, getOptions } =
+ useEditorPlugin(BlockSelectionPlugin);
+ const path = React.useMemo(
+ () => findNodePath(editor, element),
+ [editor, element]
+ );
+
+ const id = element?.id as string | undefined;
+
+ return {
+ props: {
+ className: 'slate-selectable',
+ onContextMenu: (event: React.MouseEvent) => {
+ if (!element || !path) return;
+
+ const { enableContextMenu } = getOptions();
+
+ if (!enableContextMenu) return;
+ if (editor.selection?.focus) {
+ const nodeEntry = getAboveNode(editor);
+
+ if (nodeEntry && Path.isCommon(path, nodeEntry[1])) {
+ const id = nodeEntry[0].id as string | undefined;
+ const isSelected = getOption('isSelected', id);
+ const isOpenAlways =
+ (event.target as HTMLElement).dataset?.plateOpenContextMenu ===
+ 'true';
+
+ /**
+ * When "block selected or is void or has openContextMenu props",
+ * right click can always open the context menu.
+ */
+ if (!isSelected && !isVoid(editor, nodeEntry[0]) && !isOpenAlways) {
+ return event.stopPropagation();
+ }
+ }
+ }
+ if (id) {
+ api.blockSelection.addSelectedRow(id, {
+ clear: !event?.shiftKey,
+ });
+ }
+ },
+ },
+ };
+};
diff --git a/packages/selection/src/react/hooks/useBlockSelected.ts b/packages/selection/src/react/hooks/useBlockSelected.ts
index c28da78d02..c0a18dacb9 100644
--- a/packages/selection/src/react/hooks/useBlockSelected.ts
+++ b/packages/selection/src/react/hooks/useBlockSelected.ts
@@ -6,7 +6,7 @@ export const useBlockSelected = (_id?: string) => {
const { useOption } = useEditorPlugin(BlockSelectionPlugin);
const { id } = useElement();
- const isBlockSelected = useOption('isSelected', id as string);
+ const isBlockSelected = useOption('isSelected', _id ?? (id as string));
return isBlockSelected;
};
diff --git a/packages/selection/src/react/hooks/useCursorOverlay.ts b/packages/selection/src/react/hooks/useCursorOverlay.ts
new file mode 100644
index 0000000000..ee580536c1
--- /dev/null
+++ b/packages/selection/src/react/hooks/useCursorOverlay.ts
@@ -0,0 +1,156 @@
+import React from 'react';
+
+import type { UnknownObject } from '@udecode/plate-common';
+import type { Range } from 'slate';
+
+import {
+ useEditorContainerRef,
+ useEditorRef,
+ useIsomorphicLayoutEffect,
+} from '@udecode/plate-common/react';
+
+import type { CursorOverlayState, CursorState, SelectionRect } from '../types';
+
+import { CursorOverlayPlugin } from '../CursorOverlayPlugin';
+import { getCursorOverlayState } from '../queries/getCursorOverlayState';
+import { getSelectionRects } from '../queries/getSelectionRects';
+import { useRefreshOnResize } from './useRefreshOnResize';
+
+export type UseCursorOverlayOptions = {
+ /**
+ * Minimum width of a selection rect.
+ *
+ * @default 1
+ */
+ minSelectionWidth?: number;
+
+ /**
+ * Whether to refresh the cursor overlay positions on container resize.
+ *
+ * @default true
+ */
+ refreshOnResize?: boolean;
+};
+
+export const FROZEN_EMPTY_ARRAY = Object.freeze(
+ []
+) as unknown as SelectionRect[];
+
+export const useCursorOverlay = ({
+ minSelectionWidth = 1,
+ refreshOnResize = true,
+}: UseCursorOverlayOptions = {}): {
+ cursors: CursorOverlayState[];
+ refresh: () => void;
+} => {
+ const editor = useEditorRef();
+ const containerRef = useEditorContainerRef();
+
+ const cursorStates = editor.useOption(
+ CursorOverlayPlugin,
+ 'cursors'
+ ) as Record>;
+
+ const selectionRectCache = React.useRef>(
+ new WeakMap()
+ );
+
+ const [selectionRects, setSelectionRects] = React.useState<
+ Record
+ >({});
+
+ const updateSelectionRects = React.useCallback(() => {
+ // We have a container ref but the ref is null => container
+ // isn't mounted to we can't calculate the selection rects.
+ if (!containerRef?.current) return;
+ if (!cursorStates) return;
+
+ let xOffset = 0;
+ let yOffset = 0;
+
+ if (containerRef) {
+ const contentRect = containerRef.current!.getBoundingClientRect();
+ xOffset = contentRect.x;
+ yOffset = contentRect.y;
+ yOffset -= containerRef.current.scrollTop;
+ }
+
+ let selectionRectsChanged =
+ Object.keys(selectionRects).length !== Object.keys(cursorStates).length;
+
+ const getCachedSelectionRects = ({
+ cursor,
+ }: {
+ cursor: CursorState;
+ }) => {
+ const range = cursor.selection;
+
+ if (!range) {
+ return FROZEN_EMPTY_ARRAY;
+ }
+
+ const cached = selectionRectCache.current.get(range);
+
+ if (cached) {
+ return cached;
+ }
+
+ const rects = getSelectionRects(editor, { range, xOffset, yOffset }).map(
+ (rect) => {
+ // Handle collapsed selection (cursor) positioning
+ if (rect.width < minSelectionWidth) {
+ return {
+ ...rect,
+ // Adjust left position to account for minimum width
+ left: rect.left - (minSelectionWidth - rect.width) / 2,
+ width: minSelectionWidth,
+ };
+ }
+
+ return rect;
+ }
+ );
+
+ selectionRectsChanged = true;
+ selectionRectCache.current.set(range, rects);
+
+ return rects;
+ };
+
+ const updated: Record = Object.fromEntries(
+ Object.entries(cursorStates).map(([key, cursor]) => [
+ key,
+ getCachedSelectionRects({
+ cursor,
+ }),
+ ])
+ );
+
+ if (selectionRectsChanged) {
+ setSelectionRects(updated);
+ }
+ }, [containerRef, cursorStates, editor, selectionRects, minSelectionWidth]);
+
+ // Update selection rects after paint
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ useIsomorphicLayoutEffect(() => {
+ updateSelectionRects();
+ });
+
+ const cursors = React.useMemo(
+ () =>
+ getCursorOverlayState({
+ cursors: cursorStates,
+ selectionRects,
+ }),
+ [cursorStates, selectionRects]
+ );
+
+ const { refresh } = useRefreshOnResize({
+ containerRef,
+ refreshOnResize,
+ selectionRectCache,
+ });
+
+ return { cursors, refresh };
+};
diff --git a/packages/selection/src/react/hooks/useRefreshOnResize.ts b/packages/selection/src/react/hooks/useRefreshOnResize.ts
new file mode 100644
index 0000000000..643834ea15
--- /dev/null
+++ b/packages/selection/src/react/hooks/useRefreshOnResize.ts
@@ -0,0 +1,46 @@
+import React from 'react';
+
+import type { Range } from 'slate';
+
+import type { SelectionRect } from '../types';
+
+import { useRequestReRender } from './useRequestReRender';
+
+export interface UseRefreshOnResizeOptions {
+ selectionRectCache: React.MutableRefObject>;
+ containerRef?: React.RefObject;
+ refreshOnResize?: boolean;
+}
+
+export const useRefreshOnResize = ({
+ containerRef,
+ refreshOnResize,
+ selectionRectCache,
+}: UseRefreshOnResizeOptions) => {
+ const requestReRender = useRequestReRender();
+
+ // Reset the selection rect cache and request re-render.
+ const refresh = React.useCallback(
+ (sync = false) => {
+ selectionRectCache.current = new WeakMap();
+ requestReRender(sync);
+ },
+ [requestReRender, selectionRectCache]
+ );
+
+ // Refresh on container resize
+ React.useEffect(() => {
+ if (!refreshOnResize || !containerRef?.current) {
+ return;
+ }
+
+ const resizeObserver = new ResizeObserver(() => refresh());
+ resizeObserver.observe(containerRef.current);
+
+ return () => resizeObserver.disconnect();
+ }, [containerRef, refresh, refreshOnResize]);
+
+ return {
+ refresh,
+ };
+};
diff --git a/packages/selection/src/react/hooks/useRequestReRender.ts b/packages/selection/src/react/hooks/useRequestReRender.ts
new file mode 100644
index 0000000000..59b290a048
--- /dev/null
+++ b/packages/selection/src/react/hooks/useRequestReRender.ts
@@ -0,0 +1,44 @@
+import React from 'react';
+
+export const useRequestReRender = () => {
+ const [, setUpdateCounter] = React.useState(0);
+ const animationFrameRef = React.useRef(null);
+
+ const requestReRender = React.useCallback((immediate = false) => {
+ if (animationFrameRef.current && !immediate) {
+ return;
+ }
+ if (!immediate) {
+ animationFrameRef.current = requestAnimationFrame(() => {
+ setUpdateCounter((state) => state + 1);
+ animationFrameRef.current = null;
+ });
+
+ return;
+ }
+ if (animationFrameRef.current) {
+ cancelAnimationFrame(animationFrameRef.current);
+ animationFrameRef.current = null;
+ }
+
+ setUpdateCounter((state) => state + 1);
+ }, []);
+
+ React.useEffect(() => {
+ if (animationFrameRef.current) {
+ cancelAnimationFrame(animationFrameRef.current);
+ animationFrameRef.current = null;
+ }
+ });
+
+ React.useEffect(
+ () => () => {
+ if (animationFrameRef.current) {
+ cancelAnimationFrame(animationFrameRef.current);
+ }
+ },
+ []
+ );
+
+ return requestReRender;
+};
diff --git a/packages/selection/src/react/hooks/useSelectionArea.ts b/packages/selection/src/react/hooks/useSelectionArea.ts
index 0df0598108..a5a75ff540 100644
--- a/packages/selection/src/react/hooks/useSelectionArea.ts
+++ b/packages/selection/src/react/hooks/useSelectionArea.ts
@@ -13,7 +13,11 @@ export const useSelectionArea = () => {
React.useEffect(() => {
const selection = new SelectionArea({
+ boundaries: `#${editor.uid}`,
+ container: `#${editor.uid}`,
document: window.document,
+ selectables: `#${editor.uid} .slate-selectable`,
+ selectionAreaClass: 'slate-selection-area',
...areaOptions,
})
.on('beforestart', () => {
diff --git a/packages/selection/src/react/index.ts b/packages/selection/src/react/index.ts
index 7401039991..aa54fc3dd8 100644
--- a/packages/selection/src/react/index.ts
+++ b/packages/selection/src/react/index.ts
@@ -4,8 +4,11 @@
export * from './BlockMenuPlugin';
export * from './BlockSelectionPlugin';
+export * from './CursorOverlayPlugin';
export * from './onKeyDownSelection';
+export * from './types';
export * from './components/index';
export * from './hooks/index';
+export * from './queries/index';
export * from './transforms/index';
export * from './utils/index';
diff --git a/packages/selection/src/react/queries/getCaretPosition.ts b/packages/selection/src/react/queries/getCaretPosition.ts
new file mode 100644
index 0000000000..3ccbddac0a
--- /dev/null
+++ b/packages/selection/src/react/queries/getCaretPosition.ts
@@ -0,0 +1,23 @@
+import { Range } from 'slate';
+
+import type { CaretPosition, SelectionRect } from '../types';
+
+/** Get the caret position of a range from selectionRects. */
+export const getCaretPosition = (
+ selectionRects: SelectionRect[],
+ range: Range
+): CaretPosition | null => {
+ const isCollapsed = range && Range.isCollapsed(range);
+ const isBackward = range && Range.isBackward(range);
+ const anchorRect = selectionRects[isBackward ? 0 : selectionRects.length - 1];
+
+ if (!anchorRect) {
+ return null;
+ }
+
+ return {
+ height: anchorRect.height,
+ left: anchorRect.left + (isBackward || isCollapsed ? 0 : anchorRect.width),
+ top: anchorRect.top,
+ };
+};
diff --git a/packages/selection/src/react/queries/getCursorOverlayState.ts b/packages/selection/src/react/queries/getCursorOverlayState.ts
new file mode 100644
index 0000000000..6460e4927d
--- /dev/null
+++ b/packages/selection/src/react/queries/getCursorOverlayState.ts
@@ -0,0 +1,33 @@
+import type { UnknownObject } from '@udecode/plate-common';
+
+import type { CursorOverlayState, CursorState, SelectionRect } from '../types';
+
+import { FROZEN_EMPTY_ARRAY } from '../hooks';
+import { getCaretPosition } from './getCaretPosition';
+
+/** Get cursor overlay state from selection rects. */
+export const getCursorOverlayState = <
+ TCursorData extends UnknownObject = UnknownObject,
+>({
+ cursors: cursorStates,
+ selectionRects,
+}: {
+ cursors: Record>;
+ selectionRects: Record;
+}): CursorOverlayState[] => {
+ if (!cursorStates) return [];
+
+ return Object.entries(cursorStates).map(([key, cursorState]) => {
+ const selection = cursorState?.selection ?? null;
+ const rects = selectionRects[key] ?? FROZEN_EMPTY_ARRAY;
+
+ const caretPosition = selection ? getCaretPosition(rects, selection) : null;
+
+ return {
+ ...cursorState,
+ caretPosition,
+ selection,
+ selectionRects: rects,
+ };
+ });
+};
diff --git a/packages/selection/src/react/queries/getSelectionRects.ts b/packages/selection/src/react/queries/getSelectionRects.ts
new file mode 100644
index 0000000000..278b22c40f
--- /dev/null
+++ b/packages/selection/src/react/queries/getSelectionRects.ts
@@ -0,0 +1,79 @@
+import { type TEditor, getNodeEntries, isText } from '@udecode/plate-common';
+import { toDOMNode, toDOMRange } from '@udecode/plate-common/react';
+import { Path, Range } from 'slate';
+
+import type { SelectionRect } from '../types';
+
+export const getSelectionRects = (
+ editor: TEditor,
+ {
+ range,
+ xOffset,
+ yOffset,
+ }: {
+ range: Range;
+ xOffset: number;
+ yOffset: number;
+ }
+): SelectionRect[] => {
+ const [start, end] = Range.edges(range);
+ const domRange = toDOMRange(editor, range);
+
+ if (!domRange) {
+ return [];
+ }
+
+ const selectionRects: SelectionRect[] = [];
+ const textEntries = getNodeEntries(editor, {
+ at: range,
+ match: isText,
+ });
+
+ for (const [textNode, textPath] of textEntries) {
+ const domNode = toDOMNode(editor, textNode);
+
+ // Fix: failed to execute 'selectNode' on 'Range': the given Node has no parent
+ if (!domNode?.parentElement) {
+ return [];
+ }
+
+ const isStartNode = Path.equals(textPath, start.path);
+ const isEndNode = Path.equals(textPath, end.path);
+
+ let clientRects: DOMRectList | null = null;
+
+ if (isStartNode || isEndNode) {
+ const nodeRange = document.createRange();
+
+ nodeRange.selectNode(domNode);
+
+ if (isStartNode) {
+ nodeRange.setStart(domRange.startContainer, domRange.startOffset);
+ }
+ if (isEndNode) {
+ nodeRange.setEnd(domRange.endContainer, domRange.endOffset);
+ }
+
+ clientRects = nodeRange.getClientRects();
+ } else {
+ clientRects = domNode.getClientRects();
+ }
+
+ for (let i = 0; i < clientRects.length; i++) {
+ const clientRect = clientRects.item(i);
+
+ if (!clientRect) {
+ continue;
+ }
+
+ selectionRects.push({
+ height: clientRect.height,
+ left: clientRect.left - xOffset,
+ top: clientRect.top - yOffset,
+ width: clientRect.width,
+ });
+ }
+ }
+
+ return selectionRects;
+};
diff --git a/packages/selection/src/react/queries/index.ts b/packages/selection/src/react/queries/index.ts
new file mode 100644
index 0000000000..e1b6e74d56
--- /dev/null
+++ b/packages/selection/src/react/queries/index.ts
@@ -0,0 +1,7 @@
+/**
+ * @file Automatically generated by barrelsby.
+ */
+
+export * from './getCaretPosition';
+export * from './getCursorOverlayState';
+export * from './getSelectionRects';
diff --git a/packages/selection/src/react/types.ts b/packages/selection/src/react/types.ts
new file mode 100644
index 0000000000..152735b2c3
--- /dev/null
+++ b/packages/selection/src/react/types.ts
@@ -0,0 +1,36 @@
+import type React from 'react';
+
+import type { UnknownObject } from '@udecode/plate-common';
+import type { Range } from 'slate';
+
+export type SelectionRect = {
+ height: number;
+ left: number;
+
+ top: number;
+ width: number;
+};
+
+export type CaretPosition = {
+ height: number;
+
+ left: number;
+ top: number;
+};
+
+export type CursorState = {
+ id: any;
+ selection: Range | null;
+ data?: TCursorData;
+};
+
+export interface CursorOverlayState>
+ extends CursorState {
+ caretPosition: CaretPosition | null;
+ selectionRects: SelectionRect[];
+}
+
+export type CursorData = {
+ selectionStyle?: React.CSSProperties;
+ style?: React.CSSProperties;
+};
diff --git a/packages/slash-command/package.json b/packages/slash-command/package.json
index a35814bd84..447ac92795 100644
--- a/packages/slash-command/package.json
+++ b/packages/slash-command/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/slate-react/package.json b/packages/slate-react/package.json
index 49f80a3bff..1e96024e12 100644
--- a/packages/slate-react/package.json
+++ b/packages/slate-react/package.json
@@ -51,7 +51,7 @@
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
"slate-history": ">=0.93.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/slate-react/src/index.ts b/packages/slate-react/src/index.ts
index f57ee0ffbf..5c42c83353 100644
--- a/packages/slate-react/src/index.ts
+++ b/packages/slate-react/src/index.ts
@@ -3,5 +3,5 @@
*/
export * from './react-editor/index';
-export type * from './types/index';
+export * from './types/index';
export * from './utils/index';
diff --git a/packages/slate-react/src/react-editor/hasEditorDOMNode.ts b/packages/slate-react/src/react-editor/hasEditorDOMNode.ts
index 827b5b681d..acef45255a 100644
--- a/packages/slate-react/src/react-editor/hasEditorDOMNode.ts
+++ b/packages/slate-react/src/react-editor/hasEditorDOMNode.ts
@@ -1,5 +1,5 @@
import type { TEditor } from '@udecode/slate';
-import type { DOMNode } from 'slate-react/dist/utils/dom';
+import type { DOMNode } from 'slate-dom';
import { ReactEditor } from 'slate-react';
diff --git a/packages/slate-react/src/react-editor/toSlateNode.ts b/packages/slate-react/src/react-editor/toSlateNode.ts
index 6dc29b8308..497b73fcaa 100644
--- a/packages/slate-react/src/react-editor/toSlateNode.ts
+++ b/packages/slate-react/src/react-editor/toSlateNode.ts
@@ -1,5 +1,5 @@
import type { TEditor, TNode } from '@udecode/slate';
-import type { DOMNode } from 'slate-react/dist/utils/dom';
+import type { DOMNode } from 'slate-dom';
import { ReactEditor } from 'slate-react';
diff --git a/packages/slate-react/src/react-editor/toSlatePoint.ts b/packages/slate-react/src/react-editor/toSlatePoint.ts
index 1b2076a057..445d06bf0b 100644
--- a/packages/slate-react/src/react-editor/toSlatePoint.ts
+++ b/packages/slate-react/src/react-editor/toSlatePoint.ts
@@ -1,5 +1,5 @@
import type { TEditor } from '@udecode/slate';
-import type { DOMPoint } from 'slate-react/dist/utils/dom';
+import type { DOMPoint } from 'slate-dom';
import { ReactEditor } from 'slate-react';
diff --git a/packages/slate-react/src/types/index.ts b/packages/slate-react/src/types/index.ts
index aecf9aefa5..693b3e51d8 100644
--- a/packages/slate-react/src/types/index.ts
+++ b/packages/slate-react/src/types/index.ts
@@ -2,7 +2,7 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './SlateProps';
-export type * from './TEditableProps';
-export type * from './TRenderElementProps';
-export type * from './TRenderLeafProps';
+export * from './SlateProps';
+export * from './TEditableProps';
+export * from './TRenderElementProps';
+export * from './TRenderLeafProps';
diff --git a/packages/slate/src/index.ts b/packages/slate/src/index.ts
index 33ca390098..0b47d6192a 100644
--- a/packages/slate/src/index.ts
+++ b/packages/slate/src/index.ts
@@ -7,5 +7,5 @@ export * from './interfaces/index';
export * from './queries/index';
export * from './slate-history/index';
export * from './transforms/index';
-export type * from './types/index';
+export * from './types/index';
export * from './utils/index';
diff --git a/packages/slate/src/interfaces/editor/index.ts b/packages/slate/src/interfaces/editor/index.ts
index 06a9715463..d832860676 100644
--- a/packages/slate/src/interfaces/editor/index.ts
+++ b/packages/slate/src/interfaces/editor/index.ts
@@ -2,7 +2,7 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './TEditor';
+export * from './TEditor';
export * from './addMark';
export * from './createPathRef';
export * from './createPointRef';
diff --git a/packages/slate/src/interfaces/element/index.ts b/packages/slate/src/interfaces/element/index.ts
index bebe80b9fb..2e7c2c9cc8 100644
--- a/packages/slate/src/interfaces/element/index.ts
+++ b/packages/slate/src/interfaces/element/index.ts
@@ -2,7 +2,7 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './TElement';
+export * from './TElement';
export * from './elementMatches';
export * from './isElement';
export * from './isElementList';
diff --git a/packages/slate/src/interfaces/node/index.ts b/packages/slate/src/interfaces/node/index.ts
index aeddc4c67d..8f02e66c75 100644
--- a/packages/slate/src/interfaces/node/index.ts
+++ b/packages/slate/src/interfaces/node/index.ts
@@ -2,10 +2,10 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './TAncestor';
+export * from './TAncestor';
export * from './TDescendant';
-export type * from './TNode';
-export type * from './TNodeEntry';
+export * from './TNode';
+export * from './TNodeEntry';
export * from './getCommonNode';
export * from './getNode';
export * from './getNodeAncestor';
diff --git a/packages/slate/src/interfaces/text/index.ts b/packages/slate/src/interfaces/text/index.ts
index f434b62baa..72c0a7fdc6 100644
--- a/packages/slate/src/interfaces/text/index.ts
+++ b/packages/slate/src/interfaces/text/index.ts
@@ -2,7 +2,7 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './TText';
+export * from './TText';
export * from './isText';
export * from './isTextList';
export * from './textEquals';
diff --git a/packages/slate/src/types/index.ts b/packages/slate/src/types/index.ts
index 44a9df15ec..ba15677321 100644
--- a/packages/slate/src/types/index.ts
+++ b/packages/slate/src/types/index.ts
@@ -2,8 +2,8 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './NodeMatchOption';
-export type * from './QueryEditorOptions';
-export type * from './QueryNodeOptions';
-export type * from './TOperation';
-export type * from './interfaces';
+export * from './NodeMatchOption';
+export * from './QueryEditorOptions';
+export * from './QueryNodeOptions';
+export * from './TOperation';
+export * from './interfaces';
diff --git a/packages/suggestion/package.json b/packages/suggestion/package.json
index 308aa96e75..0c8513147d 100644
--- a/packages/suggestion/package.json
+++ b/packages/suggestion/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/suggestion/src/lib/index.ts b/packages/suggestion/src/lib/index.ts
index 96bd97005d..1db7f5dc5f 100644
--- a/packages/suggestion/src/lib/index.ts
+++ b/packages/suggestion/src/lib/index.ts
@@ -4,7 +4,7 @@
export * from './BaseSuggestionPlugin';
export * from './diffToSuggestions';
-export type * from './types';
+export * from './types';
export * from './withSuggestion';
export * from './queries/index';
export * from './transforms/index';
diff --git a/packages/tabbable/package.json b/packages/tabbable/package.json
index 6a46b3be88..50843d4131 100644
--- a/packages/tabbable/package.json
+++ b/packages/tabbable/package.json
@@ -60,9 +60,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/tabbable/src/lib/index.ts b/packages/tabbable/src/lib/index.ts
index ac71133cf1..06fe22e7bb 100644
--- a/packages/tabbable/src/lib/index.ts
+++ b/packages/tabbable/src/lib/index.ts
@@ -4,4 +4,4 @@
export * from './BaseTabbablePlugin';
export * from './findTabDestination';
-export type * from './types';
+export * from './types';
diff --git a/packages/table/package.json b/packages/table/package.json
index 25c7220a9c..212200fb56 100644
--- a/packages/table/package.json
+++ b/packages/table/package.json
@@ -61,8 +61,9 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/table/src/lib/index.ts b/packages/table/src/lib/index.ts
index e4f839fa48..0367e7ea8f 100644
--- a/packages/table/src/lib/index.ts
+++ b/packages/table/src/lib/index.ts
@@ -4,7 +4,7 @@
export * from './BaseTablePlugin';
export * from './constants';
-export type * from './types';
+export * from './types';
export * from './withNormalizeTable';
export * from './withTable';
export * from './merge/index';
diff --git a/packages/table/src/lib/withNormalizeTable.ts b/packages/table/src/lib/withNormalizeTable.ts
index afbe14f86b..63d1e5bcfc 100644
--- a/packages/table/src/lib/withNormalizeTable.ts
+++ b/packages/table/src/lib/withNormalizeTable.ts
@@ -32,6 +32,18 @@ export const withNormalizeTable: ExtendEditor = ({
if (isElement(node)) {
if (node.type === type) {
+ if (
+ !node.children.some(
+ (child) =>
+ isElement(child) &&
+ child.type === editor.getType(BaseTableRowPlugin)
+ )
+ ) {
+ editor.removeNodes({ at: path });
+
+ return;
+ }
+
const tableEntry = getBlockAbove(editor, {
at: path,
match: { type: type },
diff --git a/packages/test-utils/src/hyperscript/index.ts b/packages/test-utils/src/hyperscript/index.ts
deleted file mode 100644
index 9d85fa6ab7..0000000000
--- a/packages/test-utils/src/hyperscript/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * @file Automatically generated by barrelsby.
- */
-
-export * from './creators';
-export * from './tokens';
diff --git a/packages/test-utils/src/index.ts b/packages/test-utils/src/index.ts
index 1fff2d9da5..58e031f637 100644
--- a/packages/test-utils/src/index.ts
+++ b/packages/test-utils/src/index.ts
@@ -2,7 +2,5 @@
* @file Automatically generated by barrelsby.
*/
-export * from './createDataTransfer';
export * from './getHtmlDocument';
export * from './jsx';
-export * from './hyperscript/index';
diff --git a/packages/test-utils/src/createDataTransfer.ts b/packages/test-utils/src/internals/createDataTransfer.ts
similarity index 100%
rename from packages/test-utils/src/createDataTransfer.ts
rename to packages/test-utils/src/internals/createDataTransfer.ts
diff --git a/packages/test-utils/src/hyperscript/creators.ts b/packages/test-utils/src/internals/creators.ts
similarity index 69%
rename from packages/test-utils/src/hyperscript/creators.ts
rename to packages/test-utils/src/internals/creators.ts
index 5794fc6de8..6aa9695aec 100644
--- a/packages/test-utils/src/hyperscript/creators.ts
+++ b/packages/test-utils/src/internals/creators.ts
@@ -5,7 +5,6 @@ import {
Node,
Range,
Text,
- createEditor as makeEditor,
} from 'slate';
import {
@@ -178,59 +177,61 @@ export const createText = (
};
/** Create a top-level `Editor` object. */
-export const createEditor = (
- tagName: string,
- attributes: Record,
- children: any[]
-): Editor => {
- const otherChildren: any[] = [];
- let selectionChild: Range | undefined;
+export const createEditor =
+ (makeEditor: () => Editor) =>
+ (
+ tagName: string,
+ attributes: Record,
+ children: any[]
+ ): Editor => {
+ const otherChildren: any[] = [];
+ let selectionChild: Range | undefined;
+
+ for (const child of children) {
+ if (Range.isRange(child)) {
+ selectionChild = child;
+ } else {
+ otherChildren.push(child);
+ }
+ }
- for (const child of children) {
- if (Range.isRange(child)) {
- selectionChild = child;
- } else {
- otherChildren.push(child);
+ const descendants = resolveDescendants(otherChildren);
+ const selection: Partial = {};
+ const editor = makeEditor();
+ Object.assign(editor, attributes);
+ editor.children = descendants;
+
+ // Search the document's texts to see if any of them have tokens associated
+ // that need incorporated into the selection.
+ for (const [node, path] of Node.texts(editor)) {
+ const anchor = getAnchorOffset(node);
+ const focus = getFocusOffset(node);
+
+ if (anchor != null) {
+ const [offset] = anchor;
+ selection.anchor = { offset, path };
+ }
+ if (focus != null) {
+ const [offset] = focus;
+ selection.focus = { offset, path };
+ }
}
- }
- const descendants = resolveDescendants(otherChildren);
- const selection: Partial = {};
- const editor = makeEditor();
- Object.assign(editor, attributes);
- editor.children = descendants;
-
- // Search the document's texts to see if any of them have tokens associated
- // that need incorporated into the selection.
- for (const [node, path] of Node.texts(editor)) {
- const anchor = getAnchorOffset(node);
- const focus = getFocusOffset(node);
-
- if (anchor != null) {
- const [offset] = anchor;
- selection.anchor = { offset, path };
+ if (selection.anchor && !selection.focus) {
+ throw new Error(
+ `Slate hyperscript ranges must have both \` \` and \` \` defined if one is defined, but you only defined \` \`. For collapsed selections, use \` \` instead.`
+ );
}
- if (focus != null) {
- const [offset] = focus;
- selection.focus = { offset, path };
+ if (!selection.anchor && selection.focus) {
+ throw new Error(
+ `Slate hyperscript ranges must have both \` \` and \` \` defined if one is defined, but you only defined \` \`. For collapsed selections, use \` \` instead.`
+ );
+ }
+ if (selectionChild != null) {
+ editor.selection = selectionChild;
+ } else if (Range.isRange(selection)) {
+ editor.selection = selection;
}
- }
-
- if (selection.anchor && !selection.focus) {
- throw new Error(
- `Slate hyperscript ranges must have both \` \` and \` \` defined if one is defined, but you only defined \` \`. For collapsed selections, use \` \` instead.`
- );
- }
- if (!selection.anchor && selection.focus) {
- throw new Error(
- `Slate hyperscript ranges must have both \` \` and \` \` defined if one is defined, but you only defined \` \`. For collapsed selections, use \` \` instead.`
- );
- }
- if (selectionChild != null) {
- editor.selection = selectionChild;
- } else if (Range.isRange(selection)) {
- editor.selection = selection;
- }
- return editor;
-};
+ return editor;
+ };
diff --git a/packages/test-utils/src/internals/hyperscript.ts b/packages/test-utils/src/internals/hyperscript.ts
new file mode 100644
index 0000000000..02bc9e2a0f
--- /dev/null
+++ b/packages/test-utils/src/internals/hyperscript.ts
@@ -0,0 +1,148 @@
+import { type Element, createEditor as makeEditor } from 'slate';
+
+import {
+ createAnchor,
+ createCursor,
+ createEditor,
+ createElement,
+ createFocus,
+ createFragment,
+ createSelection,
+ createText,
+} from './creators';
+
+function isPlainObject(value: unknown): value is Record {
+ return (
+ typeof value === 'object' &&
+ value !== null &&
+ Object.getPrototypeOf(value) === Object.prototype
+ );
+}
+
+/** The default creators for Slate objects. */
+
+const DEFAULT_CREATORS = {
+ anchor: createAnchor,
+ cursor: createCursor,
+ editor: createEditor(makeEditor),
+ element: createElement,
+ focus: createFocus,
+ fragment: createFragment,
+ selection: createSelection,
+ text: createText,
+};
+
+/**
+ * `HyperscriptCreators` are dictionaries of `HyperscriptCreator` functions
+ * keyed by tag name.
+ */
+
+type HyperscriptCreators = Record<
+ string,
+ (tagName: string, attributes: Record, children: any[]) => T
+>;
+
+/**
+ * `HyperscriptShorthands` are dictionaries of properties applied to specific
+ * kind of object, keyed by tag name. They allow you to easily define custom
+ * hyperscript tags for your domain.
+ */
+
+type HyperscriptShorthands = Record>;
+
+/** Create a Slate hyperscript function with `options`. */
+
+const createHyperscript = (
+ options: {
+ creators?: HyperscriptCreators;
+ elements?: HyperscriptShorthands;
+ } = {}
+) => {
+ const { elements = {} } = options;
+ const elementCreators = normalizeElements(elements);
+ const creators = {
+ ...DEFAULT_CREATORS,
+ ...elementCreators,
+ ...options.creators,
+ };
+
+ const jsx = createFactory(creators);
+
+ return jsx;
+};
+
+/** Create a Slate hyperscript function with `options`. */
+
+const createFactory = (creators: T) => {
+ const jsx = (
+ tagName: S,
+ attributes?: object,
+ ...children: any[]
+ ): ReturnType => {
+ for (const key in attributes) {
+ if (key.startsWith('__')) {
+ delete (attributes as any)[key];
+ }
+ }
+
+ const creator = creators[tagName];
+
+ if (!creator) {
+ throw new Error(`No hyperscript creator found for tag: <${tagName}>`);
+ }
+ if (attributes == null) {
+ attributes = {};
+ }
+ if (!isPlainObject(attributes)) {
+ children = [attributes].concat(children);
+ attributes = {};
+ }
+
+ children = children.filter(Boolean).flat();
+ const ret = creator(tagName, attributes, children);
+
+ return ret;
+ };
+
+ return jsx;
+};
+
+/** Normalize a dictionary of element shorthands into creator functions. */
+
+const normalizeElements = (elements: HyperscriptShorthands) => {
+ const creators: HyperscriptCreators = {};
+
+ for (const tagName in elements) {
+ const props = elements[tagName];
+
+ if (typeof props !== 'object') {
+ throw new TypeError(
+ `Properties specified for a hyperscript shorthand should be an object, but for the custom element <${tagName}> tag you passed: ${props}`
+ );
+ }
+
+ creators[tagName] = (
+ tagName: string,
+ attributes: Record,
+ children: any[]
+ ) => {
+ for (const key in attributes) {
+ if (key.startsWith('__')) {
+ delete attributes[key];
+ }
+ }
+
+ const el = createElement(
+ 'element',
+ { ...props, ...attributes },
+ children
+ );
+
+ return el;
+ };
+ }
+
+ return creators;
+};
+
+export { createHyperscript };
diff --git a/packages/test-utils/src/hyperscript/tokens.ts b/packages/test-utils/src/internals/tokens.ts
similarity index 100%
rename from packages/test-utils/src/hyperscript/tokens.ts
rename to packages/test-utils/src/internals/tokens.ts
diff --git a/packages/test-utils/src/jsx.ts b/packages/test-utils/src/jsx.ts
index 12554987c7..c28b68109d 100644
--- a/packages/test-utils/src/jsx.ts
+++ b/packages/test-utils/src/jsx.ts
@@ -1,12 +1,12 @@
/* eslint-disable prettier/prettier */
-import type { HyperscriptShorthands } from 'slate-hyperscript/dist/hyperscript';
import {
- createHyperscript,
+ type HyperscriptShorthands,
createText as createTestText,
} from 'slate-hyperscript';
-import { createText } from './hyperscript/creators';
+import { createText } from './internals/creators';
+import { createHyperscript } from './internals/hyperscript';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
@@ -82,6 +82,7 @@ const elements: HyperscriptShorthands = {
hvideo: { children: voidChildren, type: 'video' },
};
+
export const jsx = createHyperscript({
creators: {
htext: createTestText,
diff --git a/packages/toggle/package.json b/packages/toggle/package.json
index e4b9d5a684..c794cf51f2 100644
--- a/packages/toggle/package.json
+++ b/packages/toggle/package.json
@@ -62,9 +62,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/trailing-block/package.json b/packages/trailing-block/package.json
index 66f895c9dd..e158a51152 100644
--- a/packages/trailing-block/package.json
+++ b/packages/trailing-block/package.json
@@ -51,9 +51,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index 07604d5d11..0b6a7c84e8 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -11,4 +11,4 @@ export * from './isUrl';
export * from './mergeProps';
export * from './sanitizeUrl';
export * from './type-utils';
-export type * from './types/index';
+export * from './types/index';
diff --git a/packages/utils/src/types/index.ts b/packages/utils/src/types/index.ts
index d91df8d776..d6b5c76126 100644
--- a/packages/utils/src/types/index.ts
+++ b/packages/utils/src/types/index.ts
@@ -2,8 +2,8 @@
* @file Automatically generated by barrelsby.
*/
-export type * from './AnyObject';
-export type * from './Deep';
-export type * from './FunctionProperties';
-export type * from './WithOptional';
-export type * from './types';
+export * from './AnyObject';
+export * from './Deep';
+export * from './FunctionProperties';
+export * from './WithOptional';
+export * from './types';
diff --git a/packages/yjs/package.json b/packages/yjs/package.json
index 4792f01194..32a89c8988 100644
--- a/packages/yjs/package.json
+++ b/packages/yjs/package.json
@@ -63,9 +63,10 @@
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"slate": ">=0.103.0",
+ "slate-dom": ">=0.111.0",
"slate-history": ">=0.93.0",
"slate-hyperscript": ">=0.66.0",
- "slate-react": ">=0.108.0"
+ "slate-react": ">=0.111.0"
},
"publishConfig": {
"access": "public"
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
index 1aaf7d7b94..3c102575bf 100644
--- a/tailwind.config.cjs
+++ b/tailwind.config.cjs
@@ -7,6 +7,7 @@ module.exports = {
darkMode: ['class'],
plugins: [
require('tailwindcss-animate'),
+ require('tailwind-scrollbar-hide'),
require('@tailwindcss/typography'),
plugin(({ addVariant }) => {
addVariant('all', '& *');
@@ -88,6 +89,21 @@ module.exports = {
to: { height: '0' },
},
},
+ screens: {
+ /**
+ * Matches devices where the primary pointing device is capable of
+ * hovering conveniently. Usage: main-hover:group-hover:bg-red-500 See:
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover
+ *
+ * On iOS devices, buttons inside a .group element that contains
+ * descendent elements with `group-hover:` CSS rules require two taps to
+ * click. As a workaround, we disable these rules on devices that cannot
+ * conveniently hover using `main-hover:`.
+ */
+ 'main-hover': {
+ raw: '(hover: hover)',
+ },
+ },
},
},
};
diff --git a/turbo.json b/turbo.json
index fd800b0ce0..47abf48a9d 100644
--- a/turbo.json
+++ b/turbo.json
@@ -56,7 +56,7 @@
},
"test": {
"dependsOn": [],
- "outputs": ["jest.config.cjs"]
+ "outputs": []
},
"test:watch": {
"dependsOn": [],
diff --git a/yarn.lock b/yarn.lock
index 44e6a8743a..9d992886cb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6205,9 +6205,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6221,9 +6222,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6238,9 +6240,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6257,9 +6260,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6273,9 +6277,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6289,9 +6294,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6305,9 +6311,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6321,9 +6328,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6338,9 +6346,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6357,9 +6366,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6374,9 +6384,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6390,9 +6401,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6407,9 +6419,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6429,9 +6442,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6460,9 +6474,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6479,13 +6494,14 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
-"@udecode/plate-cursor@workspace:^, @udecode/plate-cursor@workspace:packages/cursor":
+"@udecode/plate-cursor@workspace:packages/cursor":
version: 0.0.0-use.local
resolution: "@udecode/plate-cursor@workspace:packages/cursor"
dependencies:
@@ -6495,9 +6511,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6529,9 +6546,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6549,9 +6567,10 @@ __metadata:
react-dnd-html5-backend: ">=14.0.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6571,9 +6590,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6589,9 +6609,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6606,9 +6627,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6622,9 +6644,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6640,9 +6663,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6657,9 +6681,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6673,9 +6698,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6689,9 +6715,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6705,9 +6732,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6723,9 +6751,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6742,9 +6771,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6758,9 +6788,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6775,9 +6806,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6791,9 +6823,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6807,9 +6840,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6823,9 +6857,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6841,9 +6876,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6859,9 +6895,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6871,6 +6908,7 @@ __metadata:
dependencies:
"@udecode/plate-common": "workspace:^"
lodash: "npm:^4.17.21"
+ remark-gfm: "npm:4.0.0"
remark-parse: "npm:^9.0.0"
unified: "npm:^11.0.5"
peerDependencies:
@@ -6878,9 +6916,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6896,9 +6935,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6913,9 +6953,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6930,9 +6971,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6947,9 +6989,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6964,9 +7007,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6981,9 +7025,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -6997,9 +7042,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7013,9 +7059,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7029,9 +7076,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7046,9 +7094,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7063,9 +7112,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7081,9 +7131,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7098,9 +7149,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7116,8 +7168,9 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7143,9 +7196,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7159,9 +7213,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7200,9 +7255,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7256,9 +7312,10 @@ __metadata:
react: ">=16.8.0"
react-dom: ">=16.8.0"
slate: ">=0.103.0"
+ slate-dom: ">=0.111.0"
slate-history: ">=0.93.0"
slate-hyperscript: ">=0.66.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -7296,7 +7353,7 @@ __metadata:
react-dom: ">=16.8.0"
slate: ">=0.103.0"
slate-history: ">=0.93.0"
- slate-react: ">=0.108.0"
+ slate-react: ">=0.111.0"
languageName: unknown
linkType: soft
@@ -16987,10 +17044,11 @@ __metadata:
react-test-renderer: "npm:18.3.1"
rimraf: "npm:^6.0.1"
shadcx: "workspace:^"
- slate: "npm:0.103.0"
- slate-history: "npm:0.109.0"
+ slate: "npm:0.110.2"
+ slate-dom: "npm:0.111.0"
+ slate-history: "npm:0.110.3"
slate-hyperscript: "npm:0.100.0"
- slate-react: "npm:0.110.1"
+ slate-react: "npm:0.111.0"
slate-test-utils: "npm:1.3.2"
tailwindcss: "npm:^3.4.11"
ts-jest: "npm:^29.2.5"
@@ -18300,7 +18358,7 @@ __metadata:
languageName: node
linkType: hard
-"remark-gfm@npm:^4.0.0":
+"remark-gfm@npm:4.0.0, remark-gfm@npm:^4.0.0":
version: 4.0.0
resolution: "remark-gfm@npm:4.0.0"
dependencies:
@@ -19183,14 +19241,31 @@ __metadata:
languageName: node
linkType: hard
-"slate-history@npm:0.109.0":
- version: 0.109.0
- resolution: "slate-history@npm:0.109.0"
+"slate-dom@npm:0.111.0":
+ version: 0.111.0
+ resolution: "slate-dom@npm:0.111.0"
+ dependencies:
+ "@juggle/resize-observer": "npm:^3.4.0"
+ direction: "npm:^1.0.4"
+ is-hotkey: "npm:^0.2.0"
+ is-plain-object: "npm:^5.0.0"
+ lodash: "npm:^4.17.21"
+ scroll-into-view-if-needed: "npm:^3.1.0"
+ tiny-invariant: "npm:1.3.1"
+ peerDependencies:
+ slate: ">=0.99.0"
+ checksum: 10c0/e803f154f89302b48bb344720560442f631e0a56468243c8d256ca909bdd10ea7afb1ad5637af8f775d0409d1e7c44faa4d0640ce8e30731a3657e52d3a9a55b
+ languageName: node
+ linkType: hard
+
+"slate-history@npm:0.110.3":
+ version: 0.110.3
+ resolution: "slate-history@npm:0.110.3"
dependencies:
is-plain-object: "npm:^5.0.0"
peerDependencies:
slate: ">=0.65.3"
- checksum: 10c0/70c97de22100307211ca9d647bc4f775899388d1cbab800a26557ef91be4d894bbe51ddd2542e57137713e95a360e41f05af61d90ef9e14b920e19fc2cf7a72d
+ checksum: 10c0/cd427263daa257840598118d9f2e7a5d239640505f30a0024b61f0491b0a70a41209a27662bf1adb65f60b4aa482c00d44356f89f0360ba5ed63a37e17534a6f
languageName: node
linkType: hard
@@ -19205,9 +19280,9 @@ __metadata:
languageName: node
linkType: hard
-"slate-react@npm:0.110.1":
- version: 0.110.1
- resolution: "slate-react@npm:0.110.1"
+"slate-react@npm:0.111.0":
+ version: 0.111.0
+ resolution: "slate-react@npm:0.111.0"
dependencies:
"@juggle/resize-observer": "npm:^3.4.0"
direction: "npm:^1.0.4"
@@ -19220,7 +19295,8 @@ __metadata:
react: ">=18.2.0"
react-dom: ">=18.2.0"
slate: ">=0.99.0"
- checksum: 10c0/270ac3068f65f2c5e12e209a8ea8b73048c1d8a7a879c9fcd94e917a773332e845a56f036e1c4cea516a5334bacebdd0a73422209d4fb0ef4110ae5226da5cf4
+ slate-dom: ">=0.110.2"
+ checksum: 10c0/9228ece95538b9286709ed08fe8d6f5b4669daf83655ab3eca93953f4c2eb8109ff7ba1af74561f6bb800dacbc41514cfc034888df020ac906cd285164f6735e
languageName: node
linkType: hard
@@ -19243,14 +19319,14 @@ __metadata:
languageName: node
linkType: hard
-"slate@npm:0.103.0":
- version: 0.103.0
- resolution: "slate@npm:0.103.0"
+"slate@npm:0.110.2":
+ version: 0.110.2
+ resolution: "slate@npm:0.110.2"
dependencies:
immer: "npm:^10.0.3"
is-plain-object: "npm:^5.0.0"
tiny-warning: "npm:^1.0.3"
- checksum: 10c0/5cde24650d71fb449382305c082310404560a73135510fc3d83bae680c5fc6e1db18347a58186f63efbc3342fd4ff4e447c134301f48683cdef312c87988ce0c
+ checksum: 10c0/90ed1b3c92898ccd4b3cb33216797acfb6eacbc2e60c7b8d8af4f02305195c3832a8cddb4651b10c4beb1da122bfaa42bb748e6464d75c8bfd545f017297041c
languageName: node
linkType: hard
@@ -19965,6 +20041,13 @@ __metadata:
languageName: node
linkType: hard
+"tailwind-scrollbar-hide@npm:1.1.7":
+ version: 1.1.7
+ resolution: "tailwind-scrollbar-hide@npm:1.1.7"
+ checksum: 10c0/1027ca724c51a43da9a9a9f730f707652bcaded6f94d82fd445e349ee19bd34d8c1312e3e075193ec89c0524d824e716a06d646ca757913f4df0f4f5faec8fe4
+ languageName: node
+ linkType: hard
+
"tailwindcss-animate@npm:^1.0.7":
version: 1.0.7
resolution: "tailwindcss-animate@npm:1.0.7"
@@ -21859,7 +21942,6 @@ __metadata:
"@udecode/plate-common": "workspace:^"
"@udecode/plate-core": "workspace:^"
"@udecode/plate-csv": "workspace:^"
- "@udecode/plate-cursor": "workspace:^"
"@udecode/plate-date": "workspace:^"
"@udecode/plate-diff": "workspace:^"
"@udecode/plate-dnd": "workspace:^"
@@ -21947,14 +22029,16 @@ __metadata:
rimraf: "npm:^6.0.1"
sass: "npm:^1.78.0"
shiki: "npm:^1.17.5"
- slate: "npm:0.103.0"
- slate-history: "npm:0.109.0"
+ slate: "npm:0.110.2"
+ slate-dom: "npm:0.111.0"
+ slate-history: "npm:0.110.3"
slate-hyperscript: "npm:0.100.0"
- slate-react: "npm:0.110.1"
+ slate-react: "npm:0.111.0"
slate-test-utils: "npm:1.3.2"
sonner: "npm:^1.5.0"
swr: "npm:2.2.6-beta.3"
tailwind-merge: "npm:^2.5.2"
+ tailwind-scrollbar-hide: "npm:1.1.7"
tailwindcss: "npm:^3.4.11"
tailwindcss-animate: "npm:^1.0.7"
ts-morph: "npm:^22.0.0"