├── .changeset ├── README.md └── config.json ├── .commitlintrc.js ├── .eslintignore ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE │ ├── BUG_REPORT_ZH.yml │ ├── BUG_REPROT_EN.yml │ ├── FEATRUE_ZH.yml │ └── config.yml └── workflows │ ├── PULL_REQUEST_TEMPLATE.md │ ├── docs.yaml │ ├── issue_checker.yaml │ ├── release.yml │ └── update_contributors.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .markdownlint.json ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .stylelintrc ├── .vscode └── settings.json ├── CONTRIBUTING.md ├── CONTRIBUTORS.svg ├── CONTRUBUTING.en-US.md ├── LICENSE ├── README.en-US.md ├── README.md ├── babel.config.json ├── examples ├── demo.html ├── engine-browser-examples │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ └── vite.svg │ ├── src │ │ ├── assets │ │ │ ├── bpmn │ │ │ │ ├── delete.png │ │ │ │ ├── end-event-none.png │ │ │ │ ├── export.png │ │ │ │ ├── gateway-xor.png │ │ │ │ ├── image.png │ │ │ │ ├── select.png │ │ │ │ ├── service-task.png │ │ │ │ ├── service.png │ │ │ │ ├── start-event-none.png │ │ │ │ ├── subprocess-collapsed.png │ │ │ │ ├── subprocess-expanded.png │ │ │ │ ├── task-none.png │ │ │ │ ├── upload.png │ │ │ │ └── user-task.png │ │ │ ├── group │ │ │ │ ├── circle.png │ │ │ │ ├── group.png │ │ │ │ ├── rect.png │ │ │ │ ├── subprocess-collapsed.png │ │ │ │ └── subprocess-expanded.png │ │ │ └── react.svg │ │ ├── index.css │ │ ├── main.tsx │ │ ├── pages │ │ │ ├── ErrorPage.tsx │ │ │ ├── Home.tsx │ │ │ ├── engine │ │ │ │ ├── Condition.tsx │ │ │ │ ├── GetStarted.tsx │ │ │ │ └── Recorder.tsx │ │ │ ├── extension │ │ │ │ ├── bpmn │ │ │ │ │ ├── bpmn.json │ │ │ │ │ ├── diagram.xml │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── svgIcons.ts │ │ │ │ │ ├── tips.ts │ │ │ │ │ └── util.ts │ │ │ │ ├── dynamic-group │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── nodes │ │ │ │ │ │ ├── custom-group │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── sub-process │ │ │ │ │ │ └── index.ts │ │ │ │ └── label │ │ │ │ │ ├── data.ts │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── noteNode.ts │ │ │ └── graph │ │ │ │ ├── edges │ │ │ │ ├── animation.ts │ │ │ │ ├── connection.ts │ │ │ │ └── index.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── nodes │ │ │ │ ├── ReactNode.tsx │ │ │ │ ├── combine.ts │ │ │ │ ├── index.ts │ │ │ │ ├── square.ts │ │ │ │ ├── star.ts │ │ │ │ ├── uml.ts │ │ │ │ └── user.ts │ │ ├── routes │ │ │ └── root.tsx │ │ ├── utls.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── engine-node-examples │ ├── index.js │ └── package.json ├── feature-examples │ ├── .gitignore │ ├── .umirc.ts │ ├── package.json │ ├── public │ │ └── images │ │ │ └── test.jpeg │ ├── src │ │ ├── assets │ │ │ ├── bpmn │ │ │ │ ├── delete.png │ │ │ │ ├── end-event-none.png │ │ │ │ ├── export.png │ │ │ │ ├── gateway-xor.png │ │ │ │ ├── image.png │ │ │ │ ├── select.png │ │ │ │ ├── service-task.png │ │ │ │ ├── service.png │ │ │ │ ├── start-event-none.png │ │ │ │ ├── subprocess-collapsed.png │ │ │ │ ├── subprocess-expanded.png │ │ │ │ ├── task-none.png │ │ │ │ ├── upload.png │ │ │ │ └── user-task.png │ │ │ ├── didi.png │ │ │ ├── group │ │ │ │ ├── circle.png │ │ │ │ ├── group.png │ │ │ │ ├── rect.png │ │ │ │ ├── subprocess-collapsed.png │ │ │ │ └── subprocess-expanded.png │ │ │ └── yay.jpg │ │ ├── components │ │ │ ├── edges │ │ │ │ ├── custom-animate-polyline │ │ │ │ │ └── index.tsx │ │ │ │ ├── custom-curved-polyline │ │ │ │ │ └── index.tsx │ │ │ │ └── custom-polyline │ │ │ │ │ └── index.tsx │ │ │ └── nodes │ │ │ │ ├── custom-circle │ │ │ │ └── index.ts │ │ │ │ ├── custom-diamond │ │ │ │ └── index.tsx │ │ │ │ ├── custom-ellipse │ │ │ │ └── index.tsx │ │ │ │ ├── custom-html │ │ │ │ ├── Html.tsx │ │ │ │ ├── Icon.tsx │ │ │ │ ├── Image.tsx │ │ │ │ ├── Text.tsx │ │ │ │ └── index.ts │ │ │ │ ├── custom-polygon │ │ │ │ └── index.tsx │ │ │ │ ├── custom-rect │ │ │ │ └── index.tsx │ │ │ │ ├── freeAnchor-circle │ │ │ │ └── index.tsx │ │ │ │ └── freeAnchor-rect │ │ │ │ └── index.tsx │ │ ├── layouts │ │ │ ├── index.less │ │ │ └── index.tsx │ │ └── pages │ │ │ ├── background │ │ │ ├── index.less │ │ │ └── index.tsx │ │ │ ├── edges │ │ │ └── custom │ │ │ │ ├── animate-polyline │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ │ ├── curved-polyline │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ │ └── polyline │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── extensions │ │ │ ├── bpmn │ │ │ │ ├── bpmn.json │ │ │ │ ├── diagram.xml │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── svgIcons.ts │ │ │ │ ├── tips.ts │ │ │ │ └── util.ts │ │ │ ├── control │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── dnd-panel │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── nodes │ │ │ │ │ ├── end.ts │ │ │ │ │ └── start.ts │ │ │ ├── dynamic-group │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── nodes │ │ │ │ │ ├── custom-group │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── sub-process │ │ │ │ │ └── index.ts │ │ │ ├── group │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── nodes │ │ │ │ │ ├── custom-group │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── sub-process │ │ │ │ │ └── index.ts │ │ │ ├── highlight │ │ │ │ ├── data.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── insert-node-in-polyline │ │ │ │ ├── NotAllowConnectRect.ts │ │ │ │ ├── data.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── menu │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── mini-map │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── node-selection │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── proximity-connect │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── rect-label-node │ │ │ │ └── index.tsx │ │ │ ├── rules │ │ │ │ ├── Start.ts │ │ │ │ ├── UserTask.ts │ │ │ │ ├── data.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── svg.ts │ │ │ ├── selection-select │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ └── snapshot │ │ │ │ ├── data.ts │ │ │ │ ├── imageNode.ts │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ └── svg.ts │ │ │ ├── graph │ │ │ ├── edges │ │ │ │ ├── animation.ts │ │ │ │ ├── connection.ts │ │ │ │ └── index.ts │ │ │ ├── index.less │ │ │ ├── index.tsx │ │ │ └── nodes │ │ │ │ ├── combine.ts │ │ │ │ ├── index.ts │ │ │ │ ├── square.ts │ │ │ │ ├── star.ts │ │ │ │ ├── uml.ts │ │ │ │ └── user.ts │ │ │ ├── grid │ │ │ ├── index.less │ │ │ └── index.tsx │ │ │ ├── nodes │ │ │ ├── custom │ │ │ │ ├── ellipse │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── freeAnchorNode │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── html │ │ │ │ │ ├── data.ts │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── style.css │ │ │ │ ├── icon │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── image │ │ │ │ │ ├── Cloud.tsx │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ ├── rect │ │ │ │ │ ├── index.less │ │ │ │ │ └── index.tsx │ │ │ │ └── theme │ │ │ │ │ ├── index.less │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── theme.ts │ │ │ └── native │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── performance │ │ │ └── snapshot-elements │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ └── react │ │ │ ├── Portal.tsx │ │ │ ├── index.less │ │ │ └── index.tsx │ ├── tsconfig.json │ └── typings.d.ts ├── material-ui-demo │ ├── .env │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── jsconfig.json │ ├── package.json │ ├── public │ │ ├── favicon.svg │ │ └── index.html │ └── src │ │ ├── App.js │ │ ├── assets │ │ ├── images │ │ │ ├── auth │ │ │ │ ├── auth-blue-card.svg │ │ │ │ ├── auth-pattern-dark.svg │ │ │ │ ├── auth-pattern.svg │ │ │ │ ├── auth-purple-card.svg │ │ │ │ ├── auth-signup-blue-card.svg │ │ │ │ └── auth-signup-white-card.svg │ │ │ ├── icons │ │ │ │ ├── earning.svg │ │ │ │ └── social-google.svg │ │ │ ├── logo-dark.svg │ │ │ ├── logo-white.svg │ │ │ ├── logo.svg │ │ │ └── users │ │ │ │ └── user-round.svg │ │ └── scss │ │ │ ├── _themes-vars.module.scss │ │ │ └── style.scss │ │ ├── config.js │ │ ├── hooks │ │ └── useScriptRef.js │ │ ├── index.js │ │ ├── layout │ │ ├── Customization │ │ │ └── index.js │ │ ├── MainLayout │ │ │ ├── Header │ │ │ │ ├── SearchSection │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ ├── LogoSection │ │ │ │ └── index.js │ │ │ ├── Sidebar │ │ │ │ ├── MenuList │ │ │ │ │ ├── NavCollapse │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── NavGroup │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── NavItem │ │ │ │ │ │ └── index.js │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── MinimalLayout │ │ │ └── index.js │ │ ├── NavMotion.js │ │ └── NavigationScroll.js │ │ ├── menu-items │ │ ├── dashboard.js │ │ ├── edges.js │ │ ├── index.js │ │ ├── layout.js │ │ └── nodes.js │ │ ├── routes │ │ ├── MainRoutes.js │ │ └── index.js │ │ ├── serviceWorker.js │ │ ├── store │ │ ├── actions.js │ │ ├── constant.js │ │ ├── customizationReducer.js │ │ ├── index.js │ │ └── reducer.js │ │ ├── themes │ │ ├── compStyleOverride.js │ │ ├── index.js │ │ ├── palette.js │ │ └── typography.js │ │ ├── ui-component │ │ ├── Loadable.js │ │ ├── Loader.js │ │ ├── Logo.js │ │ ├── cards │ │ │ ├── AuthFooter.js │ │ │ ├── CardSecondaryAction.js │ │ │ ├── MainCard.js │ │ │ ├── Skeleton │ │ │ │ ├── EarningCard.js │ │ │ │ ├── ImagePlaceholder.js │ │ │ │ ├── PopularCard.js │ │ │ │ ├── ProductPlaceholder.js │ │ │ │ ├── TotalGrowthBarChart.js │ │ │ │ └── TotalIncomeCard.js │ │ │ └── SubCard.js │ │ └── extended │ │ │ ├── AnimateButton.js │ │ │ ├── Avatar.js │ │ │ ├── Breadcrumbs.js │ │ │ └── Transitions.js │ │ ├── utils │ │ └── password-strength.js │ │ └── views │ │ ├── dashboard │ │ └── Default │ │ │ ├── BajajAreaChartCard.js │ │ │ ├── EarningCard.js │ │ │ ├── PopularCard.js │ │ │ ├── TotalGrowthBarChart.js │ │ │ ├── TotalIncomeDarkCard.js │ │ │ ├── TotalIncomeLightCard.js │ │ │ ├── TotalOrderLineChartCard.js │ │ │ ├── chart-data │ │ │ ├── bajaj-area-chart.js │ │ │ ├── total-growth-bar-chart.js │ │ │ ├── total-order-month-line-chart.js │ │ │ └── total-order-year-line-chart.js │ │ │ └── index.js │ │ ├── edges │ │ └── index.js │ │ ├── layout │ │ ├── Color.js │ │ ├── MaterialIcons.js │ │ ├── Shadow.js │ │ ├── TablerIcons.js │ │ └── Typography.js │ │ └── nodes │ │ └── index.js ├── next-app │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ │ ├── next.svg │ │ └── vercel.svg │ ├── src │ │ └── app │ │ │ ├── edges │ │ │ ├── animation.ts │ │ │ ├── connection.ts │ │ │ └── index.ts │ │ │ ├── favicon.ico │ │ │ ├── globals.css │ │ │ ├── index.css │ │ │ ├── layout.tsx │ │ │ ├── nodes │ │ │ ├── ReactNode.tsx │ │ │ ├── combine.ts │ │ │ ├── index.ts │ │ │ ├── square.ts │ │ │ ├── star.ts │ │ │ ├── uml.ts │ │ │ └── user.ts │ │ │ └── page.tsx │ ├── tailwind.config.ts │ └── tsconfig.json ├── vue3-app │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .prettierrc.json │ ├── .vscode │ │ └── extensions.json │ ├── README.md │ ├── env.d.ts │ ├── index.html │ ├── package.json │ ├── postcss.config.js │ ├── public │ │ └── favicon.ico │ ├── src │ │ ├── App.vue │ │ ├── assets │ │ │ ├── base.css │ │ │ ├── didi.png │ │ │ ├── logo.svg │ │ │ └── main.css │ │ ├── components │ │ │ ├── HelloWorld.vue │ │ │ ├── LFElements │ │ │ │ ├── ProgressNode.vue │ │ │ │ ├── edges │ │ │ │ │ ├── animation.ts │ │ │ │ │ ├── connection.ts │ │ │ │ │ └── index.ts │ │ │ │ └── nodes │ │ │ │ │ ├── combine.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── square.ts │ │ │ │ │ ├── star.ts │ │ │ │ │ ├── uml.ts │ │ │ │ │ └── user.ts │ │ │ ├── TheWelcome.vue │ │ │ ├── UILibrary │ │ │ │ ├── EchartNode.vue │ │ │ │ ├── ElementNode.vue │ │ │ │ └── echart │ │ │ │ │ ├── BarRaceChart.vue │ │ │ │ │ ├── RadarChart.vue │ │ │ │ │ ├── ScatterAggregateChart.vue │ │ │ │ │ └── StackedLineChart.vue │ │ │ ├── UmlClass.vue │ │ │ ├── WelcomeItem.vue │ │ │ ├── __tests__ │ │ │ │ └── HelloWorld.spec.ts │ │ │ ├── chart │ │ │ │ ├── confg.ts │ │ │ │ ├── graph.ts │ │ │ │ ├── linkChart.ts │ │ │ │ ├── nodes │ │ │ │ │ ├── AnalysisNode.ts │ │ │ │ │ ├── AnalysisNode.vue │ │ │ │ │ ├── DefaultNode.ts │ │ │ │ │ ├── DefaultNode.vue │ │ │ │ │ ├── FirstGroup.ts │ │ │ │ │ ├── LandingGroup.ts │ │ │ │ │ ├── MiddleGroup.ts │ │ │ │ │ └── index.ts │ │ │ │ └── types.d.ts │ │ │ ├── dom │ │ │ │ └── DomNumber.vue │ │ │ └── icons │ │ │ │ ├── IconCommunity.vue │ │ │ │ ├── IconDocumentation.vue │ │ │ │ ├── IconEcosystem.vue │ │ │ │ ├── IconSupport.vue │ │ │ │ └── IconTooling.vue │ │ ├── main.ts │ │ ├── router │ │ │ └── index.ts │ │ ├── shims-vue.d.ts │ │ ├── utils │ │ │ ├── math.ts │ │ │ └── performance.ts │ │ └── views │ │ │ ├── HomeView.vue │ │ │ ├── KeepAliveAndTeleport.vue │ │ │ ├── LFChartView.vue │ │ │ ├── LogicFlowView.vue │ │ │ └── PerformanceNode.vue │ ├── tailwind.config.js │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── tsconfig.vitest.json │ ├── vite.config.ts │ └── vitest.config.ts └── vue3-memory-leak │ ├── .gitignore │ ├── README.md │ ├── auto-imports.d.ts │ ├── components.d.ts │ ├── index.html │ ├── package.json │ ├── public │ ├── favicon.ico │ └── images │ │ ├── delay.svg │ │ ├── fetch.svg │ │ ├── function.svg │ │ ├── start.svg │ │ ├── swap.svg │ │ └── switch.svg │ ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ ├── FlowChart.vue │ │ ├── engine │ │ │ └── index.js │ │ ├── index.vue │ │ └── node-red │ │ │ ├── FlowLink.js │ │ │ ├── index.js │ │ │ ├── nodes │ │ │ ├── BaseNode.js │ │ │ ├── DelayNode.js │ │ │ ├── FetchNode.js │ │ │ ├── FunctionNode.js │ │ │ ├── StartNode.js │ │ │ ├── SwitchNode.js │ │ │ ├── VueHtmlNode.js │ │ │ └── VueNode.vue │ │ │ ├── readme.md │ │ │ ├── style.css │ │ │ ├── tools │ │ │ ├── Palette.vue │ │ │ └── Setting.vue │ │ │ └── util.js │ ├── main.js │ └── style.css │ ├── vite.config.js │ └── yarn.lock ├── jest.config.js ├── lerna.json ├── package.json ├── packages ├── core │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── algorithm │ │ │ ├── egde.test.ts │ │ │ ├── index.test.ts │ │ │ └── outline.test.ts │ │ ├── bugs │ │ │ └── 1545-spec.test.ts │ │ ├── event │ │ │ └── event.test.ts │ │ ├── history │ │ │ └── history.test.ts │ │ ├── logicflow.test.ts │ │ ├── model │ │ │ └── graphmodel.test.ts │ │ └── util │ │ │ ├── compatible.test.ts │ │ │ ├── edge.test.ts │ │ │ ├── geometry.test.ts │ │ │ ├── graph.test.ts │ │ │ ├── matrix.test.ts │ │ │ ├── node.test.ts │ │ │ ├── sampling.test.ts │ │ │ ├── vector.test.ts │ │ │ └── zIndex.test.ts │ ├── package.json │ ├── src │ │ ├── LogicFlow.tsx │ │ ├── algorithm │ │ │ ├── edge.ts │ │ │ ├── index.ts │ │ │ ├── outline.ts │ │ │ └── rotate.ts │ │ ├── common │ │ │ ├── drag.ts │ │ │ ├── history.ts │ │ │ ├── index.ts │ │ │ ├── keyboard.ts │ │ │ ├── matrix.ts │ │ │ └── vector.ts │ │ ├── constant │ │ │ └── index.ts │ │ ├── event │ │ │ ├── event.md │ │ │ ├── eventArgs.ts │ │ │ └── eventEmitter.ts │ │ ├── history │ │ │ └── index.ts │ │ ├── index.less │ │ ├── index.ts │ │ ├── keyboard │ │ │ ├── index.ts │ │ │ └── shortcut.ts │ │ ├── model │ │ │ ├── BaseModel.ts │ │ │ ├── EditConfigModel.ts │ │ │ ├── GraphModel.ts │ │ │ ├── SnaplineModel.ts │ │ │ ├── TransformModel.ts │ │ │ ├── edge │ │ │ │ ├── BaseEdgeModel.ts │ │ │ │ ├── BezierEdgeModel.ts │ │ │ │ ├── LineEdgeModel.ts │ │ │ │ ├── PolylineEdgeModel.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── node │ │ │ │ ├── BaseNodeModel.ts │ │ │ │ ├── CircleNodeModel.ts │ │ │ │ ├── DiamondNodeModel.ts │ │ │ │ ├── EllipseNodeModel.ts │ │ │ │ ├── HtmlNodeModel.ts │ │ │ │ ├── PolygonNodeModel.ts │ │ │ │ ├── RectNodeModel.ts │ │ │ │ ├── TextNodeModel.ts │ │ │ │ └── index.ts │ │ ├── options.ts │ │ ├── style │ │ │ ├── index.less │ │ │ └── raw.ts │ │ ├── tool │ │ │ ├── MultipleSelectTool.tsx │ │ │ ├── TextEditTool.tsx │ │ │ └── index.ts │ │ ├── typings.d.ts │ │ ├── util │ │ │ ├── animation.ts │ │ │ ├── browser.ts │ │ │ ├── compatible.ts │ │ │ ├── drag.ts │ │ │ ├── edge.ts │ │ │ ├── geometry.ts │ │ │ ├── graph.ts │ │ │ ├── index.ts │ │ │ ├── matrix.ts │ │ │ ├── mobx.ts │ │ │ ├── node.ts │ │ │ ├── raf.ts │ │ │ ├── resize.ts │ │ │ ├── sampling.ts │ │ │ ├── theme.ts │ │ │ ├── uuid.ts │ │ │ ├── vector.ts │ │ │ └── zIndex.ts │ │ └── view │ │ │ ├── Anchor.tsx │ │ │ ├── Control.tsx │ │ │ ├── Graph.tsx │ │ │ ├── Rotate.tsx │ │ │ ├── behavior │ │ │ ├── dnd.ts │ │ │ ├── index.ts │ │ │ └── snapline.ts │ │ │ ├── edge │ │ │ ├── AdjustPoint.tsx │ │ │ ├── Arrow.tsx │ │ │ ├── BaseEdge.tsx │ │ │ ├── BezierEdge.tsx │ │ │ ├── LineEdge.tsx │ │ │ ├── PolylineEdge.tsx │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── node │ │ │ ├── BaseNode.tsx │ │ │ ├── CircleNode.tsx │ │ │ ├── DiamondNode.tsx │ │ │ ├── EllipseNode.tsx │ │ │ ├── HtmlNode.tsx │ │ │ ├── PolygonNode.tsx │ │ │ ├── RectNode.tsx │ │ │ ├── TextNode.tsx │ │ │ └── index.ts │ │ │ ├── overlay │ │ │ ├── BackgroundOverlay.tsx │ │ │ ├── BezierAdjustOverlay.tsx │ │ │ ├── CanvasOverlay.tsx │ │ │ ├── Grid.tsx │ │ │ ├── ModificationOverlay.tsx │ │ │ ├── OutlineOverlay.tsx │ │ │ ├── SnaplineOverlay.tsx │ │ │ ├── ToolOverlay.tsx │ │ │ ├── getTransformHoc.tsx │ │ │ └── index.ts │ │ │ ├── shape │ │ │ ├── Circle.tsx │ │ │ ├── Ellipse.tsx │ │ │ ├── Line.tsx │ │ │ ├── Path.tsx │ │ │ ├── Polygon.tsx │ │ │ ├── Polyline.tsx │ │ │ ├── Rect.tsx │ │ │ ├── Text.tsx │ │ │ └── index.ts │ │ │ └── text │ │ │ ├── BaseText.tsx │ │ │ ├── LineText.tsx │ │ │ └── index.ts │ └── tsconfig.json ├── engine │ ├── .babelrc │ ├── CHANGELOG.md │ ├── README.md │ ├── __test__ │ │ ├── 01_index.test.ts │ │ ├── 02_recorder.test.ts │ │ ├── 03_condition.test.ts │ │ ├── 04_execute.test.ts │ │ ├── 05_customNode.test.ts │ │ ├── 06_parallelExecution.test.ts │ │ ├── 07_interruptedAndResume.test.ts │ │ └── 08_error.test.ts │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── EventEmitter.ts │ │ ├── FlowModel.ts │ │ ├── Scheduler.ts │ │ ├── constant │ │ │ ├── LogCode.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── nodes │ │ │ ├── base.ts │ │ │ ├── index.ts │ │ │ ├── start.ts │ │ │ └── task.ts │ │ ├── platform │ │ │ ├── browser │ │ │ │ ├── browserVm.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── node │ │ │ │ ├── index.ts │ │ │ │ └── nodeVm.ts │ │ ├── recorder │ │ │ └── index.ts │ │ └── utils │ │ │ ├── global.ts │ │ │ ├── id.ts │ │ │ ├── index.ts │ │ │ └── storage.ts │ └── tsconfig.json ├── extension │ ├── CHANGELOG.md │ ├── README.md │ ├── __test__ │ │ └── bpmn-adapter.test.js │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── NodeResize │ │ │ ├── BasicShape │ │ │ │ ├── Ellipse.tsx │ │ │ │ ├── Polygon.tsx │ │ │ │ └── Rect.tsx │ │ │ ├── control │ │ │ │ ├── Control.tsx │ │ │ │ ├── ControlGroup.tsx │ │ │ │ └── Util.ts │ │ │ ├── index.ts │ │ │ └── node │ │ │ │ ├── DiamondResize.tsx │ │ │ │ ├── EllipseResize.tsx │ │ │ │ ├── HtmlResize.tsx │ │ │ │ ├── RectResize.tsx │ │ │ │ └── index.ts │ │ ├── bpmn-adapter │ │ │ ├── bpmnIds.ts │ │ │ ├── index.ts │ │ │ ├── json2xml.ts │ │ │ └── xml2json.ts │ │ ├── bpmn-elements-adapter │ │ │ ├── README.md │ │ │ ├── __tests__ │ │ │ │ ├── adapter_in.test.js │ │ │ │ └── adapter_out.test.js │ │ │ ├── constant.ts │ │ │ ├── index.ts │ │ │ ├── json2xml.ts │ │ │ └── xml2json.ts │ │ ├── bpmn-elements │ │ │ ├── README.md │ │ │ ├── __tests__ │ │ │ │ └── definition.test.js │ │ │ ├── index.d.ts │ │ │ ├── index.ts │ │ │ ├── presets │ │ │ │ ├── Event │ │ │ │ │ ├── EndEventFactory.ts │ │ │ │ │ ├── IntermediateCatchEvent.ts │ │ │ │ │ ├── IntermediateThrowEvent.ts │ │ │ │ │ ├── StartEventFactory.ts │ │ │ │ │ ├── boundaryEventFactory.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── Flow │ │ │ │ │ ├── flow.d.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── manhattan.ts │ │ │ │ │ └── sequenceFlow.ts │ │ │ │ ├── Gateway │ │ │ │ │ ├── gateway.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── Pool │ │ │ │ │ ├── Lane.ts │ │ │ │ │ ├── Pool.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── Task │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── subProcess.ts │ │ │ │ │ └── task.ts │ │ │ │ └── icons.ts │ │ │ └── utils.ts │ │ ├── bpmn │ │ │ ├── constant.ts │ │ │ ├── events │ │ │ │ ├── EndEvent.ts │ │ │ │ ├── StartEvent.ts │ │ │ │ └── index.ts │ │ │ ├── flow │ │ │ │ ├── SequenceFlow.ts │ │ │ │ └── index.ts │ │ │ ├── gateways │ │ │ │ ├── ExclusiveGateway.ts │ │ │ │ └── index.ts │ │ │ ├── getBpmnId.ts │ │ │ ├── index.ts │ │ │ └── tasks │ │ │ │ ├── ServiceTask.ts │ │ │ │ ├── UserTask.ts │ │ │ │ └── index.ts │ │ ├── components │ │ │ ├── context-menu │ │ │ │ └── index.ts │ │ │ ├── control │ │ │ │ └── index.ts │ │ │ ├── dnd-panel │ │ │ │ └── index.ts │ │ │ ├── highlight │ │ │ │ └── index.ts │ │ │ ├── menu │ │ │ │ └── index.ts │ │ │ ├── mini-map │ │ │ │ └── index.ts │ │ │ └── selection-select │ │ │ │ └── index.ts │ │ ├── dynamic-group │ │ │ ├── index.ts │ │ │ ├── model.ts │ │ │ ├── node.ts │ │ │ └── utils.ts │ │ ├── index.less │ │ ├── index.ts │ │ ├── insert-node-in-polyline │ │ │ ├── edge.ts │ │ │ └── index.ts │ │ ├── materials │ │ │ ├── curved-edge │ │ │ │ ├── __test__ │ │ │ │ │ └── curved-edge.test.ts │ │ │ │ └── index.ts │ │ │ ├── group │ │ │ │ ├── GroupNode.ts │ │ │ │ └── index.ts │ │ │ └── node-selection │ │ │ │ └── index.ts │ │ ├── mindmap │ │ │ ├── fakerRoot.ts │ │ │ ├── index.ts │ │ │ ├── markContent.ts │ │ │ ├── markContentOption.ts │ │ │ ├── markEntity.ts │ │ │ ├── markRoot.ts │ │ │ └── theme.ts │ │ ├── rect-label-node │ │ │ ├── RectLabelNodeView.ts │ │ │ └── index.ts │ │ ├── style │ │ │ ├── index.less │ │ │ └── raw.ts │ │ ├── tools │ │ │ ├── auto-layout │ │ │ │ └── index.ts │ │ │ ├── flow-path │ │ │ │ └── index.ts │ │ │ ├── label │ │ │ │ ├── Label.tsx │ │ │ │ ├── LabelModel.ts │ │ │ │ ├── LabelOverlay.tsx │ │ │ │ ├── algorithm.ts │ │ │ │ ├── index.ts │ │ │ │ ├── mediumEditor.ts │ │ │ │ └── utils.ts │ │ │ ├── proximity-connect │ │ │ │ └── index.ts │ │ │ └── snapshot │ │ │ │ ├── README.md │ │ │ │ ├── index.ts │ │ │ │ └── utils.ts │ │ └── turbo-adapter │ │ │ └── index.ts │ └── tsconfig.json ├── react-node-registry │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── model.ts │ │ ├── portal.ts │ │ ├── registry.ts │ │ ├── view.ts │ │ └── wrapper.tsx │ └── tsconfig.json └── vue-node-registry │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ ├── index.ts │ ├── model.ts │ ├── registry.ts │ ├── teleport.ts │ └── view.ts │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── rollup.config.js ├── scripts ├── build-docs ├── build-less └── sync-gitee ├── sites └── docs │ ├── .dumi │ ├── favicon.png │ ├── global.less │ ├── global.ts │ └── tsconfig.json │ ├── .dumirc.ts │ ├── .editorconfig │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── docs │ ├── api │ │ ├── detail │ │ │ ├── constructor.en.md │ │ │ ├── constructor.zh.md │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ │ ├── eventCenter.en.md │ │ ├── eventCenter.zh.md │ │ ├── index.en.md │ │ ├── index.zh.md │ │ ├── model │ │ │ ├── edgeModel.en.md │ │ │ ├── edgeModel.zh.md │ │ │ ├── editConfigModel.en.md │ │ │ ├── editConfigModel.zh.md │ │ │ ├── graphModel.en.md │ │ │ ├── graphModel.zh.md │ │ │ ├── nodeModel.en.md │ │ │ ├── nodeModel.zh.md │ │ │ ├── transformModel.en.md │ │ │ └── transformModel.zh.md │ │ ├── theme.en.md │ │ ├── theme.zh.md │ │ └── type │ │ │ ├── MainTypes.en.md │ │ │ ├── MainTypes.zh.md │ │ │ ├── Theme.en.md │ │ │ ├── Theme.zh.md │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ ├── article │ │ ├── architecture-of-logicflow.en.md │ │ ├── architecture-of-logicflow.zh.md │ │ ├── decoding-logicflows-extension-mechanism.en.md │ │ ├── decoding-logicflows-extension-mechanism.zh.md │ │ ├── extension │ │ │ ├── node-resize.en.md │ │ │ ├── node-resize.zh.md │ │ │ ├── snapshot.en.md │ │ │ └── snapshot.zh.md │ │ ├── logicflow-edge-drawing-and-interaction.en.md │ │ ├── logicflow-edge-drawing-and-interaction.zh.md │ │ ├── logicflow-release-v1.en.md │ │ ├── logicflow-release-v1.zh.md │ │ ├── lowcode-with-logicflow.en.md │ │ ├── lowcode-with-logicflow.zh.md │ │ ├── release-v2.en.md │ │ └── release-v2.zh.md │ ├── release │ │ ├── upgrade-to-v1-0.en.md │ │ ├── upgrade-to-v1-0.zh.md │ │ ├── upgrade-to-v1-1.en.md │ │ ├── upgrade-to-v1-1.zh.md │ │ ├── upgrade-to-v1-2.en.md │ │ └── upgrade-to-v1-2.zh.md │ └── tutorial │ │ ├── about.en.md │ │ ├── about.zh.md │ │ ├── advanced │ │ ├── dnd.en.md │ │ ├── dnd.zh.md │ │ ├── edge.en.md │ │ ├── edge.zh.md │ │ ├── keyboard.en.md │ │ ├── keyboard.zh.md │ │ ├── node.en.md │ │ ├── node.zh.md │ │ ├── react.en.md │ │ ├── react.zh.md │ │ ├── silent-mode.en.md │ │ ├── silent-mode.zh.md │ │ ├── snapline.en.md │ │ ├── snapline.zh.md │ │ ├── vue.en.md │ │ └── vue.zh.md │ │ ├── basic │ │ ├── background.en.md │ │ ├── background.zh.md │ │ ├── class.en.md │ │ ├── class.zh.md │ │ ├── edge.en.md │ │ ├── edge.zh.md │ │ ├── event.en.md │ │ ├── event.zh.md │ │ ├── grid.en.md │ │ ├── grid.zh.md │ │ ├── node.en.md │ │ ├── node.zh.md │ │ ├── theme.en.md │ │ └── theme.zh.md │ │ ├── extension │ │ ├── adapter.en.md │ │ ├── adapter.zh.md │ │ ├── bpmn-element.en.md │ │ ├── bpmn-element.zh.md │ │ ├── control.en.md │ │ ├── control.zh.md │ │ ├── curved-edge.en.md │ │ ├── curved-edge.zh.md │ │ ├── custom.en.md │ │ ├── custom.zh.md │ │ ├── dnd-panel.en.md │ │ ├── dnd-panel.zh.md │ │ ├── dynamic-group.en.md │ │ ├── dynamic-group.zh.md │ │ ├── group.en.md │ │ ├── group.zh.md │ │ ├── highlight.en.md │ │ ├── highlight.zh.md │ │ ├── insert-node-in-polyline.en.md │ │ ├── insert-node-in-polyline.zh.md │ │ ├── intro.en.md │ │ ├── intro.zh.md │ │ ├── label.en.md │ │ ├── label.zh.md │ │ ├── menu.en.md │ │ ├── menu.zh.md │ │ ├── minimap.en.md │ │ ├── minimap.zh.md │ │ ├── node-resize.en.md │ │ ├── node-resize.zh.md │ │ ├── proximity-connect.en.md │ │ ├── proximity-connect.zh.md │ │ ├── selection.en.md │ │ ├── selection.zh.md │ │ ├── snapshot.en.md │ │ └── snapshot.zh.md │ │ ├── get-started.en.md │ │ ├── get-started.zh.md │ │ ├── update.en.md │ │ └── update.zh.md │ ├── examples │ ├── edge │ │ ├── custom │ │ │ ├── demo │ │ │ │ ├── animatePolyline.tsx │ │ │ │ ├── curvedPolyline.tsx │ │ │ │ ├── meta.json │ │ │ │ └── polyline.tsx │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ │ └── native │ │ │ ├── demo │ │ │ ├── basicEdge.tsx │ │ │ └── meta.json │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ ├── extension │ │ └── native │ │ │ ├── demo │ │ │ ├── bpmn.tsx │ │ │ ├── control.tsx │ │ │ ├── dndPanel.tsx │ │ │ ├── dynamicGroup.tsx │ │ │ ├── group.tsx │ │ │ ├── highlight.tsx │ │ │ ├── label.tsx │ │ │ ├── menu.tsx │ │ │ ├── meta.json │ │ │ ├── miniMap.tsx │ │ │ ├── nodeSelection.tsx │ │ │ ├── proximityConnect.tsx │ │ │ ├── selectionSelect.tsx │ │ │ └── snapshot.tsx │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ ├── graph │ │ └── basic │ │ │ ├── demo │ │ │ ├── colorfulBackground.tsx │ │ │ ├── graph.tsx │ │ │ ├── grid.tsx │ │ │ ├── meta.json │ │ │ └── theme.tsx │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ ├── node │ │ ├── custom │ │ │ ├── demo │ │ │ │ ├── ellipse.tsx │ │ │ │ ├── freeAnchorNode.tsx │ │ │ │ ├── html.tsx │ │ │ │ ├── icon.tsx │ │ │ │ ├── image.tsx │ │ │ │ ├── meta.json │ │ │ │ ├── rect.tsx │ │ │ │ └── theme.tsx │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ │ └── native │ │ │ ├── demo │ │ │ ├── basicNode.tsx │ │ │ └── meta.json │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ ├── react │ │ └── registry │ │ │ ├── demo │ │ │ ├── customReact.tsx │ │ │ ├── meta.json │ │ │ └── reactPortal.tsx │ │ │ ├── index.en.md │ │ │ └── index.zh.md │ └── showcase │ │ ├── bussiness │ │ ├── demo │ │ │ ├── approve.tsx │ │ │ ├── bpmn.tsx │ │ │ ├── draft.tsx │ │ │ ├── games.tsx │ │ │ ├── meta.json │ │ │ ├── mvp.tsx │ │ │ ├── organizer.tsx │ │ │ ├── pool.tsx │ │ │ └── profileEditor.tsx │ │ ├── index.en.md │ │ └── index.zh.md │ │ └── example │ │ ├── demo │ │ ├── angularDemo.tsx │ │ ├── beautification.tsx │ │ ├── bpmnEvent.tsx │ │ ├── bpmnVue.tsx │ │ ├── engine.tsx │ │ ├── meta.json │ │ ├── nodeRedVue3.tsx │ │ ├── treelikeDemoVue3.tsx │ │ └── vueDemo.tsx │ │ ├── index.en.md │ │ └── index.zh.md │ ├── package.json │ ├── public │ ├── control-extension-usage.html │ ├── didi.png │ ├── getGraphData-usage.html │ ├── initialized-demo.html │ ├── logicflow-8-7.jpg │ ├── logo.png │ ├── original-usage.html │ ├── overlay.png │ ├── test.jpeg │ └── vue3-app.gif │ ├── src │ └── tutorial │ │ ├── advanced │ │ ├── edge │ │ │ ├── animation │ │ │ │ ├── customEdge.ts │ │ │ │ ├── data.ts │ │ │ │ └── index.tsx │ │ │ └── reactEdge │ │ │ │ ├── customEdge.tsx │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ ├── node │ │ │ ├── connect │ │ │ │ ├── connectData.ts │ │ │ │ ├── customHexagon.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── htmlNode │ │ │ │ ├── htmlData.ts │ │ │ │ ├── htmlNode.ts │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ ├── movable │ │ │ │ ├── customNode.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── movableData.ts │ │ │ │ └── movableNode.ts │ │ │ ├── reactNode │ │ │ │ ├── box.tsx │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ │ └── sql │ │ │ │ ├── index.less │ │ │ │ ├── index.tsx │ │ │ │ ├── sqlData.ts │ │ │ │ ├── sqlEdge.ts │ │ │ │ └── sqlNode.ts │ │ └── react │ │ │ ├── Portal.tsx │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── basic │ │ ├── edge │ │ │ ├── arrow │ │ │ │ ├── customArrow.ts │ │ │ │ ├── data.ts │ │ │ │ └── index.tsx │ │ │ ├── custom │ │ │ │ ├── data.ts │ │ │ │ ├── index.tsx │ │ │ │ └── sequence.ts │ │ │ ├── shapes │ │ │ │ ├── data.ts │ │ │ │ └── index.tsx │ │ │ └── textPosition │ │ │ │ ├── customEdge.ts │ │ │ │ ├── data.ts │ │ │ │ └── index.tsx │ │ ├── instance │ │ │ └── graphData │ │ │ │ ├── index.less │ │ │ │ └── index.tsx │ │ └── node │ │ │ ├── custom-view │ │ │ ├── index.tsx │ │ │ ├── userTask.ts │ │ │ └── viewData.ts │ │ │ ├── custom │ │ │ ├── customCircle.ts │ │ │ ├── customData.ts │ │ │ ├── customDiamond.ts │ │ │ ├── customEllipse.ts │ │ │ ├── customPolygon.ts │ │ │ ├── customRect.ts │ │ │ └── index.tsx │ │ │ ├── properties │ │ │ ├── customRect.ts │ │ │ ├── data.ts │ │ │ └── index.tsx │ │ │ └── shapes │ │ │ ├── index.tsx │ │ │ └── shapesData.ts │ │ ├── components │ │ ├── edges │ │ │ ├── custom-curved-polyline │ │ │ │ └── index.tsx │ │ │ └── custom-polyline │ │ │ │ └── index.tsx │ │ └── nodes │ │ │ ├── custom-ellipse │ │ │ └── index.tsx │ │ │ ├── custom-html │ │ │ ├── Html.tsx │ │ │ ├── Icon.tsx │ │ │ ├── Image.tsx │ │ │ ├── Text.tsx │ │ │ └── index.ts │ │ │ └── custom-rect │ │ │ └── index.tsx │ │ ├── extension │ │ ├── dynamic-group │ │ │ ├── index.module.less │ │ │ ├── index.tsx │ │ │ └── nodes │ │ │ │ ├── custom-group │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ └── sub-process │ │ │ │ └── index.ts │ │ ├── globals.d.ts │ │ ├── label │ │ │ ├── data.ts │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── mini-map │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ ├── proximity-connect │ │ │ ├── index.less │ │ │ └── index.tsx │ │ ├── selection-select │ │ │ ├── index.module.less │ │ │ └── index.tsx │ │ └── snapshot │ │ │ ├── data.ts │ │ │ ├── imageNode.ts │ │ │ ├── index.module.less │ │ │ ├── index.tsx │ │ │ └── svg.ts │ │ ├── get-started │ │ ├── helloworld │ │ │ ├── data.ts │ │ │ └── index.tsx │ │ ├── index.less │ │ ├── use-in-react │ │ │ └── index.jsx │ │ ├── use-plugin │ │ │ ├── index.tsx │ │ │ └── pluginData.ts │ │ └── use-react │ │ │ ├── customEdge.tsx │ │ │ ├── index.tsx │ │ │ └── reactData.ts │ │ └── index.less │ └── tsconfig.json ├── tsconfig.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [ 11 | "engine-browser-app", 12 | "engine-node-app", 13 | "feature-examples", 14 | "material-ui-app", 15 | "next-app", 16 | "vue3-app" 17 | ], 18 | "extends": [], 19 | "pipeline": {} 20 | } 21 | -------------------------------------------------------------------------------- /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extents: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'body-leading-blank': [1, 'always'], 5 | 'footer-leading-blank': [1, 'always'], 6 | 'header-max-length': [2, 'always', 72], 7 | 'scope-case': [2, 'always', 'lower-case'], 8 | 'subject-case': [ 9 | 2, 10 | 'never', 11 | ['sentence-case', 'start-case', 'pascal-case', 'upper-case'], 12 | ], 13 | 'subject-full-stop': [2, 'never', '.'], 14 | 'type-case': [2, 'always', 'lower-case'], 15 | 'type-enum': [ 16 | 2, 17 | 'always', 18 | [ 19 | 'build', 20 | 'chore', 21 | 'ci', 22 | 'docs', 23 | 'feat', 24 | 'fix', 25 | 'improvement', 26 | 'perf', 27 | 'refactor', 28 | 'revert', 29 | 'style', 30 | 'test', 31 | ], 32 | ], 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | 4 | # don't lint build output (make sure it's set to your correct build folder name) 5 | *.min.js 6 | es/** 7 | lib/** 8 | dist/** 9 | 10 | # don't lint nyc coverage output 11 | coverage 12 | types 13 | packages/core/types 14 | 15 | packages/extension/src/bpmn-adapter/xml2json.ts 16 | packages/extension/src/bpmn-adapter/json2xml.ts 17 | 18 | examples/vue3-memory-leak 19 | 20 | **/*.d.ts 21 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "plugins": ["@typescript-eslint", "prettier", "import"], 5 | "extends": [ 6 | "eslint:recommended", 7 | "prettier", 8 | "plugin:@typescript-eslint/recommended" 9 | ], 10 | "parserOptions": { 11 | "ecmaVersion": 2020, 12 | "sourceType": "module" 13 | }, 14 | "rules": { 15 | "@typescript-eslint/no-namespace": "off", 16 | "@typescript-eslint/ban-ts-comment": "off", 17 | "@typescript-eslint/no-explicit-any": "off" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATRUE_ZH.yml: -------------------------------------------------------------------------------- 1 | name: Feature ZH 2 | description: 新的需求和提议 3 | title: "[Feature]: " 4 | labels: ["new feature"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | 感谢你的Feature提交 10 | - type: textarea 11 | id: background 12 | attributes: 13 | label: 背景&目的 14 | description: 描述需求和提议的背景和目的 15 | validations: 16 | required: true 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Ask question and discuss(提问和讨论) 4 | url: https://github.com/didi/LogicFlow/discussions 5 | about: Ask questions and discuss with other community members 6 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout Repo 16 | uses: actions/checkout@v3 17 | 18 | - name: Setup Node.js 18 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 18 22 | 23 | - name: Install Dependencies 24 | run: pnpm install 25 | 26 | - name: Create Release Pull Request 27 | uses: changesets/action@v1 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /.github/workflows/update_contributors.yml: -------------------------------------------------------------------------------- 1 | name: 🤝 Update Contributors 2 | on: 3 | schedule: 4 | - cron: '0 1 * * *' 5 | push: 6 | branches: 7 | - master 8 | - next 9 | - next-major 10 | - alpha 11 | - beta 12 | jobs: 13 | contrib-readme-job: 14 | runs-on: ubuntu-latest 15 | name: A job to automate contributors in readme 16 | # Only run workflow if the repository is not a fork 17 | if: ${{ !github.event.repository.fork }} 18 | permissions: 19 | contents: write 20 | pull-requests: write 21 | steps: 22 | - uses: wow-actions/contributors-list@v1 23 | with: 24 | GITHUB_TOKEN: ${{ secrets.CONTRIBUTORS_TOKEN }} 25 | excludeUsers: semantic-release-bot ImgBotApp 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | 4 | # production 5 | lib 6 | es 7 | dist 8 | output 9 | stats.html 10 | 11 | coverage 12 | types/** 13 | 14 | # misc 15 | .DS_Store 16 | .pnpm-*.log 17 | .idea 18 | .turbo 19 | npm-debug.log 20 | yarn-error.log 21 | 22 | /.github_token 23 | /TMP_CHANGELOG.md 24 | /.openai_token 25 | /.github_account 26 | 27 | logic-flow-docs.tar.gz 28 | 29 | .umi/ 30 | tmp 31 | tmp-production 32 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit ${1} 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD013": false, 4 | "MD024": { 5 | "allow_different_nesting": true 6 | }, 7 | "MD033": false, 8 | "MD041": false 9 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .git 2 | CVS 3 | .svn 4 | .hg 5 | .lock-wscript 6 | .wafpickle-N 7 | .*.swp 8 | .DS_Store 9 | ._* 10 | npm-debug.log 11 | .npmrc 12 | node_modules 13 | config.gypi 14 | *.orig 15 | 16 | example 17 | public 18 | config 19 | yarn.lock 20 | package-lock.json 21 | src 22 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | *.sh 3 | *.yml 4 | *.yaml 5 | *.svg 6 | *.gif 7 | *.log 8 | *.md 9 | 10 | .next 11 | .DS_Store 12 | CNAME 13 | AUTHORS 14 | LICENSE 15 | LICENSE 16 | 17 | node_modules 18 | es/ 19 | lib/ 20 | dist/ 21 | public/ 22 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "printWidth": 80, 5 | "trailingComma": "all", 6 | "proseWrap": "never", 7 | "endOfLine": "auto", 8 | "useTabs": false, 9 | "overrides": [ 10 | { "files": ".eslintrc", "options": { "parser": "json" } }, 11 | { "files": ".prettierrc", "options": { "parser": "json" } }, 12 | { "files": ".stylelintrc", "options": { "parser": "json" } } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-standard", 4 | "stylelint-config-rational-order", 5 | "stylelint-config-prettier" 6 | ], 7 | "plugins": ["stylelint-order"], 8 | "customSyntax": "postcss-less", 9 | "rules": { 10 | "block-no-empty": null, 11 | "function-name-case": "lower", 12 | "comment-empty-line-before": null, 13 | "no-invalid-double-slash-comments": null, 14 | "no-descending-specificity": null, 15 | "declaration-empty-line-before": null, 16 | "no-duplicate-selectors": null, 17 | "value-no-vendor-prefix": null, 18 | "selector-pseudo-class-no-unknown": null, 19 | "selector-class-pattern": null, 20 | "keyframes-name-pattern": null, 21 | "number-max-precision": null 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["Logicflow", "preact", "Snapline"] 3 | } 4 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { "targets": { "node": "current" } }], 4 | "@babel/preset-typescript" 5 | ], 6 | "plugins": [ 7 | ["@babel/plugin-proposal-decorators", { "legacy": true }], 8 | ["@babel/plugin-transform-class-properties", { "loose": true }], 9 | [ 10 | "@babel/plugin-transform-react-jsx", 11 | { 12 | "pragma": "h", 13 | "pragmaFrag": "Fragment" 14 | } 15 | ] 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | LogicFlow Demos with Vite 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/delete.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/end-event-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/end-event-none.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/export.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/gateway-xor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/gateway-xor.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/image.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/select.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/service-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/service-task.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/service.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/start-event-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/start-event-none.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/subprocess-collapsed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/subprocess-collapsed.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/subprocess-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/subprocess-expanded.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/task-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/task-none.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/upload.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/bpmn/user-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/bpmn/user-task.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/group/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/group/circle.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/group/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/group/group.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/group/rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/group/rect.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/group/subprocess-collapsed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/group/subprocess-collapsed.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/assets/group/subprocess-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/assets/group/subprocess-expanded.png -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/ErrorPage.tsx: -------------------------------------------------------------------------------- 1 | import { useRouteError } from 'react-router-dom' 2 | 3 | export interface IErrorProps { 4 | statusText?: string | number 5 | message?: string 6 | } 7 | 8 | export default function ErrorPage() { 9 | const error = useRouteError() 10 | console.log('page error ===>>>', error) 11 | 12 | return ( 13 |
14 |

Oops!

15 |

Sorry, an unexpected error has occurred.

16 |

17 | 18 | {(error as IErrorProps)?.statusText || 19 | (error as IErrorProps)?.message} 20 | 21 |

22 |
23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/Home.tsx: -------------------------------------------------------------------------------- 1 | import { useRouteError } from 'react-router-dom' 2 | 3 | export interface IErrorProps { 4 | statusText?: string | number 5 | message?: string 6 | } 7 | 8 | export default function ErrorPage() { 9 | const error = useRouteError() 10 | console.log('page error ===>>>', error) 11 | 12 | return ( 13 |
14 |

Wire Your Ideas with LogicFlow!

15 |

低成本实现,让逻辑管理更简单、更高效

16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/engine/Condition.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/engine-browser-examples/src/pages/engine/Condition.tsx -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/extension/bpmn/util.ts: -------------------------------------------------------------------------------- 1 | export function download(filename: string, text: string) { 2 | const element = document.createElement('a') 3 | element.setAttribute( 4 | 'href', 5 | 'data:text/plain;charset=utf-8,' + encodeURIComponent(text), 6 | ) 7 | element.setAttribute('download', filename) 8 | 9 | element.style.display = 'none' 10 | document.body.appendChild(element) 11 | 12 | element.click() 13 | document.body.removeChild(element) 14 | } 15 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/extension/dynamic-group/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 70vh; 4 | overflow: hidden; 5 | } 6 | 7 | .lf-dnd-shape { 8 | background-size: contain; 9 | } 10 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/extension/dynamic-group/nodes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-group' 2 | export * from './sub-process' 3 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/extension/label/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/graph/edges/animation.ts: -------------------------------------------------------------------------------- 1 | import { BezierEdge, BezierEdgeModel } from '@logicflow/core' 2 | 3 | class AnimationEdge extends BezierEdge {} 4 | 5 | class AnimationEdgeModel extends BezierEdgeModel { 6 | getEdgeAnimationStyle() { 7 | const style = super.getEdgeAnimationStyle() 8 | style.stroke = 'blue' 9 | style.animationDuration = '30s' 10 | style.animationDirection = 'reverse' 11 | return style 12 | } 13 | } 14 | 15 | export default { 16 | type: 'animation-edge', 17 | view: AnimationEdge, 18 | model: AnimationEdgeModel, 19 | } 20 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/graph/edges/index.ts: -------------------------------------------------------------------------------- 1 | import animation from './animation' 2 | import connection from './connection' 3 | 4 | export * from './animation' 5 | export * from './connection' 6 | 7 | export { animation, connection } 8 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/graph/nodes/index.ts: -------------------------------------------------------------------------------- 1 | import combine from './combine' 2 | import star from './star' 3 | import square from './square' 4 | import uml from './uml' 5 | import user from './user' 6 | import reactNode from './ReactNode' 7 | 8 | export * from './combine' 9 | export * from './star' 10 | export * from './square' 11 | export * from './uml' 12 | export * from './user' 13 | export * from './ReactNode' 14 | 15 | export { combine, square, star, uml, user, reactNode } 16 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/pages/graph/nodes/star.ts: -------------------------------------------------------------------------------- 1 | import { PolygonNode, PolygonNodeModel } from '@logicflow/core' 2 | 3 | class StarModel extends PolygonNodeModel { 4 | setAttributes() { 5 | this.points = [ 6 | [45, 0], 7 | [20, 90], 8 | [90, 30], 9 | [0, 30], 10 | [80, 90], 11 | ] 12 | this.fill = '#456789' 13 | this.stroke = '#456789' 14 | } 15 | } 16 | 17 | export default { 18 | type: 'star', 19 | view: PolygonNode, 20 | model: StarModel, 21 | } 22 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/utls.ts: -------------------------------------------------------------------------------- 1 | export const getImageUrl = (name: string): string => { 2 | const assetPath = `/src/assets${name}` 3 | return new URL(assetPath, import.meta.url).href 4 | } 5 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "paths": { 23 | "@/*": ["./src/*"] 24 | } 25 | }, 26 | "include": ["src"], 27 | "references": [{ "path": "./tsconfig.node.json" }] 28 | } 29 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /examples/engine-browser-examples/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import { fileURLToPath } from 'node:url' 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react()], 8 | resolve: { 9 | alias: { 10 | '@': fileURLToPath(new URL('./src', import.meta.url)), 11 | }, 12 | }, 13 | }) 14 | -------------------------------------------------------------------------------- /examples/engine-node-examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "engine-node-app", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "LogicFlow-Engine Node Demo", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "node index.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [ 12 | "Node", 13 | "LogicFlow", 14 | "LogicFlow-Engine" 15 | ], 16 | "dependencies": { 17 | "@logicflow/engine": "workspace:*" 18 | }, 19 | "author": "LogicFlow Team", 20 | "license": "MIT" 21 | } 22 | -------------------------------------------------------------------------------- /examples/feature-examples/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.env.local 3 | /.umirc.local.ts 4 | /config/config.local.ts 5 | /src/.umi 6 | /src/.umi-production 7 | /src/.umi-test 8 | /dist 9 | .swc 10 | -------------------------------------------------------------------------------- /examples/feature-examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feature-examples", 3 | "private": true, 4 | "author": "boyongjiong ", 5 | "scripts": { 6 | "dev": "umi dev", 7 | "build": "umi build", 8 | "postinstall": "umi setup", 9 | "setup": "umi setup", 10 | "start": "npm run dev" 11 | }, 12 | "dependencies": { 13 | "@ant-design/icons": "^5.0.1", 14 | "@ant-design/pro-layout": "^7.19.0", 15 | "@logicflow/core": "workspace:*", 16 | "@logicflow/engine": "workspace:*", 17 | "@logicflow/extension": "workspace:*", 18 | "@logicflow/react-node-registry": "workspace:*", 19 | "antd": "^5.4.0", 20 | "umi": "^4.2.1" 21 | }, 22 | "devDependencies": { 23 | "@types/react": "^18.0.33", 24 | "@types/react-dom": "^18.0.11", 25 | "typescript": "^5.0.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/feature-examples/public/images/test.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/public/images/test.jpeg -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/delete.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/end-event-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/end-event-none.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/export.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/gateway-xor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/gateway-xor.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/image.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/select.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/service-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/service-task.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/service.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/start-event-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/start-event-none.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/subprocess-collapsed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/subprocess-collapsed.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/subprocess-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/subprocess-expanded.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/task-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/task-none.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/upload.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/bpmn/user-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/bpmn/user-task.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/didi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/didi.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/group/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/group/circle.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/group/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/group/group.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/group/rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/group/rect.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/group/subprocess-collapsed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/group/subprocess-collapsed.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/group/subprocess-expanded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/group/subprocess-expanded.png -------------------------------------------------------------------------------- /examples/feature-examples/src/assets/yay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/assets/yay.jpg -------------------------------------------------------------------------------- /examples/feature-examples/src/components/edges/custom-curved-polyline/index.tsx: -------------------------------------------------------------------------------- 1 | import { LogicFlow } from '@logicflow/core' 2 | import { CurvedEdge, CurvedEdgeModel } from '@logicflow/extension' 3 | 4 | class CustomCurvedEdge extends CurvedEdge {} 5 | 6 | class CustomCurvedEdgeModel extends CurvedEdgeModel { 7 | initEdgeData(data: LogicFlow.EdgeData) { 8 | super.initEdgeData(data) 9 | this.radius = 20 10 | } 11 | getEdgeStyle() { 12 | const style = super.getEdgeStyle() 13 | style.strokeWidth = 3 14 | return style 15 | } 16 | } 17 | 18 | export default { 19 | type: 'customCurvedEdge', 20 | model: CustomCurvedEdgeModel, 21 | view: CustomCurvedEdge, 22 | } 23 | -------------------------------------------------------------------------------- /examples/feature-examples/src/components/nodes/custom-circle/index.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow, { CircleNode, CircleNodeModel } from '@logicflow/core' 2 | import NodeConfig = LogicFlow.NodeConfig 3 | 4 | class CustomCircleModel extends CircleNodeModel { 5 | // constructor(data: any, graphModel: any) { 6 | // console.log('CustomCircleModel', 'constructor'); 7 | // super(data, graphModel) 8 | // } 9 | 10 | initNodeData(data: NodeConfig) { 11 | // console.log('CustomCircleModel', 'initNodeData', data); 12 | super.initNodeData(data) 13 | this.r = 60 14 | } 15 | 16 | // or 17 | // setAttributes() { 18 | // console.log('CustomCircleModel', 'setAttributes'); 19 | // this.r = 30; 20 | // console.log(this.r, 'r', this); 21 | // } 22 | } 23 | 24 | export default { 25 | type: 'customCircle', 26 | view: CircleNode, 27 | model: CustomCircleModel, 28 | } 29 | -------------------------------------------------------------------------------- /examples/feature-examples/src/components/nodes/custom-diamond/index.tsx: -------------------------------------------------------------------------------- 1 | import LogicFlow, { DiamondNode, DiamondNodeModel } from '@logicflow/core' 2 | import NodeConfig = LogicFlow.NodeConfig 3 | 4 | class CustomDiamondModel extends DiamondNodeModel { 5 | // constructor(data: any, graphModel: any) { 6 | // console.log('CustomCircleModel', 'constructor'); 7 | // super(data, graphModel) 8 | // } 9 | 10 | initNodeData(data: NodeConfig) { 11 | super.initNodeData(data) 12 | this.rx = 50 13 | this.ry = 60 14 | } 15 | 16 | // or 17 | // setAttributes() { 18 | // this.rx = 50 19 | // this.ry = 60 20 | // } 21 | } 22 | 23 | export default { 24 | type: 'customDiamond', 25 | view: DiamondNode, 26 | model: CustomDiamondModel, 27 | } 28 | -------------------------------------------------------------------------------- /examples/feature-examples/src/components/nodes/custom-html/Text.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/feature-examples/src/components/nodes/custom-html/Text.tsx -------------------------------------------------------------------------------- /examples/feature-examples/src/components/nodes/custom-html/index.ts: -------------------------------------------------------------------------------- 1 | import CustomHtml from './Html' 2 | import CustomIcon from './Icon' 3 | import CustomImage from './Image' 4 | // import CustomText from './Text'; 5 | 6 | export { CustomIcon, CustomImage, CustomHtml } 7 | -------------------------------------------------------------------------------- /examples/feature-examples/src/components/nodes/custom-polygon/index.tsx: -------------------------------------------------------------------------------- 1 | import LogicFlow, { PolygonNode, PolygonNodeModel } from '@logicflow/core' 2 | import NodeConfig = LogicFlow.NodeConfig 3 | 4 | class CustomPolygonModel extends PolygonNodeModel { 5 | // constructor(data: any, graphModel: any) { 6 | // super(data, graphModel) 7 | // } 8 | 9 | initNodeData(data: NodeConfig) { 10 | super.initNodeData(data) 11 | this.points = [ 12 | [0, 100], 13 | [50, 25], 14 | [50, 75], 15 | [100, 0], 16 | ] // 闪电 17 | } 18 | 19 | // or 20 | // setAttributes() { 21 | // this.points = [[0,100], [50,25], [50,75], [100,0]] // 闪电 22 | // } 23 | } 24 | 25 | export default { 26 | type: 'customPolygon', 27 | view: PolygonNode, 28 | model: CustomPolygonModel, 29 | } 30 | -------------------------------------------------------------------------------- /examples/feature-examples/src/layouts/index.less: -------------------------------------------------------------------------------- 1 | .navs { 2 | ul { 3 | display: flex; 4 | padding: 0; 5 | list-style: none; 6 | } 7 | 8 | li { 9 | margin-right: 1em; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/background/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 300px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/edges/custom/animate-polyline/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | 7 | .btn { 8 | margin-top: 10px; 9 | margin-right: 10px; 10 | } 11 | 12 | .select { 13 | width: 200px; 14 | margin-top: 10px; 15 | margin-right: 10px; 16 | } 17 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/edges/custom/curved-polyline/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | 7 | .btn { 8 | margin-right: 10px; 9 | } 10 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/edges/custom/polyline/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | 7 | .btn { 8 | margin-top: 10px; 9 | margin-right: 10px; 10 | } 11 | 12 | .select { 13 | width: 200px; 14 | margin-top: 10px; 15 | margin-right: 10px; 16 | } 17 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/bpmn/util.ts: -------------------------------------------------------------------------------- 1 | export function download(filename: string, text: string) { 2 | const element = document.createElement('a') 3 | element.setAttribute( 4 | 'href', 5 | 'data:text/plain;charset=utf-8,' + encodeURIComponent(text), 6 | ) 7 | element.setAttribute('download', filename) 8 | 9 | element.style.display = 'none' 10 | document.body.appendChild(element) 11 | 12 | element.click() 13 | document.body.removeChild(element) 14 | } 15 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/control/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/dnd-panel/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | 6 | :global { 7 | .lf-dnd-shape { 8 | background-size: contain; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/dnd-panel/nodes/end.ts: -------------------------------------------------------------------------------- 1 | import { CustomImage } from '@/components/nodes/custom-html' 2 | 3 | // 云形状的图片节点 4 | class EndNode extends CustomImage.view { 5 | getImageHref = () => { 6 | return 'https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/core/end.png' 7 | } 8 | } 9 | 10 | export class EndNodeModel extends CustomImage.model { 11 | setAttributes() { 12 | this.width = 50 13 | this.height = 50 14 | this.radius = 5 15 | this.text.value = '' 16 | } 17 | } 18 | 19 | export default { 20 | type: 'end', 21 | view: EndNode, 22 | model: EndNodeModel, 23 | } 24 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/dnd-panel/nodes/start.ts: -------------------------------------------------------------------------------- 1 | import { CustomImage } from '@/components/nodes/custom-html' 2 | 3 | // 云形状的图片节点 4 | class StartNode extends CustomImage.view { 5 | getImageHref = () => { 6 | return 'https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/core/start.png' 7 | } 8 | } 9 | 10 | export class StartNodeModel extends CustomImage.model { 11 | setAttributes() { 12 | this.width = 50 13 | this.height = 50 14 | this.radius = 5 15 | this.text.value = '' 16 | } 17 | } 18 | 19 | export default { 20 | type: 'start', 21 | view: StartNode, 22 | model: StartNodeModel, 23 | } 24 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/dynamic-group/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 70vh; 4 | overflow: hidden; 5 | } 6 | 7 | :global { 8 | .lf-dnd-shape { 9 | background-size: contain; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/dynamic-group/nodes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-group' 2 | export * from './sub-process' 3 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/group/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 70vh; 4 | overflow: hidden; 5 | } 6 | 7 | :global { 8 | .lf-dnd-shape { 9 | background-size: contain; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/group/nodes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-group' 2 | export * from './sub-process' 3 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/highlight/index.less: -------------------------------------------------------------------------------- 1 | #graph { 2 | width: 100%; 3 | height: 80vh; 4 | } 5 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/insert-node-in-polyline/NotAllowConnectRect.ts: -------------------------------------------------------------------------------- 1 | import { RectNode, RectNodeModel } from '@logicflow/core' 2 | class NotAllowConnectRectModel extends RectNodeModel { 3 | getDefaultAnchor() { 4 | return [] 5 | } 6 | } 7 | class NotAllowConnectRectView extends RectNode {} 8 | 9 | export default { 10 | type: 'not-allow-connect', 11 | view: NotAllowConnectRectView, 12 | model: NotAllowConnectRectModel, 13 | } 14 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/insert-node-in-polyline/data.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | nodes: [ 3 | { 4 | id: 'rect', 5 | type: 'rect', 6 | x: 150, 7 | y: 70, 8 | text: '矩形', 9 | }, 10 | { 11 | id: 'circle', 12 | type: 'circle', 13 | x: 400, 14 | y: 70, 15 | text: '圆形', 16 | }, 17 | ], 18 | edges: [ 19 | { 20 | type: 'polyline', 21 | sourceNodeId: 'rect', 22 | targetNodeId: 'circle', 23 | }, 24 | ], 25 | } 26 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/insert-node-in-polyline/index.less: -------------------------------------------------------------------------------- 1 | .insert-node-in-polyline { 2 | #graph { 3 | width: 100%; 4 | height: 80vh; 5 | } 6 | 7 | #rect { 8 | width: 50px; 9 | height: 50px; 10 | background: #fff; 11 | border: 2px solid #000; 12 | } 13 | 14 | #circle { 15 | width: 50px; 16 | height: 50px; 17 | background: #fff; 18 | border: 2px solid #000; 19 | border-radius: 50%; 20 | } 21 | 22 | .circle .lf-dnd-shape { 23 | display: inline-block; 24 | width: 25px; 25 | height: 25px; 26 | border: 2px solid black; 27 | border-radius: 20px; 28 | } 29 | 30 | .rect .lf-dnd-shape { 31 | display: inline-block; 32 | width: 25px; 33 | height: 25px; 34 | border: 2px solid black; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/menu/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/mini-map/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 270px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/node-selection/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/proximity-connect/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/rules/Start.ts: -------------------------------------------------------------------------------- 1 | import { CircleNode, CircleNodeModel } from '@logicflow/core' 2 | 3 | class StartNode extends CircleNode {} 4 | class StartModel extends CircleNodeModel { 5 | constructor(data: any, graphModel: any) { 6 | if (data.text && typeof data.text === 'string') { 7 | data.text = { 8 | value: data.text, 9 | x: data.x, 10 | y: data.y + 35, 11 | } 12 | } 13 | super(data, graphModel) 14 | this.r = 18 15 | this.strokeWidth = 2 16 | this.stroke = 'rgb(24, 125, 255)' 17 | } 18 | getConnectedTargetRules() { 19 | const rules = super.getConnectedTargetRules() 20 | const notAsTarget = { 21 | message: '起始节点不能作为边的终点', 22 | validate: () => false, 23 | } 24 | rules.push(notAsTarget) 25 | return rules 26 | } 27 | } 28 | export default { 29 | type: 'start', 30 | view: StartNode, 31 | model: StartModel, 32 | } 33 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/rules/UserTask.ts: -------------------------------------------------------------------------------- 1 | import { RectNode, RectNodeModel } from '@logicflow/core' 2 | 3 | class UserTaskNode extends RectNode {} 4 | class UsetTaskModel extends RectNodeModel { 5 | constructor(data: any, graphModel: any) { 6 | if (data.text && typeof data.text === 'string') { 7 | data.text = { 8 | value: data.text, 9 | x: data.x, 10 | y: data.y, 11 | } 12 | } 13 | super(data, graphModel) 14 | this.width = 100 15 | this.height = 80 16 | this.strokeWidth = 2 17 | this.stroke = 'rgb(24, 125, 255)' 18 | this.radius = 10 19 | this.fillOpacity = 0.95 20 | } 21 | } 22 | export default { 23 | view: UserTaskNode, 24 | model: UsetTaskModel, 25 | type: 'user-task', 26 | } 27 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/rules/data.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | nodes: [ 3 | { 4 | id: 'start', 5 | type: 'start', 6 | x: 150, 7 | y: 70, 8 | text: '开始', 9 | }, 10 | { 11 | id: 'user-task', 12 | type: 'user-task', 13 | x: 400, 14 | y: 70, 15 | text: '用户节点', 16 | }, 17 | ], 18 | edges: [ 19 | { 20 | type: 'polyline', 21 | sourceNodeId: 'start', 22 | targetNodeId: 'user-task', 23 | }, 24 | ], 25 | } 26 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/rules/index.less: -------------------------------------------------------------------------------- 1 | .rules-graph { 2 | #graph { 3 | width: 100%; 4 | height: 80vh; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/selection-select/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 250px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/extensions/snapshot/index.less: -------------------------------------------------------------------------------- 1 | .graph { 2 | width: 90%; 3 | height: 500px; 4 | } 5 | 6 | .uml-wrapper { 7 | box-sizing: border-box; 8 | width: 100%; 9 | height: 100%; 10 | background: #efdbff; 11 | border: 2px solid #9254de; 12 | border-radius: 10px; 13 | } 14 | 15 | .uml-head { 16 | font-weight: bold; 17 | font-size: 16px; 18 | line-height: 30px; 19 | text-align: center; 20 | } 21 | 22 | .uml-body { 23 | padding: 5px 10px; 24 | font-size: 12px; 25 | border-top: 1px solid #9254de; 26 | border-bottom: 1px solid #9254de; 27 | } 28 | 29 | .uml-footer { 30 | padding: 5px 10px; 31 | font-size: 14px; 32 | } 33 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/graph/edges/animation.ts: -------------------------------------------------------------------------------- 1 | import { BezierEdge, BezierEdgeModel } from '@logicflow/core' 2 | 3 | class AnimationEdge extends BezierEdge {} 4 | 5 | class AnimationEdgeModel extends BezierEdgeModel { 6 | getEdgeAnimationStyle() { 7 | const style = super.getEdgeAnimationStyle() 8 | style.stroke = 'blue' 9 | style.animationDuration = '30s' 10 | style.animationDirection = 'reverse' 11 | return style 12 | } 13 | } 14 | 15 | export default { 16 | type: 'animation-edge', 17 | view: AnimationEdge, 18 | model: AnimationEdgeModel, 19 | } 20 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/graph/edges/index.ts: -------------------------------------------------------------------------------- 1 | import animation from './animation' 2 | import connection from './connection' 3 | 4 | export * from './animation' 5 | export * from './connection' 6 | 7 | export { animation, connection } 8 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/graph/nodes/index.ts: -------------------------------------------------------------------------------- 1 | import combine from './combine' 2 | import star from './star' 3 | import square from './square' 4 | import uml from './uml' 5 | import user from './user' 6 | 7 | export * from './combine' 8 | export * from './star' 9 | export * from './square' 10 | export * from './uml' 11 | export * from './user' 12 | 13 | export { combine, square, star, uml, user } 14 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/graph/nodes/star.ts: -------------------------------------------------------------------------------- 1 | import { PolygonNode, PolygonNodeModel } from '@logicflow/core' 2 | 3 | class StarModel extends PolygonNodeModel { 4 | setAttributes() { 5 | this.points = [ 6 | [45, 0], 7 | [20, 90], 8 | [90, 30], 9 | [0, 30], 10 | [80, 90], 11 | ] 12 | this.fill = '#456789' 13 | this.stroke = '#456789' 14 | } 15 | } 16 | 17 | export default { 18 | type: 'star', 19 | view: PolygonNode, 20 | model: StarModel, 21 | } 22 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/grid/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 300px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/ellipse/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/freeAnchorNode/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/html/data.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | id: '1', 5 | type: 'customHtml', 6 | x: 300, 7 | y: 150, 8 | properties: { 9 | name: 'hello', 10 | body: 'world', 11 | }, 12 | }, 13 | ], 14 | edges: [], 15 | } 16 | 17 | export default data 18 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/html/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/html/style.css: -------------------------------------------------------------------------------- 1 | .uml-wrapper { 2 | background: #efdbff; 3 | width: 100%; 4 | height: 100%; 5 | border-radius: 10px; 6 | border: 2px solid #9254de; 7 | box-sizing: border-box; 8 | } 9 | 10 | .uml-btn { 11 | width: 32px; 12 | min-width: 32px; 13 | color: #fff; 14 | background-color: #9254de; 15 | border: 1px solid #1a223f; 16 | border-radius: 4px; 17 | outline: none; 18 | cursor: pointer; 19 | } 20 | 21 | .uml-btn:hover { 22 | color: #fff; 23 | background-color: #a780d7; 24 | } 25 | 26 | .uml-head { 27 | text-align: center; 28 | line-height: 30px; 29 | font-size: 16px; 30 | font-weight: bold; 31 | } 32 | 33 | .uml-body { 34 | border-top: 1px solid #9254de; 35 | border-bottom: 1px solid #9254de; 36 | padding: 5px 10px; 37 | font-size: 12px; 38 | } 39 | 40 | .uml-footer { 41 | padding: 5px 10px; 42 | font-size: 14px; 43 | } 44 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/icon/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/image/Cloud.tsx: -------------------------------------------------------------------------------- 1 | import { CustomImage } from '@/components/nodes/custom-html' 2 | 3 | // 云形状的图片节点 4 | class CloudImageNode extends CustomImage.view { 5 | getImageHref = () => { 6 | return 'https://dpubstatic.udache.com/static/dpubimg/0oqFX1nvbD/cloud.png' 7 | } 8 | } 9 | 10 | export default { 11 | type: 'imageCloud', 12 | view: CloudImageNode, 13 | model: CustomImage.model, 14 | } 15 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/image/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/rect/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 90vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/custom/theme/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/nodes/native/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/performance/snapshot-elements/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 270px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /examples/feature-examples/src/pages/react/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | 7 | :global { 8 | .react-algo-node { 9 | display: flex; 10 | align-items: center; 11 | width: 100%; 12 | height: 100%; 13 | border: 1px solid #e59b68; 14 | border-radius: 14px; 15 | 16 | img { 17 | width: 24px; 18 | height: 24px; 19 | } 20 | 21 | span { 22 | margin-left: 4px; 23 | color: #000000a6; 24 | font-size: 12px; 25 | } 26 | 27 | &.dark { 28 | background-color: #141414; 29 | 30 | span { 31 | color: #fff; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/feature-examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./src/.umi/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /examples/feature-examples/typings.d.ts: -------------------------------------------------------------------------------- 1 | import 'umi/typings' 2 | -------------------------------------------------------------------------------- /examples/material-ui-demo/.env: -------------------------------------------------------------------------------- 1 | REACT_APP_VERSION = v1.3.0 2 | GENERATE_SOURCEMAP = false 3 | -------------------------------------------------------------------------------- /examples/material-ui-demo/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | /.idea/ 25 | -------------------------------------------------------------------------------- /examples/material-ui-demo/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "printWidth": 140, 4 | "singleQuote": true, 5 | "trailingComma": "none", 6 | "tabWidth": 2, 7 | "useTabs": false 8 | } 9 | -------------------------------------------------------------------------------- /examples/material-ui-demo/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "commonjs", 5 | "baseUrl": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/App.js: -------------------------------------------------------------------------------- 1 | import { useSelector } from 'react-redux'; 2 | 3 | import { ThemeProvider } from '@mui/material/styles'; 4 | import { CssBaseline, StyledEngineProvider } from '@mui/material'; 5 | 6 | // routing 7 | import Routes from 'routes'; 8 | 9 | // defaultTheme 10 | import themes from 'themes'; 11 | 12 | // project imports 13 | import NavigationScroll from 'layout/NavigationScroll'; 14 | 15 | // ==============================|| APP ||============================== // 16 | 17 | const App = () => { 18 | const customization = useSelector((state) => state.customization); 19 | 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ); 30 | }; 31 | 32 | export default App; 33 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/assets/images/icons/earning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | // basename: only at build time to set, and Don't add '/' at end off BASENAME for breadcrumbs, also Don't put only '/' use blank('') instead, 3 | // like '/berry-material-react/react/default' 4 | basename: '/', 5 | defaultPath: '/dashboard/default', 6 | fontFamily: `'Roboto', sans-serif`, 7 | borderRadius: 8 8 | }; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/hooks/useScriptRef.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | // ==============================|| ELEMENT REFERENCE HOOKS ||============================== // 4 | 5 | const useScriptRef = () => { 6 | const scripted = useRef(true); 7 | 8 | useEffect( 9 | () => () => { 10 | scripted.current = false; 11 | }, 12 | [] 13 | ); 14 | 15 | return scripted; 16 | }; 17 | 18 | export default useScriptRef; 19 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/layout/MainLayout/LogoSection/index.js: -------------------------------------------------------------------------------- 1 | import { Link } from 'react-router-dom'; 2 | import { useDispatch, useSelector } from 'react-redux'; 3 | 4 | // material-ui 5 | import { ButtonBase } from '@mui/material'; 6 | 7 | // project imports 8 | import config from 'config'; 9 | import Logo from 'ui-component/Logo'; 10 | import { MENU_OPEN } from 'store/actions'; 11 | 12 | // ==============================|| MAIN LOGO ||============================== // 13 | 14 | const LogoSection = () => { 15 | const defaultId = useSelector((state) => state.customization.defaultId); 16 | const dispatch = useDispatch(); 17 | return ( 18 | dispatch({ type: MENU_OPEN, id: defaultId })} component={Link} to={config.defaultPath}> 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default LogoSection; 25 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/layout/MainLayout/Sidebar/MenuList/index.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { Typography } from '@mui/material'; 3 | 4 | // project imports 5 | import NavGroup from './NavGroup'; 6 | import menuItem from 'menu-items'; 7 | 8 | // ==============================|| SIDEBAR MENU LIST ||============================== // 9 | 10 | const MenuList = () => { 11 | const navItems = menuItem.items.map((item) => { 12 | switch (item.type) { 13 | case 'group': 14 | return ; 15 | default: 16 | return ( 17 | 18 | Menu Items Error 19 | 20 | ); 21 | } 22 | }); 23 | 24 | return <>{navItems}; 25 | }; 26 | 27 | export default MenuList; 28 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/layout/MinimalLayout/index.js: -------------------------------------------------------------------------------- 1 | import { Outlet } from 'react-router-dom'; 2 | 3 | // project imports 4 | import Customization from '../Customization'; 5 | 6 | // ==============================|| MINIMAL LAYOUT ||============================== // 7 | 8 | const MinimalLayout = () => ( 9 | <> 10 | 11 | 12 | 13 | ); 14 | 15 | export default MinimalLayout; 16 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/layout/NavMotion.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { motion } from 'framer-motion'; 3 | 4 | // ==============================|| ANIMATION FOR CONTENT ||============================== // 5 | 6 | const NavMotion = ({ children }) => { 7 | const motionVariants = { 8 | initial: { 9 | opacity: 0, 10 | scale: 0.99 11 | }, 12 | in: { 13 | opacity: 1, 14 | scale: 1 15 | }, 16 | out: { 17 | opacity: 0, 18 | scale: 1.01 19 | } 20 | }; 21 | 22 | const motionTransition = { 23 | type: 'tween', 24 | ease: 'anticipate', 25 | duration: 0.4 26 | }; 27 | 28 | return ( 29 | 30 | {children} 31 | 32 | ); 33 | }; 34 | 35 | NavMotion.propTypes = { 36 | children: PropTypes.node 37 | }; 38 | 39 | export default NavMotion; 40 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/layout/NavigationScroll.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import { useEffect } from 'react'; 3 | import { useLocation } from 'react-router-dom'; 4 | 5 | // ==============================|| NAVIGATION SCROLL TO TOP ||============================== // 6 | 7 | const NavigationScroll = ({ children }) => { 8 | const location = useLocation(); 9 | const { pathname } = location; 10 | 11 | useEffect(() => { 12 | window.scrollTo({ 13 | top: 0, 14 | left: 0, 15 | behavior: 'smooth' 16 | }); 17 | }, [pathname]); 18 | 19 | return children || null; 20 | }; 21 | 22 | NavigationScroll.propTypes = { 23 | children: PropTypes.node 24 | }; 25 | 26 | export default NavigationScroll; 27 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/menu-items/dashboard.js: -------------------------------------------------------------------------------- 1 | // assets 2 | import { IconDashboard } from '@tabler/icons'; 3 | 4 | // constant 5 | const icons = { IconDashboard }; 6 | 7 | // ==============================|| DASHBOARD MENU ITEMS ||============================== // 8 | 9 | const dashboard = { 10 | id: 'dashboard', 11 | title: '场景示例', 12 | type: 'group', 13 | children: [ 14 | { 15 | id: 'default', 16 | title: '流程图', 17 | type: 'item', 18 | url: '/dashboard/default', 19 | icon: icons.IconDashboard, 20 | breadcrumbs: false 21 | } 22 | ] 23 | }; 24 | 25 | export default dashboard; 26 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/menu-items/edges.js: -------------------------------------------------------------------------------- 1 | // assets 2 | import { IconLayersLinked } from '@tabler/icons'; 3 | 4 | // constant 5 | const icons = { IconLayersLinked }; 6 | 7 | // ==============================|| DASHBOARD MENU ITEMS ||============================== // 8 | 9 | const edges = { 10 | id: 'edge', 11 | title: '边', 12 | type: 'group', 13 | children: [ 14 | { 15 | id: 'default-edge', 16 | title: '内置边', 17 | type: 'item', 18 | url: '/edges/native-edge', 19 | icon: icons.IconLayersLinked, 20 | breadcrumbs: false 21 | } 22 | ] 23 | }; 24 | 25 | export default edges; 26 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/menu-items/index.js: -------------------------------------------------------------------------------- 1 | import dashboard from './dashboard'; 2 | import nodes from './nodes'; 3 | import edges from './edges'; 4 | import layout from './layout'; 5 | 6 | // ==============================|| MENU ITEMS ||============================== // 7 | 8 | const menuItems = { 9 | items: [dashboard, nodes, edges, layout] 10 | }; 11 | 12 | export default menuItems; 13 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/menu-items/nodes.js: -------------------------------------------------------------------------------- 1 | // assets 2 | import { IconBoxMultiple } from '@tabler/icons'; 3 | 4 | // constant 5 | const icons = { IconBoxMultiple }; 6 | 7 | // ==============================|| DASHBOARD MENU ITEMS ||============================== // 8 | 9 | const nodes = { 10 | id: 'node', 11 | title: '节点', 12 | type: 'group', 13 | children: [ 14 | { 15 | id: 'default-node', 16 | title: '内置节点', 17 | type: 'item', 18 | url: '/nodes/native-node', 19 | icon: icons.IconBoxMultiple, 20 | breadcrumbs: false 21 | } 22 | ] 23 | }; 24 | 25 | export default nodes; 26 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/routes/index.js: -------------------------------------------------------------------------------- 1 | import { useRoutes } from 'react-router-dom'; 2 | 3 | // routes 4 | import MainRoutes from './MainRoutes'; 5 | 6 | // ==============================|| ROUTING RENDER ||============================== // 7 | 8 | export default function ThemeRoutes() { 9 | return useRoutes([MainRoutes]); 10 | } 11 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/store/actions.js: -------------------------------------------------------------------------------- 1 | // action - customization reducer 2 | export const SET_MENU = '@customization/SET_MENU'; 3 | export const MENU_TOGGLE = '@customization/MENU_TOGGLE'; 4 | export const MENU_OPEN = '@customization/MENU_OPEN'; 5 | export const SET_FONT_FAMILY = '@customization/SET_FONT_FAMILY'; 6 | export const SET_BORDER_RADIUS = '@customization/SET_BORDER_RADIUS'; 7 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/store/constant.js: -------------------------------------------------------------------------------- 1 | // theme constant 2 | export const gridSpacing = 3; 3 | export const drawerWidth = 260; 4 | export const appDrawerWidth = 320; 5 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'redux'; 2 | import reducer from './reducer'; 3 | 4 | // ==============================|| REDUX - MAIN STORE ||============================== // 5 | 6 | const store = createStore(reducer); 7 | const persister = 'Free'; 8 | 9 | export { store, persister }; 10 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | // reducer import 4 | import customizationReducer from './customizationReducer'; 5 | 6 | // ==============================|| COMBINE REDUCER ||============================== // 7 | 8 | const reducer = combineReducers({ 9 | customization: customizationReducer 10 | }); 11 | 12 | export default reducer; 13 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/ui-component/Loadable.js: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react'; 2 | 3 | // project imports 4 | import Loader from './Loader'; 5 | 6 | // ==============================|| LOADABLE - LAZY LOADING ||============================== // 7 | 8 | const Loadable = (Component) => (props) => { 9 | return ( 10 | }> 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default Loadable; 17 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/ui-component/Loader.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import LinearProgress from '@mui/material/LinearProgress'; 3 | import { styled } from '@mui/material/styles'; 4 | 5 | // styles 6 | const LoaderWrapper = styled('div')({ 7 | position: 'fixed', 8 | top: 0, 9 | left: 0, 10 | zIndex: 1301, 11 | width: '100%' 12 | }); 13 | 14 | // ==============================|| LOADER ||============================== // 15 | const Loader = () => ( 16 | 17 | 18 | 19 | ); 20 | 21 | export default Loader; 22 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/ui-component/cards/AuthFooter.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { Link, Typography, Stack } from '@mui/material'; 3 | 4 | // ==============================|| FOOTER - AUTHENTICATION 2 & 3 ||============================== // 5 | 6 | const AuthFooter = () => ( 7 | 8 | 9 | berrydashboard.io 10 | 11 | 12 | © codedthemes.com 13 | 14 | 15 | ); 16 | 17 | export default AuthFooter; 18 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/ui-component/cards/Skeleton/ImagePlaceholder.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import Skeleton from '@mui/material/Skeleton'; 3 | 4 | // ==============================|| SKELETON IMAGE CARD ||============================== // 5 | 6 | const ImagePlaceholder = ({ ...others }) => ; 7 | 8 | export default ImagePlaceholder; 9 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/ui-component/cards/Skeleton/TotalIncomeCard.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { Card, List, ListItem, ListItemAvatar, ListItemText, Skeleton } from '@mui/material'; 3 | 4 | // ==============================|| SKELETON - TOTAL INCOME DARK/LIGHT CARD ||============================== // 5 | 6 | const TotalIncomeCard = () => ( 7 | 8 | 9 | 10 | 11 | 12 | 13 | } secondary={} /> 14 | 15 | 16 | 17 | ); 18 | 19 | export default TotalIncomeCard; 20 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/views/dashboard/Default/chart-data/bajaj-area-chart.js: -------------------------------------------------------------------------------- 1 | // ===========================|| DASHBOARD - BAJAJ AREA CHART ||=========================== // 2 | 3 | const chartData = { 4 | type: 'area', 5 | height: 95, 6 | options: { 7 | chart: { 8 | id: 'support-chart', 9 | sparkline: { 10 | enabled: true 11 | } 12 | }, 13 | dataLabels: { 14 | enabled: false 15 | }, 16 | stroke: { 17 | curve: 'smooth', 18 | width: 1 19 | }, 20 | tooltip: { 21 | fixed: { 22 | enabled: false 23 | }, 24 | x: { 25 | show: false 26 | }, 27 | y: { 28 | title: 'Ticket ' 29 | }, 30 | marker: { 31 | show: false 32 | } 33 | } 34 | }, 35 | series: [ 36 | { 37 | data: [0, 15, 10, 50, 30, 40, 25] 38 | } 39 | ] 40 | }; 41 | 42 | export default chartData; 43 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/views/edges/index.js: -------------------------------------------------------------------------------- 1 | // material-ui 2 | import { Typography } from '@mui/material'; 3 | 4 | // project imports 5 | import MainCard from 'ui-component/cards/MainCard'; 6 | 7 | // ==============================|| SAMPLE PAGE ||============================== // 8 | 9 | const SamplePage = () => ( 10 | 11 | 12 | Lorem ipsum dolor sit amen, consenter nipissing eli, sed do elusion tempos incident ut laborers et doolie magna alissa. Ut enif ad 13 | minim venice, quin nostrum exercitation illampu laborings nisi ut liquid ex ea commons construal. Duos aube grue dolor in reprehended 14 | in voltage veil esse colum doolie eu fujian bulla parian. Exceptive sin ocean cuspidate non president, sunk in culpa qui officiate 15 | descent molls anim id est labours. 16 | 17 | 18 | ); 19 | 20 | export default SamplePage; 21 | -------------------------------------------------------------------------------- /examples/material-ui-demo/src/views/layout/MaterialIcons.js: -------------------------------------------------------------------------------- 1 | import { styled } from '@mui/material/styles'; 2 | import { Card } from '@mui/material'; 3 | 4 | // project imports 5 | import MainCard from 'ui-component/cards/MainCard'; 6 | import SecondaryAction from 'ui-component/cards/CardSecondaryAction'; 7 | 8 | // styles 9 | const IFrameWrapper = styled('iframe')(({ theme }) => ({ 10 | height: 'calc(100vh - 210px)', 11 | border: '1px solid', 12 | borderColor: theme.palette.primary.light 13 | })); 14 | 15 | // ============================|| MATERIAL ICONS ||============================ // 16 | 17 | const MaterialIcons = () => ( 18 | }> 19 | 20 | 21 | 22 | 23 | ); 24 | 25 | export default MaterialIcons; 26 | -------------------------------------------------------------------------------- /examples/next-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "import/no-anonymous-default-export": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/next-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /examples/next-app/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | export default nextConfig 5 | -------------------------------------------------------------------------------- /examples/next-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@ant-design/icons": "^5.0.1", 13 | "@logicflow/core": "workspace:*", 14 | "@logicflow/engine": "workspace:*", 15 | "@logicflow/extension": "workspace:*", 16 | "antd": "^5.4.0", 17 | "react": "^18", 18 | "react-dom": "^18", 19 | "next": "14.2.3" 20 | }, 21 | "devDependencies": { 22 | "typescript": "^5", 23 | "@types/node": "^20", 24 | "@types/react": "^18", 25 | "@types/react-dom": "^18", 26 | "postcss": "^8", 27 | "tailwindcss": "^3.4.1", 28 | "eslint": "^8", 29 | "eslint-config-next": "14.2.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/next-app/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /examples/next-app/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/next-app/src/app/edges/animation.ts: -------------------------------------------------------------------------------- 1 | import { BezierEdge, BezierEdgeModel } from '@logicflow/core' 2 | 3 | class AnimationEdge extends BezierEdge {} 4 | 5 | class AnimationEdgeModel extends BezierEdgeModel { 6 | getEdgeAnimationStyle() { 7 | const style = super.getEdgeAnimationStyle() 8 | style.stroke = 'blue' 9 | style.animationDuration = '30s' 10 | style.animationDirection = 'reverse' 11 | return style 12 | } 13 | } 14 | 15 | export default { 16 | type: 'animation-edge', 17 | view: AnimationEdge, 18 | model: AnimationEdgeModel, 19 | } 20 | -------------------------------------------------------------------------------- /examples/next-app/src/app/edges/index.ts: -------------------------------------------------------------------------------- 1 | import animation from './animation' 2 | import connection from './connection' 3 | 4 | export * from './animation' 5 | export * from './connection' 6 | 7 | export { animation, connection } 8 | -------------------------------------------------------------------------------- /examples/next-app/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/next-app/src/app/favicon.ico -------------------------------------------------------------------------------- /examples/next-app/src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --foreground-rgb: 0, 0, 0; 7 | --background-start-rgb: 214, 219, 220; 8 | --background-end-rgb: 255, 255, 255; 9 | } 10 | 11 | @media (prefers-color-scheme: dark) { 12 | :root { 13 | --foreground-rgb: 255, 255, 255; 14 | --background-start-rgb: 0, 0, 0; 15 | --background-end-rgb: 0, 0, 0; 16 | } 17 | } 18 | 19 | body { 20 | color: rgb(var(--foreground-rgb)); 21 | background: linear-gradient( 22 | to bottom, 23 | transparent, 24 | rgb(var(--background-end-rgb)) 25 | ) 26 | rgb(var(--background-start-rgb)); 27 | } 28 | 29 | @layer utilities { 30 | .text-balance { 31 | text-wrap: balance; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/next-app/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { Inter } from 'next/font/google' 3 | import './globals.css' 4 | 5 | const inter = Inter({ subsets: ['latin'] }) 6 | 7 | export const metadata: Metadata = { 8 | title: 'Create Next App', 9 | description: 'Generated by create next app', 10 | } 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode 16 | }>) { 17 | return ( 18 | 19 | {children} 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-app/src/app/nodes/index.ts: -------------------------------------------------------------------------------- 1 | import combine from './combine' 2 | import star from './star' 3 | import square from './square' 4 | import uml from './uml' 5 | import user from './user' 6 | import reactNode from './ReactNode' 7 | 8 | export * from './combine' 9 | export * from './star' 10 | export * from './square' 11 | export * from './uml' 12 | export * from './user' 13 | export * from './ReactNode' 14 | 15 | export { combine, square, star, uml, user, reactNode } 16 | -------------------------------------------------------------------------------- /examples/next-app/src/app/nodes/star.ts: -------------------------------------------------------------------------------- 1 | import { PolygonNode, PolygonNodeModel } from '@logicflow/core' 2 | 3 | class StarModel extends PolygonNodeModel { 4 | setAttributes() { 5 | this.points = [ 6 | [45, 0], 7 | [20, 90], 8 | [90, 30], 9 | [0, 30], 10 | [80, 90], 11 | ] 12 | this.fill = '#456789' 13 | this.stroke = '#456789' 14 | } 15 | } 16 | 17 | export default { 18 | type: 'star', 19 | view: PolygonNode, 20 | model: StarModel, 21 | } 22 | -------------------------------------------------------------------------------- /examples/next-app/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'tailwindcss' 2 | 3 | const config: Config = { 4 | content: [ 5 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}', 6 | './src/components/**/*.{js,ts,jsx,tsx,mdx}', 7 | './src/app/**/*.{js,ts,jsx,tsx,mdx}', 8 | ], 9 | theme: { 10 | extend: { 11 | backgroundImage: { 12 | 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 13 | 'gradient-conic': 14 | 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 15 | }, 16 | }, 17 | }, 18 | plugins: [], 19 | } 20 | export default config 21 | -------------------------------------------------------------------------------- /examples/next-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /examples/vue3-app/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | extends: [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-typescript', 10 | '@vue/eslint-config-prettier/skip-formatting' 11 | ], 12 | parserOptions: { 13 | ecmaVersion: 'latest' 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/vue3-app/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | 30 | *.tsbuildinfo 31 | -------------------------------------------------------------------------------- /examples/vue3-app/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } 9 | -------------------------------------------------------------------------------- /examples/vue3-app/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/vue3-app/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/vue3-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/vue3-app/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/vue3-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/vue3-app/public/favicon.ico -------------------------------------------------------------------------------- /examples/vue3-app/src/assets/didi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/vue3-app/src/assets/didi.png -------------------------------------------------------------------------------- /examples/vue3-app/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/vue3-app/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | #app { 8 | width: 100%; 9 | display: flex; 10 | font-weight: normal; 11 | height: 100vh; 12 | } 13 | 14 | a, 15 | .green { 16 | text-decoration: none; 17 | color: hsla(160, 100%, 37%, 1); 18 | transition: 0.4s; 19 | padding: 3px; 20 | } 21 | 22 | @media (hover: hover) { 23 | a:hover { 24 | background-color: hsla(160, 100%, 37%, 0.2); 25 | } 26 | } 27 | 28 | @media (min-width: 1024px) { 29 | body { 30 | display: flex; 31 | place-items: center; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 44 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/LFElements/edges/animation.ts: -------------------------------------------------------------------------------- 1 | import { BezierEdge, BezierEdgeModel } from '@logicflow/core' 2 | 3 | class AnimationEdge extends BezierEdge {} 4 | 5 | class AnimationEdgeModel extends BezierEdgeModel { 6 | getEdgeAnimationStyle() { 7 | const style = super.getEdgeAnimationStyle() 8 | style.stroke = 'blue' 9 | style.animationDuration = '30s' 10 | style.animationDirection = 'reverse' 11 | return style 12 | } 13 | } 14 | 15 | export default { 16 | type: 'animation-edge', 17 | view: AnimationEdge, 18 | model: AnimationEdgeModel 19 | } 20 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/LFElements/edges/index.ts: -------------------------------------------------------------------------------- 1 | import animation from './animation' 2 | import connection from './connection' 3 | 4 | export * from './animation' 5 | export * from './connection' 6 | 7 | export { animation, connection } 8 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/LFElements/nodes/index.ts: -------------------------------------------------------------------------------- 1 | import combine from './combine' 2 | import star from './star' 3 | import square from './square' 4 | import uml from './uml' 5 | import user from './user' 6 | 7 | export * from './combine' 8 | export * from './star' 9 | export * from './square' 10 | export * from './uml' 11 | export * from './user' 12 | 13 | export { combine, square, star, uml, user } 14 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/LFElements/nodes/star.ts: -------------------------------------------------------------------------------- 1 | import { PolygonNode, PolygonNodeModel } from '@logicflow/core' 2 | 3 | class StarModel extends PolygonNodeModel { 4 | setAttributes() { 5 | this.points = [ 6 | [45, 0], 7 | [20, 90], 8 | [90, 30], 9 | [0, 30], 10 | [80, 90] 11 | ] 12 | this.fill = '#456789' 13 | this.stroke = '#456789' 14 | } 15 | } 16 | 17 | export default { 18 | type: 'star', 19 | view: PolygonNode, 20 | model: StarModel 21 | } 22 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/UILibrary/EchartNode.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 16 | 22 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/__tests__/HelloWorld.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | 3 | import { mount } from '@vue/test-utils' 4 | import HelloWorld from '../HelloWorld.vue' 5 | 6 | describe('HelloWorld', () => { 7 | it('renders properly', () => { 8 | const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) 9 | expect(wrapper.text()).toContain('Hello Vitest') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/chart/confg.ts: -------------------------------------------------------------------------------- 1 | export const size = { 2 | width: window.innerWidth, 3 | height: window.innerHeight, 4 | analysisNodeHeight: 100, 5 | defaultNodeWidth: 300, 6 | defaultNodeHeight: 40 7 | } 8 | 9 | export const gap = { 10 | margin: 10, 11 | padding: 20, 12 | nodeGap: 40 13 | } 14 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/chart/nodes/AnalysisNode.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/chart/nodes/DefaultNode.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/chart/types.d.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow, { GraphModel, BaseNodeModel } from '@logicflow/core' 2 | 3 | /** 4 | * 节点数据接口 5 | */ 6 | export interface INode { 7 | id: string 8 | type: string 9 | x: number 10 | y: number 11 | properties: Record 12 | } 13 | 14 | /** 15 | * 边数据接口 16 | */ 17 | export interface IEdge { 18 | id: string 19 | type: string 20 | sourceNodeId: string 21 | targetNodeId: string 22 | } 23 | 24 | /** 25 | * 节点和边的数据接口 26 | */ 27 | export interface IGraphData { 28 | nodes: INode[] 29 | edges: IEdge[] 30 | } 31 | 32 | /** 33 | * 自定义插件构造函数接收参数 34 | */ 35 | export interface IExtension { 36 | lf: LogicFlow 37 | LogicFlow?: LogicFlow 38 | } 39 | 40 | /** 41 | * 自定义节点构造函数接收参数 42 | */ 43 | export interface INodeProps { 44 | graphModel: GraphModel 45 | model: BaseNodeModel 46 | overlay: string 47 | } 48 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/dom/DomNumber.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 22 | -------------------------------------------------------------------------------- /examples/vue3-app/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /examples/vue3-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import './assets/main.css' 2 | import 'element-plus/dist/index.css' 3 | import '@logicflow/core/dist/index.css' 4 | 5 | import { createApp } from 'vue' 6 | import ElementPlus from 'element-plus' 7 | import App from './App.vue' 8 | import router from './router' 9 | 10 | const app = createApp(App) 11 | 12 | app.use(ElementPlus) 13 | app.use(router) 14 | 15 | app.mount('#app') 16 | -------------------------------------------------------------------------------- /examples/vue3-app/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue' 3 | const component: DefineComponent<{}, {}, any> 4 | export default component 5 | } 6 | 7 | declare module 'vue-virtual-scroller' 8 | declare module '@antv/hierarchy' 9 | -------------------------------------------------------------------------------- /examples/vue3-app/src/utils/math.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取随机整数 [min, max],不包含 [excludemMin, excludeMax] 3 | * @param min 4 | * @param max 5 | * @returns 6 | */ 7 | export const getRandom = (min: number, max: number, excludemMin?: number, excludeMax?: number) => { 8 | let res = Math.floor(Math.random() * (max - min + 1) + min) 9 | 10 | if ( 11 | excludemMin !== undefined && 12 | excludeMax !== undefined && 13 | res >= excludemMin && 14 | res <= excludeMax 15 | ) { 16 | res = getRandom(min, max, excludemMin, excludeMax) 17 | } 18 | 19 | return res 20 | } 21 | -------------------------------------------------------------------------------- /examples/vue3-app/src/utils/performance.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取页面 dom 数量 3 | * @returns 4 | */ 5 | export const getTotalDOMNumber = () => document.querySelectorAll('*').length 6 | 7 | export type PerformanceLongTaskEntry = { 8 | type: 'longTask' 9 | eventType: string 10 | startTime: number 11 | duration: number 12 | } 13 | 14 | /** 15 | * 监控长任务事件响应时间:耗费了 50 毫秒或更多时间 16 | */ 17 | export const startObservingLongTasks = (callback: any) => { 18 | const observer = new PerformanceObserver((entryList) => { 19 | const entries = entryList.getEntries() 20 | entries.forEach((entry) => { 21 | requestIdleCallback(() => { 22 | callback(entry) 23 | }) 24 | }) 25 | }) 26 | observer.observe({ entryTypes: ['longtask'] }) 27 | } 28 | -------------------------------------------------------------------------------- /examples/vue3-app/src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /examples/vue3-app/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,vue}'], 4 | theme: { 5 | screens: { 6 | sm: { min: '640px', max: '767px' }, 7 | // => @media (min-width: 640px and max-width: 767px) { ... } 8 | md: { min: '768px', max: '1023px' }, 9 | // => @media (min-width: 768px and max-width: 1023px) { ... } 10 | lg: { min: '1024px', max: '1599px' }, 11 | // => @media (min-width: 1024px and max-width: 1599px) { ... } 12 | xl: { min: '1600px', max: '1919px' }, 13 | // => @media (min-width: 1600px and max-width: 1919px) { ... } 14 | '2xl': { min: '1920px' } 15 | // => @media (min-width: 1920px) { ... } 16 | }, 17 | extend: {} 18 | }, 19 | plugins: [] 20 | } 21 | -------------------------------------------------------------------------------- /examples/vue3-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/vue3-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "compilerOptions": { 4 | "verbatimModuleSyntax": false, 5 | "noImplicitAny": false 6 | }, 7 | "references": [ 8 | { 9 | "path": "./tsconfig.node.json" 10 | }, 11 | { 12 | "path": "./tsconfig.app.json" 13 | }, 14 | { 15 | "path": "./tsconfig.vitest.json" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /examples/vue3-app/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "noEmit": true, 13 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 | 15 | "module": "ESNext", 16 | "moduleResolution": "Bundler", 17 | "types": ["node"], 18 | "noImplicitAny": false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/vue3-app/tsconfig.vitest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "exclude": [], 4 | "compilerOptions": { 5 | "composite": true, 6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", 7 | 8 | "lib": [], 9 | "types": ["node", "jsdom"] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/vue3-app/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | // vite-plugin-vue-devtools 会导致所有的vue节点被记录在 全局变量 __VUE_DEVTOOLS_KIT_PLUGIN_BUFFER__ 上,导致内存溢出的bug 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)) 12 | } 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /examples/vue3-app/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' 3 | import viteConfig from './vite.config' 4 | 5 | export default mergeConfig( 6 | viteConfig, 7 | defineConfig({ 8 | test: { 9 | environment: 'jsdom', 10 | exclude: [...configDefaults.exclude, 'e2e/**'], 11 | root: fileURLToPath(new URL('./', import.meta.url)) 12 | } 13 | }) 14 | ) 15 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/README.md: -------------------------------------------------------------------------------- 1 | # LogicFlow-NodeRed 2 | 3 | LogicFlow仿NodeRed风格流程图。 4 | 5 | ## 效果 6 | 7 | ![node-red](https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/core/node-red.png) 8 | 9 | ## codesandbox地址 10 | 11 | [https://codesandbox.io/s/logicflow-node-red-vue3-u2c3zk?file=/src/components/FlowChart.vue](https://codesandbox.io/s/logicflow-node-red-vue3-u2c3zk?file=/src/components/FlowChart.vue) 12 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by 'unplugin-auto-import' 2 | // We suggest you to commit this file into source control 3 | declare global {} 4 | export {} 5 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/components.d.ts: -------------------------------------------------------------------------------- 1 | // generated by unplugin-vue-components 2 | // We suggest you to commit this file into source control 3 | // Read more: https://github.com/vuejs/vue-next/pull/3399 4 | 5 | declare module 'vue' { 6 | export interface GlobalComponents { 7 | ElButton: (typeof import('element-plus/es'))['ElButton'] 8 | ElCollapse: (typeof import('element-plus/es'))['ElCollapse'] 9 | ElCollapseItem: (typeof import('element-plus/es'))['ElCollapseItem'] 10 | ElInput: (typeof import('element-plus/es'))['ElInput'] 11 | FlowChart: (typeof import('./src/components/FlowChart.vue'))['default'] 12 | Palette: (typeof import('./src/components/node-red/tools/Palette.vue'))['default'] 13 | Setting: (typeof import('./src/components/node-red/tools/Setting.vue'))['default'] 14 | Undefined: (typeof import('./src/components/index.vue'))['default'] 15 | VueNode: (typeof import('./src/components/node-red/nodes/VueNode.vue'))['default'] 16 | } 17 | } 18 | 19 | export {} 20 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | LogicFlow 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "logicflow-node-red-vue3", 3 | "private": true, 4 | "version": "1.0.1", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@logicflow/core": "workspace:*", 13 | "@logicflow/engine": "workspace:*", 14 | "element-plus": "^2.0.4", 15 | "vue": "^3.2.25" 16 | }, 17 | "devDependencies": { 18 | "@vitejs/plugin-vue": "^2.2.0", 19 | "unplugin-auto-import": "^0.6.1", 20 | "unplugin-vue-components": "^0.17.21", 21 | "vite": "^2.8.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/vue3-memory-leak/public/favicon.ico -------------------------------------------------------------------------------- /examples/vue3-memory-leak/public/images/delay.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/public/images/function.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/public/images/start.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/public/images/swap.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/public/images/switch.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/examples/vue3-memory-leak/src/assets/logo.png -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/engine/index.js: -------------------------------------------------------------------------------- 1 | class Engine { 2 | run() {} 3 | initFlow() {} 4 | } 5 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 21 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/FlowLink.js: -------------------------------------------------------------------------------- 1 | import { BezierEdge, BezierEdgeModel } from '@logicflow/core' 2 | 3 | class FlowLinkModel extends BezierEdgeModel { 4 | getEdgeStyle() { 5 | const style = super.getEdgeStyle() 6 | style.strokeWidth = 3 7 | style.stroke = this.isSelected ? '#ff7f0e' : '#999' 8 | return style 9 | } 10 | } 11 | class FlowLink extends BezierEdge {} 12 | 13 | export default { 14 | type: 'flow-link', 15 | view: FlowLink, 16 | model: FlowLinkModel, 17 | } 18 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/nodes/DelayNode.js: -------------------------------------------------------------------------------- 1 | import { h } from '@logicflow/core' 2 | import BaseNode from './BaseNode' 3 | 4 | class DelayNode extends BaseNode.view { 5 | getIcon() { 6 | const { width, height } = this.props.model 7 | return h('image', { 8 | width: 30, 9 | height: 30, 10 | x: -width / 2, 11 | y: -height / 2, 12 | href: 'images/delay.svg', 13 | }) 14 | } 15 | } 16 | 17 | class DelayNodeModel extends BaseNode.model { 18 | initNodeData(data) { 19 | super.initNodeData(data) 20 | this.defaultFill = 'rgb(230, 224, 248)' 21 | } 22 | } 23 | 24 | export default { 25 | type: 'delay-node', 26 | model: DelayNodeModel, 27 | view: DelayNode, 28 | } 29 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/nodes/FetchNode.js: -------------------------------------------------------------------------------- 1 | import { h } from '@logicflow/core' 2 | import BaseNode from './BaseNode' 3 | 4 | class FetchNode extends BaseNode.view { 5 | getIcon() { 6 | const { width, height } = this.props.model 7 | return h('image', { 8 | width: 30, 9 | height: 30, 10 | x: -width / 2, 11 | y: -height / 2, 12 | href: 'images/fetch.svg', 13 | }) 14 | } 15 | } 16 | 17 | class FetchNodeModel extends BaseNode.model { 18 | initNodeData(data) { 19 | super.initNodeData(data) 20 | this.defaultFill = 'rgb(231, 231, 174)' 21 | } 22 | } 23 | 24 | export default { 25 | type: 'fetch-node', 26 | model: FetchNodeModel, 27 | view: FetchNode, 28 | } 29 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/nodes/FunctionNode.js: -------------------------------------------------------------------------------- 1 | import { h } from '@logicflow/core' 2 | import BaseNode from './BaseNode' 3 | 4 | class FunctionNode extends BaseNode.view { 5 | getIcon() { 6 | const { width, height } = this.props.model 7 | return h('image', { 8 | width: 30, 9 | height: 30, 10 | x: -width / 2, 11 | y: -height / 2, 12 | href: 'images/function.svg', 13 | }) 14 | } 15 | } 16 | 17 | class FunctionNodeModel extends BaseNode.model { 18 | initNodeData(data) { 19 | super.initNodeData(data) 20 | this.defaultFill = 'rgb(253, 208, 162)' 21 | } 22 | } 23 | 24 | export default { 25 | type: 'function-node', 26 | model: FunctionNodeModel, 27 | view: FunctionNode, 28 | } 29 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/nodes/SwitchNode.js: -------------------------------------------------------------------------------- 1 | import { h } from '@logicflow/core' 2 | import BaseNode from './BaseNode' 3 | 4 | class SwitchNode extends BaseNode.view { 5 | getIcon() { 6 | const { width, height } = this.props.model 7 | return h('image', { 8 | width: 30, 9 | height: 30, 10 | x: -width / 2, 11 | y: -height / 2, 12 | href: 'images/switch.svg', 13 | }) 14 | } 15 | } 16 | 17 | class SwitchNodeModel extends BaseNode.model { 18 | initNodeData(data) { 19 | super.initNodeData(data) 20 | this.defaultFill = 'rgb(226, 217, 110)' 21 | } 22 | } 23 | 24 | export default { 25 | type: 'switch-node', 26 | model: SwitchNodeModel, 27 | view: SwitchNode, 28 | } 29 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/readme.md: -------------------------------------------------------------------------------- 1 | # 说明 2 | 3 | 参考node-red样式,以logicflow插件的方式实现。 4 | 5 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/style.css: -------------------------------------------------------------------------------- 1 | .custom-anchor { 2 | stroke: #999; 3 | stroke-width: 1; 4 | fill: #d9d9d9; 5 | cursor: crosshair; 6 | rx: 3; 7 | ry: 3; 8 | } 9 | .custom-anchor:hover { 10 | fill: #ff7f0e; 11 | stroke: #ff7f0e; 12 | } 13 | .node-red-palette { 14 | width: 150px; 15 | overflow: hidden; 16 | position: absolute; 17 | left: 0px; 18 | top: 0px; 19 | } 20 | .node-red-start { 21 | cursor: pointer; 22 | pointer-events: all; 23 | } 24 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/components/node-red/util.js: -------------------------------------------------------------------------------- 1 | /* 求字符串的字节长度 */ 2 | export const getBytesLength = (word) => { 3 | if (!word) { 4 | return 0 5 | } 6 | let totalLength = 0 7 | for (let i = 0; i < word.length; i++) { 8 | const c = word.charCodeAt(i) 9 | if (word.match(/[A-Z]/)) { 10 | totalLength += 1.5 11 | } else if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) { 12 | totalLength += 1 13 | } else { 14 | totalLength += 1.8 15 | } 16 | } 17 | return totalLength 18 | } 19 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | // import ElementPlus from 'element-plus' 3 | import App from './App.vue' 4 | import './style.css' 5 | 6 | const app = createApp(App) 7 | 8 | // app.use(ElementPlus) 9 | 10 | app.mount('#app') 11 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/src/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | width: 100%; 6 | height: 100%; 7 | } 8 | #app { 9 | width: 100%; 10 | height: 100%; 11 | } 12 | -------------------------------------------------------------------------------- /examples/vue3-memory-leak/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | import AutoImport from 'unplugin-auto-import/vite' 4 | import Components from 'unplugin-vue-components/vite' 5 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | // 在codesandbox中需要用443来保证开发时不会重复刷新 10 | // server: { 11 | // hmr: { 12 | // port: 443 13 | // } 14 | // }, 15 | base: '/demo/dist/logicflow-node-red-vue3/', 16 | plugins: [ 17 | vue(), 18 | AutoImport({ 19 | resolvers: [ElementPlusResolver()], 20 | }), 21 | Components({ 22 | resolvers: [ElementPlusResolver()], 23 | }), 24 | ], 25 | }) 26 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "pnpm", 3 | "npmClientArgs": ["--no-package-lock", "--no-ci"], 4 | "version": "independent", 5 | "useWorkspaces": true, 6 | "packages": [ 7 | "packages/core", 8 | "packages/engine", 9 | "packages/extension", 10 | "packages/react-node-registry", 11 | "packages/vue-node-registry" 12 | ], 13 | "command": { 14 | "version": { 15 | "conventionalCommits": true 16 | } 17 | }, 18 | "publishConfig": { 19 | "access": "public" 20 | }, 21 | "ignoreChanges": ["**/*.md"], 22 | "bootstrap": { 23 | "hoist": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/__tests__/event/event.test.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter from '../../src/event/eventEmitter'; 2 | 3 | describe('event/eventEmitter', () => { 4 | const em = new EventEmitter(); 5 | test('event emitter', () => { 6 | const fn = jest.fn(); 7 | em.on('test', fn); 8 | em.emit('test', { a: 1 }); 9 | expect(fn).toBeCalledWith({ a: 1 }); 10 | em.off('test', fn); 11 | em.emit('test', { a: 1 }); 12 | expect(fn).toBeCalledTimes(1); 13 | 14 | em.once('test1', fn); 15 | em.emit('test1', { a: 1 }); 16 | expect(fn).toBeCalledTimes(2); 17 | em.once('test1', fn); 18 | em.emit('test1', { a: 1 }); 19 | const test1Events = em.getEvents().test1; 20 | expect(test1Events).toBeUndefined(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/core/__tests__/history/history.test.ts: -------------------------------------------------------------------------------- 1 | import History from '../../src/history/History'; 2 | import EventEmitter from '../../src/event/eventEmitter'; 3 | 4 | describe('history', () => { 5 | const event = new EventEmitter(); 6 | const history = new History(event); 7 | expect(history).toBeDefined(); 8 | test('add', () => { 9 | history.add(1); 10 | expect(history.undos).toEqual([1]); 11 | expect(history.redos).toEqual([]); 12 | }); 13 | test('undo', () => { 14 | history.add(1); 15 | history.add(2); 16 | history.undo(); 17 | expect(history.undos).toEqual([]); 18 | expect(history.redos).toEqual([2]); 19 | }); 20 | test('redo', () => { 21 | history.add(1); 22 | history.add(2); 23 | history.undo(); 24 | history.redo(); 25 | expect(history.undos).toEqual([]); 26 | expect(history.redos).toEqual([]); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /packages/core/__tests__/util/geometry.test.ts: -------------------------------------------------------------------------------- 1 | import { snapToGrid, getGridOffset } from '../../src/util'; 2 | 3 | describe('util/geometry', () => { 4 | test('snapToGrid', () => { 5 | const point = 2.5; 6 | const grid = 1.5; 7 | expect(snapToGrid(point, grid) - 3 < Number.EPSILON).toBeTruthy(); 8 | }); 9 | test('getGridOffset', () => { 10 | const distance = 3; 11 | const grid = 1.5; 12 | expect(getGridOffset(distance, grid) - 2 < Number.EPSILON).toBeTruthy(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/core/__tests__/util/graph.test.ts: -------------------------------------------------------------------------------- 1 | import { isPointInArea } from '../../src/util/graph'; 2 | 3 | describe('util/graph', () => { 4 | test('if element is in an area, truthy', () => { 5 | const point: [number, number] = [1, 1]; 6 | const leftTopPoint: [number, number] = [0, 0]; 7 | const rightBottomPoint: [number, number] = [2, 2]; 8 | expect(isPointInArea(point, leftTopPoint, rightBottomPoint)).toBeTruthy(); 9 | }); 10 | test('if element is in an area, falsy', () => { 11 | const point: [number, number] = [1, 1]; 12 | const leftTopPoint: [number, number] = [2, 2]; 13 | const rightBottomPoint: [number, number] = [4, 4]; 14 | expect(isPointInArea(point, leftTopPoint, rightBottomPoint)).toBeFalsy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/core/__tests__/util/sampling.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | degrees, 3 | getThetaOfVector, 4 | Vector, 5 | } from '../../src/util'; 6 | 7 | describe('util/sampling', () => { 8 | test('degrees', () => { 9 | expect(degrees(1)).toBe(57.29577951308232); 10 | }); 11 | test('getThetaOfVector', () => { 12 | expect( 13 | getThetaOfVector(new Vector(1, 1)) - 45 < Number.EPSILON, 14 | ).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/core/__tests__/util/zIndex.test.ts: -------------------------------------------------------------------------------- 1 | import { getZIndex, getMinIndex } from '../../src/util/zIndex'; 2 | 3 | describe('util/zIndex', () => { 4 | test('getZIndex', () => { 5 | expect(getZIndex()).toBe(1001); 6 | }); 7 | test('getMinIndex', () => { 8 | expect(getMinIndex()).toBe(998); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/core/src/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './drag' 2 | export * from './history' 3 | export * from './keyboard' 4 | 5 | export * from './matrix' 6 | export * from './vector' 7 | -------------------------------------------------------------------------------- /packages/core/src/index.less: -------------------------------------------------------------------------------- 1 | @import url('./style/index'); 2 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | import { observer as mobxObserver } from 'mobx-preact' 2 | import { createElement as h, createRef, Component } from 'preact/compat' 3 | import LogicFlow from './LogicFlow' 4 | 5 | import * as LogicFlowUtil from './util' 6 | 7 | export function observer

(props: P) { 8 | return mobxObserver(props as any) 9 | } 10 | 11 | export { LogicFlow, h, createRef, Component, LogicFlowUtil } 12 | 13 | export * from './util' 14 | export * from './tool' 15 | export * from './view' 16 | export * from './model' 17 | export * from './options' 18 | export * from './keyboard' 19 | export * from './constant' 20 | export * from './algorithm' 21 | export * from './event/eventEmitter' 22 | export { ElementState, ModelType, ElementType, EventType } from './constant' 23 | 24 | export { formatAnchorConnectValidateData } from './util/node' 25 | 26 | export default LogicFlow 27 | -------------------------------------------------------------------------------- /packages/core/src/model/edge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BaseEdgeModel'; 2 | export * from './BezierEdgeModel'; 3 | export * from './LineEdgeModel'; 4 | export * from './PolylineEdgeModel'; 5 | -------------------------------------------------------------------------------- /packages/core/src/model/index.ts: -------------------------------------------------------------------------------- 1 | export * from './edge'; 2 | export * from './node'; 3 | 4 | export * from './BaseModel'; 5 | export * from './EditConfigModel'; 6 | export * from './GraphModel'; 7 | export * from './SnaplineModel'; 8 | export * from './TransformModel'; 9 | -------------------------------------------------------------------------------- /packages/core/src/model/node/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BaseNodeModel'; 2 | export * from './CircleNodeModel'; 3 | export * from './DiamondNodeModel'; 4 | export * from './EllipseNodeModel'; 5 | export * from './PolygonNodeModel'; 6 | export * from './RectNodeModel'; 7 | export * from './TextNodeModel'; 8 | export * from './HtmlNodeModel'; 9 | -------------------------------------------------------------------------------- /packages/core/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'mobx-preact' { 2 | import { ComponentConstructor } from 'preact/compat' 3 | type Component

= ComponentConstructor

4 | export function observer(target: T): T 5 | } 6 | -------------------------------------------------------------------------------- /packages/core/src/util/animation.ts: -------------------------------------------------------------------------------- 1 | import { cloneDeep, merge } from 'lodash-es' 2 | import { Options } from '../options' 3 | 4 | import AnimationConfig = Options.AnimationConfig 5 | 6 | export const defaultAnimationOffConfig = { 7 | node: false, 8 | edge: false, 9 | } 10 | 11 | export const defaultAnimationOnConfig = { 12 | node: true, 13 | edge: true, 14 | } 15 | 16 | export const setupAnimation = ( 17 | config?: boolean | Partial, 18 | ): AnimationConfig => { 19 | if (!config || typeof config === 'boolean') { 20 | return config === true 21 | ? cloneDeep(defaultAnimationOnConfig) 22 | : cloneDeep(defaultAnimationOffConfig) 23 | } 24 | 25 | // 当传入的是对象时,将其与默认关合并 26 | return merge(cloneDeep(defaultAnimationOffConfig), config) 27 | } 28 | 29 | export const updateAnimation = setupAnimation 30 | -------------------------------------------------------------------------------- /packages/core/src/util/browser.ts: -------------------------------------------------------------------------------- 1 | import { get } from 'lodash-es' 2 | 3 | export const isIe = () => 4 | get(window, 'navigator.userAgent', '').match(/MSIE|Trident/) !== null 5 | -------------------------------------------------------------------------------- /packages/core/src/util/compatible.ts: -------------------------------------------------------------------------------- 1 | // import { cloneDeep } from 'lodash-es' 2 | /** 3 | * 对数据实现兼容处理。 4 | * 5 | * Vue 中的 data 会进行 Observe,深拷贝的原始数据对象 6 | */ 7 | export function formatData(data: T): T { 8 | try { 9 | // WARNING: cloneDeep虽然也会将Observe对象转换为plain对象,但是不会像JSON.parse那样,会将undefined去掉。 10 | // 会导致后面的pick因为存在pick覆盖默认值的情况。 11 | return JSON.parse(JSON.stringify(data)) 12 | } catch { 13 | return data 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/core/src/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from './animation' 2 | export * from './browser' 3 | export * from './compatible' 4 | export * from './drag' 5 | export * from './edge' 6 | export * from './geometry' 7 | export * from './graph' 8 | export * from './matrix' 9 | export * from './mobx' 10 | export * from './node' 11 | export * from './raf' 12 | export * from './resize' 13 | export * from './sampling' 14 | export * from './theme' 15 | export * from './uuid' 16 | export * from './vector' 17 | export * from './zIndex' 18 | -------------------------------------------------------------------------------- /packages/core/src/util/mobx.ts: -------------------------------------------------------------------------------- 1 | import { 2 | action, 3 | observable, 4 | computed, 5 | toJS, 6 | isObservable, 7 | configure, 8 | reaction, 9 | IReactionDisposer, 10 | } from 'mobx' 11 | 12 | configure({ isolateGlobalState: true }) 13 | 14 | export { 15 | action, 16 | observable, 17 | computed, 18 | isObservable, 19 | toJS, 20 | configure, 21 | reaction, 22 | IReactionDisposer, 23 | } 24 | -------------------------------------------------------------------------------- /packages/core/src/util/raf.ts: -------------------------------------------------------------------------------- 1 | import { createUuid } from './uuid' 2 | 3 | const rafIdMap = new Map() 4 | 5 | export const createRaf = (callback: () => void) => { 6 | const rafId = createUuid() 7 | 8 | function run() { 9 | callback() 10 | const eId = rafIdMap.get(rafId) 11 | if (eId) { 12 | const nId = window.requestAnimationFrame(run) 13 | rafIdMap.set(rafId, nId) 14 | } 15 | } 16 | 17 | const id = window.requestAnimationFrame(run) 18 | rafIdMap.set(rafId, id) 19 | return rafId 20 | } 21 | 22 | export const cancelRaf = (rafId: string) => { 23 | const eId = rafIdMap.get(rafId) 24 | if (eId) { 25 | window.cancelAnimationFrame(eId) 26 | rafIdMap.delete(rafId) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/src/util/uuid.ts: -------------------------------------------------------------------------------- 1 | import { v4 as uuidV4 } from 'uuid' 2 | import LogicFlow from '../LogicFlow' 3 | 4 | import GraphData = LogicFlow.GraphData 5 | 6 | export const createUuid = (): string => uuidV4() 7 | 8 | /** 9 | * 重新刷新流程图的所有id 10 | */ 11 | export const refreshGraphId = ( 12 | graphData: GraphData, 13 | prefix = '', 14 | ): GraphData => { 15 | const nodeIdMap = graphData.nodes.reduce((nMap, node) => { 16 | nMap[node.id] = prefix + uuidV4() 17 | node.id = nMap[node.id] 18 | return nMap 19 | }, {}) 20 | graphData.edges.forEach((edge) => { 21 | edge.id = prefix + uuidV4() 22 | edge.sourceNodeId = nodeIdMap[edge.sourceNodeId] 23 | edge.targetNodeId = nodeIdMap[edge.targetNodeId] 24 | }) 25 | return graphData 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/src/util/zIndex.ts: -------------------------------------------------------------------------------- 1 | let maxIndex = 1000 2 | let minIndex = 999 3 | 4 | export const getZIndex = () => ++maxIndex 5 | 6 | export const getMinIndex = () => --minIndex 7 | -------------------------------------------------------------------------------- /packages/core/src/view/behavior/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dnd' 2 | export * from './snapline' 3 | -------------------------------------------------------------------------------- /packages/core/src/view/behavior/snapline.ts: -------------------------------------------------------------------------------- 1 | import EventEmitter from '../../event/eventEmitter' 2 | import SnaplineModel from '../../model/SnaplineModel' 3 | 4 | export function snapline( 5 | eventCenter: EventEmitter, 6 | snaplineModel: SnaplineModel, 7 | ): void { 8 | // 节点拖动时启动对齐线计算 9 | eventCenter.on('node:mousemove', ({ data }) => { 10 | snaplineModel.setNodeSnapLine(data) 11 | }) 12 | // 节点拖动结束时,对齐线消失 13 | eventCenter.on('node:mouseup', () => { 14 | snaplineModel.clearSnapline() 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /packages/core/src/view/edge/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AdjustPoint' 2 | export * from './Arrow' 3 | export * from './BaseEdge' 4 | export * from './BezierEdge' 5 | export * from './LineEdge' 6 | export * from './PolylineEdge' 7 | -------------------------------------------------------------------------------- /packages/core/src/view/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Anchor' 2 | export * from './Rotate' 3 | export * from './Graph' 4 | 5 | export * from './shape' 6 | export * from './node' 7 | export * from './edge' 8 | export * from './text' 9 | -------------------------------------------------------------------------------- /packages/core/src/view/node/CircleNode.tsx: -------------------------------------------------------------------------------- 1 | import Circle from '../shape/Circle' 2 | import BaseNode from './BaseNode' 3 | import { GraphModel, CircleNodeModel } from '../../model' 4 | 5 | export type ICircleNodeProps = { 6 | model: CircleNodeModel 7 | graphModel: GraphModel 8 | } 9 | 10 | export class CircleNode< 11 | P extends ICircleNodeProps = ICircleNodeProps, 12 | > extends BaseNode

{ 13 | getShape() { 14 | const { model } = this.props 15 | const { x, y, r } = model 16 | const style = model.getNodeStyle() 17 | return 18 | } 19 | } 20 | 21 | export default CircleNode 22 | -------------------------------------------------------------------------------- /packages/core/src/view/node/DiamondNode.tsx: -------------------------------------------------------------------------------- 1 | import BaseNode from './BaseNode' 2 | import Polygon from '../shape/Polygon' 3 | import { GraphModel, DiamondNodeModel } from '../../model' 4 | 5 | export type IDiamondNodeProps = { 6 | model: DiamondNodeModel 7 | graphModel: GraphModel 8 | } 9 | 10 | export class DiamondNode< 11 | P extends IDiamondNodeProps = IDiamondNodeProps, 12 | > extends BaseNode

{ 13 | getShape() { 14 | const { model } = this.props 15 | const style = model.getNodeStyle() 16 | return ( 17 | 18 | 19 | 20 | ) 21 | } 22 | } 23 | 24 | export default DiamondNode 25 | -------------------------------------------------------------------------------- /packages/core/src/view/node/EllipseNode.tsx: -------------------------------------------------------------------------------- 1 | import BaseNode from './BaseNode' 2 | import Ellipse from '../shape/Ellipse' 3 | import { GraphModel, EllipseNodeModel } from '../../model' 4 | 5 | export type IEllipseNodeProps = { 6 | model: EllipseNodeModel 7 | graphModel: GraphModel 8 | } 9 | 10 | export class EllipseNode< 11 | P extends IEllipseNodeProps = IEllipseNodeProps, 12 | > extends BaseNode

{ 13 | getShape() { 14 | const { model } = this.props 15 | const style = model.getNodeStyle() 16 | return ( 17 | 18 | ) 19 | } 20 | } 21 | 22 | export default EllipseNode 23 | -------------------------------------------------------------------------------- /packages/core/src/view/node/PolygonNode.tsx: -------------------------------------------------------------------------------- 1 | import BaseNode from './BaseNode' 2 | import { Polygon } from '../shape' 3 | import { GraphModel, PolygonNodeModel } from '../../model' 4 | 5 | export type IPolygonNodeProps = { 6 | model: PolygonNodeModel 7 | graphModel: GraphModel 8 | } 9 | 10 | export class PolygonNode< 11 | P extends IPolygonNodeProps = IPolygonNodeProps, 12 | > extends BaseNode

{ 13 | getShape() { 14 | const { model } = this.props 15 | const { x, y, width, height, points } = model as PolygonNodeModel 16 | const style = model.getNodeStyle() 17 | const attr = { 18 | transform: `matrix(1 0 0 1 ${x - width / 2} ${y - height / 2})`, 19 | } 20 | return ( 21 | 22 | 23 | 24 | ) 25 | } 26 | } 27 | 28 | export default PolygonNode 29 | -------------------------------------------------------------------------------- /packages/core/src/view/node/RectNode.tsx: -------------------------------------------------------------------------------- 1 | import { createElement as h } from 'preact/compat' 2 | import BaseNode from './BaseNode' 3 | import { Rect } from '../shape' 4 | import { GraphModel, RectNodeModel } from '../../model' 5 | 6 | export type IRectNodeProps = { 7 | model: RectNodeModel 8 | graphModel: GraphModel 9 | } 10 | 11 | export class RectNode< 12 | P extends IRectNodeProps = IRectNodeProps, 13 | > extends BaseNode

{ 14 | getShape(): h.JSX.Element | null { 15 | const { model } = this.props 16 | const style = model.getNodeStyle() 17 | return ( 18 | 26 | ) 27 | } 28 | } 29 | 30 | export default RectNode 31 | -------------------------------------------------------------------------------- /packages/core/src/view/node/TextNode.tsx: -------------------------------------------------------------------------------- 1 | import Rect from '../shape/Rect' 2 | import BaseNode from './BaseNode' 3 | import { GraphModel, TextNodeModel } from '../../model' 4 | 5 | export type ITextNodeProps = { 6 | model: TextNodeModel 7 | graphModel: GraphModel 8 | } 9 | 10 | export class TextNode< 11 | P extends ITextNodeProps = ITextNodeProps, 12 | > extends BaseNode

{ 13 | getBackground() { 14 | const { model } = this.props 15 | const style = model.getTextStyle() 16 | // 背景框宽度,最长一行字节数/2 * fontsize + 2 17 | // 背景框宽度, 行数 * fontsize + 2 18 | // FIX: #1067 19 | const { width, height, x, y } = model 20 | const rectAttr = { 21 | ...style.background, 22 | x, 23 | y, 24 | width, 25 | height, 26 | } 27 | return 28 | } 29 | 30 | getResizeControl() { 31 | return null 32 | } 33 | 34 | getShape() { 35 | return {this.getBackground()} 36 | } 37 | } 38 | 39 | export default TextNode 40 | -------------------------------------------------------------------------------- /packages/core/src/view/node/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BaseNode' 2 | export * from './RectNode' 3 | export * from './CircleNode' 4 | export * from './PolygonNode' 5 | export * from './DiamondNode' 6 | export * from './EllipseNode' 7 | export * from './TextNode' 8 | export * from './HtmlNode' 9 | -------------------------------------------------------------------------------- /packages/core/src/view/overlay/BackgroundOverlay.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'preact/compat' 2 | import { isObject } from 'lodash-es' 3 | import { Options as LFOptions } from '../../options' 4 | import { observer } from '../..' 5 | 6 | /** 7 | * 背景配置, 支持css属性配置 8 | * https://developer.mozilla.org/zh-CN/docs/Web/CSS/background 9 | * @example 10 | * { 11 | * backgroundImage: "url('./img/grid.svg')", 12 | backgroundRepeat: 'repeat', 13 | * } 14 | */ 15 | type IProps = { 16 | background: boolean | LFOptions.BackgroundConfig 17 | } 18 | 19 | @observer 20 | export class BackgroundOverlay extends Component { 21 | render() { 22 | const { background } = this.props 23 | return ( 24 |

25 |
29 |
30 | ) 31 | } 32 | } 33 | 34 | export default BackgroundOverlay 35 | -------------------------------------------------------------------------------- /packages/core/src/view/overlay/ModificationOverlay.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'preact/compat' 2 | import { observer } from '../..' 3 | import GraphModel from '../../model/GraphModel' 4 | 5 | type IProps = { 6 | graphModel: GraphModel 7 | } 8 | 9 | @observer 10 | export class ModificationOverlay extends Component { 11 | render() { 12 | const { 13 | graphModel: { transformModel }, 14 | } = this.props 15 | const { transform } = transformModel.getTransformStyle() 16 | const { children } = this.props 17 | return ( 18 | 25 | {children} 26 | 27 | ) 28 | } 29 | } 30 | 31 | export default ModificationOverlay 32 | -------------------------------------------------------------------------------- /packages/core/src/view/overlay/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CanvasOverlay' 2 | export * from './BezierAdjustOverlay' 3 | export * from './BackgroundOverlay' 4 | export * from './Grid' 5 | export * from './ModificationOverlay' 6 | export * from './OutlineOverlay' 7 | export * from './SnaplineOverlay' 8 | export * from './ToolOverlay' 9 | -------------------------------------------------------------------------------- /packages/core/src/view/shape/Line.tsx: -------------------------------------------------------------------------------- 1 | import { createElement as h } from 'preact/compat' 2 | import { forEach, toPairs } from 'lodash-es' 3 | 4 | export type ILineProps = { 5 | id?: string 6 | tabindex?: number 7 | x1?: number 8 | y1?: number 9 | x2?: number 10 | y2?: number 11 | stroke?: string // Color 12 | className?: string 13 | style?: h.JSX.CSSProperties 14 | [key: string]: any 15 | } 16 | 17 | export function Line(props: ILineProps): h.JSX.Element { 18 | const attrs: ILineProps = { 19 | // default 20 | x1: 10, 21 | y1: 10, 22 | x2: 20, 23 | y2: 20, 24 | stroke: 'black', 25 | // ...props 26 | } 27 | 28 | forEach(toPairs(props), ([k, v]: [k: string, v: any]) => { 29 | if (k === 'style') { 30 | attrs[k] = v 31 | } else if (typeof v !== 'object') { 32 | attrs[k] = v 33 | } 34 | }) 35 | 36 | return 37 | } 38 | 39 | export default Line 40 | -------------------------------------------------------------------------------- /packages/core/src/view/shape/Path.tsx: -------------------------------------------------------------------------------- 1 | import { createElement as h } from 'preact/compat' 2 | import { forEach, toPairs } from 'lodash-es' 3 | 4 | export type IPathProps = { 5 | d: string 6 | [key: string]: any 7 | } 8 | 9 | export function Path(props: IPathProps): h.JSX.Element { 10 | const attrs: Record = { 11 | d: '', 12 | } 13 | forEach(toPairs(props), ([k, v]: [key: string, v: any]) => { 14 | if (k === 'style' || typeof v !== 'object') { 15 | attrs[k] = v 16 | } 17 | }) 18 | 19 | return 20 | } 21 | 22 | export default Path 23 | -------------------------------------------------------------------------------- /packages/core/src/view/shape/Polyline.tsx: -------------------------------------------------------------------------------- 1 | import { createElement as h } from 'preact/compat' 2 | import { forEach, toPairs } from 'lodash-es' 3 | 4 | export type IPolylineProps = { 5 | points: string 6 | pathLength?: number | 'none' 7 | className?: string 8 | } 9 | 10 | export function Polyline(props: IPolylineProps): h.JSX.Element { 11 | const { className } = props 12 | const attrs: Record = { 13 | points: '', 14 | fill: 'none', 15 | } 16 | 17 | forEach(toPairs(props), ([k, v]: [k: string, v: unknown]) => { 18 | if (k === 'style') { 19 | attrs[k] = v 20 | } else if (typeof v !== 'object') { 21 | attrs[k] = v 22 | } 23 | }) 24 | if (className) { 25 | attrs.className = `${className}` 26 | } 27 | 28 | return 29 | } 30 | 31 | export default Polyline 32 | -------------------------------------------------------------------------------- /packages/core/src/view/shape/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Text' 2 | export * from './Line' 3 | export * from './Rect' 4 | export * from './Path' 5 | export * from './Circle' 6 | export * from './Ellipse' 7 | export * from './Polygon' 8 | export * from './Polyline' 9 | -------------------------------------------------------------------------------- /packages/core/src/view/text/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BaseText' 2 | export * from './LineText' 3 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "allowImportingTsExtensions": false, 5 | "experimentalDecorators": true, 6 | "outDir": "es", 7 | "skipLibCheck": true, 8 | "downlevelIteration": true, 9 | "noImplicitAny": false, 10 | "baseUrl": "./", 11 | "paths": { 12 | "react": ["./node_modules/preact/compat/"], 13 | "react-dom": ["./node_modules/preact/compat/"] 14 | } 15 | }, 16 | "include": ["src/**/*", "**/*.d.ts"], 17 | "exclude": ["node_modules", "**/*.spec.ts", "es", "lib", "__tests__"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/engine/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../babel.config.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/engine/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @logicflow/engine 2 | 3 | ## 0.1.1 4 | 5 | ### Patch Changes 6 | 7 | - 更新依赖 8 | 9 | ## 0.1.0 10 | 11 | ### Minor Changes 12 | 13 | - Release 0.1.0 New Version 🎉🎉🎉🎉 14 | 15 | - refactor: 重构 engine 模块代码,使用 sandbox.js 解决 iframe 频繁 append 导致的性能问题 16 | - @logicflow/engine 默认使用 browser 执行代码,node 端也使用 @nyariv/sandboxjs 执行代码片段,保持两端一致 17 | -------------------------------------------------------------------------------- /packages/engine/README.md: -------------------------------------------------------------------------------- 1 | # @logicflow/engine 2 | 3 | 一个可以在JavaScript环境执行的流程引擎 4 | 5 | ## 使用方式 6 | 7 | ```shell 8 | pnpm run test 9 | ``` 10 | 11 | ## 参考资料 12 | ![package.json 中 browser. module, main 字段优先级](https://github.com/SunshowerC/blog/issues/8) 13 | ![编写兼容 nodejs/浏览器的库](https://blog.rxliuli.com/p/b8a95af9134a488e9d94463bd18768c9/) 14 | -------------------------------------------------------------------------------- /packages/engine/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { rollupConfig } from '../../rollup.config' 2 | 3 | export default rollupConfig() 4 | -------------------------------------------------------------------------------- /packages/engine/src/constant/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LogCode' 2 | 3 | // baseType 4 | export const BASE_START_NODE = 'start' 5 | 6 | // eventType 7 | export const EVENT_INSTANCE_COMPLETE = 'instance:complete' 8 | export const EVENT_INSTANCE_INTERRUPTED = 'instance:interrupted' 9 | export const EVENT_INSTANCE_ERROR = 'instance:error' 10 | 11 | // flowStatus 12 | export enum FlowStatus { 13 | COMPLETED = 'completed', 14 | INTERRUPTED = 'interrupted', 15 | RUNNING = 'running', 16 | PENDING = 'pending', 17 | ERROR = 'error', 18 | } 19 | 20 | // actionStatus 21 | export enum ActionStatus { 22 | SUCCESS = 'success', 23 | ERROR = 'error', 24 | INTERRUPTED = 'interrupted', 25 | } 26 | -------------------------------------------------------------------------------- /packages/engine/src/nodes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './base' 2 | export * from './start' 3 | export * from './task' 4 | -------------------------------------------------------------------------------- /packages/engine/src/nodes/start.ts: -------------------------------------------------------------------------------- 1 | import BaseNode from './base' 2 | 3 | export default class StartNode extends BaseNode { 4 | readonly baseType = 'start' 5 | static nodeTypeName = 'StartNode' 6 | } 7 | 8 | export { StartNode } 9 | -------------------------------------------------------------------------------- /packages/engine/src/nodes/task.ts: -------------------------------------------------------------------------------- 1 | import BaseNode from './base' 2 | 3 | export default class TaskNode extends BaseNode { 4 | readonly baseType = 'task' 5 | static nodeTypeName = 'TaskNode' 6 | } 7 | 8 | export { TaskNode } 9 | -------------------------------------------------------------------------------- /packages/engine/src/platform/browser/index.ts: -------------------------------------------------------------------------------- 1 | import { runInBrowserContext } from './browserVm' 2 | 3 | const isInBrowser = typeof window === 'object' && window.window === window 4 | 5 | const globalScope: any = (() => { 6 | if (isInBrowser) { 7 | return window 8 | } 9 | 10 | if (typeof self === 'object' && self.self === self) { 11 | return self 12 | } 13 | 14 | if (typeof globalThis === 'object') { 15 | return globalThis 16 | } 17 | 18 | return { 19 | eval: () => undefined, 20 | } as Record 21 | })() 22 | 23 | const getExpressionResult = async (code: string, context: any) => { 24 | const r = await runInBrowserContext(code, context) 25 | return r 26 | } 27 | 28 | export { isInBrowser, globalScope, getExpressionResult } 29 | -------------------------------------------------------------------------------- /packages/engine/src/platform/index.ts: -------------------------------------------------------------------------------- 1 | export * from './browser' 2 | -------------------------------------------------------------------------------- /packages/engine/src/platform/node/index.ts: -------------------------------------------------------------------------------- 1 | import { runInNodeContext } from './nodeVm' 2 | 3 | const isInNodeJS = typeof global === 'object' && global.global === global 4 | 5 | const globalScope: any = (() => { 6 | if (typeof self === 'object' && self.self === self) { 7 | return self 8 | } 9 | 10 | if (isInNodeJS) { 11 | return global 12 | } 13 | 14 | if (typeof globalThis === 'object') { 15 | return globalThis 16 | } 17 | 18 | return { 19 | eval: () => undefined, 20 | } as Record 21 | })() 22 | 23 | const getExpressionResult = async (code: string, context: any) => { 24 | const r = await runInNodeContext(code, context) 25 | return r 26 | } 27 | 28 | export { isInNodeJS, globalScope, getExpressionResult } 29 | -------------------------------------------------------------------------------- /packages/engine/src/platform/node/nodeVm.ts: -------------------------------------------------------------------------------- 1 | import vm from 'node:vm' 2 | // const vm = require('node:vm'); 3 | 4 | export const runInNodeContext = async ( 5 | code: string, 6 | globalData: Record = {}, 7 | ): Promise => { 8 | const context = vm.createContext(globalData) 9 | vm.runInContext(code, context) 10 | 11 | console.log('context ===>>>', context) 12 | 13 | return context 14 | } 15 | -------------------------------------------------------------------------------- /packages/engine/src/utils/global.ts: -------------------------------------------------------------------------------- 1 | // 判断当前环境是否为服务端 2 | // const isServer = typeof window === undefined; 3 | 4 | // const isServer = process.env.BROWSER === true; 5 | 6 | const isInBrowser = typeof window === 'object' && window.window === window 7 | 8 | const isInNodeJS = typeof global === 'object' && global.global === global 9 | 10 | const isInWebWorker = 11 | !isInBrowser && typeof self === 'object' && self.constructor 12 | 13 | const globalScope: any = (() => { 14 | if (isInBrowser) { 15 | return window 16 | } 17 | 18 | if (typeof self === 'object' && self.self === self) { 19 | return self 20 | } 21 | 22 | if (isInNodeJS) { 23 | return global 24 | } 25 | 26 | if (typeof globalThis === 'object') { 27 | return globalThis 28 | } 29 | 30 | return { 31 | eval: () => undefined, 32 | } as Record 33 | })() 34 | 35 | export { 36 | // 环境相关方法 37 | globalScope, 38 | isInWebWorker, 39 | isInBrowser, 40 | isInNodeJS, 41 | } 42 | -------------------------------------------------------------------------------- /packages/engine/src/utils/id.ts: -------------------------------------------------------------------------------- 1 | import { v4 as uuidV4 } from 'uuid' 2 | 3 | export const createExecId = (): string => { 4 | const uuid = uuidV4() 5 | return `exec-${uuid}` 6 | } 7 | 8 | export const createActionId = (): string => { 9 | const uuid = uuidV4() 10 | return `action-${uuid}` 11 | } 12 | 13 | export const createEngineId = (): string => { 14 | const uuid = uuidV4() 15 | return `engine-${uuid}` 16 | } 17 | -------------------------------------------------------------------------------- /packages/engine/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import storage from './storage' 2 | 3 | export * from './global' 4 | export * from './id' 5 | export { storage } 6 | -------------------------------------------------------------------------------- /packages/engine/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2016", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "declaration": true, 7 | "sourceMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "strict": true, 11 | "noImplicitAny": false, 12 | "skipLibCheck": true, 13 | "importHelpers": true 14 | }, 15 | "include": ["src/**/*"], 16 | "exclude": ["node_modules", "examples", "**/*.spec.ts", "**/*.d.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /packages/extension/README.md: -------------------------------------------------------------------------------- 1 | # extension 2 | 3 | LogicFlow 扩展包 4 | 5 | ## 使用方式 6 | 7 | ```js 8 | import LogicFlow from '@logicflow/core'; 9 | import { BpmnAdapter } from '@logicflow/extension'; 10 | 11 | LogicFlow.use(BpmnAdapter); 12 | ``` 13 | -------------------------------------------------------------------------------- /packages/extension/src/NodeResize/BasicShape/Ellipse.tsx: -------------------------------------------------------------------------------- 1 | import { h } from '@logicflow/core' 2 | 3 | function Ellipse(props: Record): h.JSX.Element { 4 | const { x = 0, y = 0, rx = 4, ry = 4 } = props 5 | 6 | const attrs = { 7 | cx: x, 8 | cy: y, 9 | rx, 10 | ry, 11 | fill: 'transparent', 12 | fillOpacity: 1, 13 | strokeWidth: 1, 14 | stroke: '#000', 15 | strokeOpacity: 1, 16 | ...props, 17 | } 18 | 19 | return 20 | } 21 | 22 | export default Ellipse 23 | -------------------------------------------------------------------------------- /packages/extension/src/NodeResize/BasicShape/Polygon.tsx: -------------------------------------------------------------------------------- 1 | import { h } from '@logicflow/core' 2 | 3 | export default function Polygon({ 4 | fillOpacity = 1, 5 | strokeWidth = 1, 6 | strokeOpacity = 1, 7 | fill = 'transparent', 8 | stroke = '#000', 9 | points, 10 | className = 'lf-basic-shape', 11 | }: any): h.JSX.Element { 12 | const attrs = { 13 | fill, 14 | fillOpacity, 15 | strokeWidth, 16 | stroke, 17 | strokeOpacity, 18 | points: '', 19 | className, 20 | } 21 | attrs.points = points.map((point: any) => point.join(',')).join(' ') 22 | 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /packages/extension/src/NodeResize/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @deprecated 3 | * 待废弃,2.0 版本将 NodeResize 能力内置,该插件设计和实现有比较多的问题,后续不再维护,请及时切换 4 | */ 5 | import LogicFlow from '@logicflow/core' 6 | 7 | import EllipseResize from './node/EllipseResize' 8 | import DiamondResize from './node/DiamondResize' 9 | import HtmlResize from './node/HtmlResize' 10 | import RectResize from './node/RectResize' 11 | 12 | export * from './node' 13 | export const NodeResize = { 14 | pluginName: 'nodeResize', 15 | // 拖动step 16 | step: 0, 17 | 18 | install(lf: LogicFlow) { 19 | lf.register(EllipseResize) 20 | lf.register(DiamondResize) 21 | lf.register(HtmlResize) 22 | lf.register(RectResize) 23 | }, 24 | } 25 | 26 | export default NodeResize 27 | -------------------------------------------------------------------------------- /packages/extension/src/NodeResize/node/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DiamondResize' 2 | export * from './EllipseResize' 3 | export * from './HtmlResize' 4 | export * from './RectResize' 5 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn-adapter/bpmnIds.ts: -------------------------------------------------------------------------------- 1 | export class IDs { 2 | private _ids: Set 3 | 4 | constructor() { 5 | globalThis._ids = this 6 | this._ids = new Set() 7 | } 8 | 9 | generateId() { 10 | return 'xxxxxxx'.replace(/[x]/g, (c) => { 11 | const r = (Math.random() * 16) | 0 12 | const v = c === 'x' ? r : (r & 0x3) | 0x8 13 | return v.toString(16) 14 | }) 15 | } 16 | 17 | next() { 18 | let id = this.generateId() 19 | while (this._ids.has(id)) { 20 | id = this.generateId() 21 | } 22 | this._ids.add(id) 23 | return id 24 | } 25 | } 26 | 27 | const ids = globalThis?._ids || new IDs() 28 | 29 | export function getBpmnId(): string { 30 | return ids.next() 31 | } 32 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn-elements/index.d.ts: -------------------------------------------------------------------------------- 1 | type DefinitionConfigType = { 2 | nodes: string[]; 3 | definition: EventDefinitionType[] | TaskDefinitionType[]; 4 | }; 5 | 6 | type DefinitionPropertiesType = { 7 | definitionType: string; 8 | timerType?: TimerType; 9 | timerValue?: string; 10 | [key: string]: any; 11 | }; 12 | 13 | type EventDefinitionType = { 14 | type: string; 15 | icon: string | Object; 16 | toJSON: Function; 17 | properties: DefinitionPropertiesType; 18 | [key: string]: any; 19 | }; 20 | 21 | type TaskDefinitionType = { 22 | type: string; 23 | [key: string]: any; 24 | }; 25 | 26 | type TimerType = 'timerCycle' | 'timerDate' | 'timerDuration'; 27 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn-elements/presets/Event/index.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow from '@logicflow/core' 2 | import { EndEventFactory } from './EndEventFactory' 3 | import { IntermediateCatchEventFactory } from './IntermediateCatchEvent' 4 | import { StartEventFactory } from './StartEventFactory' 5 | import { BoundaryEventFactory } from './boundaryEventFactory' 6 | import { IntermediateThrowEventFactory } from './IntermediateThrowEvent' 7 | 8 | export function registerEventNodes(lf: LogicFlow) { 9 | lf.register(StartEventFactory(lf)) 10 | lf.register(EndEventFactory(lf)) 11 | lf.register(IntermediateCatchEventFactory(lf)) 12 | lf.register(IntermediateThrowEventFactory(lf)) 13 | lf.register(BoundaryEventFactory(lf)) 14 | } 15 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn-elements/presets/Flow/flow.d.ts: -------------------------------------------------------------------------------- 1 | export type BBoxType = { 2 | minX: number; 3 | minY: number; 4 | maxX: number; 5 | maxY: number; 6 | } 7 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn-elements/presets/Flow/index.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow from '@logicflow/core' 2 | import { sequenceFlowFactory } from './sequenceFlow' 3 | 4 | export const SequenceFlow = sequenceFlowFactory() 5 | 6 | export function registerFlows(lf: LogicFlow) { 7 | lf.register(SequenceFlow) 8 | } 9 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn-elements/presets/Gateway/index.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow from '@logicflow/core' 2 | import { exclusiveIcon, parallelIcon, inclusiveIcon } from '../icons' 3 | import { GatewayNodeFactory } from './gateway' 4 | 5 | export function registerGatewayNodes(lf: LogicFlow) { 6 | const ExclusiveGateway = GatewayNodeFactory( 7 | 'bpmn:exclusiveGateway', 8 | exclusiveIcon, 9 | ) 10 | 11 | const ParallelGateway = GatewayNodeFactory( 12 | 'bpmn:parallelGateway', 13 | parallelIcon, 14 | ) 15 | 16 | const InclusiveGateway = GatewayNodeFactory( 17 | 'bpmn:inclusiveGateway', 18 | inclusiveIcon, 19 | ) 20 | lf.register(ExclusiveGateway) 21 | lf.register(InclusiveGateway) 22 | lf.register(ParallelGateway) 23 | } 24 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn/events/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StartEvent' 2 | export * from './EndEvent' 3 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn/flow/SequenceFlow.ts: -------------------------------------------------------------------------------- 1 | import { PolylineEdge, PolylineEdgeModel } from '@logicflow/core' 2 | import { getBpmnId } from '../getBpmnId' 3 | 4 | export class SequenceFlowModel extends PolylineEdgeModel { 5 | static extendKey = 'SequenceFlowModel' 6 | 7 | constructor(data, graphModel) { 8 | if (!data.id) { 9 | data.id = `Flow_${getBpmnId()}` 10 | } 11 | super(data, graphModel) 12 | } 13 | } 14 | 15 | export class SequenceFlowView extends PolylineEdge { 16 | static extendKey = 'SequenceFlowEdge' 17 | } 18 | 19 | export const SequenceFlow = { 20 | type: 'bpmn:sequenceFlow', 21 | view: SequenceFlowView, 22 | model: SequenceFlowModel, 23 | } 24 | 25 | export default SequenceFlow 26 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn/flow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SequenceFlow' 2 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn/gateways/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ExclusiveGateway' 2 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn/getBpmnId.ts: -------------------------------------------------------------------------------- 1 | class IDS { 2 | private _ids: Set 3 | 4 | constructor() { 5 | globalThis._ids = this 6 | this._ids = new Set() 7 | } 8 | 9 | generateId() { 10 | return 'xxxxxxx'.replace(/[x]/g, (c) => { 11 | const r = (Math.random() * 16) | 0 12 | const v = c === 'x' ? r : (r & 0x3) | 0x8 13 | return v.toString(16) 14 | }) 15 | } 16 | 17 | next() { 18 | let id = this.generateId() 19 | while (this._ids.has(id)) { 20 | id = this.generateId() 21 | } 22 | this._ids.add(id) 23 | return id 24 | } 25 | } 26 | 27 | const ids = globalThis?._ids || new IDS() 28 | 29 | export function getBpmnId(): string { 30 | return ids.next() 31 | } 32 | -------------------------------------------------------------------------------- /packages/extension/src/bpmn/tasks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ServiceTask' 2 | export * from './UserTask' 3 | -------------------------------------------------------------------------------- /packages/extension/src/index.less: -------------------------------------------------------------------------------- 1 | @import url('./style/index.less'); 2 | -------------------------------------------------------------------------------- /packages/extension/src/mindmap/fakerRoot.ts: -------------------------------------------------------------------------------- 1 | import { BaseNode, RectNodeModel } from '@logicflow/core' 2 | 3 | class MarkRootModel extends RectNodeModel { 4 | static extendKey = 'MarkRootModel' 5 | } 6 | 7 | class MarkRootView extends BaseNode { 8 | getShape() { 9 | return null 10 | } 11 | } 12 | 13 | const MarkRoot = { 14 | type: 'faker:root', 15 | view: MarkRootView, 16 | model: MarkRootModel, 17 | } 18 | 19 | export default MarkRoot 20 | -------------------------------------------------------------------------------- /packages/extension/src/mindmap/theme.ts: -------------------------------------------------------------------------------- 1 | export const theme = { 2 | rect: { 3 | // outlineColor: 'transparent' 4 | stroke: '#187DFF', 5 | }, 6 | bezier: { 7 | offset: 100, 8 | strokeWidth: 1, 9 | stroke: '#a4a5a6', 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /packages/extension/src/rect-label-node/RectLabelNodeView.ts: -------------------------------------------------------------------------------- 1 | import { RectNode, h } from '@logicflow/core' 2 | 3 | export class RectLabelNodeView extends RectNode { 4 | getLabelShape(): h.JSX.Element { 5 | const { x, y, width, height, properties } = this.props.model 6 | 7 | return h( 8 | 'text', 9 | { 10 | x: x - width / 2 + 5, 11 | y: y - height / 2 + 16, 12 | fontSize: 12, 13 | fill: 'blue', 14 | }, 15 | properties.moreText as string, 16 | ) 17 | } 18 | 19 | getShape(): h.JSX.Element { 20 | const { x, y, width, height } = this.props.model 21 | const style = this.props.model.getNodeStyle() 22 | // todo: 将basic-shape对外暴露,在这里可以直接用。现在纯手写有点麻烦。 23 | return h('g', {}, [ 24 | h('rect', { 25 | ...style, 26 | fill: '#FFFFFF', 27 | x: x - width / 2, 28 | y: y - height / 2, 29 | }), 30 | this.getLabelShape(), 31 | ]) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/extension/src/rect-label-node/index.ts: -------------------------------------------------------------------------------- 1 | import { RectNodeModel } from '@logicflow/core' 2 | import { RectLabelNodeView } from './RectLabelNodeView' 3 | 4 | export const RectLabelNode = { 5 | pluginName: 'rectLabelNode', 6 | install(lf) { 7 | lf.register({ 8 | type: 'rect-label', 9 | model: RectNodeModel, 10 | view: RectLabelNodeView, 11 | }) 12 | }, 13 | } 14 | 15 | export default RectLabelNode 16 | -------------------------------------------------------------------------------- /packages/extension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "allowImportingTsExtensions": false, 5 | "experimentalDecorators": true, 6 | "outDir": "es", 7 | "skipLibCheck": true, 8 | "downlevelIteration": true, 9 | "noImplicitAny": false, 10 | "baseUrl": "./", 11 | "paths": { 12 | "react": ["./node_modules/preact/compat/"], 13 | "react-dom": ["./node_modules/preact/compat/"] 14 | } 15 | }, 16 | "include": ["src/**/*", "**/*.d.ts"], 17 | "exclude": ["node_modules", "**/*.spec.ts", "es", "lib"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/react-node-registry/README.md: -------------------------------------------------------------------------------- 1 | # @logicflow/react-node-registry 2 | 3 | LogicFlow Shape for rendering React components. 4 | 5 | ## Installation 6 | ```shell 7 | npm install @logicflow/react-node-registry 8 | ``` 9 | or 10 | ```shell 11 | yarn add @logicflow/react-node-registry 12 | ``` 13 | or 14 | ```shell 15 | pnpm add @logicflow/react-node-registry 16 | ``` 17 | 18 | ## Usage 19 | 用户自定义 React 节点 CustomReactComp 20 | 21 | 我们需要将该内容注册到某个地方 22 | 23 | 1. 如果基于默认的 HTML 节点,只是调整节点里面的内容, 24 | 25 | ```typescript 26 | register({ 27 | type: 'custom-react-shape', 28 | view: ReactComponent, 29 | model: ReactNodeModel, 30 | }, lf) 31 | ``` 32 | 33 | 1. 注册节点 34 | 2. `view` 为 React 组件(基于 HTMLNode 自定义) 35 | 3. `model` 为节点数据模型 36 | -------------------------------------------------------------------------------- /packages/react-node-registry/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './view' 2 | export * from './model' 3 | export * from './registry' 4 | export * from './wrapper' 5 | export * from './portal' 6 | -------------------------------------------------------------------------------- /packages/react-node-registry/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "sourceMap": true, 6 | "declaration": true, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "noImplicitAny": true, 10 | "noEmitOnError": true, 11 | "noUnusedLocals": true, 12 | "strictNullChecks": true, 13 | "resolveJsonModule": true, 14 | "experimentalDecorators": true, 15 | "jsx": "react", 16 | "target": "es6", 17 | "lib": ["DOM", "ES2020"] 18 | }, 19 | "include": ["src/**/*", "**/*.d.ts"], 20 | "exclude": ["node_modules", "**/*.spec.ts", "es", "lib", "dist"] 21 | } 22 | -------------------------------------------------------------------------------- /packages/vue-node-registry/README.md: -------------------------------------------------------------------------------- 1 | # @logicflow/vue-node-registry 2 | 3 | LogicFlow Shape for rendering Vue components. 4 | 5 | ## Installation 6 | ```shell 7 | npm install @logicflow/vue-node-registry 8 | ``` 9 | or 10 | ```shell 11 | yarn add @logicflow/vue-node-registry 12 | ``` 13 | or 14 | ```shell 15 | pnpm add @logicflow/vue-node-registry 16 | ``` 17 | 18 | ## Usage 19 | 用户自定义 Vue 节点 CustomVueComponent 20 | 21 | 我们需要将该内容注册到某个地方 22 | 23 | 1. 如果基于默认的 HTML 节点,只是调整节点里面的内容, 24 | 25 | ```typescript 26 | register({ 27 | type: 'custom-vue-shape', 28 | view: VueComponent, 29 | model: VueNodeModel, 30 | }, lf) 31 | ``` 32 | 33 | 1. 注册节点 34 | 2. `view` 为 Vue 组件(基于 HTMLNode 自定义) 35 | 3. `model` 为节点数据模型 36 | -------------------------------------------------------------------------------- /packages/vue-node-registry/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './view' 2 | export * from './model' 3 | export * from './registry' 4 | export * from './teleport' 5 | -------------------------------------------------------------------------------- /packages/vue-node-registry/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["node_modules", "**/es", "**/lib"], 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "skipLibCheck": true, 9 | "esModuleInterop": true, 10 | "noImplicitAny": true, 11 | "noEmitOnError": true, 12 | "noUnusedLocals": true, 13 | "strictNullChecks": true, 14 | "resolveJsonModule": true, 15 | "experimentalDecorators": true, 16 | "jsx": "react", 17 | "target": "es6", 18 | "lib": ["DOM", "ES2020"] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/**' 3 | - 'examples/**' 4 | - 'sites/**' 5 | - 'scripts' 6 | -------------------------------------------------------------------------------- /scripts/build-docs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if ! [ -x "$(command -v pnpm)" ]; then 4 | echo 'Error: pnpm is not installed. install pnpm...' >&2 5 | npm install -g pnpm 6 | fi 7 | 8 | pnpm install 9 | pnpm build 10 | 11 | cd sites/docs 12 | rm -rf ./dist 13 | pnpm build 14 | -------------------------------------------------------------------------------- /scripts/sync-gitee: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | SOURCE_REPO=git@github.com:didi/LogicFlow.git 6 | DESTINATION_REPO=git@gitee.com:logic-flow/LogicFlow.git 7 | SOURCE_DIR=./tmp 8 | DRY_RUN=false 9 | 10 | GIT_SSH_COMMAND="ssh -v" 11 | 12 | echo "SOURCE=$SOURCE_REPO" 13 | echo "DESTINATION=$DESTINATION_REPO" 14 | echo "DRY RUN=$DRY_RUN" 15 | 16 | git clone --mirror "$SOURCE_REPO" "$SOURCE_DIR" && cd "$SOURCE_DIR" 17 | git remote set-url --push origin "$DESTINATION_REPO" 18 | git fetch -p origin 19 | # Exclude refs created by GitHub for pull request. 20 | git for-each-ref --format 'delete %(refname)' refs/pull | git update-ref --stdin 21 | 22 | if [ "$DRY_RUN" = "true" ] 23 | then 24 | echo "INFO: Dry Run, no data is pushed" 25 | git push --mirror --dry-run 26 | else 27 | git push --mirror 28 | fi -------------------------------------------------------------------------------- /sites/docs/.dumi/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/.dumi/favicon.png -------------------------------------------------------------------------------- /sites/docs/.dumi/global.less: -------------------------------------------------------------------------------- 1 | @import url('@logicflow/core/es/index.css'); 2 | @import url('@logicflow/extension/es/index.css'); 3 | -------------------------------------------------------------------------------- /sites/docs/.dumi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["**/*"] 4 | } 5 | -------------------------------------------------------------------------------- /sites/docs/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /sites/docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | .dumi/tmp 4 | .dumi/tmp-production 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /sites/docs/.prettierignore: -------------------------------------------------------------------------------- 1 | .dumi/tmp 2 | .dumi/tmp-production 3 | *.yaml 4 | -------------------------------------------------------------------------------- /sites/docs/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 80, 3 | proseWrap: 'never', 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | overrides: [ 7 | { 8 | files: '*', 9 | options: { 10 | proseWrap: 'preserve', 11 | }, 12 | }, 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /sites/docs/README.md: -------------------------------------------------------------------------------- 1 | # @logicflow-sites 2 | 3 | A static site base on [dumi](https://d.umijs.org). 4 | 5 | ## Development 6 | 7 | ```bash 8 | # install dependencies 9 | $ pnpm install 10 | 11 | # start dev server 12 | $ pnpm start 13 | 14 | # build docs 15 | $ pnpm run build 16 | ``` 17 | 18 | ## LICENSE 19 | 20 | MIT 21 | -------------------------------------------------------------------------------- /sites/docs/docs/tutorial/advanced/snapline.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | nav: 指南 3 | group: 4 | title: 进阶 5 | order: 2 6 | title: 对齐线 7 | order: 2 8 | toc: content 9 | --- 10 | 11 | 对齐线能够在节点移动过程中,将移动节点的位置与画布中其他节点位置进行对比,辅助位置调整。位置对比有如下两个方面。 12 | 13 | - 节点中心位置 14 | - 节点的边框 15 | 16 | ## 对齐线使用 17 | 18 | 普通编辑模式下,默认开启对齐线,也可通过配置进行关闭。 19 | 在[静默模式](silent-mode.zh.md#静默模式)下,无法移动节点,所以关闭了对齐线功能,无法通过配置开启。 20 | 21 | ```tsx | pure 22 | // 关闭对齐线功能 23 | const lf = new LogicFlow({ 24 | snapline: false, 25 | }) 26 | ``` 27 | 28 | ## 对齐线样式设置 29 | 30 | 对齐线的样式包括颜色和宽度,可以通过设置主题的方式进行修改。 31 | 32 | ```tsx | pure 33 | // 默认配置 34 | // { 35 | // stroke: '#1E90FF', 36 | // strokeWidth: 1, 37 | // } 38 | 39 | // 修改对齐线样式 40 | lf.setTheme({ 41 | snapline: { 42 | stroke: '#1E90FF', // 对齐线颜色 43 | strokeWidth: 1, // 对齐线宽度 44 | }, 45 | }) 46 | ``` 47 | 48 | 49 | 50 | 更多样式修改参见[主题](../basic/theme.zh.md) 51 | -------------------------------------------------------------------------------- /sites/docs/examples/edge/custom/demo/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "demos": [ 3 | { 4 | "filename": "polyline.tsx", 5 | "title": { 6 | "zh": "自定义折线", 7 | "en": "Custom Polyline" 8 | }, 9 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/edge/custom-polyline.png" 10 | }, 11 | { 12 | "filename": "curvedPolyline.tsx", 13 | "title": { 14 | "zh": "圆角折线", 15 | "en": "Curved Polyline" 16 | }, 17 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/edge/rounded-polyline.png" 18 | }, 19 | { 20 | "filename": "animatePolyline.tsx", 21 | "title": { 22 | "zh": "动画折线", 23 | "en": "Animate Polyline" 24 | }, 25 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/edge/animate-edge.png" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /sites/docs/examples/edge/custom/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Edges 3 | order: 2 4 | redirect_from: 5 | - /zh/examples/edge 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/edge/custom/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 自定义边 3 | order: 2 4 | redirect_from: 5 | - /zh/examples/edge 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/edge/native/demo/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "demos": [ 3 | { 4 | "filename": "basicEdge.tsx", 5 | "title": { 6 | "zh": "基础内置边", 7 | "en": "Basic Native Edges" 8 | }, 9 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/edge/basic-edge.png" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /sites/docs/examples/edge/native/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Native Edges 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/native 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/edge/native/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 内置边 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/native 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/extension/native/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Built-in plugins 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/extension 6 | --- -------------------------------------------------------------------------------- /sites/docs/examples/extension/native/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 内置插件 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/extension 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/graph/basic/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Basic Graph 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/basic 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/graph/basic/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 基础画布 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/basic 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/node/custom/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Nodes 3 | order: 2 4 | redirect_from: 5 | - /zh/examples/custom 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/node/custom/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 自定义节点 3 | order: 2 4 | redirect_from: 5 | - /zh/examples/custom 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/node/native/demo/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "demos": [ 3 | { 4 | "filename": "basicNode.tsx", 5 | "title": { 6 | "zh": "基础内置节点", 7 | "en": "Basic Native Nodes" 8 | }, 9 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/node/native-node.png" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /sites/docs/examples/node/native/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Native Nodes 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/native 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/node/native/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 内置节点 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/native 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/react/registry/demo/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "demos": [ 3 | { 4 | "filename": "customReact.tsx", 5 | "title": { 6 | "zh": "自定义 react 节点", 7 | "en": "Custom React Nodes" 8 | }, 9 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/react/react-portal.png" 10 | }, 11 | { 12 | "filename": "reactPortal.tsx", 13 | "title": { 14 | "zh": "React Portal 节点", 15 | "en": "React Portal Nodes" 16 | }, 17 | "screenshot": "https://cdn.jsdelivr.net/gh/Logic-Flow/static@latest/docs/examples/react/react-portal.png" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /sites/docs/examples/react/registry/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: React Node Registry 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/registry 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/react/registry/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: react 注册节点 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/registry 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/demo/draft.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/bussiness/demo/draft.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/demo/games.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/bussiness/demo/games.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/demo/mvp.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/bussiness/demo/mvp.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/demo/organizer.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/bussiness/demo/organizer.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/demo/pool.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/bussiness/demo/pool.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/demo/profileEditor.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/bussiness/demo/profileEditor.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bussiness Scene 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/bussiness 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/showcase/bussiness/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 业务场景 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/bussiness 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/angularDemo.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/angularDemo.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/beautification.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/beautification.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/bpmnEvent.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/bpmnEvent.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/bpmnVue.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/bpmnVue.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/engine.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/engine.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/nodeRedVue3.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/nodeRedVue3.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/treelikeDemoVue3.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/treelikeDemoVue3.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/demo/vueDemo.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/examples/showcase/example/demo/vueDemo.tsx -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/index.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Example 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/example 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/examples/showcase/example/index.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 示例 3 | order: 1 4 | redirect_from: 5 | - /zh/examples/example 6 | --- 7 | -------------------------------------------------------------------------------- /sites/docs/public/didi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/public/didi.png -------------------------------------------------------------------------------- /sites/docs/public/logicflow-8-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/public/logicflow-8-7.jpg -------------------------------------------------------------------------------- /sites/docs/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/public/logo.png -------------------------------------------------------------------------------- /sites/docs/public/overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/public/overlay.png -------------------------------------------------------------------------------- /sites/docs/public/test.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/public/test.jpeg -------------------------------------------------------------------------------- /sites/docs/public/vue3-app.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/public/vue3-app.gif -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/edge/reactEdge/index.less: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | 6 | .lf-custom-edge-wrapper { 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | } 11 | 12 | .custom-edge { 13 | flex: 1; 14 | text-align: center; 15 | background-color: white; 16 | border: 1px solid black; 17 | border-radius: 8px; 18 | } 19 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/connect/connectData.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | id: '1', 5 | type: 'rect', 6 | x: 300, 7 | y: 100, 8 | }, 9 | { 10 | id: '2', 11 | type: 'circle', 12 | x: 300, 13 | y: 250, 14 | }, 15 | { 16 | id: '3', 17 | type: 'hexagonNode', 18 | x: 100, 19 | y: 100, 20 | text: '只能连接到圆', 21 | }, 22 | ], 23 | edges: [], 24 | }; 25 | 26 | export default data; 27 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/connect/index.less: -------------------------------------------------------------------------------- 1 | .helloworld-app { 2 | width: 100%; 3 | 4 | .app-content { 5 | height: 380px; 6 | 7 | .lf-node-allow { 8 | .lf-basic-shape { 9 | fill: #67c23a; 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/htmlNode/htmlData.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | id: '1', 5 | type: 'button-node', 6 | x: 300, 7 | y: 100, 8 | properties: { 9 | name: 'hello', 10 | body: 'world', 11 | }, 12 | }, 13 | ], 14 | edges: [], 15 | }; 16 | 17 | export default data; 18 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/htmlNode/index.less: -------------------------------------------------------------------------------- 1 | .uml-wrapper { 2 | box-sizing: border-box; 3 | width: 100%; 4 | height: 100%; 5 | background: #efdbff; 6 | border: 2px solid #9254de; 7 | border-radius: 10px; 8 | } 9 | 10 | .uml-head { 11 | font-weight: bold; 12 | font-size: 16px; 13 | line-height: 30px; 14 | text-align: center; 15 | } 16 | 17 | .uml-body { 18 | padding: 5px 10px; 19 | font-size: 12px; 20 | border-top: 1px solid #838382; 21 | border-bottom: 1px solid #838382; 22 | } 23 | 24 | .uml-footer { 25 | padding: 5px 10px; 26 | font-size: 14px; 27 | } 28 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/movable/movableData.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | type: 'custom-node', 5 | x: 300, 6 | y: 250, 7 | text: '你好', 8 | children: ['circle-1'], 9 | }, 10 | { 11 | type: 'movable-node', 12 | x: 100, 13 | y: 70, 14 | text: '你好', 15 | }, 16 | { 17 | id: 'circle-1', 18 | type: 'circle', 19 | x: 300, 20 | y: 250, 21 | text: 'hello world', 22 | }, 23 | ], 24 | edges: [], 25 | }; 26 | 27 | export default data; 28 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/movable/movableNode.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow, { RectNode, RectNodeModel } from '@logicflow/core'; 2 | 3 | class MovableNode extends RectNode {} 4 | 5 | class MovableNodeModel extends RectNodeModel { 6 | initNodeData(data: LogicFlow.NodeConfig) { 7 | super.initNodeData(data); 8 | this.moveRules.push((model, deltaX, deltaY) => { 9 | // 不允许移动到坐标为负值的地方 10 | if ( 11 | model.x + deltaX - this.width / 2 < 0 || 12 | model.y + deltaY - this.height / 2 < 0 13 | ) { 14 | return false; 15 | } 16 | return true; 17 | }); 18 | } 19 | } 20 | 21 | export default { 22 | type: 'movable-node', 23 | view: MovableNode, 24 | model: MovableNodeModel, 25 | }; 26 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/node/reactNode/index.less: -------------------------------------------------------------------------------- 1 | .box-title { 2 | width: 82px; 3 | height: 62px; 4 | line-height: 62px; 5 | text-align: center; 6 | background: url('https://dpubstatic.udache.com/static/dpubimg/0oqFX1nvbD/cloud.png'); 7 | background-repeat: no-repeat; 8 | background-size: 80px; 9 | } 10 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/advanced/react/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 200px; 4 | overflow: hidden; 5 | } 6 | 7 | .antd-node-wrapper { 8 | display: flex; 9 | align-items: center; 10 | background-color: #cecece60; 11 | border-radius: 8px; 12 | } 13 | 14 | .react-algo-node { 15 | display: flex; 16 | align-items: center; 17 | width: 100%; 18 | height: 100%; 19 | border: 1px solid #e59b68; 20 | border-radius: 14px; 21 | 22 | img { 23 | width: 24px; 24 | height: 24px; 25 | } 26 | 27 | span { 28 | margin-left: 4px; 29 | color: #000000a6; 30 | font-size: 12px; 31 | } 32 | 33 | &.dark { 34 | background-color: #141414; 35 | 36 | span { 37 | color: #fff; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/edge/arrow/index.tsx: -------------------------------------------------------------------------------- 1 | import LogicFlow from '@logicflow/core'; 2 | import '@logicflow/core/dist/index.css'; 3 | import { useEffect, useRef } from 'react'; 4 | 5 | import CustomArrow from './customArrow'; 6 | import data from './data'; 7 | 8 | const SilentConfig = { 9 | isSilentMode: true, 10 | stopScrollGraph: true, 11 | stopMoveGraph: true, 12 | stopZoomGraph: true, 13 | adjustNodePosition: true, 14 | }; 15 | 16 | export default function App() { 17 | const refContainer = useRef(null); 18 | useEffect(() => { 19 | const lf = new LogicFlow({ 20 | container: refContainer.current!, 21 | grid: true, 22 | height: 400, 23 | ...SilentConfig, 24 | }); 25 | lf.register(CustomArrow); 26 | lf.render(data); 27 | lf.translateCenter(); 28 | }); 29 | return
; 30 | } 31 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/edge/shapes/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import LogicFlow from '@logicflow/core'; 3 | import '@logicflow/core/es/index.css'; 4 | 5 | import data from './data'; 6 | import '../../../index.less'; 7 | 8 | const SilentConfig = { 9 | stopScrollGraph: true, 10 | stopMoveGraph: true, 11 | stopZoomGraph: true, 12 | }; 13 | 14 | export default class Example extends React.Component { 15 | private container!: HTMLDivElement; 16 | 17 | componentDidMount() { 18 | const lf = new LogicFlow({ 19 | container: this.container, 20 | grid: true, 21 | ...SilentConfig, 22 | }); 23 | 24 | lf.render(data); 25 | lf.translateCenter(); 26 | } 27 | 28 | refContainer = (container: HTMLDivElement) => { 29 | this.container = container; 30 | }; 31 | 32 | render() { 33 | return ( 34 |
35 |
36 |
37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/edge/textPosition/data.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | id: 'rect_1', 5 | type: 'rect', 6 | x: 150, 7 | y: 100, 8 | text: 'rect', 9 | }, 10 | { 11 | id: 'circle_1', 12 | type: 'circle', 13 | x: 450, 14 | y: 300, 15 | text: 'circle', 16 | }, 17 | ], 18 | edges: [ 19 | { 20 | sourceNodeId: 'rect_1', 21 | targetNodeId: 'circle_1', 22 | type: 'custom-edge', 23 | text: '连线文本', 24 | }, 25 | ], 26 | }; 27 | 28 | export default data; 29 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/instance/graphData/index.less: -------------------------------------------------------------------------------- 1 | .container { 2 | height: 500px; 3 | } 4 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/custom/customCircle.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow, { 2 | CircleNode, 3 | CircleNodeModel, 4 | GraphModel, 5 | } from '@logicflow/core'; 6 | 7 | class CustomCircleModel extends CircleNodeModel { 8 | constructor(data: LogicFlow.NodeConfig, graphModel: GraphModel) { 9 | data.text = { 10 | // 自定义文本坐标:向下移动40px 11 | value: data.text as string, 12 | x: data.x, 13 | y: data.y + 40, 14 | }; 15 | super(data, graphModel); 16 | 17 | // 半径:控制圆形大小 18 | this.r = 20; 19 | } 20 | } 21 | 22 | export default { 23 | type: 'custom-circle', 24 | view: CircleNode, 25 | model: CustomCircleModel, 26 | }; 27 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/custom/customData.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | id: 'node_id_1', 5 | type: 'custom-circle', 6 | x: 100, 7 | y: 60, 8 | text: '自定义圆形', 9 | }, 10 | { 11 | id: 'node_id_2', 12 | type: 'custom-ellipse', 13 | x: 300, 14 | y: 60, 15 | text: '自定义椭圆', 16 | }, 17 | { 18 | id: 'node_id_4', 19 | type: 'custom-diamond', 20 | x: 500, 21 | y: 60, 22 | text: '自定义菱形', 23 | }, 24 | { 25 | id: 'node_id_3', 26 | type: 'custom-polygon', 27 | x: 110, 28 | y: 220, 29 | text: '自定义多边形', 30 | }, 31 | { 32 | id: 'node_id_5', 33 | type: 'custom-rect', 34 | x: 350, 35 | y: 220, 36 | text: '自定义矩形', 37 | }, 38 | ], 39 | edges: [], 40 | }; 41 | 42 | export default data; 43 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/custom/customDiamond.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow, { 2 | DiamondNode, 3 | DiamondNodeModel, 4 | GraphModel, 5 | } from '@logicflow/core'; 6 | 7 | class CustomDiamondModel extends DiamondNodeModel { 8 | constructor(data: LogicFlow.NodeConfig, graphModel: GraphModel) { 9 | data.text = { 10 | // 自定义文本坐标:向下移动40px 11 | value: data.text as string, 12 | x: data.x, 13 | y: data.y + 40, 14 | }; 15 | super(data, graphModel); 16 | 17 | this.rx = 50; 18 | this.ry = 20; 19 | } 20 | } 21 | 22 | export default { 23 | type: 'custom-diamond', 24 | view: DiamondNode, 25 | model: CustomDiamondModel, 26 | }; 27 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/custom/customEllipse.ts: -------------------------------------------------------------------------------- 1 | import LogicFlow, { 2 | EllipseNode, 3 | EllipseNodeModel, 4 | GraphModel, 5 | } from '@logicflow/core'; 6 | 7 | class CustomEllipseModel extends EllipseNodeModel { 8 | constructor(data: LogicFlow.NodeConfig, graphModel: GraphModel) { 9 | if (data.text && typeof data.text === 'string') { 10 | data.text = { 11 | // 自定义文本坐标:向下移动40px 12 | value: data.text, 13 | x: data.x, 14 | y: data.y + 40, 15 | }; 16 | } 17 | super(data, graphModel); 18 | 19 | // rx:x轴的半径 ry:y轴的半径,通过rx,ry控制椭圆大小 20 | this.rx = 50; 21 | this.ry = 20; 22 | } 23 | } 24 | 25 | export default { 26 | type: 'custom-ellipse', 27 | view: EllipseNode, 28 | model: CustomEllipseModel, 29 | }; 30 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/properties/customRect.ts: -------------------------------------------------------------------------------- 1 | import { RectNode, RectNodeModel } from '@logicflow/core'; 2 | 3 | class CustomRectModel extends RectNodeModel { 4 | getNodeStyle() { 5 | const style = super.getNodeStyle(); 6 | 7 | const properties = this.properties; 8 | if (properties.statu === 'pass') { 9 | // 业务属性statu为‘pass’时 展示边框颜色为green 10 | style.stroke = 'green'; 11 | } else if (properties.statu === 'reject') { 12 | // 业务属性statu为‘reject’时 展示边框颜色为red 13 | style.stroke = 'red'; 14 | } else { 15 | style.stroke = 'rgb(24, 125, 255)'; 16 | } 17 | return style; 18 | } 19 | } 20 | 21 | class CustomRectNode extends RectNode {} 22 | 23 | export default { 24 | type: 'custom-rect', 25 | view: CustomRectNode, 26 | model: CustomRectModel, 27 | }; 28 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/properties/data.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | nodes: [ 3 | { 4 | id: '1', 5 | type: 'custom-rect', 6 | x: 100, 7 | y: 100, 8 | text: 'default', 9 | properties: { 10 | width: 70, 11 | height: 70, 12 | }, 13 | }, 14 | { 15 | id: '2', 16 | type: 'custom-rect', 17 | x: 300, 18 | y: 100, 19 | text: 'pass', 20 | properties: { 21 | statu: 'pass', // 业务属性 22 | width: 100, // 形状属性 23 | height: 100, 24 | radius: 20, 25 | style: { 26 | // 样式属性 27 | strokeWidth: 3, 28 | }, 29 | }, 30 | }, 31 | { 32 | id: '3', 33 | type: 'custom-rect', 34 | x: 500, 35 | y: 100, 36 | text: 'reject', 37 | properties: { 38 | statu: 'reject', 39 | width: 130, 40 | height: 130, 41 | }, 42 | }, 43 | ], 44 | }; 45 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/basic/node/properties/index.tsx: -------------------------------------------------------------------------------- 1 | import LogicFlow from '@logicflow/core'; 2 | import '@logicflow/core/dist/index.css'; 3 | import { useEffect, useRef } from 'react'; 4 | 5 | import UserTask from './customRect'; 6 | import data from './data'; 7 | 8 | const SilentConfig = { 9 | isSilentMode: true, 10 | stopScrollGraph: true, 11 | stopMoveGraph: true, 12 | stopZoomGraph: true, 13 | adjustNodePosition: true, 14 | }; 15 | 16 | export default function App() { 17 | const refContainer = useRef(null); 18 | useEffect(() => { 19 | const lf = new LogicFlow({ 20 | container: refContainer.current!, 21 | grid: true, 22 | height: 200, 23 | ...SilentConfig, 24 | }); 25 | lf.register(UserTask); 26 | lf.render(data); 27 | lf.translateCenter(); 28 | }); 29 | return
; 30 | } 31 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/components/edges/custom-curved-polyline/index.tsx: -------------------------------------------------------------------------------- 1 | import { LogicFlow } from '@logicflow/core'; 2 | import { CurvedEdge, CurvedEdgeModel } from '@logicflow/extension'; 3 | 4 | class CustomCurvedEdge extends CurvedEdge {} 5 | 6 | class CustomCurvedEdgeModel extends CurvedEdgeModel { 7 | initEdgeData(data: LogicFlow.EdgeData) { 8 | super.initEdgeData(data); 9 | this.radius = 20; 10 | } 11 | getEdgeStyle() { 12 | const style = super.getEdgeStyle(); 13 | style.strokeWidth = 3; 14 | return style; 15 | } 16 | } 17 | 18 | export default { 19 | type: 'customCurvedEdge', 20 | model: CustomCurvedEdgeModel, 21 | view: CustomCurvedEdge, 22 | }; 23 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/components/nodes/custom-html/Text.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/LogicFlow/f614a29a5aa563e55224ea06d9af49cc1c9630a5/sites/docs/src/tutorial/components/nodes/custom-html/Text.tsx -------------------------------------------------------------------------------- /sites/docs/src/tutorial/components/nodes/custom-html/index.ts: -------------------------------------------------------------------------------- 1 | import CustomHtml from './Html'; 2 | import CustomIcon from './Icon'; 3 | import CustomImage from './Image'; 4 | // import CustomText from './Text'; 5 | 6 | export { CustomIcon, CustomImage, CustomHtml }; 7 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/dynamic-group/index.module.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 450px; 4 | overflow: hidden; 5 | 6 | :global { 7 | .lf-dnd-shape { 8 | background-size: contain; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/dynamic-group/nodes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './custom-group'; 2 | export * from './sub-process'; 3 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.less' { 2 | const content: Record; 3 | export default content; 4 | } 5 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/label/index.module.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 450px; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/mini-map/index.module.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 270px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/proximity-connect/index.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: 80vh; 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/selection-select/index.module.less: -------------------------------------------------------------------------------- 1 | .viewport { 2 | position: relative; 3 | height: calc(100vh - 250px); 4 | overflow: hidden; 5 | } 6 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/extension/snapshot/index.module.less: -------------------------------------------------------------------------------- 1 | .graph { 2 | width: 90%; 3 | height: 500px; 4 | 5 | :global { 6 | .lf-dndpanel .lf-dnd-shape { 7 | width: 20px !important; 8 | height: 20px !important; 9 | } 10 | 11 | .uml-wrapper { 12 | box-sizing: border-box; 13 | width: 100%; 14 | height: 100%; 15 | background: #efdbff; 16 | border: 2px solid #9254de; 17 | border-radius: 10px; 18 | } 19 | 20 | .uml-head { 21 | font-weight: bold; 22 | font-size: 16px; 23 | line-height: 30px; 24 | text-align: center; 25 | } 26 | 27 | .uml-body { 28 | padding: 5px 10px; 29 | font-size: 12px; 30 | border-top: 1px solid #9254de; 31 | border-bottom: 1px solid #9254de; 32 | } 33 | 34 | .uml-footer { 35 | padding: 5px 10px; 36 | font-size: 14px; 37 | } 38 | } 39 | } 40 | 41 | .input { 42 | width: 280px; 43 | } 44 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/get-started/helloworld/data.ts: -------------------------------------------------------------------------------- 1 | const data = { 2 | nodes: [ 3 | { 4 | id: '1', 5 | type: 'rect', 6 | x: 100, 7 | y: 100, 8 | text: '节点1', 9 | }, 10 | { 11 | id: '2', 12 | type: 'circle', 13 | x: 300, 14 | y: 100, 15 | text: '节点2', 16 | }, 17 | ], 18 | edges: [ 19 | { 20 | sourceNodeId: '1', 21 | targetNodeId: '2', 22 | type: 'polyline', 23 | text: '连线', 24 | startPoint: { 25 | x: 140, 26 | y: 100, 27 | }, 28 | endPoint: { 29 | x: 250, 30 | y: 100, 31 | }, 32 | }, 33 | ], 34 | }; 35 | 36 | export default data; 37 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/get-started/index.less: -------------------------------------------------------------------------------- 1 | .getting-started.helloworld-app { 2 | width: 100%; 3 | 4 | .app-content { 5 | height: 200px; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /sites/docs/src/tutorial/index.less: -------------------------------------------------------------------------------- 1 | .helloworld-app { 2 | width: 100%; 3 | 4 | .app-content { 5 | height: 380px; 6 | } 7 | } 8 | 9 | .viewport { 10 | position: relative; 11 | height: 80vh; 12 | overflow: hidden; 13 | } 14 | -------------------------------------------------------------------------------- /sites/docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-jsx", 4 | "jsxImportSource": "react", 5 | "strict": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "baseUrl": "./", 9 | "resolveJsonModule": true, 10 | "paths": { 11 | "@@/*": [".dumi/tmp/*"] 12 | } 13 | }, 14 | "exclude": ["examples/**/*.tsx"], 15 | "include": [".dumirc.ts", "src/**/*"] 16 | } 17 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "tasks": { 4 | "clean": { 5 | "outputs": [] 6 | }, 7 | "build:esm": { 8 | "dependsOn": ["^build:dev"], 9 | "outputs": ["es/**", "src/style/raw.ts"] 10 | }, 11 | "build:cjs": { 12 | "dependsOn": ["^build:dev"], 13 | "outputs": ["lib/**", "src/style/raw.ts"] 14 | }, 15 | "build:umd": { 16 | "dependsOn": ["^build:dev"], 17 | "outputs": ["dist/**", "src/style/raw.ts"] 18 | }, 19 | "build:dev": { 20 | "dependsOn": ["^build:dev"], 21 | "outputs": ["lib/**", "es/**", "src/style/raw.ts"] 22 | }, 23 | "build": { 24 | "dependsOn": ["^build:dev"], 25 | "outputs": ["lib/**", "es/**", "dist/**", "src/style/raw.ts"] 26 | } 27 | } 28 | } 29 | --------------------------------------------------------------------------------