mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
chore: add raw-loader fixed demo (#79)
This commit is contained in:
parent
d90fdad677
commit
b77dfc9faf
@ -1,624 +1,22 @@
|
|||||||
import { PreviewEditor } from '../preview-editor';
|
import { PreviewEditor } from '../preview-editor';
|
||||||
import { FixedLayoutSimple } from './index';
|
import { FixedLayoutSimple } from './index';
|
||||||
|
|
||||||
|
import nodeRegistriesCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/node-registries.ts';
|
||||||
|
import initialDataCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/initial-data.ts';
|
||||||
|
import indexCssCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/index.css';
|
||||||
|
import useEditorPropsCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/hooks/use-editor-props.tsx';
|
||||||
|
import editorCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/editor.tsx';
|
||||||
|
import toolsCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/components/tools.tsx';
|
||||||
|
import nodeAdderCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/components/node-adder.tsx';
|
||||||
|
import miniMapCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/components/minimap.tsx';
|
||||||
|
import branchAdderCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/components/branch-adder.tsx';
|
||||||
|
import baseNodeCode from '!!raw-loader!@flowgram.ai/demo-fixed-layout-simple/src/components/base-node.tsx';
|
||||||
|
|
||||||
const indexCode = {
|
const indexCode = {
|
||||||
code: `import { FixedLayoutEditorProvider, EditorRenderer } from '@flowgram.ai/fixed-layout-editor';
|
code: editorCode,
|
||||||
|
|
||||||
import '@flowgram.ai/fixed-layout-editor/index.css';
|
|
||||||
import './index.css'
|
|
||||||
|
|
||||||
import { useEditorProps } from './use-editor-props';
|
|
||||||
import { initialData } from './initial-data'
|
|
||||||
import { nodeRegistries } from './node-registries'
|
|
||||||
import { Tools } from './tools'
|
|
||||||
import { Minimap } from './minimap'
|
|
||||||
|
|
||||||
export const Editor = () => {
|
|
||||||
const editorProps = useEditorProps(initialData, nodeRegistries);
|
|
||||||
return (
|
|
||||||
<FixedLayoutEditorProvider {...editorProps}>
|
|
||||||
<div className="demo-fixed-container">
|
|
||||||
<EditorRenderer>{/* add child panel here */}</EditorRenderer>
|
|
||||||
</div>
|
|
||||||
<Tools />
|
|
||||||
<Minimap />
|
|
||||||
</FixedLayoutEditorProvider>
|
|
||||||
);
|
|
||||||
}`,
|
|
||||||
active: true,
|
active: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const indexCssCode = `.demo-fixed-node {
|
|
||||||
align-items: flex-start;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid rgba(6, 7, 9, 0.15);
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.04), 0 4px 12px 0 rgba(0, 0, 0, 0.02);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
width: 360px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-fixed-node-title {
|
|
||||||
background-color: #93bfe2;
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 8px 8px 0 0;
|
|
||||||
padding: 4px 12px;
|
|
||||||
}
|
|
||||||
.demo-fixed-node-content {
|
|
||||||
padding: 16px;
|
|
||||||
flex-grow: 1;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-fixed-adder {
|
|
||||||
width: 28px;
|
|
||||||
height: 18px;
|
|
||||||
background: rgb(187, 191, 196);
|
|
||||||
display: flex;
|
|
||||||
border-radius: 9px;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
align-items: center;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
div {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
svg {
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-fixed-adder.activated {
|
|
||||||
background: #82A7FC
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-fixed-adder.isHorizontal {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.gedit-playground * {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}`;
|
|
||||||
|
|
||||||
const initialDataCode = `import { FlowDocumentJSON } from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置流程数据,数据为 blocks 嵌套的格式
|
|
||||||
*/
|
|
||||||
export const initialData: FlowDocumentJSON = {
|
|
||||||
nodes: [
|
|
||||||
// 开始节点
|
|
||||||
{
|
|
||||||
id: 'start_0',
|
|
||||||
type: 'start',
|
|
||||||
data: {
|
|
||||||
title: 'Start',
|
|
||||||
content: 'start content'
|
|
||||||
},
|
|
||||||
blocks: [],
|
|
||||||
},
|
|
||||||
// 分支节点
|
|
||||||
{
|
|
||||||
id: 'condition_0',
|
|
||||||
type: 'condition',
|
|
||||||
data: {
|
|
||||||
title: 'Condition'
|
|
||||||
},
|
|
||||||
blocks: [
|
|
||||||
{
|
|
||||||
id: 'branch_0',
|
|
||||||
type: 'block',
|
|
||||||
data: {
|
|
||||||
title: 'Branch 0',
|
|
||||||
content: 'branch 1 content'
|
|
||||||
},
|
|
||||||
blocks: [
|
|
||||||
{
|
|
||||||
id: 'custom_0',
|
|
||||||
type: 'custom',
|
|
||||||
data: {
|
|
||||||
title: 'Custom',
|
|
||||||
content: 'custrom content'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'branch_1',
|
|
||||||
type: 'block',
|
|
||||||
data: {
|
|
||||||
title: 'Branch 1',
|
|
||||||
content: 'branch 1 content'
|
|
||||||
},
|
|
||||||
blocks: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// 结束节点
|
|
||||||
{
|
|
||||||
id: 'end_0',
|
|
||||||
type: 'end',
|
|
||||||
data: {
|
|
||||||
title: 'End',
|
|
||||||
content: 'end content'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};`;
|
|
||||||
|
|
||||||
const nodeRegistriesCode = `import { FlowNodeRegistry } from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义节点注册
|
|
||||||
*/
|
|
||||||
export const nodeRegistries: FlowNodeRegistry[] = [
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 自定义节点类型
|
|
||||||
*/
|
|
||||||
type: 'condition',
|
|
||||||
/**
|
|
||||||
* 自定义节点扩展:
|
|
||||||
* - loop: 扩展为循环节点
|
|
||||||
* - start: 扩展为开始节点
|
|
||||||
* - dynamicSplit: 扩展为分支节点
|
|
||||||
* - end: 扩展为结束节点
|
|
||||||
* - tryCatch: 扩展为 tryCatch 节点
|
|
||||||
* - default: 扩展为普通节点 (默认)
|
|
||||||
*/
|
|
||||||
extend: 'dynamicSplit',
|
|
||||||
/**
|
|
||||||
* 节点配置信息
|
|
||||||
*/
|
|
||||||
meta: {
|
|
||||||
// isStart: false, // 是否为开始节点
|
|
||||||
// isNodeEnd: false, // 是否为结束节点,结束节点后边无法再添加节点
|
|
||||||
// draggable: false, // 是否可拖拽,如开始节点和结束节点无法拖拽
|
|
||||||
// selectable: false, // 触发器等开始节点不能被框选
|
|
||||||
// deleteDisable: true, // 禁止删除
|
|
||||||
// copyDisable: true, // 禁止copy
|
|
||||||
// addDisable: true, // 禁止添加
|
|
||||||
},
|
|
||||||
onAdd() {
|
|
||||||
return {
|
|
||||||
id: \`condition_\${nanoid(5)}\`,
|
|
||||||
type: 'condition',
|
|
||||||
data: {
|
|
||||||
title: 'Condition',
|
|
||||||
},
|
|
||||||
blocks: [
|
|
||||||
{
|
|
||||||
id: nanoid(5),
|
|
||||||
type: 'block',
|
|
||||||
data: {
|
|
||||||
title: 'If_0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: nanoid(5),
|
|
||||||
type: 'block',
|
|
||||||
data: {
|
|
||||||
title: 'If_1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'custom',
|
|
||||||
meta: {},
|
|
||||||
onAdd() {
|
|
||||||
return {
|
|
||||||
id: \`custom_\${nanoid(5)}\`,
|
|
||||||
type: 'custom',
|
|
||||||
data: {
|
|
||||||
title: 'Custom',
|
|
||||||
content: 'this is custom content'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];`;
|
|
||||||
|
|
||||||
const useEditorPropsCode = `import { useMemo } from 'react';
|
|
||||||
|
|
||||||
import { defaultFixedSemiMaterials } from '@flowgram.ai/fixed-semi-materials';
|
|
||||||
import { createMinimapPlugin } from '@flowgram.ai/minimap-plugin';
|
|
||||||
import {
|
|
||||||
type FixedLayoutProps,
|
|
||||||
FlowDocumentJSON,
|
|
||||||
FlowNodeRegistry,
|
|
||||||
FlowTextKey,
|
|
||||||
Field,
|
|
||||||
FlowRendererKey,
|
|
||||||
} from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
|
|
||||||
import { BaseNode } from './base-node'
|
|
||||||
import { BranchAdder } from './branch-adder'
|
|
||||||
import { NodeAdder } from '../components/node-adder';
|
|
||||||
|
|
||||||
/** semi materials */
|
|
||||||
|
|
||||||
export function useEditorProps(
|
|
||||||
initialData: FlowDocumentJSON, // 初始化数据
|
|
||||||
nodeRegistries: FlowNodeRegistry[], // 节点定义
|
|
||||||
): FixedLayoutProps {
|
|
||||||
return useMemo<FixedLayoutProps>(
|
|
||||||
() => ({
|
|
||||||
/**
|
|
||||||
* Whether to enable the background
|
|
||||||
*/
|
|
||||||
background: true,
|
|
||||||
/**
|
|
||||||
* Whether it is read-only or not, the node cannot be dragged in read-only mode
|
|
||||||
*/
|
|
||||||
readonly: false,
|
|
||||||
/**
|
|
||||||
* Initial data
|
|
||||||
* 初始化数据
|
|
||||||
*/
|
|
||||||
initialData,
|
|
||||||
/**
|
|
||||||
* 画布节点定义
|
|
||||||
*/
|
|
||||||
nodeRegistries,
|
|
||||||
/**
|
|
||||||
* Get the default node registry, which will be merged with the 'nodeRegistries'
|
|
||||||
* 提供默认的节点注册,这个会和 nodeRegistries 做合并
|
|
||||||
*/
|
|
||||||
getNodeDefaultRegistry(type) {
|
|
||||||
return {
|
|
||||||
type,
|
|
||||||
meta: {
|
|
||||||
defaultExpanded: true,
|
|
||||||
},
|
|
||||||
formMeta: {
|
|
||||||
/**
|
|
||||||
* Render form
|
|
||||||
*/
|
|
||||||
render: () => <>
|
|
||||||
<Field<string> name="title">
|
|
||||||
{({ field }) => <div className="demo-fixed-node-title">{field.value}</div>}
|
|
||||||
</Field>
|
|
||||||
<div className="demo-fixed-node-content">
|
|
||||||
<Field<string> name="content">
|
|
||||||
<input />
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Materials, components can be customized based on the key
|
|
||||||
* 可以通过 key 自定义 UI 组件
|
|
||||||
*/
|
|
||||||
materials: {
|
|
||||||
renderNodes: {
|
|
||||||
...defaultFixedSemiMaterials,
|
|
||||||
/**
|
|
||||||
* Components can be customized based on key business-side requirements.
|
|
||||||
* 这里可以根据 key 业务侧定制组件
|
|
||||||
*/
|
|
||||||
[FlowRendererKey.ADDER]: NodeAdder,
|
|
||||||
[FlowRendererKey.BRANCH_ADDER]: BranchAdder,
|
|
||||||
// [FlowRendererKey.DRAG_NODE]: DragNode,
|
|
||||||
},
|
|
||||||
renderDefaultNode: BaseNode, // 节点渲染
|
|
||||||
renderTexts: {
|
|
||||||
[FlowTextKey.LOOP_END_TEXT]: 'loop end',
|
|
||||||
[FlowTextKey.LOOP_TRAVERSE_TEXT]: 'looping',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Node engine enable, you can configure formMeta in the FlowNodeRegistry
|
|
||||||
*/
|
|
||||||
nodeEngine: {
|
|
||||||
enable: true,
|
|
||||||
},
|
|
||||||
history: {
|
|
||||||
enable: true,
|
|
||||||
enableChangeNode: true, // Listen Node engine data change
|
|
||||||
onApply(ctx, opt) {
|
|
||||||
// Listen change to trigger auto save
|
|
||||||
// console.log('auto save: ', ctx.document.toJSON(), opt);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 画布初始化
|
|
||||||
*/
|
|
||||||
onInit: ctx => {
|
|
||||||
/**
|
|
||||||
* Data can also be dynamically loaded via fromJSON
|
|
||||||
* 也可以通过 fromJSON 动态加载数据
|
|
||||||
*/
|
|
||||||
// ctx.document.fromJSON(initialData)
|
|
||||||
console.log('---- Playground Init ----');
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 画布销毁
|
|
||||||
*/
|
|
||||||
onDispose: () => {
|
|
||||||
console.log('---- Playground Dispose ----');
|
|
||||||
},
|
|
||||||
plugins: () => [
|
|
||||||
/**
|
|
||||||
* Minimap plugin
|
|
||||||
* 缩略图插件
|
|
||||||
*/
|
|
||||||
createMinimapPlugin({
|
|
||||||
disableLayer: true,
|
|
||||||
enableDisplayAllNodes: true,
|
|
||||||
canvasStyle: {
|
|
||||||
canvasWidth: 182,
|
|
||||||
canvasHeight: 102,
|
|
||||||
canvasPadding: 50,
|
|
||||||
canvasBackground: 'rgba(245, 245, 245, 1)',
|
|
||||||
canvasBorderRadius: 10,
|
|
||||||
viewportBackground: 'rgba(235, 235, 235, 1)',
|
|
||||||
viewportBorderRadius: 4,
|
|
||||||
viewportBorderColor: 'rgba(201, 201, 201, 1)',
|
|
||||||
viewportBorderWidth: 1,
|
|
||||||
viewportBorderDashLength: 2,
|
|
||||||
nodeColor: 'rgba(255, 255, 255, 1)',
|
|
||||||
nodeBorderRadius: 2,
|
|
||||||
nodeBorderWidth: 0.145,
|
|
||||||
nodeBorderColor: 'rgba(6, 7, 9, 0.10)',
|
|
||||||
overlayColor: 'rgba(255, 255, 255, 0)',
|
|
||||||
},
|
|
||||||
inactiveDebounceTime: 1,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const baseNodeCode = `import { FlowNodeEntity, useNodeRender } from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
|
|
||||||
export const BaseNode = ({ node }: { node: FlowNodeEntity }) => {
|
|
||||||
/**
|
|
||||||
* Provides methods related to node rendering
|
|
||||||
* 提供节点渲染相关的方法
|
|
||||||
*/
|
|
||||||
const nodeRender = useNodeRender();
|
|
||||||
/**
|
|
||||||
* It can only be used when nodeEngine is enabled
|
|
||||||
* 只有在节点引擎开启时候才能使用表单
|
|
||||||
*/
|
|
||||||
const form = nodeRender.form;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="demo-fixed-node"
|
|
||||||
onMouseEnter={nodeRender.onMouseEnter}
|
|
||||||
onMouseLeave={nodeRender.onMouseLeave}
|
|
||||||
onMouseDown={e => {
|
|
||||||
// trigger drag node
|
|
||||||
nodeRender.startDrag(e);
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
...(nodeRender.isBlockOrderIcon || nodeRender.isBlockIcon ? { width: 260 } : {}),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{form?.render()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const branchAdderCode = `import { type FlowNodeEntity, useClientContext } from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
import { IconPlus } from '@douyinfe/semi-icons';
|
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
|
|
||||||
|
|
||||||
interface PropsType {
|
|
||||||
activated?: boolean;
|
|
||||||
node: FlowNodeEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function BranchAdder(props: PropsType) {
|
|
||||||
const { activated, node } = props;
|
|
||||||
const nodeData = node.firstChild!.renderData;
|
|
||||||
const ctx = useClientContext();
|
|
||||||
const { operation, playground } = ctx;
|
|
||||||
const { isVertical } = node;
|
|
||||||
|
|
||||||
function addBranch() {
|
|
||||||
const block = operation.addBlock(node, {
|
|
||||||
id: \`branch_\${nanoid(5)}\`,
|
|
||||||
type: 'block',
|
|
||||||
data: {
|
|
||||||
title: 'New Branch',
|
|
||||||
content: ''
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
playground.scrollToView({
|
|
||||||
bounds: block.bounds,
|
|
||||||
scrollToCenter: true,
|
|
||||||
});
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
if (playground.config.readonlyOrDisabled) return null;
|
|
||||||
|
|
||||||
const className = [
|
|
||||||
'demo-fixed-adder',
|
|
||||||
isVertical ? '' : 'isHorizontal',
|
|
||||||
activated ? 'activated' : ''
|
|
||||||
].join(' ');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={className}
|
|
||||||
onMouseEnter={() => nodeData?.toggleMouseEnter()}
|
|
||||||
onMouseLeave={() => nodeData?.toggleMouseLeave()}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
addBranch();
|
|
||||||
}}
|
|
||||||
aria-hidden="true"
|
|
||||||
style={{ flexGrow: 1, textAlign: 'center' }}
|
|
||||||
>
|
|
||||||
<IconPlus />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const miniMapCode = `import { FlowMinimapService, MinimapRender } from '@flowgram.ai/minimap-plugin';
|
|
||||||
import { useService } from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
|
|
||||||
|
|
||||||
export const Minimap = () => {
|
|
||||||
const minimapService = useService(FlowMinimapService);
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
left: 16,
|
|
||||||
bottom: 51,
|
|
||||||
zIndex: 100,
|
|
||||||
width: 182,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MinimapRender
|
|
||||||
service={minimapService}
|
|
||||||
containerStyles={{
|
|
||||||
pointerEvents: 'auto',
|
|
||||||
position: 'relative',
|
|
||||||
top: 'unset',
|
|
||||||
right: 'unset',
|
|
||||||
bottom: 'unset',
|
|
||||||
left: 'unset',
|
|
||||||
}}
|
|
||||||
inactiveStyle={{
|
|
||||||
opacity: 1,
|
|
||||||
scale: 1,
|
|
||||||
translateX: 0,
|
|
||||||
translateY: 0,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const nodeAdderCode = `import { FlowNodeEntity, FlowOperationService, useClientContext, usePlayground, useService } from "@flowgram.ai/fixed-layout-editor"
|
|
||||||
|
|
||||||
import { Dropdown } from '@douyinfe/semi-ui'
|
|
||||||
|
|
||||||
import { IconPlusCircle } from "@douyinfe/semi-icons";
|
|
||||||
import { nodeRegistries } from '../node-registries';
|
|
||||||
|
|
||||||
export const NodeAdder = (props: {
|
|
||||||
from: FlowNodeEntity;
|
|
||||||
to?: FlowNodeEntity;
|
|
||||||
hoverActivated: boolean;
|
|
||||||
}) => {
|
|
||||||
const { from, hoverActivated } = props;
|
|
||||||
const playground = usePlayground();
|
|
||||||
const context = useClientContext();
|
|
||||||
const flowOperationService = useService(FlowOperationService) as FlowOperationService;
|
|
||||||
|
|
||||||
const add = (addProps: any) => {
|
|
||||||
const blocks = addProps.blocks ? addProps.blocks : undefined;
|
|
||||||
const block = flowOperationService.addFromNode(from, {
|
|
||||||
...addProps,
|
|
||||||
blocks,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
playground.scrollToView({
|
|
||||||
bounds: block.bounds,
|
|
||||||
scrollToCenter: true,
|
|
||||||
});
|
|
||||||
}, 10);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (playground.config.readonlyOrDisabled) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dropdown
|
|
||||||
render={
|
|
||||||
<Dropdown.Menu>
|
|
||||||
{nodeRegistries.map(registry => <Dropdown.Item onClick={() => {
|
|
||||||
const props = registry?.onAdd(context, from);
|
|
||||||
add(props);
|
|
||||||
}}>{registry.type}</Dropdown.Item>)}
|
|
||||||
</Dropdown.Menu>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: hoverActivated ? 15 : 6,
|
|
||||||
height: hoverActivated ? 15 : 6,
|
|
||||||
backgroundColor: 'rgb(143, 149, 158)',
|
|
||||||
color: '#fff',
|
|
||||||
borderRadius: '50%',
|
|
||||||
cursor: 'pointer'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{hoverActivated ?
|
|
||||||
<IconPlusCircle
|
|
||||||
style={{
|
|
||||||
color: '#3370ff',
|
|
||||||
backgroundColor: '#fff',
|
|
||||||
borderRadius: 15
|
|
||||||
}}
|
|
||||||
/> : null
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Dropdown>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const toolsCode = `import { useEffect, useState } from 'react'
|
|
||||||
import { usePlaygroundTools, useClientContext } from '@flowgram.ai/fixed-layout-editor';
|
|
||||||
|
|
||||||
export function Tools() {
|
|
||||||
const { history } = useClientContext();
|
|
||||||
const tools = usePlaygroundTools();
|
|
||||||
const [canUndo, setCanUndo] = useState(false);
|
|
||||||
const [canRedo, setCanRedo] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const disposable = history.undoRedoService.onChange(() => {
|
|
||||||
setCanUndo(history.canUndo());
|
|
||||||
setCanRedo(history.canRedo());
|
|
||||||
});
|
|
||||||
return () => disposable.dispose();
|
|
||||||
}, [history]);
|
|
||||||
|
|
||||||
return <div style={{ position: 'absolute', zIndex: 10, bottom: 16, left: 16, display: 'flex', gap: 8 }}>
|
|
||||||
<button onClick={() => tools.zoomin()}>ZoomIn</button>
|
|
||||||
<button onClick={() => tools.zoomout()}>ZoomOut</button>
|
|
||||||
<button onClick={() => tools.fitView()}>Fitview</button>
|
|
||||||
<button onClick={() => tools.changeLayout()}>ChangeLayout</button>
|
|
||||||
<button onClick={() => history.undo()} disabled={!canUndo}>Undo</button>
|
|
||||||
<button onClick={() => history.redo()} disabled={!canRedo}>Redo</button>
|
|
||||||
<span>{Math.floor(tools.zoom * 100)}%</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const FixedLayoutSimplePreview = () => (
|
export const FixedLayoutSimplePreview = () => (
|
||||||
<PreviewEditor
|
<PreviewEditor
|
||||||
files={{
|
files={{
|
||||||
|
|||||||
4
apps/docs/src/global.d.ts
vendored
Normal file
4
apps/docs/src/global.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module "!!raw-loader!*" {
|
||||||
|
const content: string;
|
||||||
|
export default content;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user