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; }