Skip to content

Commit

Permalink
Merge pull request #4038 from udecode/node-wrapper-type
Browse files Browse the repository at this point in the history
refactor: update types and docs of aboveNodes and belowNodes
  • Loading branch information
zbeyens authored Jan 27, 2025
2 parents 7069fda + 2740b76 commit 25ab000
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 46 deletions.
8 changes: 8 additions & 0 deletions .changeset/thin-pears-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@udecode/plate-indent-list': patch
'@udecode/plate-toggle': patch
'@udecode/plate-core': patch
'@udecode/plate-ai': patch
---

Update types and docs of `aboveNodes` and `belowNodes`
8 changes: 4 additions & 4 deletions apps/www/content/docs/cn/api/core/plate-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ HTML React 序列化器配置。
<APISubListItem parent="render" name="aboveEditable" type="Component" optional>
`Editable` 组件上方但在 `Slate` 包装器内渲染组件。
</APISubListItem>
<APISubListItem parent="render" name="aboveNodes" type="Component" optional>
在所有其他插件的 `node` 组件上方渲染组件
<APISubListItem parent="render" name="aboveNodes" type="RenderNodeWrapper<WithAnyKey<C>>" optional>
创建一个函数,该函数为所有其他插件的 `node` React节点生成父节点
</APISubListItem>
<APISubListItem parent="render" name="aboveSlate" type="React.FC<{ children: React.ReactNode }>" optional>
`Slate` 包装器上方渲染组件。
Expand All @@ -183,8 +183,8 @@ HTML React 序列化器配置。
<APISubListItem parent="render" name="beforeEditable" type="EditableSiblingComponent" optional>
`Editable` 组件前渲染组件。
</APISubListItem>
<APISubListItem parent="render" name="belowNodes" type="NodeWrapperComponent<WithAnyKey<C>>" optional>
在所有其他插件的 `node` 组件下方但在其 `children` 上方渲染组件
<APISubListItem parent="render" name="belowNodes" type="RenderNodeWrapper<WithAnyKey<C>>" optional>
创建一个函数,该函数为所有其他插件的 `node` React节点和其`children`React节点之间生成一个React节点
</APISubListItem>
<APISubListItem parent="render" name="node" type="NodeComponent" optional>
渲染节点组件。
Expand Down
8 changes: 4 additions & 4 deletions apps/www/content/docs/en/api/core/plate-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ Defines how the plugin renders components.
<APISubListItem parent="render" name="aboveEditable" type="Component" optional>
Component rendered above the Editable component but inside the Slate wrapper.
</APISubListItem>
<APISubListItem parent="render" name="aboveNodes" type="Component" optional>
Component rendered above all other plugins' node components.
<APISubListItem parent="render" name="aboveNodes" type="RenderNodeWrapper<WithAnyKey<C>>" optional>
Create a function that generates a parent React node for all other plugins' node components.
</APISubListItem>
<APISubListItem parent="render" name="aboveSlate" type="Component" optional>
Component rendered above the Slate wrapper.
Expand All @@ -162,8 +162,8 @@ Renders a component after the Editable component.
<APISubListItem parent="render" name="beforeEditable" type="EditableSiblingComponent" optional>
Renders a component before the Editable component.
</APISubListItem>
<APISubListItem parent="render" name="belowNodes" type="NodeWrapperComponent<WithAnyKey<C>>" optional>
Renders a component below all other plugins' node components, but above their children.
<APISubListItem parent="render" name="belowNodes" type="RenderNodeWrapper<WithAnyKey<C>>" optional>
Create a function that generates a React node below all other plugins' node React node, but above their children.
</APISubListItem>
<APISubListItem parent="render" name="node" type="NodeComponent" optional>
Renders the node component.
Expand Down
4 changes: 2 additions & 2 deletions apps/www/src/registry/default/plate-ui/draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import React, { useMemo } from 'react';
import { cn, withRef } from '@udecode/cn';
import { isType } from '@udecode/plate';
import {
type NodeWrapperComponent,
type PlateRenderElementProps,
type RenderNodeWrapper,
MemoizedChildren,
ParagraphPlugin,
useEditorPlugin,
Expand Down Expand Up @@ -46,7 +46,7 @@ const UNDRAGGABLE_KEYS = [
TableCellPlugin.key,
];

export const DraggableAboveNodes: NodeWrapperComponent = (props) => {
export const DraggableAboveNodes: RenderNodeWrapper = (props) => {
const { editor, element, path } = props;
const readOnly = useReadOnly();

Expand Down
6 changes: 3 additions & 3 deletions packages/ai/src/react/copilot/renderCopilotBelowNodes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import React from 'react';

import {
type NodeWrapperComponentProps,
type RenderNodeWrapperProps,
getEditorPlugin,
} from '@udecode/plate/react';

import type { CopilotPluginConfig } from './CopilotPlugin';

export const renderCopilotBelowNodes = ({
editor,
}: NodeWrapperComponentProps<CopilotPluginConfig>) => {
}: RenderNodeWrapperProps<CopilotPluginConfig>) => {
const copilot = getEditorPlugin<CopilotPluginConfig>(editor, {
key: 'copilot',
});
Expand All @@ -20,7 +20,7 @@ export const renderCopilotBelowNodes = ({

if (!GhostText) return;

return function Component({ children }: { children: React.ReactNode }) {
return ({ children }: { children: React.ReactNode }) => {
return (
<React.Fragment>
{children}
Expand Down
40 changes: 33 additions & 7 deletions packages/core/src/lib/plugin/SlatePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,15 @@ export type SlatePlugin<C extends AnyPluginConfig = PluginConfig> =
};
render: Nullable<{
/**
* Renders a component above all other plugins' `node` components.
* Useful for wrapping or decorating nodes with additional UI elements.
* When other plugins' `node` components are rendered, this function can
* return an optional wrapper function that turns a `node`'s props to a
* wrapper React node as its parent. Useful for wrapping or decorating
* nodes with additional UI elements.
*
* NOTE: The function can run React hooks. NOTE: Do not run React hooks
* in the wrapper function. It is not equivalent to a React component.
*/
aboveNodes?: NodeStaticWrapperComponent<WithAnyKey<C>>;
aboveNodes?: RenderStaticNodeWrapper<WithAnyKey<C>>;

/**
* Renders a component after the `Editable` component. This is the last
Expand All @@ -85,11 +90,16 @@ export type SlatePlugin<C extends AnyPluginConfig = PluginConfig> =
beforeEditable?: () => React.ReactElement | null;

/**
* Renders a component below all other plugins' `node` components, but
* above their `children`. This allows for injecting content or UI
* elements within nodes but before their child content.
* When other plugins' `node` components are rendered, this function can
* return an optional wrapper function that turns a `node`'s props to a
* wrapper React node. The wrapper node is the `node`'s child and its
* original children's parent. Useful for wrapping or decorating nodes
* with additional UI elements.
*
* NOTE: The function can run React hooks. NOTE: Do not run React hooks
* in the wrapper function. It is not equivalent to a React component.
*/
belowNodes?: NodeStaticWrapperComponent<WithAnyKey<C>>;
belowNodes?: RenderStaticNodeWrapper<WithAnyKey<C>>;

node?: React.FC;
}>;
Expand Down Expand Up @@ -514,16 +524,32 @@ export type NodeStaticProps<C extends AnyPluginConfig = PluginConfig> =
) => AnyObject | undefined)
| AnyObject;

export type RenderStaticNodeWrapper<C extends AnyPluginConfig = PluginConfig> =
(props: RenderStaticNodeWrapperProps<C>) => RenderStaticNodeWrapperFunction;

export type RenderStaticNodeWrapperFunction =
| ((hocProps: SlateRenderElementProps) => React.ReactNode)
| undefined;

export interface RenderStaticNodeWrapperProps<
C extends AnyPluginConfig = PluginConfig,
> extends SlateRenderElementProps<TElement, C> {
key: string;
}

/** @deprecated Use {@link RenderStaticNodeWrapper} instead. */
export type NodeStaticWrapperComponent<
C extends AnyPluginConfig = PluginConfig,
> = (
props: NodeStaticWrapperComponentProps<C>
) => NodeStaticWrapperComponentReturnType<C>;

/** @deprecated Use {@link RenderStaticNodeWrapperFunction} instead. */
export type NodeStaticWrapperComponentReturnType<
C extends AnyPluginConfig = PluginConfig,
> = React.FC<SlateRenderElementProps<TElement, C>> | undefined;

/** @deprecated Use {@link RenderStaticNodeWrapperProps} instead. */
export interface NodeStaticWrapperComponentProps<
C extends AnyPluginConfig = PluginConfig,
> extends SlateRenderElementProps<TElement, C> {
Expand Down
49 changes: 38 additions & 11 deletions packages/core/src/react/plugin/PlatePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,15 @@ export type PlatePlugin<C extends AnyPluginConfig = PluginConfig> =

render: Nullable<{
/**
* Renders a component above all other plugins' `node` components.
* Useful for wrapping or decorating nodes with additional UI elements.
* When other plugins' `node` components are rendered, this function can
* return an optional wrapper function that turns a `node`'s props to a
* wrapper React node as its parent. Useful for wrapping or decorating
* nodes with additional UI elements.
*
* NOTE: The function can run React hooks. NOTE: Do not run React hooks
* in the wrapper function. It is not equivalent to a React component.
*/
aboveNodes?: NodeWrapperComponent<WithAnyKey<C>>;
aboveNodes?: RenderNodeWrapper<WithAnyKey<C>>;

/**
* Renders a component after the `Editable` component. This is the last
Expand All @@ -142,11 +147,16 @@ export type PlatePlugin<C extends AnyPluginConfig = PluginConfig> =
beforeEditable?: EditableSiblingComponent;

/**
* Renders a component below all other plugins' `node` components, but
* above their `children`. This allows for injecting content or UI
* elements within nodes but before their child content.
* When other plugins' `node` components are rendered, this function can
* return an optional wrapper function that turns a `node`'s props to a
* wrapper React node. The wrapper node is the `node`'s child and its
* original children's parent. Useful for wrapping or decorating nodes
* with additional UI elements.
*
* NOTE: The function can run React hooks. NOTE: Do not run React hooks
* in the wrapper function. It is not equivalent to a React component.
*/
belowNodes?: NodeWrapperComponent<WithAnyKey<C>>;
belowNodes?: RenderNodeWrapper<WithAnyKey<C>>;

/** @see {@link NodeComponent} */
node?: NodeComponent;
Expand Down Expand Up @@ -727,19 +737,36 @@ export type EditableSiblingComponent = (
editableProps: EditableProps
) => React.ReactElement | null;

export interface NodeWrapperComponentProps<
export interface RenderNodeWrapperProps<
C extends AnyPluginConfig = PluginConfig,
> extends PlateRenderElementProps<TElement, C> {
key: string;
}

export type NodeWrapperComponentReturnType =
| React.FC<PlateRenderElementProps>
export type RenderNodeWrapperFunction =
| ((elementProps: PlateRenderElementProps) => React.ReactNode)
| undefined;

export type RenderNodeWrapper<C extends AnyPluginConfig = PluginConfig> = (
props: RenderNodeWrapperProps<C>
) => RenderNodeWrapperFunction;

/** @deprecated Use {@link RenderNodeWrapperProps} instead. */
export interface NodeWrapperComponentProps<
C extends AnyPluginConfig = PluginConfig,
> extends PlateRenderElementProps<TElement, C> {
key: string;
}

/** @deprecated Use {@link RenderNodeWrapperFunction} instead. */
export type NodeWrapperComponentReturnType<
C extends AnyPluginConfig = PluginConfig,
> = React.FC<PlateRenderElementProps<TElement, C>> | undefined;

/** @deprecated Use {@link RenderNodeWrapper} instead. */
export type NodeWrapperComponent<C extends AnyPluginConfig = PluginConfig> = (
props: NodeWrapperComponentProps<C>
) => NodeWrapperComponentReturnType;
) => NodeWrapperComponentReturnType<C>;

/**
* Function called whenever a change occurs in the editor. Return `false` to
Expand Down
14 changes: 7 additions & 7 deletions packages/indent-list/src/lib/renderIndentListBelowNodes.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';

import type {
NodeStaticWrapperComponent,
NodeStaticWrapperComponentProps,
NodeStaticWrapperComponentReturnType,
RenderStaticNodeWrapper,
RenderStaticNodeWrapperFunction,
RenderStaticNodeWrapperProps,
} from '@udecode/plate';

import { clsx } from 'clsx';
Expand All @@ -15,9 +15,9 @@ import {
} from '../lib';
import { ULIST_STYLE_TYPES } from '../lib/types';

export const renderIndentListBelowNodes: NodeStaticWrapperComponent = (
injectProps: NodeStaticWrapperComponentProps<BaseIndentListConfig>
): NodeStaticWrapperComponentReturnType => {
export const renderIndentListBelowNodes: RenderStaticNodeWrapper = (
injectProps: RenderStaticNodeWrapperProps<BaseIndentListConfig>
): RenderStaticNodeWrapperFunction => {
const { element } = injectProps;

const listStyleType = element[BaseIndentListPlugin.key] as string;
Expand All @@ -32,7 +32,7 @@ export const renderIndentListBelowNodes: NodeStaticWrapperComponent = (
position: 'relative',
};

return function Component({ children, ...props }) {
return ({ children, ...props }) => {
const { editor } = props;

const { listStyleTypes = {} } = editor.getOptions(BaseIndentListPlugin);
Expand Down
12 changes: 4 additions & 8 deletions packages/toggle/src/react/renderToggleAboveNodes.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import React from 'react';

import type {
NodeWrapperComponent,
NodeWrapperComponentReturnType,
RenderNodeWrapper,
RenderNodeWrapperFunction,
} from '@udecode/plate/react';

import { useIsVisible } from './toggleIndexAtom';

export const renderToggleAboveNodes: NodeWrapperComponent<any> = () =>
ToggleAboveNodes;
export const renderToggleAboveNodes: RenderNodeWrapper = () => ToggleAboveNodes;

const ToggleAboveNodes: NodeWrapperComponentReturnType = ({
children,
element,
}) => {
const ToggleAboveNodes: RenderNodeWrapperFunction = ({ children, element }) => {
const isVisible = useIsVisible(element.id as string);

if (isVisible) return children;
Expand Down

0 comments on commit 25ab000

Please sign in to comment.