diff --git a/apps/demo-free-layout/src/components/base-node/index.tsx b/apps/demo-free-layout/src/components/base-node/index.tsx
index b016cf77..7e0c953c 100644
--- a/apps/demo-free-layout/src/components/base-node/index.tsx
+++ b/apps/demo-free-layout/src/components/base-node/index.tsx
@@ -38,7 +38,9 @@ export const BaseNode = ({ node }: { node: FlowNodeEntity }) => {
outline: form?.state.invalid ? '1px solid red' : 'none',
}}
>
- {form?.render()}
+
+ {form?.render()}
+
diff --git a/apps/demo-free-layout/src/components/container-content/index.tsx b/apps/demo-free-layout/src/components/container-content/index.tsx
new file mode 100644
index 00000000..3bd83192
--- /dev/null
+++ b/apps/demo-free-layout/src/components/container-content/index.tsx
@@ -0,0 +1,14 @@
+import { useNodeRender } from '@flowgram.ai/free-layout-editor';
+import { ContainerNodeForm } from '@flowgram.ai/free-container-plugin';
+
+import { NodeRenderContext } from '../../context';
+
+export const ContainerNodeContent = () => {
+ const nodeRender = useNodeRender();
+
+ return (
+
+ ;
+
+ );
+};
diff --git a/apps/demo-free-layout/src/components/index.ts b/apps/demo-free-layout/src/components/index.ts
index d6cba9a0..806a7ef0 100644
--- a/apps/demo-free-layout/src/components/index.ts
+++ b/apps/demo-free-layout/src/components/index.ts
@@ -1,3 +1,4 @@
export * from './base-node';
export * from './line-add-button';
export * from './node-panel';
+export * from './container-content';
diff --git a/apps/demo-free-layout/src/context/node-render-context.ts b/apps/demo-free-layout/src/context/node-render-context.ts
index 5cf001a7..926016b2 100644
--- a/apps/demo-free-layout/src/context/node-render-context.ts
+++ b/apps/demo-free-layout/src/context/node-render-context.ts
@@ -1,6 +1,8 @@
import React from 'react';
-interface INodeRenderContext {}
+import type { NodeRenderReturnType } from '@flowgram.ai/free-layout-editor';
+
+interface INodeRenderContext extends NodeRenderReturnType {}
/** 业务自定义节点上下文 */
-export const NodeRenderContext = React.createContext({});
+export const NodeRenderContext = React.createContext({} as INodeRenderContext);
diff --git a/apps/demo-free-layout/src/form-components/form-content/index.tsx b/apps/demo-free-layout/src/form-components/form-content/index.tsx
index 761f5c33..9235393b 100644
--- a/apps/demo-free-layout/src/form-components/form-content/index.tsx
+++ b/apps/demo-free-layout/src/form-components/form-content/index.tsx
@@ -1,7 +1,8 @@
import React from 'react';
-import { FlowNodeRegistry, useNodeRender } from '@flowgram.ai/free-layout-editor';
+import { FlowNodeRegistry } from '@flowgram.ai/free-layout-editor';
+import { useNodeRenderContext } from '../../hooks';
import { FormTitleDescription, FormWrapper } from './styles';
/**
@@ -9,7 +10,7 @@ import { FormTitleDescription, FormWrapper } from './styles';
* @constructor
*/
export function FormContent(props: { children?: React.ReactNode }) {
- const { expanded, node } = useNodeRender();
+ const { expanded, node } = useNodeRenderContext();
const registry = node.getNodeRegistry();
return (
diff --git a/apps/demo-free-layout/src/form-components/form-header/index.tsx b/apps/demo-free-layout/src/form-components/form-header/index.tsx
index 53d625e4..0e9bbeb8 100644
--- a/apps/demo-free-layout/src/form-components/form-header/index.tsx
+++ b/apps/demo-free-layout/src/form-components/form-header/index.tsx
@@ -5,7 +5,6 @@ import {
Field,
FieldRenderProps,
useClientContext,
- useNodeRender,
useService,
} from '@flowgram.ai/free-layout-editor';
import { NodeIntoContainerService } from '@flowgram.ai/free-container-plugin';
@@ -14,6 +13,7 @@ import { IconMore } from '@douyinfe/semi-icons';
import { Feedback } from '../feedback';
import { FlowNodeRegistry } from '../../typings';
+import { useNodeRenderContext } from '../../hooks';
import { getIcon } from './utils';
import { Header, Operators, Title } from './styles';
@@ -21,7 +21,7 @@ const { Text } = Typography;
function DropdownButton() {
const [key, setKey] = useState(0);
- const { node, deleteNode } = useNodeRender();
+ const { node, deleteNode } = useNodeRenderContext();
const clientContext = useClientContext();
const registry = node.getNodeRegistry();
const nodeIntoContainerService = useService(NodeIntoContainerService);
@@ -76,7 +76,7 @@ function DropdownButton() {
}
export function FormHeader() {
- const { node, readonly } = useNodeRender();
+ const { node, readonly } = useNodeRenderContext();
return (
diff --git a/apps/demo-free-layout/src/form-components/form-inputs/index.tsx b/apps/demo-free-layout/src/form-components/form-inputs/index.tsx
index 3e03b3eb..0b549d32 100644
--- a/apps/demo-free-layout/src/form-components/form-inputs/index.tsx
+++ b/apps/demo-free-layout/src/form-components/form-inputs/index.tsx
@@ -1,12 +1,13 @@
-import { Field, useNodeRender } from '@flowgram.ai/free-layout-editor';
+import { Field } from '@flowgram.ai/free-layout-editor';
import { FxExpression } from '../fx-expression';
import { FormItem } from '../form-item';
import { Feedback } from '../feedback';
import { JsonSchema } from '../../typings';
+import { useNodeRenderContext } from '../../hooks';
export function FormInputs() {
- const { readonly } = useNodeRender();
+ const { readonly } = useNodeRenderContext();
return (
name="inputs">
{({ field: inputsField }) => {
diff --git a/apps/demo-free-layout/src/form-components/properties-edit/index.tsx b/apps/demo-free-layout/src/form-components/properties-edit/index.tsx
index 0277be87..bc8966d0 100644
--- a/apps/demo-free-layout/src/form-components/properties-edit/index.tsx
+++ b/apps/demo-free-layout/src/form-components/properties-edit/index.tsx
@@ -1,10 +1,10 @@
import React, { useState } from 'react';
-import { useNodeRender } from '@flowgram.ai/free-layout-editor';
import { Button } from '@douyinfe/semi-ui';
import { IconPlus } from '@douyinfe/semi-icons';
import { JsonSchema } from '../../typings';
+import { useNodeRenderContext } from '../../hooks';
import { PropertyEdit } from './property-edit';
export interface PropertiesEditProps {
@@ -15,7 +15,7 @@ export interface PropertiesEditProps {
export const PropertiesEdit: React.FC = (props) => {
const value = (props.value || {}) as Record;
- const { readonly } = useNodeRender();
+ const { readonly } = useNodeRenderContext();
const [newProperty, updateNewPropertyFromCache] = useState<{ key: string; value: JsonSchema }>({
key: '',
value: { type: 'string' },
diff --git a/apps/demo-free-layout/src/hooks/index.ts b/apps/demo-free-layout/src/hooks/index.ts
index a7f481d9..570a09e3 100644
--- a/apps/demo-free-layout/src/hooks/index.ts
+++ b/apps/demo-free-layout/src/hooks/index.ts
@@ -1 +1,2 @@
export { useEditorProps } from './use-editor-props';
+export { useNodeRenderContext } from './use-node-render-context';
diff --git a/apps/demo-free-layout/src/hooks/use-editor-props.tsx b/apps/demo-free-layout/src/hooks/use-editor-props.tsx
index 7f382fbb..95ae19a4 100644
--- a/apps/demo-free-layout/src/hooks/use-editor-props.tsx
+++ b/apps/demo-free-layout/src/hooks/use-editor-props.tsx
@@ -17,6 +17,7 @@ import { createSyncVariablePlugin } from '../plugins';
import { defaultFormMeta } from '../nodes/default-form-meta';
import { SelectorBoxPopover } from '../components/selector-box-popover';
import { BaseNode, LineAddButton, NodePanel } from '../components';
+import { ContainerNodeContent } from '../components';
export function useEditorProps(
initialData: FlowDocumentJSON,
@@ -200,7 +201,9 @@ export function useEditorProps(
createFreeNodePanelPlugin({
renderer: NodePanel,
}),
- createContainerNodePlugin({}),
+ createContainerNodePlugin({
+ renderContent: ,
+ }),
],
}),
[]
diff --git a/apps/demo-free-layout/src/hooks/use-node-render-context.ts b/apps/demo-free-layout/src/hooks/use-node-render-context.ts
new file mode 100644
index 00000000..bd5cc26a
--- /dev/null
+++ b/apps/demo-free-layout/src/hooks/use-node-render-context.ts
@@ -0,0 +1,5 @@
+import { useContext } from 'react';
+
+import { NodeRenderContext } from '../context';
+
+export const useNodeRenderContext = () => useContext(NodeRenderContext);
diff --git a/apps/demo-free-layout/src/nodes/condition/condition-inputs/index.tsx b/apps/demo-free-layout/src/nodes/condition/condition-inputs/index.tsx
index a20ce907..955d8dcf 100644
--- a/apps/demo-free-layout/src/nodes/condition/condition-inputs/index.tsx
+++ b/apps/demo-free-layout/src/nodes/condition/condition-inputs/index.tsx
@@ -1,9 +1,10 @@
import { nanoid } from 'nanoid';
-import { Field, FieldArray, useNodeRender } from '@flowgram.ai/free-layout-editor';
+import { Field, FieldArray } from '@flowgram.ai/free-layout-editor';
import { Button } from '@douyinfe/semi-ui';
import { IconPlus, IconCrossCircleStroked } from '@douyinfe/semi-icons';
import { FlowLiteralValueSchema, FlowRefValueSchema } from '../../../typings';
+import { useNodeRenderContext } from '../../../hooks';
import { FxExpression } from '../../../form-components/fx-expression';
import { FormItem } from '../../../form-components';
import { Feedback } from '../../../form-components';
@@ -15,7 +16,7 @@ interface ConditionValue {
}
export function ConditionInputs() {
- const { readonly } = useNodeRender();
+ const { readonly } = useNodeRenderContext();
return (
{({ field }) => (
diff --git a/packages/canvas-engine/free-layout-core/src/hooks/use-node-render-context.ts b/packages/canvas-engine/free-layout-core/src/hooks/use-node-render-context.ts
new file mode 100644
index 00000000..f4a36616
--- /dev/null
+++ b/packages/canvas-engine/free-layout-core/src/hooks/use-node-render-context.ts
@@ -0,0 +1,5 @@
+import React from 'react';
+
+import { NodeRenderReturnType } from './typings';
+
+export const NodeRenderContext = React.createContext({} as any);
diff --git a/packages/plugins/free-container-plugin/src/container-node-render/index.ts b/packages/plugins/free-container-plugin/src/container-node-render/index.ts
index b213a88a..d05bf7c8 100644
--- a/packages/plugins/free-container-plugin/src/container-node-render/index.ts
+++ b/packages/plugins/free-container-plugin/src/container-node-render/index.ts
@@ -1,3 +1,4 @@
export { ContainerNodeRenderKey } from './constant';
export { ContainerNodeRender } from './render';
export type { ContainerNodeMetaRenderProps, ContainerNodeRenderProps } from './type';
+export * from './components';
diff --git a/packages/plugins/free-container-plugin/src/container-node-render/render.tsx b/packages/plugins/free-container-plugin/src/container-node-render/render.tsx
index a5dd7c84..bb35147a 100644
--- a/packages/plugins/free-container-plugin/src/container-node-render/render.tsx
+++ b/packages/plugins/free-container-plugin/src/container-node-render/render.tsx
@@ -7,16 +7,13 @@ import {
ContainerNodePorts,
ContainerNodeBorder,
ContainerNodeContainer,
- ContainerNodeForm,
} from './components';
-export const ContainerNodeRender: FC = () => (
+export const ContainerNodeRender: FC = ({ content }) => (
-
-
-
+ {content}
);
diff --git a/packages/plugins/free-container-plugin/src/container-node-render/type.ts b/packages/plugins/free-container-plugin/src/container-node-render/type.ts
index 726c4716..54f98c55 100644
--- a/packages/plugins/free-container-plugin/src/container-node-render/type.ts
+++ b/packages/plugins/free-container-plugin/src/container-node-render/type.ts
@@ -1,3 +1,5 @@
+import { ReactNode } from 'react';
+
import type { WorkflowNodeEntity } from '@flowgram.ai/free-layout-core';
export interface ContainerNodeMetaRenderProps {
@@ -13,4 +15,5 @@ export interface ContainerNodeMetaRenderProps {
export interface ContainerNodeRenderProps {
node: WorkflowNodeEntity;
+ content?: ReactNode;
}
diff --git a/packages/plugins/free-container-plugin/src/plugin.ts b/packages/plugins/free-container-plugin/src/plugin.tsx
similarity index 68%
rename from packages/plugins/free-container-plugin/src/plugin.ts
rename to packages/plugins/free-container-plugin/src/plugin.tsx
index dc7aa1ea..5284cfbd 100644
--- a/packages/plugins/free-container-plugin/src/plugin.ts
+++ b/packages/plugins/free-container-plugin/src/plugin.tsx
@@ -1,19 +1,27 @@
+import React from 'react';
+
import { FlowRendererRegistry } from '@flowgram.ai/renderer';
import { definePluginCreator } from '@flowgram.ai/core';
import type { WorkflowContainerPluginOptions } from './type';
import { NodeIntoContainerService } from './node-into-container';
-import { ContainerNodeRenderKey, ContainerNodeRender } from './container-node-render';
+import {
+ ContainerNodeRenderKey,
+ ContainerNodeRender,
+ ContainerNodeRenderProps,
+} from './container-node-render';
export const createContainerNodePlugin = definePluginCreator({
onBind: ({ bind }) => {
bind(NodeIntoContainerService).toSelf().inSingletonScope();
},
- onInit(ctx) {
+ onInit(ctx, options) {
ctx.get(NodeIntoContainerService).init();
const registry = ctx.get(FlowRendererRegistry);
- registry.registerReactComponent(ContainerNodeRenderKey, ContainerNodeRender);
+ registry.registerReactComponent(ContainerNodeRenderKey, (props: ContainerNodeRenderProps) => (
+
+ ));
},
onReady(ctx, options) {
if (options.disableNodeIntoContainer !== true) {
diff --git a/packages/plugins/free-container-plugin/src/type.ts b/packages/plugins/free-container-plugin/src/type.ts
index b62aeba6..1ab1d49f 100644
--- a/packages/plugins/free-container-plugin/src/type.ts
+++ b/packages/plugins/free-container-plugin/src/type.ts
@@ -1,3 +1,6 @@
+import type { ReactNode } from 'react';
+
export interface WorkflowContainerPluginOptions {
disableNodeIntoContainer?: boolean;
+ renderContent?: ReactNode;
}