Răsfoiți Sursa

chore: read source code directly in example docs (#77)

tecvan 9 luni în urmă
părinte
comite
d90fdad677

+ 1 - 0
.vscode/settings.json

@@ -47,6 +47,7 @@
     "stylelintrc": "jsonc",
     "*.json": "jsonc",
     "package.json": "json",
+    "*.mdc": "markdown",
     ".htmlhintrc": "jsonc",
     "htmlhintrc": "jsonc",
     "Procfile*": "shellscript",

+ 7 - 370
apps/docs/components/free-layout-simple/preview.tsx

@@ -1,377 +1,14 @@
 import { PreviewEditor } from '../preview-editor';
 import { FreeLayoutSimple } from '.';
 
-const indexCode = {
-  code: `import {
-  EditorRenderer,
-  FreeLayoutEditorProvider,
-} from '@flowgram.ai/free-layout-editor';
+import nodeRegistriesCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/node-registries.ts';
+import dataCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/initial-data.ts';
+import useEditorPropsCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/hooks/use-editor-props.tsx';
+import indexCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/editor.tsx';
+import toolsCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/components/tools.tsx';
+import nodeAddPanelCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/components/node-add-panel.tsx';
+import minimapCode from '!!raw-loader!@flowgram.ai/demo-free-layout-simple/src/components/minimap.tsx';
 
-import { NodeAddPanel } from './components/node-add-panel';
-import { Tools } from './components/tools'
-import { Minimap } from './components/minimap'
-import { useEditorProps } from './hooks/use-editor-props'
-import '@flowgram.ai/free-layout-editor/index.css';
-import './index.css';
-
-export const Editor = () => {
-  const editorProps = useEditorProps()
-  return (
-    <FreeLayoutEditorProvider {...editorProps}>
-      <div className="demo-free-container">
-        <div className="demo-free-layout">
-          <NodeAddPanel />
-          <EditorRenderer className="demo-free-editor" />
-        </div>
-        <Tools />
-        <Minimap />
-      </div>
-    </FreeLayoutEditorProvider>
-  )
-};
-  `,
-  active: true,
-};
-
-const dataCode = `import { WorkflowJSON } from '@flowgram.ai/free-layout-editor';
-
-export const initialData: WorkflowJSON = {
-  nodes: [
-    {
-      id: 'start_0',
-      type: 'start',
-      meta: {
-        position: { x: 0, y: 0 },
-      },
-      data: {
-        title: 'Start',
-        content: 'Start content'
-      },
-    },
-    {
-      id: 'node_0',
-      type: 'custom',
-      meta: {
-        position: { x: 400, y: 0 },
-      },
-      data: {
-        title: 'Custom',
-        content: 'Custom node content'
-      },
-    },
-    {
-      id: 'end_0',
-      type: 'end',
-      meta: {
-        position: { x: 800, y: 0 },
-      },
-      data: {
-        title: 'End',
-        content: 'End content'
-      },
-    },
-  ],
-  edges: [
-    {
-      sourceNodeID: 'start_0',
-      targetNodeID: 'node_0',
-    },
-    {
-      sourceNodeID: 'node_0',
-      targetNodeID: 'end_0',
-    },
-  ],
-};
-
-
-`;
-
-const nodeAddPanelCode = `import React from 'react';
-
-import { WorkflowDragService, useService } from '@flowgram.ai/free-layout-editor';
-
-const cardkeys = ['Node1', 'Node2'];
-
-export const NodeAddPanel: React.FC = props => {
-  const startDragSerivce = useService<WorkflowDragService>(WorkflowDragService);
-
-  return (
-    <div className="demo-free-sidebar">
-      {cardkeys.map(nodeType => (
-        <div
-          key={nodeType}
-          className="demo-free-card"
-          onMouseDown={e => startDragSerivce.startDragCard(nodeType, e, {
-            data: {
-              title: \`New \${nodeType}\`,
-              content: 'xxxx'
-            }
-          })}
-        >
-          {nodeType}
-        </div>
-      ))}
-    </div>
-  );
-};
-`;
-
-const useEditorPropsCode = `import { useMemo } from 'react';
-
-import {
-  FreeLayoutProps,
-  WorkflowNodeProps,
-  WorkflowNodeRenderer,
-  Field,
-  useNodeRender
-} from '@flowgram.ai/free-layout-editor';
-import { createMinimapPlugin } from '@flowgram.ai/minimap-plugin';
-import { createFreeSnapPlugin } from '@flowgram.ai/free-snap-plugin';
-
-import { initialData } from '../initial-data';
-import { nodeRegistries } from '../node-registries'
-
-export const useEditorProps = () => useMemo<FreeLayoutProps>(
-    () => ({
-      /**
-       * 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,
-      /**
-       * Node registries
-       * 节点注册
-       */
-      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-free-node-title">{field.value}</div>}
-                </Field>
-                <div className="demo-free-node-content">
-                  <Field<string> name="content">
-                    <input />
-                  </Field>
-                </div>
-              </>
-          }
-        };
-      },
-      materials: {
-        /**
-         * Render Node
-         */
-        renderDefaultNode: (props: WorkflowNodeProps) => {
-          const { form } = useNodeRender()
-          return (
-            <WorkflowNodeRenderer className="demo-free-node" node={props.node}>
-              {form?.render()}
-            </WorkflowNodeRenderer>
-          )
-        },
-      },
-      /**
-       * Content change
-       */
-      onContentChange(ctx, event) {
-        // console.log('Auto Save: ', event, ctx.document.toJSON());
-      },
-      // /**
-      //  * Node engine enable, you can configure formMeta in the FlowNodeRegistry
-      //  */
-      nodeEngine: {
-        enable: true,
-      },
-      /**
-       * Redo/Undo enable
-       */
-      history: {
-        enable: true,
-        enableChangeNode: true, // Listen Node engine data change
-      },
-      /**
-       * Playground init
-       */
-      onInit: ctx => {},
-      /**
-       * Playground render
-       */
-      onAllLayersRendered(ctx) {
-        //  Fitview
-        ctx.document.fitView(false);
-      },
-      /**
-       * Playground dispose
-       */
-      onDispose() {
-        console.log('---- Playground Dispose ----');
-      },
-      plugins: () => [
-        /**
-         * Minimap plugin
-         * 缩略图插件
-         */
-        createMinimapPlugin({
-          disableLayer: 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,
-        }),
-        /**
-         * Snap plugin
-         * 自动对齐及辅助线插件
-         */
-        createFreeSnapPlugin({
-          edgeColor: '#00B2B2',
-          alignColor: '#00B2B2',
-          edgeLineWidth: 1,
-          alignLineWidth: 1,
-          alignCrossWidth: 8,
-        }),
-      ]
-    }),
-    [],
-  );
-
-`;
-
-const nodeRegistriesCode = `import { WorkflowNodeRegistry } from '@flowgram.ai/free-layout-editor';
-
-/**
- * You can customize your own node registry
- * 你可以自定义节点的注册器
- */
-export const nodeRegistries: WorkflowNodeRegistry[] = [
-  {
-    type: 'start',
-    meta: {
-      isStart: true, // Mark as start
-      deleteDisable: true, // The start node cannot be deleted
-      copyDisable: true, // The start node cannot be copied
-      defaultPorts: [{ type: 'output' }], // Used to define the input and output ports, the start node only has the output port
-    },
-  },
-  {
-    type: 'end',
-    meta: {
-      deleteDisable: true,
-      copyDisable: true,
-      defaultPorts: [{ type: 'input' }],
-    },
-  },
-  {
-    type: 'custom',
-    meta: {
-    },
-    defaultPorts: [{ type: 'output' }, { type: 'input' }], // A normal node has two ports
-  },
-];
-
-`;
-
-const toolsCode = `import { useEffect, useState } from 'react'
-import { usePlaygroundTools, useClientContext } from '@flowgram.ai/free-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: 226, 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.autoLayout()}>AutoLayout</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>
-}
-`;
-
-const minimapCode = `import { FlowMinimapService, MinimapRender } from '@flowgram.ai/minimap-plugin';
-import { useService } from '@flowgram.ai/free-layout-editor';
-
-
-export const Minimap = () => {
-  const minimapService = useService(FlowMinimapService);
-  return (
-    <div
-      style={{
-        position: 'absolute',
-        left: 226,
-        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>
-  );
-};
-
-`;
 export const FreeLayoutSimplePreview = () => {
   const files = {
     'index.tsx': indexCode,

+ 2 - 0
apps/docs/package.json

@@ -47,7 +47,9 @@
   "devDependencies": {
     "@flowgram.ai/ts-config": "workspace:*",
     "@flowgram.ai/eslint-config": "workspace:*",
+    "webpack-merge": "^5.9.0",
     "@eslint/js": "^9.12.0",
+    "raw-loader": "^4.0.2",
     "@rspress/plugin-typedoc": "^1.38.0",
     "@types/node": "^18",
     "@types/lodash-es": "^4.17.12",

+ 38 - 23
apps/docs/rspress.config.ts

@@ -1,5 +1,6 @@
 import * as path from 'node:path';
 
+import { merge } from 'webpack-merge';
 import { defineConfig } from 'rspress/config';
 
 export default defineConfig({
@@ -9,32 +10,46 @@ export default defineConfig({
   globalStyles: path.join(__dirname, './global.less'),
   builderConfig: {
     tools: {
-      rspack: {
-        optimization: {
-          splitChunks: {
-            chunks: 'all', // 拆分所有模块,包括异步和同步
-            minSize: 30 * 1024, // 30KB 以下不拆分
-            maxSize: 500 * 1024, // 500KB 以上强制拆分
-            minChunks: 1, // 最少被引用 1 次就可以拆分
-            automaticNameDelimiter: '-',
-            cacheGroups: {
-              vendors: {
-                test: /[\\/]node_modules[\\/]/,
-                name: 'vendors',
-                chunks: 'all',
-                priority: -10, // 优先级
+      rspack(options) {
+        return merge(options, {
+          module: {
+            rules: [
+              {
+                test: /\.mdc$/,
+                type: 'asset/source',
+              },
+              {
+                resourceQuery: /raw/,
+                type: 'asset/source',
+              },
+            ],
+          },
+          optimization: {
+            splitChunks: {
+              chunks: 'all', // 拆分所有模块,包括异步和同步
+              minSize: 30 * 1024, // 30KB 以下不拆分
+              maxSize: 500 * 1024, // 500KB 以上强制拆分
+              minChunks: 1, // 最少被引用 1 次就可以拆分
+              automaticNameDelimiter: '-',
+              cacheGroups: {
+                vendors: {
+                  test: /[\\/]node_modules[\\/]/,
+                  name: 'vendors',
+                  chunks: 'all',
+                  priority: -10, // 优先级
+                },
               },
             },
           },
-        },
-        // 禁用 ES 模块输出(启用 CommonJS)
-        experiments: {
-          outputModule: false,
-        },
-        // 允许省略文件扩展名
-        resolve: {
-          fullySpecified: false,
-        },
+          // 禁用 ES 模块输出(启用 CommonJS)
+          experiments: {
+            outputModule: false,
+          },
+          // 允许省略文件扩展名
+          resolve: {
+            fullySpecified: false,
+          },
+        });
       },
     },
   },

+ 63 - 0
common/config/rush/pnpm-lock.yaml

@@ -494,12 +494,18 @@ importers:
       globals:
         specifier: ^15.11.0
         version: 15.13.0
+      raw-loader:
+        specifier: ^4.0.2
+        version: 4.0.2(webpack@5.76.0)
       sucrase:
         specifier: 3.35.0
         version: 3.35.0
       typescript-eslint:
         specifier: ^8.8.1
         version: 8.18.0(eslint@8.57.1)(typescript@5.0.4)
+      webpack-merge:
+        specifier: ^5.9.0
+        version: 5.10.0
 
   ../../config/eslint-config:
     dependencies:
@@ -8001,6 +8007,15 @@ packages:
     engines: {node: '>= 12'}
     dev: false
 
+  /clone-deep@4.0.1:
+    resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
+    engines: {node: '>=6'}
+    dependencies:
+      is-plain-object: 2.0.4
+      kind-of: 6.0.3
+      shallow-clone: 3.0.1
+    dev: true
+
   /clone-response@1.0.2:
     resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==}
     dependencies:
@@ -9479,6 +9494,11 @@ packages:
       keyv: 4.5.4
       rimraf: 3.0.2
 
+  /flat@5.0.2:
+    resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
+    hasBin: true
+    dev: true
+
   /flatted@3.3.2:
     resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
 
@@ -10356,6 +10376,13 @@ packages:
     resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
     engines: {node: '>=12'}
 
+  /is-plain-object@2.0.4:
+    resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      isobject: 3.0.1
+    dev: true
+
   /is-potential-custom-element-name@1.0.1:
     resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
     dev: true
@@ -10456,6 +10483,11 @@ packages:
   /isexe@2.0.0:
     resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
 
+  /isobject@3.0.1:
+    resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
   /isomorphic-rslog@0.0.6:
     resolution: {integrity: sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==}
     engines: {node: '>=14.17.6'}
@@ -12585,6 +12617,17 @@ packages:
     dependencies:
       safe-buffer: 5.2.1
 
+  /raw-loader@4.0.2(webpack@5.76.0):
+    resolution: {integrity: sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==}
+    engines: {node: '>= 10.13.0'}
+    peerDependencies:
+      webpack: ^4.0.0 || ^5.0.0
+    dependencies:
+      loader-utils: 2.0.4
+      schema-utils: 3.3.0
+      webpack: 5.76.0
+    dev: true
+
   /react-devtools-inline@4.4.0:
     resolution: {integrity: sha512-ES0GolSrKO8wsKbsEkVeiR/ZAaHQTY4zDh1UW8DImVmm8oaGLl3ijJDvSGe+qDRKPZdPRnDtWWnSvvrgxXdThQ==}
     dependencies:
@@ -13524,6 +13567,13 @@ packages:
       functions-have-names: 1.2.3
       has-property-descriptors: 1.0.2
 
+  /shallow-clone@3.0.1:
+    resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
+    engines: {node: '>=8'}
+    dependencies:
+      kind-of: 6.0.3
+    dev: true
+
   /shallowequal@1.1.0:
     resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
 
@@ -14801,6 +14851,15 @@ packages:
     engines: {node: '>=12'}
     dev: true
 
+  /webpack-merge@5.10.0:
+    resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==}
+    engines: {node: '>=10.0.0'}
+    dependencies:
+      clone-deep: 4.0.1
+      flat: 5.0.2
+      wildcard: 2.0.1
+    dev: true
+
   /webpack-sources@3.2.3:
     resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
     engines: {node: '>=10.13.0'}
@@ -14936,6 +14995,10 @@ packages:
       stackback: 0.0.2
     dev: true
 
+  /wildcard@2.0.1:
+    resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
+    dev: true
+
   /word-wrap@1.2.5:
     resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
     engines: {node: '>=0.10.0'}