diff --git a/apps/create-app/src/index.ts b/apps/create-app/src/index.ts index d890d754..0c0235b3 100644 --- a/apps/create-app/src/index.ts +++ b/apps/create-app/src/index.ts @@ -41,7 +41,8 @@ program { name: 'Free Layout Demo', value: 'demo-free-layout' }, { name: 'Fixed Layout Demo Simple', value: 'demo-fixed-layout-simple' }, { name: 'Free Layout Demo Simple', value: 'demo-free-layout-simple' }, - { name: 'Free Layout Nextjs Demo', value: 'demo-nextjs' } + { name: 'Free Layout Nextjs Demo', value: 'demo-nextjs' }, + { name: 'Free Layout Vite Demo Simple', value: 'demo-vite' } ], }, ]); diff --git a/apps/demo-fixed-layout/src/nodes/condition/index.ts b/apps/demo-fixed-layout/src/nodes/condition/index.ts index f0b0a619..f260b6b0 100644 --- a/apps/demo-fixed-layout/src/nodes/condition/index.ts +++ b/apps/demo-fixed-layout/src/nodes/condition/index.ts @@ -43,6 +43,7 @@ export const ConditionNodeRegistry: FlowNodeRegistry = { }, }, }, + blocks: [], }, { id: nanoid(5), diff --git a/apps/demo-vite/.eslintrc.js b/apps/demo-vite/.eslintrc.js new file mode 100644 index 00000000..eb44479a --- /dev/null +++ b/apps/demo-vite/.eslintrc.js @@ -0,0 +1,16 @@ +const { defineConfig } = require('@flowgram.ai/eslint-config'); + +module.exports = defineConfig({ + preset: 'web', + packageRoot: __dirname, + rules: { + 'no-console': 'off', + 'react/prop-types': 'off', + 'react/no-deprecated': 'off', + }, + settings: { + react: { + version: 'detect', // 自动检测 React 版本 + }, + }, +}); diff --git a/apps/demo-vite/index.html b/apps/demo-vite/index.html new file mode 100644 index 00000000..698444fb --- /dev/null +++ b/apps/demo-vite/index.html @@ -0,0 +1,13 @@ + + + + + + + Flow FreeLayoutEditor Demo + + +
+ + + diff --git a/apps/demo-vite/package.json b/apps/demo-vite/package.json new file mode 100644 index 00000000..bead384f --- /dev/null +++ b/apps/demo-vite/package.json @@ -0,0 +1,55 @@ +{ + "name": "@flowgram.ai/demo-vite", + "version": "0.1.0", + "description": "", + "keywords": [], + "license": "MIT", + "main": "./src/index.tsx", + "files": [ + "src/", + ".eslintrc.js", + ".gitignore", + "index.html", + "package.json", + "vite.config.js", + "tsconfig.json" + ], + "scripts": { + "dev": "vite", + "start": "vite", + "build": "exit 0", + "clean": "rimraf dist", + "build:production": "vite build", + "lint": "eslint ./src --cache", + "lint:fix": "eslint ./src --fix", + "test": "exit", + "test:cov": "exit", + "watch": "exit 0", + "preview": "vite preview" + }, + "dependencies": { + "@flowgram.ai/free-layout-editor": "workspace:*", + "@flowgram.ai/free-snap-plugin": "workspace:*", + "@flowgram.ai/minimap-plugin": "workspace:*", + "react": "^18", + "react-dom": "^18" + }, + "devDependencies": { + "@flowgram.ai/ts-config": "workspace:*", + "@flowgram.ai/eslint-config": "workspace:*", + "@vitejs/plugin-react": "^4.4.1", + "@types/lodash-es": "^4.17.12", + "@types/node": "^18", + "@types/react": "^18", + "@types/react-dom": "^18", + "eslint": "^8.54.0", + "cross-env": "~7.0.3", + "globals": "^15.11.0", + "less": "^4.1.2", + "vite": "^6.3.5" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + } +} diff --git a/apps/demo-vite/src/app.tsx b/apps/demo-vite/src/app.tsx new file mode 100644 index 00000000..150c56b5 --- /dev/null +++ b/apps/demo-vite/src/app.tsx @@ -0,0 +1,7 @@ +import { createRoot } from 'react-dom/client'; + +import { Editor } from './editor'; + +const app = createRoot(document.getElementById('root')!); + +app.render(); diff --git a/apps/demo-vite/src/components/minimap.tsx b/apps/demo-vite/src/components/minimap.tsx new file mode 100644 index 00000000..518eacfa --- /dev/null +++ b/apps/demo-vite/src/components/minimap.tsx @@ -0,0 +1,35 @@ +import { FlowMinimapService, MinimapRender } from '@flowgram.ai/minimap-plugin'; +import { useService } from '@flowgram.ai/free-layout-editor'; + +export const Minimap = () => { + const minimapService = useService(FlowMinimapService); + return ( +
+ +
+ ); +}; diff --git a/apps/demo-vite/src/components/node-add-panel.tsx b/apps/demo-vite/src/components/node-add-panel.tsx new file mode 100644 index 00000000..ba7ede20 --- /dev/null +++ b/apps/demo-vite/src/components/node-add-panel.tsx @@ -0,0 +1,30 @@ +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); + + return ( +
+ {cardkeys.map((nodeType) => ( +
+ startDragSerivce.startDragCard(nodeType, e, { + data: { + title: `New ${nodeType}`, + content: 'xxxx', + }, + }) + } + > + {nodeType} +
+ ))} +
+ ); +}; diff --git a/apps/demo-vite/src/components/tools.tsx b/apps/demo-vite/src/components/tools.tsx new file mode 100644 index 00000000..6f38bac3 --- /dev/null +++ b/apps/demo-vite/src/components/tools.tsx @@ -0,0 +1,36 @@ +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 ( +
+ + + + + + + {Math.floor(tools.zoom * 100)}% +
+ ); +} diff --git a/apps/demo-vite/src/editor.tsx b/apps/demo-vite/src/editor.tsx new file mode 100644 index 00000000..267f7012 --- /dev/null +++ b/apps/demo-vite/src/editor.tsx @@ -0,0 +1,24 @@ +import { EditorRenderer, FreeLayoutEditorProvider } from '@flowgram.ai/free-layout-editor'; + +import { useEditorProps } from './hooks/use-editor-props'; +import { Tools } from './components/tools'; +import { NodeAddPanel } from './components/node-add-panel'; +import { Minimap } from './components/minimap'; +import '@flowgram.ai/free-layout-editor/index.css'; +import './index.css'; + +export const Editor = () => { + const editorProps = useEditorProps(); + return ( + +
+
+ + +
+ + +
+
+ ); +}; diff --git a/apps/demo-vite/src/hooks/use-editor-props.tsx b/apps/demo-vite/src/hooks/use-editor-props.tsx new file mode 100644 index 00000000..84163317 --- /dev/null +++ b/apps/demo-vite/src/hooks/use-editor-props.tsx @@ -0,0 +1,155 @@ +import { useMemo } from 'react'; + +import { createMinimapPlugin } from '@flowgram.ai/minimap-plugin'; +import { createFreeSnapPlugin } from '@flowgram.ai/free-snap-plugin'; +import { + FreeLayoutProps, + WorkflowNodeProps, + WorkflowNodeRenderer, + Field, + useNodeRender, +} from '@flowgram.ai/free-layout-editor'; + +import { nodeRegistries } from '../node-registries'; +import { initialData } from '../initial-data'; + +export const useEditorProps = () => + useMemo( + () => ({ + /** + * 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: () => ( + <> + name="title"> + {({ field }) =>
{field.value}
} + +
+ name="content"> + + +
+ + ), + }, + }; + }, + materials: { + /** + * Render Node + */ + renderDefaultNode: (props: WorkflowNodeProps) => { + const { form } = useNodeRender(); + return ( + + {form?.render()} + + ); + }, + }, + /** + * 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, + }), + ], + }), + [] + ); diff --git a/apps/demo-vite/src/index.css b/apps/demo-vite/src/index.css new file mode 100644 index 00000000..c76cebfb --- /dev/null +++ b/apps/demo-vite/src/index.css @@ -0,0 +1,107 @@ +.demo-free-node { + display: flex; + min-width: 300px; + min-height: 100px; + flex-direction: column; + align-items: flex-start; + box-sizing: border-box; + border-radius: 8px; + border: 1px solid var(--light-usage-border-color-border, rgba(28, 31, 35, 0.08)); + background: #fff; + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1); +} + +.demo-free-node-title { + background-color: #93bfe2; + width: 100%; + border-radius: 8px 8px 0 0; + padding: 4px 12px; +} +.demo-free-node-content { + padding: 4px 12px; + flex-grow: 1; + width: 100%; +} +.demo-free-node::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + background-color: white; + border-radius: 7px; +} + +.demo-free-node:hover:before { + -webkit-filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.3)) drop-shadow(0 4px 14px rgba(0, 0, 0, 0.1)); + filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.3)) drop-shadow(0 4px 14px rgba(0, 0, 0, 0.1)); +} + +.demo-free-node.activated:before, +.demo-free-node.selected:before { + outline: 2px solid var(--light-usage-primary-color-primary, #4d53e8); + -webkit-filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.3)) drop-shadow(0 4px 14px rgba(0, 0, 0, 0.1)); + filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.3)) drop-shadow(0 4px 14px rgba(0, 0, 0, 0.1)); +} + +.demo-free-sidebar { + height: 100%; + overflow-y: auto; + padding: 12px 16px 0; + box-sizing: border-box; + background: #f7f7fa; + border-right: 1px solid rgba(29, 28, 35, 0.08); +} + +.demo-free-right-top-panel { + position: fixed; + right: 10px; + top: 70px; + width: 300px; + z-index: 999; +} + +.demo-free-card { + width: 140px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + background: #fff; + border-radius: 8px; + box-shadow: 0 6px 8px 0 rgba(28, 31, 35, 0.03); + cursor: -webkit-grab; + cursor: grab; + line-height: 16px; + margin-bottom: 12px; + overflow: hidden; + padding: 16px; + position: relative; + color: black; +} + +.demo-free-layout { + display: flex; + flex-direction: row; + flex-grow: 1; +} + +.demo-free-editor { + flex-grow: 1; + position: relative; + height: 100%; +} + +.demo-free-container { + position: absolute; + left: 0; + top: 0; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; +} + diff --git a/apps/demo-vite/src/index.tsx b/apps/demo-vite/src/index.tsx new file mode 100644 index 00000000..c38080e9 --- /dev/null +++ b/apps/demo-vite/src/index.tsx @@ -0,0 +1 @@ +export { Editor as DemoFreeLayout } from './editor'; diff --git a/apps/demo-vite/src/initial-data.ts b/apps/demo-vite/src/initial-data.ts new file mode 100644 index 00000000..e23756e0 --- /dev/null +++ b/apps/demo-vite/src/initial-data.ts @@ -0,0 +1,49 @@ +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', + }, + ], +}; diff --git a/apps/demo-vite/src/node-registries.ts b/apps/demo-vite/src/node-registries.ts new file mode 100644 index 00000000..703a1f60 --- /dev/null +++ b/apps/demo-vite/src/node-registries.ts @@ -0,0 +1,30 @@ +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 + }, +]; diff --git a/apps/demo-vite/tsconfig.json b/apps/demo-vite/tsconfig.json new file mode 100644 index 00000000..171a60f5 --- /dev/null +++ b/apps/demo-vite/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "@flowgram.ai/ts-config/tsconfig.flow.path.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "experimentalDecorators": true, + "target": "es2020", + "module": "esnext", + "strictPropertyInitialization": false, + "strict": true, + "esModuleInterop": true, + "moduleResolution": "node", + "skipLibCheck": true, + "noUnusedLocals": true, + "noImplicitAny": true, + "allowJs": true, + "resolveJsonModule": true, + "types": ["node"], + "jsx": "react-jsx", + "lib": ["es6", "dom", "es2020", "es2019.Array"] + }, + "include": ["./src"], +} diff --git a/apps/demo-vite/vite.config.js b/apps/demo-vite/vite.config.js new file mode 100644 index 00000000..4a5def4c --- /dev/null +++ b/apps/demo-vite/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index ec9341ba..7341fb5e 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -532,6 +532,61 @@ importers: specifier: ^8.54.0 version: 8.57.1 + ../../apps/demo-vite: + dependencies: + '@flowgram.ai/free-layout-editor': + specifier: workspace:* + version: link:../../packages/client/free-layout-editor + '@flowgram.ai/free-snap-plugin': + specifier: workspace:* + version: link:../../packages/plugins/free-snap-plugin + '@flowgram.ai/minimap-plugin': + specifier: workspace:* + version: link:../../packages/plugins/minimap-plugin + react: + specifier: ^18 + version: 18.3.1 + react-dom: + specifier: ^18 + version: 18.3.1(react@18.3.1) + devDependencies: + '@flowgram.ai/eslint-config': + specifier: workspace:* + version: link:../../config/eslint-config + '@flowgram.ai/ts-config': + specifier: workspace:* + version: link:../../config/ts-config + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/node': + specifier: ^18 + version: 18.19.68 + '@types/react': + specifier: ^18 + version: 18.3.16 + '@types/react-dom': + specifier: ^18 + version: 18.3.5(@types/react@18.3.16) + '@vitejs/plugin-react': + specifier: ^4.4.1 + version: 4.4.1(vite@6.3.5) + cross-env: + specifier: ~7.0.3 + version: 7.0.3 + eslint: + specifier: ^8.54.0 + version: 8.57.1 + globals: + specifier: ^15.11.0 + version: 15.13.0 + less: + specifier: ^4.1.2 + version: 4.3.0 + vite: + specifier: ^6.3.5 + version: 6.3.5(@types/node@18.19.68)(less@4.3.0) + ../../apps/docs: dependencies: '@codesandbox/sandpack-react': @@ -3979,6 +4034,11 @@ packages: resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} engines: {node: '>=6.9.0'} + /@babel/helper-plugin-utils@7.27.1: + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.0): resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} engines: {node: '>=6.9.0'} @@ -4755,6 +4815,26 @@ packages: - supports-color dev: false + /@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.26.10): + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + + /@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.26.10): + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.27.1 + dev: true + /@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0): resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} engines: {node: '>=6.9.0'} @@ -6718,6 +6798,14 @@ packages: dev: true optional: true + /@rollup/rollup-android-arm-eabi@4.40.2: + resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-android-arm64@4.28.1: resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==} cpu: [arm64] @@ -6726,6 +6814,14 @@ packages: dev: true optional: true + /@rollup/rollup-android-arm64@4.40.2: + resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-darwin-arm64@4.28.1: resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==} cpu: [arm64] @@ -6734,6 +6830,14 @@ packages: dev: true optional: true + /@rollup/rollup-darwin-arm64@4.40.2: + resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-darwin-x64@4.28.1: resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==} cpu: [x64] @@ -6742,6 +6846,14 @@ packages: dev: true optional: true + /@rollup/rollup-darwin-x64@4.40.2: + resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-freebsd-arm64@4.28.1: resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==} cpu: [arm64] @@ -6750,6 +6862,14 @@ packages: dev: true optional: true + /@rollup/rollup-freebsd-arm64@4.40.2: + resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-freebsd-x64@4.28.1: resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==} cpu: [x64] @@ -6758,6 +6878,14 @@ packages: dev: true optional: true + /@rollup/rollup-freebsd-x64@4.40.2: + resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm-gnueabihf@4.28.1: resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==} cpu: [arm] @@ -6767,6 +6895,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm-gnueabihf@4.40.2: + resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm-musleabihf@4.28.1: resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==} cpu: [arm] @@ -6776,6 +6912,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm-musleabihf@4.40.2: + resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm64-gnu@4.28.1: resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==} cpu: [arm64] @@ -6785,6 +6929,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm64-gnu@4.40.2: + resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-arm64-musl@4.28.1: resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==} cpu: [arm64] @@ -6794,6 +6946,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-arm64-musl@4.40.2: + resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-loongarch64-gnu@4.28.1: resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==} cpu: [loong64] @@ -6803,6 +6963,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-loongarch64-gnu@4.40.2: + resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-powerpc64le-gnu@4.28.1: resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==} cpu: [ppc64] @@ -6812,6 +6980,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-powerpc64le-gnu@4.40.2: + resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-riscv64-gnu@4.28.1: resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==} cpu: [riscv64] @@ -6821,6 +6997,22 @@ packages: dev: true optional: true + /@rollup/rollup-linux-riscv64-gnu@4.40.2: + resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-musl@4.40.2: + resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-s390x-gnu@4.28.1: resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==} cpu: [s390x] @@ -6830,6 +7022,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-s390x-gnu@4.40.2: + resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-x64-gnu@4.28.1: resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==} cpu: [x64] @@ -6839,6 +7039,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-x64-gnu@4.40.2: + resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-linux-x64-musl@4.28.1: resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==} cpu: [x64] @@ -6848,6 +7056,14 @@ packages: dev: true optional: true + /@rollup/rollup-linux-x64-musl@4.40.2: + resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-win32-arm64-msvc@4.28.1: resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==} cpu: [arm64] @@ -6856,6 +7072,14 @@ packages: dev: true optional: true + /@rollup/rollup-win32-arm64-msvc@4.40.2: + resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-win32-ia32-msvc@4.28.1: resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==} cpu: [ia32] @@ -6864,6 +7088,14 @@ packages: dev: true optional: true + /@rollup/rollup-win32-ia32-msvc@4.40.2: + resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-win32-x64-msvc@4.28.1: resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==} cpu: [x64] @@ -6872,6 +7104,14 @@ packages: dev: true optional: true + /@rollup/rollup-win32-x64-msvc@4.40.2: + resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@rsbuild/core@1.1.13: resolution: {integrity: sha512-XBL2hrin8731W6iTGGL+x3cv07n4vm2D7u6XHRwtQkRfySzAqGx7ThlQLdNX/dJwfsoQrYQuWl/qzaljjXtGtg==} engines: {node: '>=16.7.0'} @@ -7744,6 +7984,35 @@ packages: resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} dev: true + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + dev: true + + /@types/babel__generator@7.27.0: + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + dependencies: + '@babel/types': 7.27.0 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + dev: true + + /@types/babel__traverse@7.20.7: + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + dependencies: + '@babel/types': 7.27.0 + dev: true + /@types/bezier-js@4.1.3: resolution: {integrity: sha512-FNVVCu5mx/rJCWBxLTcL7oOajmGtWtBTDjq6DSUWUI12GeePivrZZXz+UgE0D6VYsLEjvExRO03z4hVtu3pTEQ==} dev: true @@ -8367,6 +8636,22 @@ packages: /@ungap/structured-clone@1.2.1: resolution: {integrity: sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==} + /@vitejs/plugin-react@4.4.1(vite@6.3.5): + resolution: {integrity: sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.26.10) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.26.10) + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.3.5(@types/node@18.19.68)(less@4.3.0) + transitivePeerDependencies: + - supports-color + dev: true + /@vitest/coverage-v8@0.32.4(vitest@0.34.6): resolution: {integrity: sha512-itiCYY3TmWEK+5wnFBoNr0ZA+adACp7Op1r2TeX5dPOgU2See7+Gx2NlK2lVMHVxfPsu5z9jszKa3i//eR+hqg==} peerDependencies: @@ -10702,6 +10987,17 @@ packages: dependencies: picomatch: 4.0.2 + /fdir@6.4.4(picomatch@4.0.2): + resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + dependencies: + picomatch: 4.0.2 + dev: true + /fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} @@ -12062,6 +12358,24 @@ packages: source-map: 0.6.1 dev: true + /less@4.3.0: + resolution: {integrity: sha512-X9RyH9fvemArzfdP8Pi3irr7lor2Ok4rOttDXBhlwDg+wKQsXOXgHWduAJE1EsF7JJx0w0bcO6BC6tCKKYnXKA==} + engines: {node: '>=14'} + hasBin: true + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.3.1 + source-map: 0.6.1 + dev: true + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -13973,6 +14287,15 @@ packages: picocolors: 1.1.1 source-map-js: 1.2.1 + /postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + dev: true + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -14199,6 +14522,11 @@ packages: resolution: {integrity: sha512-FPvF2XxTSikpJxcr+bHut2H4gJ17+18Uy20D5/F+SKzFap62R3cM5wH6b8WN3LyGSYeQilLEcJcR1fjBSI2S1A==} engines: {node: '>=0.10.0'} + /react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + dev: true + /react-resizable@3.0.5(react-dom@18.3.1)(react@18.3.1): resolution: {integrity: sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==} peerDependencies: @@ -14660,6 +14988,36 @@ packages: fsevents: 2.3.3 dev: true + /rollup@4.40.2: + resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.40.2 + '@rollup/rollup-android-arm64': 4.40.2 + '@rollup/rollup-darwin-arm64': 4.40.2 + '@rollup/rollup-darwin-x64': 4.40.2 + '@rollup/rollup-freebsd-arm64': 4.40.2 + '@rollup/rollup-freebsd-x64': 4.40.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 + '@rollup/rollup-linux-arm-musleabihf': 4.40.2 + '@rollup/rollup-linux-arm64-gnu': 4.40.2 + '@rollup/rollup-linux-arm64-musl': 4.40.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-musl': 4.40.2 + '@rollup/rollup-linux-s390x-gnu': 4.40.2 + '@rollup/rollup-linux-x64-gnu': 4.40.2 + '@rollup/rollup-linux-x64-musl': 4.40.2 + '@rollup/rollup-win32-arm64-msvc': 4.40.2 + '@rollup/rollup-win32-ia32-msvc': 4.40.2 + '@rollup/rollup-win32-x64-msvc': 4.40.2 + fsevents: 2.3.3 + dev: true + /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true @@ -15651,6 +16009,14 @@ packages: fdir: 6.4.2(picomatch@4.0.2) picomatch: 4.0.2 + /tinyglobby@0.2.13: + resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + engines: {node: '>=12.0.0'} + dependencies: + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + dev: true + /tinypool@0.7.0: resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} engines: {node: '>=14.0.0'} @@ -16279,6 +16645,58 @@ packages: fsevents: 2.3.3 dev: true + /vite@6.3.5(@types/node@18.19.68)(less@4.3.0): + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + dependencies: + '@types/node': 18.19.68 + esbuild: 0.25.4 + fdir: 6.4.4(picomatch@4.0.2) + less: 4.3.0 + picomatch: 4.0.2 + postcss: 8.5.3 + rollup: 4.40.2 + tinyglobby: 0.2.13 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vitest@0.34.6(jsdom@22.1.0): resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} diff --git a/packages/canvas-engine/document/src/flow-document.ts b/packages/canvas-engine/document/src/flow-document.ts index 35a2c43f..807376a2 100644 --- a/packages/canvas-engine/document/src/flow-document.ts +++ b/packages/canvas-engine/document/src/flow-document.ts @@ -79,6 +79,8 @@ export class FlowDocument implements Disposable { readonly onLayoutChange = this.onLayoutChangeEmitter.event; + private _disposed = false; + root: FlowNodeEntity; /** @@ -98,6 +100,13 @@ export class FlowDocument implements Disposable { */ renderTree: FlowRenderTree; + /** + * + */ + get disposed(): boolean { + return this._disposed; + } + @postConstruct() init(): void { if (!this.options) this.options = FlowDocumentOptionsDefault; @@ -126,6 +135,7 @@ export class FlowDocument implements Disposable { * @param fireRender 是否要触发渲染,默认 true */ fromJSON(json: FlowDocumentJSON | any, fireRender = true): void { + if (this._disposed) return; // 清空 tree 数据 重新计算 this.originTree.clear(); this.renderTree.clear(); @@ -665,6 +675,7 @@ export class FlowDocument implements Disposable { } dispose() { + if (this._disposed) return; this.registers.clear(); this.nodeRegistryCache.clear(); this.originTree.dispose(); @@ -673,5 +684,6 @@ export class FlowDocument implements Disposable { this.onNodeCreateEmitter.dispose(); this.onNodeDisposeEmitter.dispose(); this.onLayoutChangeEmitter.dispose(); + this._disposed = true; } } diff --git a/packages/canvas-engine/free-layout-core/src/workflow-document.ts b/packages/canvas-engine/free-layout-core/src/workflow-document.ts index 2d6376a1..5286d65a 100644 --- a/packages/canvas-engine/free-layout-core/src/workflow-document.ts +++ b/packages/canvas-engine/free-layout-core/src/workflow-document.ts @@ -55,8 +55,6 @@ export class WorkflowDocument extends FlowDocument { readonly onReload = this._onReloadEmitter.event; - private disposed = false; - /** * 数据加载完成 */ @@ -102,6 +100,7 @@ export class WorkflowDocument extends FlowDocument { } async load(): Promise { + if (this.disposed) return; this._loading = true; await super.load(); this._loading = false; @@ -109,6 +108,7 @@ export class WorkflowDocument extends FlowDocument { } async reload(json: WorkflowJSON, delayTime = 0): Promise { + if (this.disposed) return; this._loading = true; this.clear(); this.fromJSON(json); @@ -123,6 +123,7 @@ export class WorkflowDocument extends FlowDocument { * @param json */ fromJSON(json: Partial, fireRender = true): void { + if (this.disposed) return; const workflowJSON: WorkflowJSON = { nodes: json.nodes ?? [], edges: json.edges ?? [], @@ -563,11 +564,7 @@ export class WorkflowDocument extends FlowDocument { } dispose() { - if (this.disposed) { - return; - } super.dispose(); - this.disposed = true; this._onReloadEmitter.dispose(); } diff --git a/rush.json b/rush.json index d69ec530..1d096573 100644 --- a/rush.json +++ b/rush.json @@ -771,6 +771,12 @@ "projectFolder": "apps/demo-react-16", "versionPolicyName": "appPolicy", "tags": ["level-1", "team-flow", "demo"] + }, + { + "packageName": "@flowgram.ai/demo-vite", + "projectFolder": "apps/demo-vite", + "versionPolicyName": "appPolicy", + "tags": ["level-1", "team-flow", "demo"] } ] }