mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
refactor(container): allow user to customize render content component
This commit is contained in:
parent
429164671e
commit
088368d48c
@ -38,7 +38,9 @@ export const BaseNode = ({ node }: { node: FlowNodeEntity }) => {
|
||||
outline: form?.state.invalid ? '1px solid red' : 'none',
|
||||
}}
|
||||
>
|
||||
<NodeRenderContext.Provider value={{}}>{form?.render()}</NodeRenderContext.Provider>
|
||||
<NodeRenderContext.Provider value={nodeRender}>
|
||||
{form?.render()}
|
||||
</NodeRenderContext.Provider>
|
||||
</BaseNodeStyle>
|
||||
</WorkflowNodeRenderer>
|
||||
</ConfigProvider>
|
||||
|
||||
@ -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 (
|
||||
<NodeRenderContext.Provider value={nodeRender}>
|
||||
<ContainerNodeForm />;
|
||||
</NodeRenderContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './base-node';
|
||||
export * from './line-add-button';
|
||||
export * from './node-panel';
|
||||
export * from './container-content';
|
||||
|
||||
@ -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<INodeRenderContext>({});
|
||||
export const NodeRenderContext = React.createContext<INodeRenderContext>({} as INodeRenderContext);
|
||||
|
||||
@ -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<FlowNodeRegistry>();
|
||||
return (
|
||||
<FormWrapper>
|
||||
|
||||
@ -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<FlowNodeRegistry>();
|
||||
const nodeIntoContainerService = useService<NodeIntoContainerService>(NodeIntoContainerService);
|
||||
@ -76,7 +76,7 @@ function DropdownButton() {
|
||||
}
|
||||
|
||||
export function FormHeader() {
|
||||
const { node, readonly } = useNodeRender();
|
||||
const { node, readonly } = useNodeRenderContext();
|
||||
|
||||
return (
|
||||
<Header>
|
||||
|
||||
@ -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 (
|
||||
<Field<JsonSchema> name="inputs">
|
||||
{({ field: inputsField }) => {
|
||||
|
||||
@ -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<PropertiesEditProps> = (props) => {
|
||||
const value = (props.value || {}) as Record<string, JsonSchema>;
|
||||
const { readonly } = useNodeRender();
|
||||
const { readonly } = useNodeRenderContext();
|
||||
const [newProperty, updateNewPropertyFromCache] = useState<{ key: string; value: JsonSchema }>({
|
||||
key: '',
|
||||
value: { type: 'string' },
|
||||
|
||||
@ -1 +1,2 @@
|
||||
export { useEditorProps } from './use-editor-props';
|
||||
export { useNodeRenderContext } from './use-node-render-context';
|
||||
|
||||
@ -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: <ContainerNodeContent />,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
[]
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { NodeRenderContext } from '../context';
|
||||
|
||||
export const useNodeRenderContext = () => useContext(NodeRenderContext);
|
||||
@ -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 (
|
||||
<FieldArray name="inputsValues.conditions">
|
||||
{({ field }) => (
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
import { NodeRenderReturnType } from './typings';
|
||||
|
||||
export const NodeRenderContext = React.createContext<NodeRenderReturnType>({} as any);
|
||||
@ -1,3 +1,4 @@
|
||||
export { ContainerNodeRenderKey } from './constant';
|
||||
export { ContainerNodeRender } from './render';
|
||||
export type { ContainerNodeMetaRenderProps, ContainerNodeRenderProps } from './type';
|
||||
export * from './components';
|
||||
|
||||
@ -7,16 +7,13 @@ import {
|
||||
ContainerNodePorts,
|
||||
ContainerNodeBorder,
|
||||
ContainerNodeContainer,
|
||||
ContainerNodeForm,
|
||||
} from './components';
|
||||
|
||||
export const ContainerNodeRender: FC<ContainerNodeRenderProps> = () => (
|
||||
export const ContainerNodeRender: FC<ContainerNodeRenderProps> = ({ content }) => (
|
||||
<ContainerNodeContainer>
|
||||
<ContainerNodeBackground />
|
||||
<ContainerNodeBorder />
|
||||
<ContainerNodeHeader>
|
||||
<ContainerNodeForm />
|
||||
</ContainerNodeHeader>
|
||||
<ContainerNodeHeader>{content}</ContainerNodeHeader>
|
||||
<ContainerNodePorts />
|
||||
</ContainerNodeContainer>
|
||||
);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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<WorkflowContainerPluginOptions>({
|
||||
onBind: ({ bind }) => {
|
||||
bind(NodeIntoContainerService).toSelf().inSingletonScope();
|
||||
},
|
||||
onInit(ctx) {
|
||||
onInit(ctx, options) {
|
||||
ctx.get(NodeIntoContainerService).init();
|
||||
|
||||
const registry = ctx.get<FlowRendererRegistry>(FlowRendererRegistry);
|
||||
registry.registerReactComponent(ContainerNodeRenderKey, ContainerNodeRender);
|
||||
registry.registerReactComponent(ContainerNodeRenderKey, (props: ContainerNodeRenderProps) => (
|
||||
<ContainerNodeRender {...props} content={options.renderContent} />
|
||||
));
|
||||
},
|
||||
onReady(ctx, options) {
|
||||
if (options.disableNodeIntoContainer !== true) {
|
||||
@ -1,3 +1,6 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export interface WorkflowContainerPluginOptions {
|
||||
disableNodeIntoContainer?: boolean;
|
||||
renderContent?: ReactNode;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user