@flowuent-org/diagramming-core 1.3.10 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +13 -13
- package/.eslintignore +1 -1
- package/.eslintrc.json +35 -35
- package/.prettierignore +3 -3
- package/.prettierrc +3 -3
- package/.vscode/settings.json +6 -6
- package/README.md +95 -95
- package/apps/authentication/tsconfig.app.json +23 -23
- package/apps/authentication/tsconfig.json +21 -21
- package/apps/authentication/tsconfig.spec.json +28 -28
- package/apps/diagramming/.eslintrc.json +18 -18
- package/apps/diagramming/index.html +16 -16
- package/apps/diagramming/project.json +53 -53
- package/apps/diagramming/public/aws-icons/compute/App Runner.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Application Auto Scaling.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Batch.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Bottlerocket.svg +19 -19
- package/apps/diagramming/public/aws-icons/compute/Compute Optimizer.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/EC2 Auto Scaling.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/EC2 Image Builder.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/EC2.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Elastic Beanstalk.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Elastic Fabric Adapter.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Fargate.svg +19 -19
- package/apps/diagramming/public/aws-icons/compute/Genomics CLI.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Lambda.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Local Zones.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/NICE DCV.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/NICE EnginFrame.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Nitro Enclaves.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Outposts family.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Outposts rack.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Outposts servers.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/ParallelCluster.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Serverless Application Repository.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/SimSpace Weaver.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Deadline.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Frost.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Sequoia.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox Stoke.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Thinkbox XMesh.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/VMware Cloud on AWS.svg +17 -17
- package/apps/diagramming/public/aws-icons/compute/Wavelength.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/ECS Anywhere.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/EKS Anywhere.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/EKS Cloud.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/EKS Distro.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Elastic Container Registry.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Elastic Container Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Elastic Kubernetes Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/container/Fargate.svg +19 -19
- package/apps/diagramming/public/aws-icons/container/Red Hat OpenShift Service on AWS.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Aurora.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Database Migration Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/DocumentDB.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/ElastiCache.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Keyspaces.svg +15 -15
- package/apps/diagramming/public/aws-icons/database/MemoryDB for Redis.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Neptune.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/RDS on VMware.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/RDS.svg +17 -17
- package/apps/diagramming/public/aws-icons/database/Timestream.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/App Mesh.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Client VPN.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Cloud Directory.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Cloud Map.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Cloud WAN.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/CloudFront.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Direct Connect.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Elastic Load Balancing.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Global Accelerator.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Private 5G.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/PrivateLink.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Route 53.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Site to Site VPN.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Transit Gateway.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/VPC Lattice.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Verified Access.svg +17 -17
- package/apps/diagramming/public/aws-icons/networking/Virtual Private Cloud.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Artifact.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Audit Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Certificate Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/CloudHSM.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Cognito.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Detective.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Directory Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Firewall Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/GuardDuty.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/IAM Identity Center.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Identity and Access Management.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Inspector.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Key Management Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Macie.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Network Firewall.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Resource Access Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Secrets Manager.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Security Hub.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Security Lake.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Shield.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Signer.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/Verified Permissions.svg +17 -17
- package/apps/diagramming/public/aws-icons/security/WAF.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Backup.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/EFS.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Elastic Block Store.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Elastic Disaster Recovery.svg +15 -15
- package/apps/diagramming/public/aws-icons/storage/FSx for Lustre.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx for NetApp ONTAP.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx for OpenZFS.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx for WFS.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/FSx.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/File Cache.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/S3 on Outposts.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Simple Storage Service Glacier.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Simple Storage Service.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowball Edge.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowball.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowcone.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Snowmobile.svg +17 -17
- package/apps/diagramming/public/aws-icons/storage/Storage Gateway.svg +17 -17
- package/apps/diagramming/public/azure-icons/compute/02112-icon-service-Automanaged-VM.svg +1 -1
- package/apps/diagramming/public/azure-icons/databases/02390-icon-service-Azure-SQL.svg +1 -1
- package/apps/diagramming/public/azure-icons/databases/02392-icon-service-SSIS-Lift-And-Shift-IR.svg +1 -1
- package/apps/diagramming/public/azure-icons/networking/02145-icon-service-Resource-Management-Private-Link.svg +1 -1
- package/apps/diagramming/public/azure-icons/security/02247-icon-service-Microsoft-Defender-for-IoT.svg +1 -1
- package/apps/diagramming/public/sample-node-complete.json +63 -63
- package/apps/diagramming/public/sample-node-data.json +63 -63
- package/apps/diagramming/src/AutomationDiagramData.ts +147 -480
- package/apps/diagramming/src/CollaborationDiagramData.ts +127 -127
- package/apps/diagramming/src/CustomIconExamples.ts +233 -233
- package/apps/diagramming/src/DiagramTabs.tsx +205 -205
- package/apps/diagramming/src/Pages/DevPlayground.tsx +3 -3
- package/apps/diagramming/src/Pages/Home.tsx +111 -111
- package/apps/diagramming/src/SequenceDiagramData.ts +215 -215
- package/apps/diagramming/src/StateMachineDiagramData.ts +64 -64
- package/apps/diagramming/src/UseCaseDiagramData.ts +52 -52
- package/apps/diagramming/src/cloud-data.ts +371 -371
- package/apps/diagramming/src/components/AddNodeView.tsx +252 -252
- package/apps/diagramming/src/createSelecors.tsx +17 -17
- package/apps/diagramming/src/index.scss +12 -12
- package/apps/diagramming/src/main.tsx +463 -463
- package/apps/diagramming/src/node-data.ts +664 -664
- package/apps/diagramming/src/sample-workflow-content.ts +55 -55
- package/apps/diagramming/src/stencil-items.ts +31 -31
- package/apps/diagramming/src/style.css +13 -13
- package/apps/diagramming/src/tabsStore.tsx +152 -152
- package/apps/diagramming/src/vite-env.d.ts +1 -1
- package/apps/diagramming/tsconfig.app.json +23 -23
- package/apps/diagramming/tsconfig.json +21 -21
- package/apps/diagramming/tsconfig.spec.json +28 -28
- package/apps/diagramming/vite.config.ts +34 -34
- package/apps/diagramming/webpack.config.js +13 -13
- package/apps/workflow/.eslintrc.json +18 -18
- package/apps/workflow/group/group-form-hooks/index.ts +3 -3
- package/apps/workflow/group/group-form-hooks/useFormValidation.ts +20 -20
- package/apps/workflow/group/group-form-schema/SettingsTabFormSchema.ts +7 -7
- package/apps/workflow/group/group-form-schema/index.ts +3 -3
- package/apps/workflow/i18n.ts +19 -19
- package/apps/workflow/index.html +16 -16
- package/apps/workflow/locales/en/translation.json +713 -713
- package/apps/workflow/project.json +8 -8
- package/apps/workflow/src/app/app.module.css +1 -1
- package/apps/workflow/src/app/app.spec.tsx +15 -15
- package/apps/workflow/src/app/app.tsx +370 -370
- package/apps/workflow/src/main.tsx +13 -13
- package/apps/workflow/src/styles.css +1 -1
- package/apps/workflow/src/theme/index.ts +546 -546
- package/apps/workflow/tsconfig.app.json +23 -23
- package/apps/workflow/tsconfig.json +21 -21
- package/apps/workflow/tsconfig.spec.json +28 -28
- package/apps/workflow/vite.config.ts +51 -51
- package/nx.json +58 -58
- package/package.json +1 -1
- package/packages/api/.babelrc +12 -12
- package/packages/api/.eslintrc.json +18 -18
- package/packages/api/README.md +7 -7
- package/packages/api/project.json +8 -8
- package/packages/api/src/index.ts +3 -3
- package/packages/api/src/lib/jsonPlaceholderService/endpoints.ts +3 -3
- package/packages/api/src/lib/jsonPlaceholderService/service.ts +13 -13
- package/packages/api/tsconfig.json +17 -17
- package/packages/api/tsconfig.lib.json +24 -24
- package/packages/atoms/.babelrc +12 -12
- package/packages/atoms/.eslintrc.json +18 -18
- package/packages/atoms/README.md +7 -7
- package/packages/atoms/forms/AuthenticationTabForm/authenticationTabForm.json +224 -224
- package/packages/atoms/forms/AuthenticationTabForm/index.tsx +255 -255
- package/packages/atoms/forms/SettingsTabForm/index.tsx +85 -85
- package/packages/atoms/forms/SettingsTabForm/settingTabForm.json +27 -27
- package/packages/atoms/forms/index.ts +4 -4
- package/packages/atoms/project.json +8 -8
- package/packages/atoms/src/index.ts +33 -33
- package/packages/atoms/src/lib/Accordion/Accordion.module.css +7 -7
- package/packages/atoms/src/lib/Accordion/Accordion.spec.tsx +13 -13
- package/packages/atoms/src/lib/Accordion/Accordion.tsx +29 -29
- package/packages/atoms/src/lib/Alert/Alert.module.css +7 -7
- package/packages/atoms/src/lib/Alert/Alert.spec.tsx +10 -10
- package/packages/atoms/src/lib/Alert/Alert.tsx +19 -19
- package/packages/atoms/src/lib/Avatar/Avatar.module.css +7 -7
- package/packages/atoms/src/lib/Avatar/Avatar.spec.tsx +10 -10
- package/packages/atoms/src/lib/Avatar/Avatar.tsx +22 -22
- package/packages/atoms/src/lib/Box/Box.module.css +7 -7
- package/packages/atoms/src/lib/Box/Box.spec.tsx +10 -10
- package/packages/atoms/src/lib/Box/Box.tsx +19 -19
- package/packages/atoms/src/lib/BulkEdit/BulkEdit.module.css +7 -7
- package/packages/atoms/src/lib/BulkEdit/BulkEdit.spec.tsx +10 -10
- package/packages/atoms/src/lib/BulkEdit/BulkEdit.tsx +15 -15
- package/packages/atoms/src/lib/Button/Button.module.css +7 -7
- package/packages/atoms/src/lib/Button/Button.spec.tsx +10 -10
- package/packages/atoms/src/lib/Button/Button.tsx +78 -78
- package/packages/atoms/src/lib/Card/Card.module.css +7 -7
- package/packages/atoms/src/lib/Card/Card.spec.tsx +10 -10
- package/packages/atoms/src/lib/Card/Card.tsx +19 -19
- package/packages/atoms/src/lib/CardContent/CardContent.module.css +7 -7
- package/packages/atoms/src/lib/CardContent/CardContent.spec.tsx +10 -10
- package/packages/atoms/src/lib/CardContent/CardContent.tsx +22 -22
- package/packages/atoms/src/lib/FormTextField/FormTextField.module.css +7 -7
- package/packages/atoms/src/lib/FormTextField/FormTextField.spec.tsx +10 -10
- package/packages/atoms/src/lib/FormTextField/FormTextField.tsx +35 -35
- package/packages/atoms/src/lib/Grid/Grid.module.css +7 -7
- package/packages/atoms/src/lib/Grid/Grid.spec.tsx +10 -10
- package/packages/atoms/src/lib/Grid/Grid.tsx +19 -19
- package/packages/atoms/src/lib/Stack/Stack.module.css +7 -7
- package/packages/atoms/src/lib/Stack/Stack.spec.tsx +10 -10
- package/packages/atoms/src/lib/Stack/Stack.tsx +19 -19
- package/packages/atoms/src/lib/Switch/Switch.module.css +7 -7
- package/packages/atoms/src/lib/Switch/Switch.spec.tsx +10 -10
- package/packages/atoms/src/lib/Switch/Switch.tsx +46 -46
- package/packages/atoms/src/lib/TableView/TableView.module.css +7 -7
- package/packages/atoms/src/lib/TableView/TableView.spec.tsx +10 -10
- package/packages/atoms/src/lib/TableView/TableView.tsx +88 -88
- package/packages/atoms/src/lib/TextField/TextField.module.css +7 -7
- package/packages/atoms/src/lib/TextField/TextField.spec.tsx +10 -10
- package/packages/atoms/src/lib/TextField/TextField.tsx +17 -17
- package/packages/atoms/src/lib/Typography/Typography.module.css +7 -7
- package/packages/atoms/src/lib/Typography/Typography.spec.tsx +10 -10
- package/packages/atoms/src/lib/Typography/Typography.tsx +22 -22
- package/packages/atoms/tsconfig.json +17 -17
- package/packages/atoms/tsconfig.lib.json +30 -30
- package/packages/common/.babelrc +12 -12
- package/packages/common/.eslintrc.json +18 -18
- package/packages/common/README.md +7 -7
- package/packages/common/project.json +8 -8
- package/packages/common/src/index.ts +4 -4
- package/packages/common/src/lib/generateRandomProfilePic.ts +3 -3
- package/packages/common/src/lib/generateValidationSchema.ts +46 -46
- package/packages/common/tsconfig.json +17 -17
- package/packages/common/tsconfig.lib.json +24 -24
- package/packages/contexts/.babelrc +12 -12
- package/packages/contexts/.eslintrc.json +18 -18
- package/packages/contexts/README.md +7 -7
- package/packages/contexts/project.json +8 -8
- package/packages/contexts/src/index.ts +2 -2
- package/packages/contexts/tsconfig.json +17 -17
- package/packages/contexts/tsconfig.lib.json +24 -24
- package/packages/diagrams/.babelrc +12 -12
- package/packages/diagrams/.ctirc +208 -208
- package/packages/diagrams/.eslintrc.json +17 -17
- package/packages/diagrams/CUSTOM_ICONS.md +232 -232
- package/packages/diagrams/GOOGLE_SHEETS_IMPLEMENTATION.md +233 -233
- package/packages/diagrams/NODE_DATA_UPDATE_API.md +430 -430
- package/packages/diagrams/README.md +7 -7
- package/packages/diagrams/UNDO_REDO_API.md +306 -306
- package/packages/diagrams/locales/en/translation.json +713 -713
- package/packages/diagrams/package.json +27 -27
- package/packages/diagrams/pnpm-lock.yaml +2606 -2606
- package/packages/diagrams/project.json +42 -42
- package/packages/diagrams/rollup.config.js +26 -26
- package/packages/diagrams/src/DiagramFlow.tsx +7 -7
- package/packages/diagrams/src/declarations.d.ts +7 -7
- package/packages/diagrams/src/index.ts +8 -1
- package/packages/diagrams/src/index.ts.bak +99 -99
- package/packages/diagrams/src/lib/assets/markers/markers.param.tsx +101 -101
- package/packages/diagrams/src/lib/assets/markers/markers.type.ts +10 -10
- package/packages/diagrams/src/lib/atoms/ActorNode.tsx +123 -123
- package/packages/diagrams/src/lib/atoms/AddParallelColButton.tsx +26 -26
- package/packages/diagrams/src/lib/atoms/BendpointNode.tsx +71 -71
- package/packages/diagrams/src/lib/atoms/CardBlockTypeSelector.tsx +35 -35
- package/packages/diagrams/src/lib/atoms/CardEditableTitle.tsx +76 -76
- package/packages/diagrams/src/lib/atoms/CardMainContent.tsx +19 -19
- package/packages/diagrams/src/lib/atoms/ConnectionPoints.tsx +149 -149
- package/packages/diagrams/src/lib/atoms/ContentAssist.tsx +341 -341
- package/packages/diagrams/src/lib/atoms/DiagramControls.tsx +56 -56
- package/packages/diagrams/src/lib/atoms/ExpressionInput.tsx +437 -437
- package/packages/diagrams/src/lib/atoms/FloatingConnectionLine.tsx +73 -73
- package/packages/diagrams/src/lib/atoms/LazyIcon.tsx +31 -31
- package/packages/diagrams/src/lib/atoms/MarkerSelector.tsx +106 -106
- package/packages/diagrams/src/lib/atoms/MultiSelectInput.tsx +87 -87
- package/packages/diagrams/src/lib/atoms/ParameterInput.tsx +199 -199
- package/packages/diagrams/src/lib/atoms/PropertyInput.tsx +114 -114
- package/packages/diagrams/src/lib/atoms/StyledBox.tsx +69 -69
- package/packages/diagrams/src/lib/atoms/ValidationError.tsx +37 -37
- package/packages/diagrams/src/lib/atoms/ValidationMessage.tsx +63 -63
- package/packages/diagrams/src/lib/components/AiButton.tsx +52 -52
- package/packages/diagrams/src/lib/components/ControlEdgeList.tsx +303 -303
- package/packages/diagrams/src/lib/components/CreateFunctionModal.tsx +264 -264
- package/packages/diagrams/src/lib/components/CustomCodeModal.tsx +287 -287
- package/packages/diagrams/src/lib/components/DiagramPanel.tsx +331 -331
- package/packages/diagrams/src/lib/components/FunctionModalTooltip.tsx +30 -30
- package/packages/diagrams/src/lib/components/GraphQLCustomCodeModal.tsx +210 -210
- package/packages/diagrams/src/lib/components/Header.tsx +143 -143
- package/packages/diagrams/src/lib/components/MiniMapCommon.tsx +24 -24
- package/packages/diagrams/src/lib/components/ResizeIcon.tsx +81 -81
- package/packages/diagrams/src/lib/components/SideBar.tsx +40 -40
- package/packages/diagrams/src/lib/components/automation/AISuggestionsModal.tsx +269 -269
- package/packages/diagrams/src/lib/components/automation/AISuggestionsPanel.tsx +28 -175
- package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationDecisionNode.tsx +94 -0
- package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationExecutionPanel.tsx +439 -439
- package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationInteractionNode.tsx +693 -693
- package/packages/diagrams/src/lib/components/automation/AutomationMonitoringNode.tsx +399 -399
- package/packages/diagrams/src/lib/components/automation/AutomationNavigationNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationNodeCard.tsx +414 -0
- package/packages/diagrams/src/lib/components/automation/AutomationSlackNode.tsx +694 -694
- package/packages/diagrams/src/lib/components/automation/AutomationSmsNode.tsx +62 -0
- package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationTelegramNode.tsx +664 -664
- package/packages/diagrams/src/lib/components/automation/AutomationVoiceCallNode.tsx +65 -0
- package/packages/diagrams/src/lib/components/automation/AutomationWorkflowNode.tsx +85 -0
- package/packages/diagrams/src/lib/components/automation/NodeAIAssistantPopup.tsx +504 -504
- package/packages/diagrams/src/lib/components/automation/index.ts +29 -19
- package/packages/diagrams/src/lib/components/automation/statusColors.ts +124 -124
- package/packages/diagrams/src/lib/contexts/CardDataProvider.tsx +111 -111
- package/packages/diagrams/src/lib/contexts/DiagramProvider.tsx +392 -391
- package/packages/diagrams/src/lib/contexts/diagramStoreTypes.tsx +134 -134
- package/packages/diagrams/src/lib/contexts/onConnect.ts +39 -39
- package/packages/diagrams/src/lib/contexts/onDragStart.ts +45 -45
- package/packages/diagrams/src/lib/contexts/onNodeDragEnd.ts +179 -179
- package/packages/diagrams/src/lib/contexts/onNodesChange.ts +406 -406
- package/packages/diagrams/src/lib/contexts/onReconnect.ts +59 -59
- package/packages/diagrams/src/lib/contexts/onWorkflowNodeDelete.ts +65 -65
- package/packages/diagrams/src/lib/contexts/setContentHeight.ts +14 -14
- package/packages/diagrams/src/lib/contexts/setDiagramType.ts +10 -10
- package/packages/diagrams/src/lib/contexts/setEdgeShapeType.ts +7 -7
- package/packages/diagrams/src/lib/contexts/setEdges.ts +9 -9
- package/packages/diagrams/src/lib/contexts/setLayoutDirection.ts +9 -9
- package/packages/diagrams/src/lib/contexts/setNodeSetting.ts +17 -17
- package/packages/diagrams/src/lib/contexts/setNodes.ts +10 -10
- package/packages/diagrams/src/lib/contexts/setPannable.ts +7 -7
- package/packages/diagrams/src/lib/contexts/setSelectedEdge.ts +7 -7
- package/packages/diagrams/src/lib/contexts/setSelectedNode.ts +7 -7
- package/packages/diagrams/src/lib/contexts/undo.ts +163 -163
- package/packages/diagrams/src/lib/contexts/updateNodeSetting.ts +17 -17
- package/packages/diagrams/src/lib/examples/TwilioWhatsAppConfigExample.ts +128 -128
- package/packages/diagrams/src/lib/externals.ts +4 -4
- package/packages/diagrams/src/lib/hooks/customUseReactFlow.tsx +90 -90
- package/packages/diagrams/src/lib/hooks/updateNodes.ts +45 -45
- package/packages/diagrams/src/lib/hooks/useAddChildButton.tsx +61 -61
- package/packages/diagrams/src/lib/hooks/useAddSwitchCase.ts +75 -75
- package/packages/diagrams/src/lib/hooks/useAutoRegisterFunctions.ts +135 -135
- package/packages/diagrams/src/lib/hooks/useAutoRegisterVariables.ts +286 -286
- package/packages/diagrams/src/lib/hooks/useDeleteNodeByEvent.ts +64 -64
- package/packages/diagrams/src/lib/hooks/useDragCallbacks.tsx +122 -122
- package/packages/diagrams/src/lib/hooks/useFormValidation.ts +349 -349
- package/packages/diagrams/src/lib/hooks/useFunctionFormCallbacks.ts +136 -136
- package/packages/diagrams/src/lib/hooks/useIsSelectedNode.ts +11 -11
- package/packages/diagrams/src/lib/hooks/useModalControls.ts +13 -13
- package/packages/diagrams/src/lib/hooks/useNodeDragHandlers.ts +43 -43
- package/packages/diagrams/src/lib/hooks/useNodeSelection.ts +55 -55
- package/packages/diagrams/src/lib/hooks/useRenderDividers.tsx +19 -19
- package/packages/diagrams/src/lib/hooks/useRenderPins.tsx +74 -74
- package/packages/diagrams/src/lib/hooks/useResizeObserver.ts +21 -21
- package/packages/diagrams/src/lib/hooks/useTreeChildNode.ts +536 -536
- package/packages/diagrams/src/lib/i18n.ts +42 -42
- package/packages/diagrams/src/lib/icons/icons.tsx +324 -0
- package/packages/diagrams/src/lib/icons/index.ts +29 -0
- package/packages/diagrams/src/lib/icons/types.ts +7 -0
- package/packages/diagrams/src/lib/molecules/AddingBlock.tsx +147 -147
- package/packages/diagrams/src/lib/molecules/AvailableVariablesDisplay.tsx +57 -57
- package/packages/diagrams/src/lib/molecules/Block.tsx +143 -143
- package/packages/diagrams/src/lib/molecules/BlockProvider.tsx +28 -28
- package/packages/diagrams/src/lib/molecules/BlockWrapper.tsx +14 -14
- package/packages/diagrams/src/lib/molecules/ConditionRule.tsx +131 -131
- package/packages/diagrams/src/lib/molecules/DraggablePane.tsx +198 -198
- package/packages/diagrams/src/lib/molecules/EntityNodeBlocks.tsx +66 -66
- package/packages/diagrams/src/lib/molecules/SideHandles.tsx +215 -215
- package/packages/diagrams/src/lib/molecules/StencilItem.tsx +85 -85
- package/packages/diagrams/src/lib/molecules/WorkflowNodeActionButtons.tsx +62 -62
- package/packages/diagrams/src/lib/molecules/animated-add-button.tsx +83 -83
- package/packages/diagrams/src/lib/molecules/json-viewer.tsx +107 -107
- package/packages/diagrams/src/lib/organisms/AddNodeView.tsx +102 -102
- package/packages/diagrams/src/lib/organisms/Card/EntityNode.tsx +259 -259
- package/packages/diagrams/src/lib/organisms/Card/card.params.ts +29 -29
- package/packages/diagrams/src/lib/organisms/Card/card.types.ts +5 -5
- package/packages/diagrams/src/lib/organisms/CodeModal.tsx +105 -105
- package/packages/diagrams/src/lib/organisms/ConditionRuleGroup.tsx +138 -138
- package/packages/diagrams/src/lib/organisms/CustomEdge/EdgeMarkers.tsx +51 -51
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge-generator.tsx +135 -135
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge.params.ts +6 -6
- package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge.type.ts +15 -15
- package/packages/diagrams/src/lib/organisms/CustomEdge/useCreateBendPoint.tsx +121 -121
- package/packages/diagrams/src/lib/organisms/CustomEdge/useEdgeModal.ts +37 -37
- package/packages/diagrams/src/lib/organisms/CustomEdge/useEdgePath.tsx +99 -99
- package/packages/diagrams/src/lib/organisms/DownloadPanel.tsx +345 -345
- package/packages/diagrams/src/lib/organisms/EdgeModal.tsx +243 -243
- package/packages/diagrams/src/lib/organisms/HistoryPane.tsx +118 -118
- package/packages/diagrams/src/lib/organisms/NodeContextMenu.tsx +259 -259
- package/packages/diagrams/src/lib/organisms/PropertiesPane.tsx +276 -276
- package/packages/diagrams/src/lib/organisms/SmartDynamicForm.tsx +226 -226
- package/packages/diagrams/src/lib/organisms/Stencil.tsx +60 -60
- package/packages/diagrams/src/lib/organisms/UseDiagramStore.tsx +4 -4
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeActionButtons.tsx +45 -45
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeTypeDisplay.tsx +114 -114
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/WorkflowNodeIcons.tsx +21 -23
- package/packages/diagrams/src/lib/organisms/WorkflowNode.tsx +484 -484
- package/packages/diagrams/src/lib/services/GoogleSheetsService.ts +961 -961
- package/packages/diagrams/src/lib/services/SlackService.ts +134 -134
- package/packages/diagrams/src/lib/services/TwilioWhatsAppService.ts +273 -273
- package/packages/diagrams/src/lib/styles.css +55 -55
- package/packages/diagrams/src/lib/templates/PageLinks.tsx +13 -13
- package/packages/diagrams/src/lib/templates/arch/ArchDiagram.tsx +793 -793
- package/packages/diagrams/src/lib/templates/arch/components/EdgeDialog.tsx +82 -82
- package/packages/diagrams/src/lib/templates/arch/components/EdgeSettings.tsx +81 -81
- package/packages/diagrams/src/lib/templates/arch/components/GroupControls.tsx +59 -59
- package/packages/diagrams/src/lib/templates/arch/components/GroupSizeDialog.tsx +81 -81
- package/packages/diagrams/src/lib/templates/arch/components/NodeDialog.tsx +214 -214
- package/packages/diagrams/src/lib/templates/arch/components/nodeTypes.ts +91 -91
- package/packages/diagrams/src/lib/templates/arch/controls/ArchDiagramControls.tsx +349 -349
- package/packages/diagrams/src/lib/templates/arch/data/templatee-data.ts +212 -212
- package/packages/diagrams/src/lib/templates/cloud-arch/components/CloudArchitectureDiagram.tsx +3912 -3912
- package/packages/diagrams/src/lib/templates/cloud-arch/components/FormatConverter.tsx +809 -809
- package/packages/diagrams/src/lib/templates/cloud-arch/components/FragmentImporter.tsx +276 -276
- package/packages/diagrams/src/lib/templates/cloud-arch/components/PropertiesPanel.tsx +1063 -1063
- package/packages/diagrams/src/lib/templates/cloud-arch/components/ServiceIconPicker.tsx +138 -138
- package/packages/diagrams/src/lib/templates/cloud-arch/components/SettingsSidebar.tsx +656 -656
- package/packages/diagrams/src/lib/templates/cloud-arch/components/SubnetSelector.tsx +468 -468
- package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/ServiceNode.tsx +310 -310
- package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/SubnetNode.tsx +475 -475
- package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/UsersNode.tsx +277 -277
- package/packages/diagrams/src/lib/templates/cloud-arch/data/diagramManager.ts +364 -364
- package/packages/diagrams/src/lib/templates/cloud-arch/data/types.ts +183 -183
- package/packages/diagrams/src/lib/templates/cloud-arch/integration/diagramValidator.ts +379 -379
- package/packages/diagrams/src/lib/templates/cloud-arch/messages/errorMessages.json +95 -95
- package/packages/diagrams/src/lib/templates/cloud-arch/types/localization.ts +368 -368
- package/packages/diagrams/src/lib/templates/cloud-arch/types/validation.ts +72 -72
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/aws-icons.ts +557 -557
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/awsValidation.ts +446 -446
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/azure-icons.ts +802 -802
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/azureValidation.ts +495 -495
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/cloudValidation.ts +929 -929
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/errorMessages.ts +283 -283
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/gcp-icons.ts +186 -186
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/gcpValidation.ts +312 -312
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/genericValidation.ts +689 -689
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/iconMapping.ts +383 -383
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/idGenerator.ts +220 -220
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/localizationManager.ts +300 -300
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/restrictionEngine.ts +550 -550
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/restrictionValidator.ts +400 -400
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/serviceIcons.tsx +129 -129
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/serviceMapping.ts +330 -330
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/translations.ts +54 -54
- package/packages/diagrams/src/lib/templates/cloud-arch/utils/validationExtractor.ts +342 -342
- package/packages/diagrams/src/lib/templates/collaborationDiagram/CollaborationDiagram.tsx +15 -15
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/AddCollabEdgeDialog.tsx +181 -181
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollabLayout.ts +182 -182
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollabObjectNodeSettings.tsx +86 -86
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollaborationDiagramFlow.tsx +731 -731
- package/packages/diagrams/src/lib/templates/collaborationDiagram/components/DraggableEdgeLabel.tsx +123 -123
- package/packages/diagrams/src/lib/templates/collaborationDiagram/controls/CollaborationControls.tsx +131 -131
- package/packages/diagrams/src/lib/templates/collaborationDiagram/nodes/CollabEdge.tsx +170 -170
- package/packages/diagrams/src/lib/templates/collaborationDiagram/nodes/CollabObjectNode.tsx +178 -178
- package/packages/diagrams/src/lib/templates/home.style.css +16 -16
- package/packages/diagrams/src/lib/templates/node-forms/ApiForm.tsx +416 -416
- package/packages/diagrams/src/lib/templates/node-forms/CallForm.tsx +370 -370
- package/packages/diagrams/src/lib/templates/node-forms/ForLoopNode.tsx +313 -313
- package/packages/diagrams/src/lib/templates/node-forms/FunctionForm.tsx +211 -211
- package/packages/diagrams/src/lib/templates/node-forms/GraphQLForm.tsx +679 -679
- package/packages/diagrams/src/lib/templates/node-forms/IfNodeForm.tsx +97 -97
- package/packages/diagrams/src/lib/templates/node-forms/LetNodeForm.tsx +533 -533
- package/packages/diagrams/src/lib/templates/node-forms/LoopNode.tsx +149 -149
- package/packages/diagrams/src/lib/templates/node-forms/NodeForm.tsx +383 -383
- package/packages/diagrams/src/lib/templates/node-forms/ReturnNodeForm.tsx +96 -96
- package/packages/diagrams/src/lib/templates/node-forms/SetNodeForm.tsx +141 -141
- package/packages/diagrams/src/lib/templates/node-forms/SwitchNodeForm.tsx +249 -249
- package/packages/diagrams/src/lib/templates/node-forms/TryCatchForm.tsx +167 -167
- package/packages/diagrams/src/lib/templates/nodeFormSchema.json +84 -84
- package/packages/diagrams/src/lib/templates/sequence/SequenceDiagram.tsx +22 -22
- package/packages/diagrams/src/lib/templates/sequence/components/ActivationBarNode.tsx +33 -33
- package/packages/diagrams/src/lib/templates/sequence/components/AddMessageDialog.tsx +302 -302
- package/packages/diagrams/src/lib/templates/sequence/components/CombinedFragmentNode.tsx +65 -65
- package/packages/diagrams/src/lib/templates/sequence/components/EntitySettings.tsx +559 -559
- package/packages/diagrams/src/lib/templates/sequence/components/FragmentSettings.tsx +116 -116
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceComponents.tsx +14 -14
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceDiagramFlow.tsx +1361 -1361
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceEntityNode.tsx +394 -394
- package/packages/diagrams/src/lib/templates/sequence/components/SequenceMessageEdge.tsx +272 -272
- package/packages/diagrams/src/lib/templates/sequence/components/SimpleEntitySettings.tsx +89 -89
- package/packages/diagrams/src/lib/templates/sequence/controls/DiagramControls.tsx +707 -707
- package/packages/diagrams/src/lib/templates/sequence/data/template-data.ts +635 -635
- package/packages/diagrams/src/lib/templates/stateMachine/StateMachineDiagram.tsx +66 -66
- package/packages/diagrams/src/lib/templates/stateMachine/components/CompositeStateNodeSettings.tsx +638 -638
- package/packages/diagrams/src/lib/templates/stateMachine/components/CustomEdge.tsx +220 -220
- package/packages/diagrams/src/lib/templates/stateMachine/components/EdgeSettings.tsx +193 -193
- package/packages/diagrams/src/lib/templates/stateMachine/components/SelfConnectingEdge.tsx +41 -41
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineComponents.tsx +49 -49
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineDiagramFlow.tsx +1238 -1238
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineLayout.ts +350 -350
- package/packages/diagrams/src/lib/templates/stateMachine/components/StateNodeSettings.tsx +188 -188
- package/packages/diagrams/src/lib/templates/stateMachine/components/useSelfTransition.ts +114 -114
- package/packages/diagrams/src/lib/templates/stateMachine/controls/StateDiagramControls.tsx +488 -488
- package/packages/diagrams/src/lib/templates/stateMachine/data/template-data.ts +4 -4
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/ChoicePointNode.tsx +54 -54
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/CompositeStateNode.tsx +225 -225
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/EntryPointNode.tsx +31 -31
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/ExitPointNode.tsx +44 -44
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/FinalStateNode.tsx +41 -41
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/ForkJoinNode.tsx +53 -53
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/HistoryStateNode.tsx +36 -36
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/InitialStateNode.tsx +29 -29
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/JunctionPointNode.tsx +33 -33
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/PinPointNode.tsx +111 -111
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/StateNode.tsx +124 -124
- package/packages/diagrams/src/lib/templates/stateMachine/nodes/bendPoint.tsx +71 -71
- package/packages/diagrams/src/lib/templates/systemFlow/SystemFlowDiagram.tsx +67 -67
- package/packages/diagrams/src/lib/templates/systemFlow/components/EdgeSettings.tsx +330 -330
- package/packages/diagrams/src/lib/templates/systemFlow/components/FloatingEdge.tsx +219 -219
- package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowComponents.tsx +28 -28
- package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowDiagramFlow.tsx +1179 -1179
- package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowNodeSettings.tsx +151 -151
- package/packages/diagrams/src/lib/templates/systemFlow/controls/SystemFlowControls.tsx +435 -435
- package/packages/diagrams/src/lib/templates/systemFlow/data/template-data.ts +308 -308
- package/packages/diagrams/src/lib/templates/systemFlow/demo.tsx +91 -91
- package/packages/diagrams/src/lib/templates/systemFlow/index.ts +5 -5
- package/packages/diagrams/src/lib/templates/systemFlow/nodes/BendpointNode.tsx +80 -80
- package/packages/diagrams/src/lib/templates/systemFlow/nodes/SystemNode.tsx +92 -92
- package/packages/diagrams/src/lib/templates/systemFlow/nodes/TreeSystemNode.tsx +755 -755
- package/packages/diagrams/src/lib/templates/useCaseDiagram/UseCaseDiagram.tsx +16 -16
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/ActorNodeSettings.tsx +103 -103
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/AddRelationshipDialog.tsx +186 -186
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/PackageNodeSettings.tsx +205 -205
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/UseCaseDiagramFlow.tsx +637 -637
- package/packages/diagrams/src/lib/templates/useCaseDiagram/components/UseCaseNodeSettings.tsx +120 -120
- package/packages/diagrams/src/lib/templates/useCaseDiagram/controls/UseCaseControls.tsx +289 -289
- package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/PackageNode.tsx +83 -83
- package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/UseCaseEdge.tsx +115 -115
- package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/UseCaseNode.tsx +230 -230
- package/packages/diagrams/src/lib/templates/validationSchema.json +277 -277
- package/packages/diagrams/src/lib/theme.ts +439 -439
- package/packages/diagrams/src/lib/types/FunctionSignature.ts +11 -11
- package/packages/diagrams/src/lib/types/SmartDynamicFormField.ts +37 -37
- package/packages/diagrams/src/lib/types/automation-node-data-types.ts +45 -131
- package/packages/diagrams/src/lib/types/available-variables.ts +18 -18
- package/packages/diagrams/src/lib/types/card-node.ts +68 -68
- package/packages/diagrams/src/lib/types/collaboration-types.ts +114 -114
- package/packages/diagrams/src/lib/types/colors.ts +25 -25
- package/packages/diagrams/src/lib/types/condition-builder.ts +18 -18
- package/packages/diagrams/src/lib/types/diagram-types.ts +14 -14
- package/packages/diagrams/src/lib/types/edge-types.ts +39 -39
- package/packages/diagrams/src/lib/types/function-execution.ts +35 -35
- package/packages/diagrams/src/lib/types/hooks.types.ts +6 -6
- package/packages/diagrams/src/lib/types/ndoe-form-types.ts +139 -139
- package/packages/diagrams/src/lib/types/node-types.ts +13 -23
- package/packages/diagrams/src/lib/types/sequence-types.ts +178 -178
- package/packages/diagrams/src/lib/types/shared-node-types.ts +21 -21
- package/packages/diagrams/src/lib/types/state-machine-types.ts +225 -225
- package/packages/diagrams/src/lib/types/stencil-item.ts +7 -7
- package/packages/diagrams/src/lib/types/structures.ts +80 -80
- package/packages/diagrams/src/lib/types/system-flow-types.ts +129 -129
- package/packages/diagrams/src/lib/types/usecase-types.ts +84 -84
- package/packages/diagrams/src/lib/types/validation-types.ts +134 -134
- package/packages/diagrams/src/lib/types/workflow-content-dynamic-form-type.ts +23 -23
- package/packages/diagrams/src/lib/types/workflow-node-data-types.ts +172 -172
- package/packages/diagrams/src/lib/utils/AutomationExecutionEngine.ts +658 -1179
- package/packages/diagrams/src/lib/utils/add-new-block.ts +34 -34
- package/packages/diagrams/src/lib/utils/add-new-node.ts +52 -52
- package/packages/diagrams/src/lib/utils/addToHistory.ts +15 -15
- package/packages/diagrams/src/lib/utils/automation-flow-processor.ts +556 -619
- package/packages/diagrams/src/lib/utils/closestPoint.ts +45 -45
- package/packages/diagrams/src/lib/utils/color-options.tsx +26 -26
- package/packages/diagrams/src/lib/utils/compress-img.ts +59 -59
- package/packages/diagrams/src/lib/utils/configLoader.ts +329 -329
- package/packages/diagrams/src/lib/utils/constant-lengths.ts +8 -8
- package/packages/diagrams/src/lib/utils/create-updated.tsx +40 -40
- package/packages/diagrams/src/lib/utils/createHistoryChange.ts +3 -3
- package/packages/diagrams/src/lib/utils/dividerUtils.tsx +59 -59
- package/packages/diagrams/src/lib/utils/edge-hooks.ts +53 -53
- package/packages/diagrams/src/lib/utils/elkLayout.ts +297 -297
- package/packages/diagrams/src/lib/utils/event-hooks.ts +69 -69
- package/packages/diagrams/src/lib/utils/event-store.ts +58 -58
- package/packages/diagrams/src/lib/utils/flow-node-hooks.ts +28 -28
- package/packages/diagrams/src/lib/utils/flow-to-js.ts +1465 -1465
- package/packages/diagrams/src/lib/utils/functionGenerator.ts +38 -38
- package/packages/diagrams/src/lib/utils/generateEdgesFromNodeOrder.ts +113 -113
- package/packages/diagrams/src/lib/utils/helpers.types.ts +10 -10
- package/packages/diagrams/src/lib/utils/highlightText.tsx +93 -93
- package/packages/diagrams/src/lib/utils/iconMapper.tsx +76 -76
- package/packages/diagrams/src/lib/utils/logger.ts +5 -5
- package/packages/diagrams/src/lib/utils/model-hooks.ts +129 -129
- package/packages/diagrams/src/lib/utils/node-hooks.ts +78 -78
- package/packages/diagrams/src/lib/utils/nodeAIAssistantConfig.ts +54 -54
- package/packages/diagrams/src/lib/utils/nodeOrderByEdges.ts +437 -437
- package/packages/diagrams/src/lib/utils/nodeutils.ts +242 -242
- package/packages/diagrams/src/lib/utils/object.ts +13 -13
- package/packages/diagrams/src/lib/utils/useDebounce.ts +19 -19
- package/packages/diagrams/src/lib/utils/utilities.ts +105 -105
- package/packages/diagrams/src/lib/utils/validationEngine.ts +610 -610
- package/packages/diagrams/src/lib/utils/vhToPixels.ts +9 -9
- package/packages/diagrams/tsconfig.json +21 -21
- package/packages/diagrams/tsconfig.lib.json +26 -25
- package/packages/diagrams/webpack.config.js +17 -17
- package/packages/interfaces/.babelrc +12 -12
- package/packages/interfaces/.eslintrc.json +18 -18
- package/packages/interfaces/README.md +7 -7
- package/packages/interfaces/project.json +8 -8
- package/packages/interfaces/src/index.ts +21 -21
- package/packages/interfaces/src/lib/Button.tsx +1 -1
- package/packages/interfaces/src/lib/DataGrid.ts +14 -14
- package/packages/interfaces/src/lib/StyledBox.tsx +1 -1
- package/packages/interfaces/src/lib/ToolbarItem.ts +7 -7
- package/packages/interfaces/src/lib/UserCard.ts +8 -8
- package/packages/interfaces/src/lib/yup.ts +3 -3
- package/packages/interfaces/tsconfig.json +17 -17
- package/packages/interfaces/tsconfig.lib.json +24 -24
- package/packages/molecules/.babelrc +12 -12
- package/packages/molecules/.eslintrc.json +18 -18
- package/packages/molecules/README.md +7 -7
- package/packages/molecules/project.json +8 -8
- package/packages/molecules/src/index.ts +47 -41
- package/packages/molecules/src/lib/ActionTextField/ActionTextField.module.css +7 -7
- package/packages/molecules/src/lib/ActionTextField/ActionTextField.spec.tsx +10 -10
- package/packages/molecules/src/lib/ActionTextField/ActionTextField.tsx +33 -33
- package/packages/molecules/src/lib/ClosableButton/CloseableButton.module.css +7 -7
- package/packages/molecules/src/lib/ClosableButton/CloseableButton.spec.tsx +11 -11
- package/packages/molecules/src/lib/ClosableButton/CloseableButton.tsx +69 -69
- package/packages/molecules/src/lib/EditorTab/EditorTab.module.css +7 -7
- package/packages/molecules/src/lib/EditorTab/EditorTab.spec.tsx +10 -10
- package/packages/molecules/src/lib/EditorTab/EditorTab.tsx +42 -42
- package/packages/molecules/src/lib/EditorTab/TabPanel.tsx +25 -25
- package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.module.css +7 -7
- package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.spec.tsx +10 -10
- package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.tsx +24 -24
- package/packages/molecules/src/lib/SvgIcons/icons.tsx +323 -291
- package/packages/molecules/src/lib/SvgIcons/index.ts +31 -25
- package/packages/molecules/src/lib/SvgIcons/types.ts +7 -7
- package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.module.css +7 -7
- package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.spec.tsx +10 -10
- package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.tsx +47 -47
- package/packages/molecules/src/lib/UserCard/UserCard.module.css +7 -7
- package/packages/molecules/src/lib/UserCard/UserCard.spec.tsx +11 -11
- package/packages/molecules/src/lib/UserCard/UserCard.tsx +22 -22
- package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.module.css +7 -7
- package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.spec.tsx +10 -10
- package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.tsx +72 -72
- package/packages/molecules/tsconfig.json +17 -17
- package/packages/molecules/tsconfig.lib.json +30 -30
- package/packages/organisms/.babelrc +12 -12
- package/packages/organisms/.eslintrc.json +18 -18
- package/packages/organisms/README.md +7 -7
- package/packages/organisms/project.json +8 -8
- package/packages/organisms/src/index.ts +4 -4
- package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.module.css +7 -7
- package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.spec.tsx +10 -10
- package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.tsx +117 -117
- package/packages/organisms/src/lib/EditorToolbar/SortableItem.tsx +51 -51
- package/packages/organisms/src/lib/UserList/UserList.module.css +7 -7
- package/packages/organisms/src/lib/UserList/UserList.spec.tsx +11 -11
- package/packages/organisms/src/lib/UserList/UserList.tsx +48 -48
- package/packages/organisms/src/lib/UserList/store.ts +49 -49
- package/packages/organisms/tsconfig.json +17 -17
- package/packages/organisms/tsconfig.lib.json +24 -24
- package/packages/zustand/.babelrc +12 -12
- package/packages/zustand/.eslintrc.json +18 -18
- package/packages/zustand/README.md +7 -7
- package/packages/zustand/project.json +8 -8
- package/packages/zustand/src/index.ts +4 -4
- package/packages/zustand/tsconfig.json +17 -17
- package/packages/zustand/tsconfig.lib.json +24 -24
- package/tsconfig.base.json +29 -29
- package/packages/diagrams/src/lib/components/automation/AutomationAISuggestionNode.tsx +0 -304
- package/packages/diagrams/src/lib/components/automation/AutomationEmailNode.tsx +0 -773
- package/packages/diagrams/src/lib/components/automation/AutomationGoogleServicesNode.tsx +0 -779
- package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +0 -422
- package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +0 -1135
- package/packages/diagrams/src/lib/examples/GoogleSheetsConfigurationExamples.ts +0 -306
|
@@ -1,755 +1,755 @@
|
|
|
1
|
-
import { memo, useRef, useCallback, useState, useEffect } from "react"
|
|
2
|
-
import { Handle, Position, type NodeProps, useReactFlow } from "@xyflow/react"
|
|
3
|
-
import { Paper, Typography, Box } from "@mui/material"
|
|
4
|
-
import { useResizeObserver } from "../../../hooks/useResizeObserver";
|
|
5
|
-
import { useTreeChildNode } from "../../../hooks/useTreeChildNode";
|
|
6
|
-
import { useAddChildButton } from "../../../hooks/useAddChildButton";
|
|
7
|
-
import { SystemFlowNodeData } from '../../../types/system-flow-types';
|
|
8
|
-
|
|
9
|
-
const TreeSystemNode = ({ id, data, isConnectable }: NodeProps) => {
|
|
10
|
-
const nodeRef = useRef<HTMLDivElement>(null);
|
|
11
|
-
const { getNode, setNodes, getNodes, addNodes } = useReactFlow();
|
|
12
|
-
|
|
13
|
-
const nodeData = data as SystemFlowNodeData;
|
|
14
|
-
const isTreeStructure = nodeData.isTreeStructure;
|
|
15
|
-
const structureId = nodeData.structureId;
|
|
16
|
-
const nodeType = nodeData.nodeType;
|
|
17
|
-
|
|
18
|
-
// State to track node dimensions for auto-centering
|
|
19
|
-
const [nodeDimensions, setNodeDimensions] = useState<{
|
|
20
|
-
width: number;
|
|
21
|
-
height: number;
|
|
22
|
-
}>({ width: 120, height: 60 });
|
|
23
|
-
|
|
24
|
-
// State to track if root node is being edited
|
|
25
|
-
const [isRootBeingEdited, setIsRootBeingEdited] = useState(false);
|
|
26
|
-
|
|
27
|
-
// Use custom hooks for tree child node functionality
|
|
28
|
-
const { addChildNode, adjustChildPositions, forceLayoutRecalculation } = useTreeChildNode({
|
|
29
|
-
id,
|
|
30
|
-
isTreeStructure: isTreeStructure || false,
|
|
31
|
-
nodeType: nodeType || 'root',
|
|
32
|
-
structureId
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Function to auto-center root node after editing
|
|
36
|
-
const autoCenterRootNode = useCallback(() => {
|
|
37
|
-
if (isTreeStructure && nodeType === 'root') {
|
|
38
|
-
const allNodes = getNodes();
|
|
39
|
-
const currentNode = allNodes.find(n => n.id === id);
|
|
40
|
-
if (!currentNode) return;
|
|
41
|
-
|
|
42
|
-
// Calculate new center position based on current width
|
|
43
|
-
const newWidth = nodeDimensions.width;
|
|
44
|
-
const currentX = currentNode.position.x;
|
|
45
|
-
const currentCenterX = currentX + (currentNode.width || 120) / 2;
|
|
46
|
-
const newCenterX = currentX + newWidth / 2;
|
|
47
|
-
|
|
48
|
-
// Calculate offset to keep the node centered
|
|
49
|
-
const offsetX = currentCenterX - newCenterX;
|
|
50
|
-
const newPosition = {
|
|
51
|
-
x: currentX + offsetX,
|
|
52
|
-
y: currentNode.position.y
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// Update the root node position
|
|
56
|
-
const updatedNodes = allNodes.map(n => {
|
|
57
|
-
if (n.id === id) {
|
|
58
|
-
return {
|
|
59
|
-
...n,
|
|
60
|
-
position: newPosition,
|
|
61
|
-
measured: {
|
|
62
|
-
width: newWidth,
|
|
63
|
-
height: nodeDimensions.height
|
|
64
|
-
},
|
|
65
|
-
width: newWidth,
|
|
66
|
-
height: nodeDimensions.height
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
return n;
|
|
70
|
-
});
|
|
71
|
-
setNodes(updatedNodes);
|
|
72
|
-
|
|
73
|
-
// Adjust child positions after centering
|
|
74
|
-
setTimeout(() => adjustChildPositions(), 0);
|
|
75
|
-
}
|
|
76
|
-
}, [isTreeStructure, nodeType, nodeDimensions, getNodes, setNodes, adjustChildPositions, id]);
|
|
77
|
-
|
|
78
|
-
const { isHovered, setIsHovered, AddChildButton } = useAddChildButton({
|
|
79
|
-
isTreeStructure: isTreeStructure || false,
|
|
80
|
-
nodeType: nodeType || 'root',
|
|
81
|
-
nodeColor: nodeData.color || '#2196F3',
|
|
82
|
-
onAddChild: addChildNode
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Debounced layout recalculation to prevent excessive recalculations
|
|
86
|
-
const layoutTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
87
|
-
|
|
88
|
-
// Flag to prevent infinite loops during layout recalculation
|
|
89
|
-
const isRecalculatingLayout = useRef(false);
|
|
90
|
-
|
|
91
|
-
// Timestamp to prevent rapid successive calls
|
|
92
|
-
const lastResizeTime = useRef(0);
|
|
93
|
-
|
|
94
|
-
// Store last calculated dimensions to prevent unnecessary recalculations
|
|
95
|
-
const lastCalculatedDimensions = useRef<Map<string, { width: number; height: number }>>(new Map());
|
|
96
|
-
|
|
97
|
-
// Store last node labels to detect content changes
|
|
98
|
-
const lastNodeLabels = useRef<Map<string, string>>(new Map());
|
|
99
|
-
|
|
100
|
-
// Debounced layout recalculation to prevent excessive recalculations
|
|
101
|
-
const debouncedLayoutRecalculation = useCallback(() => {
|
|
102
|
-
if (layoutTimeoutRef.current) {
|
|
103
|
-
clearTimeout(layoutTimeoutRef.current);
|
|
104
|
-
}
|
|
105
|
-
layoutTimeoutRef.current = setTimeout(() => {
|
|
106
|
-
// Only recalculate if we're not already recalculating
|
|
107
|
-
if (!isRecalculatingLayout.current) {
|
|
108
|
-
adjustChildPositions();
|
|
109
|
-
}
|
|
110
|
-
}, 50); // 50ms debounce
|
|
111
|
-
}, [adjustChildPositions]);
|
|
112
|
-
|
|
113
|
-
// Use a ref to store the resize handler to prevent callback recreation
|
|
114
|
-
const handleResizeRef = useRef<(({ width, height }: { width: number; height: number }) => void) | null>(null);
|
|
115
|
-
|
|
116
|
-
// Create a stable resize handler that doesn't change on every render
|
|
117
|
-
const createResizeHandler = useCallback(() => {
|
|
118
|
-
return ({ width, height }: { width: number; height: number }) => {
|
|
119
|
-
const actualWidth = nodeRef.current?.scrollWidth || width;
|
|
120
|
-
const actualHeight = nodeRef.current?.scrollHeight || height;
|
|
121
|
-
|
|
122
|
-
// Update local dimensions state
|
|
123
|
-
setNodeDimensions({ width: actualWidth, height: actualHeight });
|
|
124
|
-
|
|
125
|
-
// For root nodes, don't auto-center during editing - let it extend freely
|
|
126
|
-
if (isTreeStructure && nodeType === 'root') {
|
|
127
|
-
// Mark that root is being edited
|
|
128
|
-
setIsRootBeingEdited(true);
|
|
129
|
-
// Don't auto-center during editing, just update dimensions
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// For child nodes, trigger layout recalculation when dimensions change
|
|
133
|
-
if (isTreeStructure && nodeType === 'child') {
|
|
134
|
-
const now = Date.now();
|
|
135
|
-
const timeSinceLastResize = now - lastResizeTime.current;
|
|
136
|
-
|
|
137
|
-
// Skip if we're already recalculating layout to prevent loops
|
|
138
|
-
if (isRecalculatingLayout.current) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Skip if resize happened too recently (less than 100ms ago)
|
|
143
|
-
if (timeSinceLastResize < 100) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
lastResizeTime.current = now;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
// Update this child node's measured dimensions first
|
|
151
|
-
const allNodes = getNodes();
|
|
152
|
-
const updatedNodes = allNodes.map(n => {
|
|
153
|
-
if (n.id === id) {
|
|
154
|
-
return {
|
|
155
|
-
...n,
|
|
156
|
-
measured: {
|
|
157
|
-
width: actualWidth,
|
|
158
|
-
height: actualHeight
|
|
159
|
-
},
|
|
160
|
-
width: actualWidth,
|
|
161
|
-
height: actualHeight
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
return n;
|
|
165
|
-
});
|
|
166
|
-
setNodes(updatedNodes);
|
|
167
|
-
|
|
168
|
-
// Clear the stored dimensions and labels for this node to force recalculation
|
|
169
|
-
lastCalculatedDimensions.current.delete(id);
|
|
170
|
-
lastNodeLabels.current.delete(id);
|
|
171
|
-
|
|
172
|
-
// Find the root node and trigger its layout recalculation
|
|
173
|
-
const rootNode = allNodes.find(n =>
|
|
174
|
-
n.data.isTreeStructure &&
|
|
175
|
-
n.data.structureId === structureId &&
|
|
176
|
-
n.data.nodeType === 'root'
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
if (rootNode) {
|
|
180
|
-
// Use a longer delay to ensure the node dimensions are updated before layout calculation
|
|
181
|
-
setTimeout(() => {
|
|
182
|
-
const forceLayoutRecalculation = rootNode.data?.forceLayoutRecalculation;
|
|
183
|
-
if (typeof forceLayoutRecalculation === 'function') {
|
|
184
|
-
forceLayoutRecalculation();
|
|
185
|
-
} else {
|
|
186
|
-
// Fallback: Use debounced layout recalculation
|
|
187
|
-
debouncedLayoutRecalculation();
|
|
188
|
-
}
|
|
189
|
-
}, 150); // Increased delay to ensure dimensions are updated
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Call parent onResize if provided
|
|
194
|
-
if (typeof nodeData.onResize === 'function') {
|
|
195
|
-
nodeData.onResize(id, actualWidth, actualHeight);
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
}, [
|
|
199
|
-
isTreeStructure,
|
|
200
|
-
nodeType,
|
|
201
|
-
structureId,
|
|
202
|
-
id,
|
|
203
|
-
nodeData.label,
|
|
204
|
-
nodeData.onResize,
|
|
205
|
-
adjustChildPositions,
|
|
206
|
-
debouncedLayoutRecalculation,
|
|
207
|
-
getNodes,
|
|
208
|
-
setNodes
|
|
209
|
-
]);
|
|
210
|
-
|
|
211
|
-
// Update the ref with the latest handler
|
|
212
|
-
handleResizeRef.current = createResizeHandler();
|
|
213
|
-
|
|
214
|
-
// Create a stable callback that uses the ref
|
|
215
|
-
const stableResizeHandler = useCallback(({ width, height }: { width: number; height: number }) => {
|
|
216
|
-
if (handleResizeRef.current) {
|
|
217
|
-
handleResizeRef.current({ width, height });
|
|
218
|
-
}
|
|
219
|
-
}, []); // Empty dependency array - this callback never changes
|
|
220
|
-
|
|
221
|
-
useResizeObserver(nodeRef, stableResizeHandler);
|
|
222
|
-
|
|
223
|
-
// Effect to adjust child positions when dimensions change
|
|
224
|
-
useEffect(() => {
|
|
225
|
-
if (isTreeStructure && nodeType === 'root' && nodeDimensions.width > 0) {
|
|
226
|
-
adjustChildPositions();
|
|
227
|
-
}
|
|
228
|
-
}, [nodeDimensions.width, adjustChildPositions, isTreeStructure, nodeType]);
|
|
229
|
-
|
|
230
|
-
// Effect to detect label changes and trigger layout recalculation
|
|
231
|
-
useEffect(() => {
|
|
232
|
-
if (isTreeStructure && nodeType === 'child' && nodeData.label) {
|
|
233
|
-
const lastLabel = lastNodeLabels.current.get(id);
|
|
234
|
-
if (lastLabel !== nodeData.label) {
|
|
235
|
-
lastNodeLabels.current.set(id, nodeData.label as string);
|
|
236
|
-
|
|
237
|
-
// Trigger layout recalculation after a short delay to allow for resize
|
|
238
|
-
setTimeout(() => {
|
|
239
|
-
const allNodes = getNodes();
|
|
240
|
-
const rootNode = allNodes.find(n =>
|
|
241
|
-
n.data.isTreeStructure &&
|
|
242
|
-
n.data.structureId === structureId &&
|
|
243
|
-
n.data.nodeType === 'root'
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
if (rootNode) {
|
|
247
|
-
debouncedLayoutRecalculation();
|
|
248
|
-
}
|
|
249
|
-
}, 100);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}, [nodeData.label, isTreeStructure, nodeType, structureId, id, getNodes, debouncedLayoutRecalculation]);
|
|
253
|
-
|
|
254
|
-
// Effect to trigger initial layout calculation when component mounts
|
|
255
|
-
useEffect(() => {
|
|
256
|
-
if (isTreeStructure && nodeType === 'root') {
|
|
257
|
-
// Small delay to ensure all nodes are loaded
|
|
258
|
-
const timer = setTimeout(() => {
|
|
259
|
-
const allNodes = getNodes();
|
|
260
|
-
const childNodes = allNodes.filter(n =>
|
|
261
|
-
n.data.isTreeStructure &&
|
|
262
|
-
n.data.structureId === structureId &&
|
|
263
|
-
n.data.nodeType === 'child'
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
if (childNodes.length > 0) {
|
|
267
|
-
// Clear caches to force initial layout calculation
|
|
268
|
-
lastCalculatedDimensions.current.clear();
|
|
269
|
-
lastNodeLabels.current.clear();
|
|
270
|
-
adjustChildPositions();
|
|
271
|
-
}
|
|
272
|
-
}, 100);
|
|
273
|
-
|
|
274
|
-
return () => clearTimeout(timer);
|
|
275
|
-
}
|
|
276
|
-
}, [isTreeStructure, nodeType, structureId, getNodes, adjustChildPositions]);
|
|
277
|
-
|
|
278
|
-
// Effect to update existing child nodes with structure type when component mounts
|
|
279
|
-
useEffect(() => {
|
|
280
|
-
if (isTreeStructure && nodeType === 'root' && nodeData.structureType) {
|
|
281
|
-
const timer = setTimeout(() => {
|
|
282
|
-
const allNodes = getNodes();
|
|
283
|
-
const childNodes = allNodes.filter(n =>
|
|
284
|
-
n.data.isTreeStructure &&
|
|
285
|
-
n.data.structureId === structureId &&
|
|
286
|
-
n.data.nodeType === 'child' &&
|
|
287
|
-
!n.data.structureType
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
if (childNodes.length > 0) {
|
|
291
|
-
const updatedNodes = allNodes.map(node => {
|
|
292
|
-
if (
|
|
293
|
-
node.data.isTreeStructure &&
|
|
294
|
-
node.data.structureId === structureId &&
|
|
295
|
-
node.data.nodeType === 'child' &&
|
|
296
|
-
!node.data.structureType
|
|
297
|
-
) {
|
|
298
|
-
return {
|
|
299
|
-
...node,
|
|
300
|
-
data: {
|
|
301
|
-
...node.data,
|
|
302
|
-
structureType: nodeData.structureType,
|
|
303
|
-
},
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
return node;
|
|
307
|
-
});
|
|
308
|
-
setNodes(updatedNodes);
|
|
309
|
-
}
|
|
310
|
-
}, 200);
|
|
311
|
-
|
|
312
|
-
return () => clearTimeout(timer);
|
|
313
|
-
}
|
|
314
|
-
}, [isTreeStructure, nodeType, structureId, nodeData.structureType, getNodes, setNodes]);
|
|
315
|
-
|
|
316
|
-
// Effect to recalculate positions when child nodes change (add/remove)
|
|
317
|
-
useEffect(() => {
|
|
318
|
-
if (isTreeStructure && nodeType === 'root') {
|
|
319
|
-
const allNodes = getNodes();
|
|
320
|
-
const childNodes = allNodes.filter(n =>
|
|
321
|
-
n.data.isTreeStructure &&
|
|
322
|
-
n.data.structureId === structureId &&
|
|
323
|
-
n.data.nodeType === 'child'
|
|
324
|
-
);
|
|
325
|
-
|
|
326
|
-
// If we have child nodes, ensure they're positioned correctly
|
|
327
|
-
if (childNodes.length > 0) {
|
|
328
|
-
// Clear caches to force initial layout calculation
|
|
329
|
-
lastCalculatedDimensions.current.clear();
|
|
330
|
-
lastNodeLabels.current.clear();
|
|
331
|
-
setTimeout(() => adjustChildPositions(), 0);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}, [getNodes, isTreeStructure, nodeType, structureId, adjustChildPositions]);
|
|
335
|
-
|
|
336
|
-
// Effect to trigger layout recalculation when lastLayoutUpdate changes
|
|
337
|
-
useEffect(() => {
|
|
338
|
-
if (isTreeStructure && nodeType === 'root' && nodeData.lastLayoutUpdate) {
|
|
339
|
-
// Clear caches and recalculate layout
|
|
340
|
-
lastCalculatedDimensions.current.clear();
|
|
341
|
-
lastNodeLabels.current.clear();
|
|
342
|
-
setTimeout(() => adjustChildPositions(), 0);
|
|
343
|
-
}
|
|
344
|
-
}, [nodeData.lastLayoutUpdate, isTreeStructure, nodeType, adjustChildPositions]);
|
|
345
|
-
|
|
346
|
-
// Expose forceLayoutRecalculation and autoCenterRootNode functions through node data
|
|
347
|
-
useEffect(() => {
|
|
348
|
-
if (isTreeStructure) {
|
|
349
|
-
// Update the node data to include the functions
|
|
350
|
-
const allNodes = getNodes();
|
|
351
|
-
const updatedNodes = allNodes.map(n => {
|
|
352
|
-
if (n.id === id) {
|
|
353
|
-
return {
|
|
354
|
-
...n,
|
|
355
|
-
data: {
|
|
356
|
-
...n.data,
|
|
357
|
-
forceLayoutRecalculation,
|
|
358
|
-
autoCenterRootNode: nodeType === 'root' ? autoCenterRootNode : undefined,
|
|
359
|
-
isRootBeingEdited: nodeType === 'root' ? isRootBeingEdited : undefined
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
return n;
|
|
364
|
-
});
|
|
365
|
-
setNodes(updatedNodes);
|
|
366
|
-
}
|
|
367
|
-
}, [id, isTreeStructure, nodeType, forceLayoutRecalculation, autoCenterRootNode, isRootBeingEdited, getNodes, setNodes]);
|
|
368
|
-
|
|
369
|
-
// Cleanup effect to clear timeouts
|
|
370
|
-
useEffect(() => {
|
|
371
|
-
return () => {
|
|
372
|
-
if (layoutTimeoutRef.current) {
|
|
373
|
-
clearTimeout(layoutTimeoutRef.current);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
}, []);
|
|
377
|
-
|
|
378
|
-
return (
|
|
379
|
-
<div style={{ position: 'relative' }}>
|
|
380
|
-
{/* Main Node */}
|
|
381
|
-
<Paper
|
|
382
|
-
ref={nodeRef}
|
|
383
|
-
elevation={2}
|
|
384
|
-
onMouseEnter={() => setIsHovered(true)}
|
|
385
|
-
onMouseLeave={() => setIsHovered(false)}
|
|
386
|
-
sx={{
|
|
387
|
-
minWidth: 120,
|
|
388
|
-
minHeight: 60,
|
|
389
|
-
width: 'max-content',
|
|
390
|
-
height: 'max-content',
|
|
391
|
-
borderRadius: 2,
|
|
392
|
-
border: `2px solid ${nodeData.color || '#2196F3'}`,
|
|
393
|
-
padding: 2,
|
|
394
|
-
display: 'flex',
|
|
395
|
-
flexDirection: 'column',
|
|
396
|
-
justifyContent: 'center',
|
|
397
|
-
position: 'relative',
|
|
398
|
-
overflow: 'visible',
|
|
399
|
-
boxSizing: 'border-box',
|
|
400
|
-
backgroundColor: 'white',
|
|
401
|
-
cursor: 'move',
|
|
402
|
-
userSelect: 'none',
|
|
403
|
-
}}
|
|
404
|
-
>
|
|
405
|
-
<Handle
|
|
406
|
-
type="target"
|
|
407
|
-
position={Position.Left}
|
|
408
|
-
isConnectable={isConnectable}
|
|
409
|
-
style={{
|
|
410
|
-
left: '-6px',
|
|
411
|
-
backgroundColor: nodeData.color || '#2196F3',
|
|
412
|
-
border: '2px solid #fff',
|
|
413
|
-
width: '12px',
|
|
414
|
-
height: '12px'
|
|
415
|
-
}}
|
|
416
|
-
/>
|
|
417
|
-
|
|
418
|
-
<Box sx={{
|
|
419
|
-
textAlign: "center",
|
|
420
|
-
display: 'flex',
|
|
421
|
-
flexDirection: 'column',
|
|
422
|
-
justifyContent: 'center',
|
|
423
|
-
width: 'max-content',
|
|
424
|
-
minWidth: 'min-content'
|
|
425
|
-
}}>
|
|
426
|
-
<Typography
|
|
427
|
-
variant="subtitle1"
|
|
428
|
-
fontWeight="bold"
|
|
429
|
-
sx={{
|
|
430
|
-
whiteSpace: 'nowrap',
|
|
431
|
-
overflow: 'visible',
|
|
432
|
-
width: 'max-content',
|
|
433
|
-
color: nodeData.color || '#2196F3',
|
|
434
|
-
}}
|
|
435
|
-
>
|
|
436
|
-
{(nodeData.label as string) || 'System'}
|
|
437
|
-
</Typography>
|
|
438
|
-
|
|
439
|
-
{/* Add Child Button - Using custom hook */}
|
|
440
|
-
{AddChildButton}
|
|
441
|
-
</Box>
|
|
442
|
-
|
|
443
|
-
<Handle
|
|
444
|
-
type="source"
|
|
445
|
-
position={Position.Right}
|
|
446
|
-
isConnectable={isConnectable}
|
|
447
|
-
style={{
|
|
448
|
-
right: '-6px',
|
|
449
|
-
backgroundColor: nodeData.color || '#2196F3',
|
|
450
|
-
border: '2px solid #fff',
|
|
451
|
-
width: '12px',
|
|
452
|
-
height: '12px'
|
|
453
|
-
}}
|
|
454
|
-
/>
|
|
455
|
-
</Paper>
|
|
456
|
-
|
|
457
|
-
{/* SVG Connection Lines - Render for all nodes that have children */}
|
|
458
|
-
{isTreeStructure && (() => {
|
|
459
|
-
// Get structure type from current node, or fallback to root node's structure type
|
|
460
|
-
let structureType: 'structure1' | 'structure2' | 'structure3' = nodeData.structureType || 'structure1';
|
|
461
|
-
if (!nodeData.structureType && structureId) {
|
|
462
|
-
const allNodes = getNodes();
|
|
463
|
-
const rootNode = allNodes.find(n =>
|
|
464
|
-
n.data.isTreeStructure &&
|
|
465
|
-
n.data.structureId === structureId &&
|
|
466
|
-
n.data.nodeType === 'root'
|
|
467
|
-
);
|
|
468
|
-
structureType = (rootNode?.data?.structureType as 'structure1' | 'structure2' | 'structure3') || 'structure1';
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// Calculate SVG positioning based on node position and width
|
|
472
|
-
// Use current dimensions if root is being edited, otherwise use measured dimensions
|
|
473
|
-
const currentNode = getNodes().find(n => n.id === id);
|
|
474
|
-
if (!currentNode) return null;
|
|
475
|
-
|
|
476
|
-
const actualNodeWidth = isRootBeingEdited ? nodeDimensions.width : (currentNode?.measured?.width || currentNode?.width || nodeDimensions.width);
|
|
477
|
-
const nodeCenterX = actualNodeWidth / 2; // This is the center relative to the node's left edge
|
|
478
|
-
|
|
479
|
-
// Calculate the actual span needed for child nodes
|
|
480
|
-
const allNodes = getNodes();
|
|
481
|
-
const childNodes = allNodes.filter(n =>
|
|
482
|
-
n.data.isTreeStructure &&
|
|
483
|
-
n.data.structureId === structureId &&
|
|
484
|
-
n.data.parentId === id
|
|
485
|
-
);
|
|
486
|
-
|
|
487
|
-
// Only render SVG if this node has children
|
|
488
|
-
if (childNodes.length === 0) return null;
|
|
489
|
-
|
|
490
|
-
// Calculate SVG bounds based on child node positions
|
|
491
|
-
const leftmostChild = Math.min(...childNodes.map(n => {
|
|
492
|
-
const childWidth = n.measured?.width || n.width || 120;
|
|
493
|
-
return n.position.x;
|
|
494
|
-
}));
|
|
495
|
-
const rightmostChild = Math.max(...childNodes.map(n => {
|
|
496
|
-
const childWidth = n.measured?.width || n.width || 120;
|
|
497
|
-
return n.position.x + childWidth;
|
|
498
|
-
}));
|
|
499
|
-
|
|
500
|
-
// Add padding to ensure the SVG covers the extended horizontal line
|
|
501
|
-
const padding = 40;
|
|
502
|
-
const minWidth = 400;
|
|
503
|
-
const svgWidth = Math.max(minWidth, rightmostChild - leftmostChild + padding * 2);
|
|
504
|
-
const svgLeft = leftmostChild - padding - currentNode.position.x; // Relative to current node position
|
|
505
|
-
|
|
506
|
-
// Render different SVG designs based on structure type
|
|
507
|
-
if (structureType === 'structure2') {
|
|
508
|
-
// Structure 2: Arrow from root with space before horizontal line
|
|
509
|
-
return (
|
|
510
|
-
<svg
|
|
511
|
-
style={{
|
|
512
|
-
position: 'absolute',
|
|
513
|
-
top: 0,
|
|
514
|
-
left: `${svgLeft}px`,
|
|
515
|
-
width: `${svgWidth}px`,
|
|
516
|
-
height: '210px',
|
|
517
|
-
pointerEvents: 'none',
|
|
518
|
-
zIndex: 5,
|
|
519
|
-
}}
|
|
520
|
-
viewBox={`${svgLeft} 0 ${svgWidth} 210`}
|
|
521
|
-
>
|
|
522
|
-
{/* Arrow from root node bottom center */}
|
|
523
|
-
<g>
|
|
524
|
-
{/* Arrow shaft */}
|
|
525
|
-
<line
|
|
526
|
-
x1={nodeCenterX}
|
|
527
|
-
y1="60" // Bottom of root node
|
|
528
|
-
x2={nodeCenterX}
|
|
529
|
-
y2="110" // Extended down with space
|
|
530
|
-
stroke="#666"
|
|
531
|
-
strokeWidth="2"
|
|
532
|
-
/>
|
|
533
|
-
{/* Arrow head pointing down */}
|
|
534
|
-
<polygon
|
|
535
|
-
points={`${nodeCenterX},110 ${nodeCenterX - 6},104 ${nodeCenterX + 6},104`}
|
|
536
|
-
fill="#666"
|
|
537
|
-
/>
|
|
538
|
-
</g>
|
|
539
|
-
|
|
540
|
-
{/* Dynamic horizontal line connecting all child nodes with space from arrow */}
|
|
541
|
-
{childNodes.length > 0 && (() => {
|
|
542
|
-
const leftmostChild = Math.min(...childNodes.map(n => {
|
|
543
|
-
const relativePos = n.data.relativePosition as { x: number; y: number };
|
|
544
|
-
const childWidth = n.measured?.width || n.width || 120;
|
|
545
|
-
return relativePos ? nodeCenterX + relativePos.x + (childWidth / 2) : 0;
|
|
546
|
-
}));
|
|
547
|
-
const rightmostChild = Math.max(...childNodes.map(n => {
|
|
548
|
-
const relativePos = n.data.relativePosition as { x: number; y: number };
|
|
549
|
-
const childWidth = n.measured?.width || n.width || 120;
|
|
550
|
-
return relativePos ? nodeCenterX + relativePos.x + (childWidth / 2) : 0;
|
|
551
|
-
}));
|
|
552
|
-
|
|
553
|
-
return (
|
|
554
|
-
<line
|
|
555
|
-
x1={leftmostChild}
|
|
556
|
-
y1="110" // Space below the arrow
|
|
557
|
-
x2={rightmostChild}
|
|
558
|
-
y2="110" // Same y
|
|
559
|
-
stroke="#666"
|
|
560
|
-
strokeWidth="2"
|
|
561
|
-
/>
|
|
562
|
-
);
|
|
563
|
-
})()}
|
|
564
|
-
|
|
565
|
-
{/* Dynamic vertical lines and arrows for each child node */}
|
|
566
|
-
{childNodes.map((childNode, index) => {
|
|
567
|
-
const relativePos = childNode.data.relativePosition as { x: number; y: number };
|
|
568
|
-
if (!relativePos) return null;
|
|
569
|
-
|
|
570
|
-
const childWidth = childNode.measured?.width || childNode.width || 120;
|
|
571
|
-
const childX = nodeCenterX + relativePos.x + (childWidth / 2);
|
|
572
|
-
|
|
573
|
-
return (
|
|
574
|
-
<g key={childNode.id}>
|
|
575
|
-
{/* Vertical line down to child node - connect directly to node */}
|
|
576
|
-
<line
|
|
577
|
-
x1={childX}
|
|
578
|
-
y1="110" // From horizontal line
|
|
579
|
-
x2={childX}
|
|
580
|
-
y2="145" // Connect directly to child node top
|
|
581
|
-
stroke="#666"
|
|
582
|
-
strokeWidth="2"
|
|
583
|
-
/>
|
|
584
|
-
|
|
585
|
-
{/* Arrow head pointing down to child node - positioned at node top */}
|
|
586
|
-
<polygon
|
|
587
|
-
points={`${childX},150 ${childX - 6},144 ${childX + 6},144`}
|
|
588
|
-
fill="#666"
|
|
589
|
-
/>
|
|
590
|
-
</g>
|
|
591
|
-
);
|
|
592
|
-
})}
|
|
593
|
-
</svg>
|
|
594
|
-
);
|
|
595
|
-
} else if (structureType === 'structure3') {
|
|
596
|
-
// Structure 3: Normal root line with circle center point for child connections
|
|
597
|
-
return (
|
|
598
|
-
<svg
|
|
599
|
-
style={{
|
|
600
|
-
position: 'absolute',
|
|
601
|
-
top: 0,
|
|
602
|
-
left: `${svgLeft}px`,
|
|
603
|
-
width: `${svgWidth}px`,
|
|
604
|
-
height: '210px',
|
|
605
|
-
pointerEvents: 'none',
|
|
606
|
-
zIndex: 5,
|
|
607
|
-
}}
|
|
608
|
-
viewBox={`${svgLeft} 0 ${svgWidth} 210`}
|
|
609
|
-
>
|
|
610
|
-
{/* Vertical line from root node bottom center */}
|
|
611
|
-
<line
|
|
612
|
-
x1={nodeCenterX}
|
|
613
|
-
y1="60" // Bottom of root node
|
|
614
|
-
x2={nodeCenterX}
|
|
615
|
-
y2="90" // Fixed distance down
|
|
616
|
-
stroke="#666"
|
|
617
|
-
strokeWidth="2"
|
|
618
|
-
/>
|
|
619
|
-
|
|
620
|
-
{/* Circle center point for child connections */}
|
|
621
|
-
{childNodes.length > 0 && (
|
|
622
|
-
<circle
|
|
623
|
-
cx={nodeCenterX}
|
|
624
|
-
cy="90"
|
|
625
|
-
r="8"
|
|
626
|
-
fill="white"
|
|
627
|
-
stroke="white"
|
|
628
|
-
strokeWidth="2"
|
|
629
|
-
/>
|
|
630
|
-
)}
|
|
631
|
-
|
|
632
|
-
{/* Dynamic lines from circle to each child node */}
|
|
633
|
-
{childNodes.map((childNode, index) => {
|
|
634
|
-
const relativePos = childNode.data.relativePosition as { x: number; y: number };
|
|
635
|
-
if (!relativePos) return null;
|
|
636
|
-
|
|
637
|
-
const childWidth = childNode.measured?.width || childNode.width || 120;
|
|
638
|
-
const childX = nodeCenterX + relativePos.x + (childWidth / 2);
|
|
639
|
-
const childY = 160; // Child nodes start at y=160
|
|
640
|
-
|
|
641
|
-
// Calculate angle from circle center to child node
|
|
642
|
-
const deltaX = childX - nodeCenterX;
|
|
643
|
-
const deltaY = childY - 90;
|
|
644
|
-
const angle = Math.atan2(deltaY, deltaX);
|
|
645
|
-
|
|
646
|
-
// Calculate circle edge point
|
|
647
|
-
const circleRadius = 8;
|
|
648
|
-
const circleEdgeX = nodeCenterX + circleRadius * Math.cos(angle);
|
|
649
|
-
const circleEdgeY = 90 + circleRadius * Math.sin(angle);
|
|
650
|
-
|
|
651
|
-
return (
|
|
652
|
-
<g key={childNode.id}>
|
|
653
|
-
{/* Line from circle edge to child node */}
|
|
654
|
-
<line
|
|
655
|
-
x1={circleEdgeX}
|
|
656
|
-
y1={circleEdgeY}
|
|
657
|
-
x2={childX}
|
|
658
|
-
y2="145" // Connect directly to child node top
|
|
659
|
-
stroke="#666"
|
|
660
|
-
strokeWidth="2"
|
|
661
|
-
/>
|
|
662
|
-
|
|
663
|
-
{/* Arrow head pointing down to child node */}
|
|
664
|
-
<polygon
|
|
665
|
-
points={`${childX},150 ${childX - 6},144 ${childX + 6},144`}
|
|
666
|
-
fill="#666"
|
|
667
|
-
/>
|
|
668
|
-
</g>
|
|
669
|
-
);
|
|
670
|
-
})}
|
|
671
|
-
</svg>
|
|
672
|
-
);
|
|
673
|
-
} else {
|
|
674
|
-
// Structure 1: Original design with connected lines
|
|
675
|
-
return (
|
|
676
|
-
<svg
|
|
677
|
-
style={{
|
|
678
|
-
position: 'absolute',
|
|
679
|
-
top: 0,
|
|
680
|
-
left: `${svgLeft}px`,
|
|
681
|
-
width: `${svgWidth}px`,
|
|
682
|
-
height: '210px',
|
|
683
|
-
pointerEvents: 'none',
|
|
684
|
-
zIndex: 5,
|
|
685
|
-
}}
|
|
686
|
-
viewBox={`0 0 ${svgWidth} 210`}
|
|
687
|
-
>
|
|
688
|
-
{/* Vertical line from current node bottom center */}
|
|
689
|
-
<line
|
|
690
|
-
x1={nodeCenterX - svgLeft}
|
|
691
|
-
y1="60" // Bottom of current node
|
|
692
|
-
x2={nodeCenterX - svgLeft}
|
|
693
|
-
y2="90" // Fixed distance down
|
|
694
|
-
stroke="#666"
|
|
695
|
-
strokeWidth="2"
|
|
696
|
-
/>
|
|
697
|
-
|
|
698
|
-
{/* Dynamic horizontal line connecting all child nodes */}
|
|
699
|
-
{childNodes.length > 0 && (() => {
|
|
700
|
-
const leftmostChild = Math.min(...childNodes.map(n => {
|
|
701
|
-
const childWidth = n.measured?.width || n.width || 120;
|
|
702
|
-
return n.position.x + (childWidth / 2) - currentNode.position.x;
|
|
703
|
-
}));
|
|
704
|
-
const rightmostChild = Math.max(...childNodes.map(n => {
|
|
705
|
-
const childWidth = n.measured?.width || n.width || 120;
|
|
706
|
-
return n.position.x + (childWidth / 2) - currentNode.position.x;
|
|
707
|
-
}));
|
|
708
|
-
|
|
709
|
-
return (
|
|
710
|
-
<line
|
|
711
|
-
x1={leftmostChild - svgLeft}
|
|
712
|
-
y1="90" // Same y as vertical line end
|
|
713
|
-
x2={rightmostChild - svgLeft}
|
|
714
|
-
y2="90" // Same y
|
|
715
|
-
stroke="#666"
|
|
716
|
-
strokeWidth="2"
|
|
717
|
-
/>
|
|
718
|
-
);
|
|
719
|
-
})()}
|
|
720
|
-
|
|
721
|
-
{/* Dynamic vertical lines and arrows for each child node */}
|
|
722
|
-
{childNodes.map((childNode, index) => {
|
|
723
|
-
const childWidth = childNode.measured?.width || childNode.width || 120;
|
|
724
|
-
const childX = childNode.position.x + (childWidth / 2) - currentNode.position.x;
|
|
725
|
-
|
|
726
|
-
return (
|
|
727
|
-
<g key={childNode.id}>
|
|
728
|
-
{/* Vertical line down to child node - connect directly to node */}
|
|
729
|
-
<line
|
|
730
|
-
x1={childX - svgLeft}
|
|
731
|
-
y1="90" // From horizontal line
|
|
732
|
-
x2={childX - svgLeft}
|
|
733
|
-
y2="145" // Connect directly to child node top
|
|
734
|
-
stroke="#666"
|
|
735
|
-
strokeWidth="2"
|
|
736
|
-
/>
|
|
737
|
-
|
|
738
|
-
{/* Arrow head pointing down to child node - positioned at node top */}
|
|
739
|
-
<polygon
|
|
740
|
-
points={`${childX - svgLeft},150 ${childX - svgLeft - 6},144 ${childX - svgLeft + 6},144`}
|
|
741
|
-
fill="#666"
|
|
742
|
-
/>
|
|
743
|
-
</g>
|
|
744
|
-
);
|
|
745
|
-
})}
|
|
746
|
-
</svg>
|
|
747
|
-
);
|
|
748
|
-
}
|
|
749
|
-
})()}
|
|
750
|
-
</div>
|
|
751
|
-
)
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
export default memo(TreeSystemNode)
|
|
755
|
-
|
|
1
|
+
import { memo, useRef, useCallback, useState, useEffect } from "react"
|
|
2
|
+
import { Handle, Position, type NodeProps, useReactFlow } from "@xyflow/react"
|
|
3
|
+
import { Paper, Typography, Box } from "@mui/material"
|
|
4
|
+
import { useResizeObserver } from "../../../hooks/useResizeObserver";
|
|
5
|
+
import { useTreeChildNode } from "../../../hooks/useTreeChildNode";
|
|
6
|
+
import { useAddChildButton } from "../../../hooks/useAddChildButton";
|
|
7
|
+
import { SystemFlowNodeData } from '../../../types/system-flow-types';
|
|
8
|
+
|
|
9
|
+
const TreeSystemNode = ({ id, data, isConnectable }: NodeProps) => {
|
|
10
|
+
const nodeRef = useRef<HTMLDivElement>(null);
|
|
11
|
+
const { getNode, setNodes, getNodes, addNodes } = useReactFlow();
|
|
12
|
+
|
|
13
|
+
const nodeData = data as SystemFlowNodeData;
|
|
14
|
+
const isTreeStructure = nodeData.isTreeStructure;
|
|
15
|
+
const structureId = nodeData.structureId;
|
|
16
|
+
const nodeType = nodeData.nodeType;
|
|
17
|
+
|
|
18
|
+
// State to track node dimensions for auto-centering
|
|
19
|
+
const [nodeDimensions, setNodeDimensions] = useState<{
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}>({ width: 120, height: 60 });
|
|
23
|
+
|
|
24
|
+
// State to track if root node is being edited
|
|
25
|
+
const [isRootBeingEdited, setIsRootBeingEdited] = useState(false);
|
|
26
|
+
|
|
27
|
+
// Use custom hooks for tree child node functionality
|
|
28
|
+
const { addChildNode, adjustChildPositions, forceLayoutRecalculation } = useTreeChildNode({
|
|
29
|
+
id,
|
|
30
|
+
isTreeStructure: isTreeStructure || false,
|
|
31
|
+
nodeType: nodeType || 'root',
|
|
32
|
+
structureId
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Function to auto-center root node after editing
|
|
36
|
+
const autoCenterRootNode = useCallback(() => {
|
|
37
|
+
if (isTreeStructure && nodeType === 'root') {
|
|
38
|
+
const allNodes = getNodes();
|
|
39
|
+
const currentNode = allNodes.find(n => n.id === id);
|
|
40
|
+
if (!currentNode) return;
|
|
41
|
+
|
|
42
|
+
// Calculate new center position based on current width
|
|
43
|
+
const newWidth = nodeDimensions.width;
|
|
44
|
+
const currentX = currentNode.position.x;
|
|
45
|
+
const currentCenterX = currentX + (currentNode.width || 120) / 2;
|
|
46
|
+
const newCenterX = currentX + newWidth / 2;
|
|
47
|
+
|
|
48
|
+
// Calculate offset to keep the node centered
|
|
49
|
+
const offsetX = currentCenterX - newCenterX;
|
|
50
|
+
const newPosition = {
|
|
51
|
+
x: currentX + offsetX,
|
|
52
|
+
y: currentNode.position.y
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Update the root node position
|
|
56
|
+
const updatedNodes = allNodes.map(n => {
|
|
57
|
+
if (n.id === id) {
|
|
58
|
+
return {
|
|
59
|
+
...n,
|
|
60
|
+
position: newPosition,
|
|
61
|
+
measured: {
|
|
62
|
+
width: newWidth,
|
|
63
|
+
height: nodeDimensions.height
|
|
64
|
+
},
|
|
65
|
+
width: newWidth,
|
|
66
|
+
height: nodeDimensions.height
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return n;
|
|
70
|
+
});
|
|
71
|
+
setNodes(updatedNodes);
|
|
72
|
+
|
|
73
|
+
// Adjust child positions after centering
|
|
74
|
+
setTimeout(() => adjustChildPositions(), 0);
|
|
75
|
+
}
|
|
76
|
+
}, [isTreeStructure, nodeType, nodeDimensions, getNodes, setNodes, adjustChildPositions, id]);
|
|
77
|
+
|
|
78
|
+
const { isHovered, setIsHovered, AddChildButton } = useAddChildButton({
|
|
79
|
+
isTreeStructure: isTreeStructure || false,
|
|
80
|
+
nodeType: nodeType || 'root',
|
|
81
|
+
nodeColor: nodeData.color || '#2196F3',
|
|
82
|
+
onAddChild: addChildNode
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Debounced layout recalculation to prevent excessive recalculations
|
|
86
|
+
const layoutTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
87
|
+
|
|
88
|
+
// Flag to prevent infinite loops during layout recalculation
|
|
89
|
+
const isRecalculatingLayout = useRef(false);
|
|
90
|
+
|
|
91
|
+
// Timestamp to prevent rapid successive calls
|
|
92
|
+
const lastResizeTime = useRef(0);
|
|
93
|
+
|
|
94
|
+
// Store last calculated dimensions to prevent unnecessary recalculations
|
|
95
|
+
const lastCalculatedDimensions = useRef<Map<string, { width: number; height: number }>>(new Map());
|
|
96
|
+
|
|
97
|
+
// Store last node labels to detect content changes
|
|
98
|
+
const lastNodeLabels = useRef<Map<string, string>>(new Map());
|
|
99
|
+
|
|
100
|
+
// Debounced layout recalculation to prevent excessive recalculations
|
|
101
|
+
const debouncedLayoutRecalculation = useCallback(() => {
|
|
102
|
+
if (layoutTimeoutRef.current) {
|
|
103
|
+
clearTimeout(layoutTimeoutRef.current);
|
|
104
|
+
}
|
|
105
|
+
layoutTimeoutRef.current = setTimeout(() => {
|
|
106
|
+
// Only recalculate if we're not already recalculating
|
|
107
|
+
if (!isRecalculatingLayout.current) {
|
|
108
|
+
adjustChildPositions();
|
|
109
|
+
}
|
|
110
|
+
}, 50); // 50ms debounce
|
|
111
|
+
}, [adjustChildPositions]);
|
|
112
|
+
|
|
113
|
+
// Use a ref to store the resize handler to prevent callback recreation
|
|
114
|
+
const handleResizeRef = useRef<(({ width, height }: { width: number; height: number }) => void) | null>(null);
|
|
115
|
+
|
|
116
|
+
// Create a stable resize handler that doesn't change on every render
|
|
117
|
+
const createResizeHandler = useCallback(() => {
|
|
118
|
+
return ({ width, height }: { width: number; height: number }) => {
|
|
119
|
+
const actualWidth = nodeRef.current?.scrollWidth || width;
|
|
120
|
+
const actualHeight = nodeRef.current?.scrollHeight || height;
|
|
121
|
+
|
|
122
|
+
// Update local dimensions state
|
|
123
|
+
setNodeDimensions({ width: actualWidth, height: actualHeight });
|
|
124
|
+
|
|
125
|
+
// For root nodes, don't auto-center during editing - let it extend freely
|
|
126
|
+
if (isTreeStructure && nodeType === 'root') {
|
|
127
|
+
// Mark that root is being edited
|
|
128
|
+
setIsRootBeingEdited(true);
|
|
129
|
+
// Don't auto-center during editing, just update dimensions
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// For child nodes, trigger layout recalculation when dimensions change
|
|
133
|
+
if (isTreeStructure && nodeType === 'child') {
|
|
134
|
+
const now = Date.now();
|
|
135
|
+
const timeSinceLastResize = now - lastResizeTime.current;
|
|
136
|
+
|
|
137
|
+
// Skip if we're already recalculating layout to prevent loops
|
|
138
|
+
if (isRecalculatingLayout.current) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Skip if resize happened too recently (less than 100ms ago)
|
|
143
|
+
if (timeSinceLastResize < 100) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
lastResizeTime.current = now;
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
// Update this child node's measured dimensions first
|
|
151
|
+
const allNodes = getNodes();
|
|
152
|
+
const updatedNodes = allNodes.map(n => {
|
|
153
|
+
if (n.id === id) {
|
|
154
|
+
return {
|
|
155
|
+
...n,
|
|
156
|
+
measured: {
|
|
157
|
+
width: actualWidth,
|
|
158
|
+
height: actualHeight
|
|
159
|
+
},
|
|
160
|
+
width: actualWidth,
|
|
161
|
+
height: actualHeight
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return n;
|
|
165
|
+
});
|
|
166
|
+
setNodes(updatedNodes);
|
|
167
|
+
|
|
168
|
+
// Clear the stored dimensions and labels for this node to force recalculation
|
|
169
|
+
lastCalculatedDimensions.current.delete(id);
|
|
170
|
+
lastNodeLabels.current.delete(id);
|
|
171
|
+
|
|
172
|
+
// Find the root node and trigger its layout recalculation
|
|
173
|
+
const rootNode = allNodes.find(n =>
|
|
174
|
+
n.data.isTreeStructure &&
|
|
175
|
+
n.data.structureId === structureId &&
|
|
176
|
+
n.data.nodeType === 'root'
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
if (rootNode) {
|
|
180
|
+
// Use a longer delay to ensure the node dimensions are updated before layout calculation
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
const forceLayoutRecalculation = rootNode.data?.forceLayoutRecalculation;
|
|
183
|
+
if (typeof forceLayoutRecalculation === 'function') {
|
|
184
|
+
forceLayoutRecalculation();
|
|
185
|
+
} else {
|
|
186
|
+
// Fallback: Use debounced layout recalculation
|
|
187
|
+
debouncedLayoutRecalculation();
|
|
188
|
+
}
|
|
189
|
+
}, 150); // Increased delay to ensure dimensions are updated
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Call parent onResize if provided
|
|
194
|
+
if (typeof nodeData.onResize === 'function') {
|
|
195
|
+
nodeData.onResize(id, actualWidth, actualHeight);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}, [
|
|
199
|
+
isTreeStructure,
|
|
200
|
+
nodeType,
|
|
201
|
+
structureId,
|
|
202
|
+
id,
|
|
203
|
+
nodeData.label,
|
|
204
|
+
nodeData.onResize,
|
|
205
|
+
adjustChildPositions,
|
|
206
|
+
debouncedLayoutRecalculation,
|
|
207
|
+
getNodes,
|
|
208
|
+
setNodes
|
|
209
|
+
]);
|
|
210
|
+
|
|
211
|
+
// Update the ref with the latest handler
|
|
212
|
+
handleResizeRef.current = createResizeHandler();
|
|
213
|
+
|
|
214
|
+
// Create a stable callback that uses the ref
|
|
215
|
+
const stableResizeHandler = useCallback(({ width, height }: { width: number; height: number }) => {
|
|
216
|
+
if (handleResizeRef.current) {
|
|
217
|
+
handleResizeRef.current({ width, height });
|
|
218
|
+
}
|
|
219
|
+
}, []); // Empty dependency array - this callback never changes
|
|
220
|
+
|
|
221
|
+
useResizeObserver(nodeRef, stableResizeHandler);
|
|
222
|
+
|
|
223
|
+
// Effect to adjust child positions when dimensions change
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
if (isTreeStructure && nodeType === 'root' && nodeDimensions.width > 0) {
|
|
226
|
+
adjustChildPositions();
|
|
227
|
+
}
|
|
228
|
+
}, [nodeDimensions.width, adjustChildPositions, isTreeStructure, nodeType]);
|
|
229
|
+
|
|
230
|
+
// Effect to detect label changes and trigger layout recalculation
|
|
231
|
+
useEffect(() => {
|
|
232
|
+
if (isTreeStructure && nodeType === 'child' && nodeData.label) {
|
|
233
|
+
const lastLabel = lastNodeLabels.current.get(id);
|
|
234
|
+
if (lastLabel !== nodeData.label) {
|
|
235
|
+
lastNodeLabels.current.set(id, nodeData.label as string);
|
|
236
|
+
|
|
237
|
+
// Trigger layout recalculation after a short delay to allow for resize
|
|
238
|
+
setTimeout(() => {
|
|
239
|
+
const allNodes = getNodes();
|
|
240
|
+
const rootNode = allNodes.find(n =>
|
|
241
|
+
n.data.isTreeStructure &&
|
|
242
|
+
n.data.structureId === structureId &&
|
|
243
|
+
n.data.nodeType === 'root'
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
if (rootNode) {
|
|
247
|
+
debouncedLayoutRecalculation();
|
|
248
|
+
}
|
|
249
|
+
}, 100);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}, [nodeData.label, isTreeStructure, nodeType, structureId, id, getNodes, debouncedLayoutRecalculation]);
|
|
253
|
+
|
|
254
|
+
// Effect to trigger initial layout calculation when component mounts
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
if (isTreeStructure && nodeType === 'root') {
|
|
257
|
+
// Small delay to ensure all nodes are loaded
|
|
258
|
+
const timer = setTimeout(() => {
|
|
259
|
+
const allNodes = getNodes();
|
|
260
|
+
const childNodes = allNodes.filter(n =>
|
|
261
|
+
n.data.isTreeStructure &&
|
|
262
|
+
n.data.structureId === structureId &&
|
|
263
|
+
n.data.nodeType === 'child'
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
if (childNodes.length > 0) {
|
|
267
|
+
// Clear caches to force initial layout calculation
|
|
268
|
+
lastCalculatedDimensions.current.clear();
|
|
269
|
+
lastNodeLabels.current.clear();
|
|
270
|
+
adjustChildPositions();
|
|
271
|
+
}
|
|
272
|
+
}, 100);
|
|
273
|
+
|
|
274
|
+
return () => clearTimeout(timer);
|
|
275
|
+
}
|
|
276
|
+
}, [isTreeStructure, nodeType, structureId, getNodes, adjustChildPositions]);
|
|
277
|
+
|
|
278
|
+
// Effect to update existing child nodes with structure type when component mounts
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
if (isTreeStructure && nodeType === 'root' && nodeData.structureType) {
|
|
281
|
+
const timer = setTimeout(() => {
|
|
282
|
+
const allNodes = getNodes();
|
|
283
|
+
const childNodes = allNodes.filter(n =>
|
|
284
|
+
n.data.isTreeStructure &&
|
|
285
|
+
n.data.structureId === structureId &&
|
|
286
|
+
n.data.nodeType === 'child' &&
|
|
287
|
+
!n.data.structureType
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (childNodes.length > 0) {
|
|
291
|
+
const updatedNodes = allNodes.map(node => {
|
|
292
|
+
if (
|
|
293
|
+
node.data.isTreeStructure &&
|
|
294
|
+
node.data.structureId === structureId &&
|
|
295
|
+
node.data.nodeType === 'child' &&
|
|
296
|
+
!node.data.structureType
|
|
297
|
+
) {
|
|
298
|
+
return {
|
|
299
|
+
...node,
|
|
300
|
+
data: {
|
|
301
|
+
...node.data,
|
|
302
|
+
structureType: nodeData.structureType,
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
return node;
|
|
307
|
+
});
|
|
308
|
+
setNodes(updatedNodes);
|
|
309
|
+
}
|
|
310
|
+
}, 200);
|
|
311
|
+
|
|
312
|
+
return () => clearTimeout(timer);
|
|
313
|
+
}
|
|
314
|
+
}, [isTreeStructure, nodeType, structureId, nodeData.structureType, getNodes, setNodes]);
|
|
315
|
+
|
|
316
|
+
// Effect to recalculate positions when child nodes change (add/remove)
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
if (isTreeStructure && nodeType === 'root') {
|
|
319
|
+
const allNodes = getNodes();
|
|
320
|
+
const childNodes = allNodes.filter(n =>
|
|
321
|
+
n.data.isTreeStructure &&
|
|
322
|
+
n.data.structureId === structureId &&
|
|
323
|
+
n.data.nodeType === 'child'
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
// If we have child nodes, ensure they're positioned correctly
|
|
327
|
+
if (childNodes.length > 0) {
|
|
328
|
+
// Clear caches to force initial layout calculation
|
|
329
|
+
lastCalculatedDimensions.current.clear();
|
|
330
|
+
lastNodeLabels.current.clear();
|
|
331
|
+
setTimeout(() => adjustChildPositions(), 0);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}, [getNodes, isTreeStructure, nodeType, structureId, adjustChildPositions]);
|
|
335
|
+
|
|
336
|
+
// Effect to trigger layout recalculation when lastLayoutUpdate changes
|
|
337
|
+
useEffect(() => {
|
|
338
|
+
if (isTreeStructure && nodeType === 'root' && nodeData.lastLayoutUpdate) {
|
|
339
|
+
// Clear caches and recalculate layout
|
|
340
|
+
lastCalculatedDimensions.current.clear();
|
|
341
|
+
lastNodeLabels.current.clear();
|
|
342
|
+
setTimeout(() => adjustChildPositions(), 0);
|
|
343
|
+
}
|
|
344
|
+
}, [nodeData.lastLayoutUpdate, isTreeStructure, nodeType, adjustChildPositions]);
|
|
345
|
+
|
|
346
|
+
// Expose forceLayoutRecalculation and autoCenterRootNode functions through node data
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
if (isTreeStructure) {
|
|
349
|
+
// Update the node data to include the functions
|
|
350
|
+
const allNodes = getNodes();
|
|
351
|
+
const updatedNodes = allNodes.map(n => {
|
|
352
|
+
if (n.id === id) {
|
|
353
|
+
return {
|
|
354
|
+
...n,
|
|
355
|
+
data: {
|
|
356
|
+
...n.data,
|
|
357
|
+
forceLayoutRecalculation,
|
|
358
|
+
autoCenterRootNode: nodeType === 'root' ? autoCenterRootNode : undefined,
|
|
359
|
+
isRootBeingEdited: nodeType === 'root' ? isRootBeingEdited : undefined
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return n;
|
|
364
|
+
});
|
|
365
|
+
setNodes(updatedNodes);
|
|
366
|
+
}
|
|
367
|
+
}, [id, isTreeStructure, nodeType, forceLayoutRecalculation, autoCenterRootNode, isRootBeingEdited, getNodes, setNodes]);
|
|
368
|
+
|
|
369
|
+
// Cleanup effect to clear timeouts
|
|
370
|
+
useEffect(() => {
|
|
371
|
+
return () => {
|
|
372
|
+
if (layoutTimeoutRef.current) {
|
|
373
|
+
clearTimeout(layoutTimeoutRef.current);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}, []);
|
|
377
|
+
|
|
378
|
+
return (
|
|
379
|
+
<div style={{ position: 'relative' }}>
|
|
380
|
+
{/* Main Node */}
|
|
381
|
+
<Paper
|
|
382
|
+
ref={nodeRef}
|
|
383
|
+
elevation={2}
|
|
384
|
+
onMouseEnter={() => setIsHovered(true)}
|
|
385
|
+
onMouseLeave={() => setIsHovered(false)}
|
|
386
|
+
sx={{
|
|
387
|
+
minWidth: 120,
|
|
388
|
+
minHeight: 60,
|
|
389
|
+
width: 'max-content',
|
|
390
|
+
height: 'max-content',
|
|
391
|
+
borderRadius: 2,
|
|
392
|
+
border: `2px solid ${nodeData.color || '#2196F3'}`,
|
|
393
|
+
padding: 2,
|
|
394
|
+
display: 'flex',
|
|
395
|
+
flexDirection: 'column',
|
|
396
|
+
justifyContent: 'center',
|
|
397
|
+
position: 'relative',
|
|
398
|
+
overflow: 'visible',
|
|
399
|
+
boxSizing: 'border-box',
|
|
400
|
+
backgroundColor: 'white',
|
|
401
|
+
cursor: 'move',
|
|
402
|
+
userSelect: 'none',
|
|
403
|
+
}}
|
|
404
|
+
>
|
|
405
|
+
<Handle
|
|
406
|
+
type="target"
|
|
407
|
+
position={Position.Left}
|
|
408
|
+
isConnectable={isConnectable}
|
|
409
|
+
style={{
|
|
410
|
+
left: '-6px',
|
|
411
|
+
backgroundColor: nodeData.color || '#2196F3',
|
|
412
|
+
border: '2px solid #fff',
|
|
413
|
+
width: '12px',
|
|
414
|
+
height: '12px'
|
|
415
|
+
}}
|
|
416
|
+
/>
|
|
417
|
+
|
|
418
|
+
<Box sx={{
|
|
419
|
+
textAlign: "center",
|
|
420
|
+
display: 'flex',
|
|
421
|
+
flexDirection: 'column',
|
|
422
|
+
justifyContent: 'center',
|
|
423
|
+
width: 'max-content',
|
|
424
|
+
minWidth: 'min-content'
|
|
425
|
+
}}>
|
|
426
|
+
<Typography
|
|
427
|
+
variant="subtitle1"
|
|
428
|
+
fontWeight="bold"
|
|
429
|
+
sx={{
|
|
430
|
+
whiteSpace: 'nowrap',
|
|
431
|
+
overflow: 'visible',
|
|
432
|
+
width: 'max-content',
|
|
433
|
+
color: nodeData.color || '#2196F3',
|
|
434
|
+
}}
|
|
435
|
+
>
|
|
436
|
+
{(nodeData.label as string) || 'System'}
|
|
437
|
+
</Typography>
|
|
438
|
+
|
|
439
|
+
{/* Add Child Button - Using custom hook */}
|
|
440
|
+
{AddChildButton}
|
|
441
|
+
</Box>
|
|
442
|
+
|
|
443
|
+
<Handle
|
|
444
|
+
type="source"
|
|
445
|
+
position={Position.Right}
|
|
446
|
+
isConnectable={isConnectable}
|
|
447
|
+
style={{
|
|
448
|
+
right: '-6px',
|
|
449
|
+
backgroundColor: nodeData.color || '#2196F3',
|
|
450
|
+
border: '2px solid #fff',
|
|
451
|
+
width: '12px',
|
|
452
|
+
height: '12px'
|
|
453
|
+
}}
|
|
454
|
+
/>
|
|
455
|
+
</Paper>
|
|
456
|
+
|
|
457
|
+
{/* SVG Connection Lines - Render for all nodes that have children */}
|
|
458
|
+
{isTreeStructure && (() => {
|
|
459
|
+
// Get structure type from current node, or fallback to root node's structure type
|
|
460
|
+
let structureType: 'structure1' | 'structure2' | 'structure3' = nodeData.structureType || 'structure1';
|
|
461
|
+
if (!nodeData.structureType && structureId) {
|
|
462
|
+
const allNodes = getNodes();
|
|
463
|
+
const rootNode = allNodes.find(n =>
|
|
464
|
+
n.data.isTreeStructure &&
|
|
465
|
+
n.data.structureId === structureId &&
|
|
466
|
+
n.data.nodeType === 'root'
|
|
467
|
+
);
|
|
468
|
+
structureType = (rootNode?.data?.structureType as 'structure1' | 'structure2' | 'structure3') || 'structure1';
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Calculate SVG positioning based on node position and width
|
|
472
|
+
// Use current dimensions if root is being edited, otherwise use measured dimensions
|
|
473
|
+
const currentNode = getNodes().find(n => n.id === id);
|
|
474
|
+
if (!currentNode) return null;
|
|
475
|
+
|
|
476
|
+
const actualNodeWidth = isRootBeingEdited ? nodeDimensions.width : (currentNode?.measured?.width || currentNode?.width || nodeDimensions.width);
|
|
477
|
+
const nodeCenterX = actualNodeWidth / 2; // This is the center relative to the node's left edge
|
|
478
|
+
|
|
479
|
+
// Calculate the actual span needed for child nodes
|
|
480
|
+
const allNodes = getNodes();
|
|
481
|
+
const childNodes = allNodes.filter(n =>
|
|
482
|
+
n.data.isTreeStructure &&
|
|
483
|
+
n.data.structureId === structureId &&
|
|
484
|
+
n.data.parentId === id
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
// Only render SVG if this node has children
|
|
488
|
+
if (childNodes.length === 0) return null;
|
|
489
|
+
|
|
490
|
+
// Calculate SVG bounds based on child node positions
|
|
491
|
+
const leftmostChild = Math.min(...childNodes.map(n => {
|
|
492
|
+
const childWidth = n.measured?.width || n.width || 120;
|
|
493
|
+
return n.position.x;
|
|
494
|
+
}));
|
|
495
|
+
const rightmostChild = Math.max(...childNodes.map(n => {
|
|
496
|
+
const childWidth = n.measured?.width || n.width || 120;
|
|
497
|
+
return n.position.x + childWidth;
|
|
498
|
+
}));
|
|
499
|
+
|
|
500
|
+
// Add padding to ensure the SVG covers the extended horizontal line
|
|
501
|
+
const padding = 40;
|
|
502
|
+
const minWidth = 400;
|
|
503
|
+
const svgWidth = Math.max(minWidth, rightmostChild - leftmostChild + padding * 2);
|
|
504
|
+
const svgLeft = leftmostChild - padding - currentNode.position.x; // Relative to current node position
|
|
505
|
+
|
|
506
|
+
// Render different SVG designs based on structure type
|
|
507
|
+
if (structureType === 'structure2') {
|
|
508
|
+
// Structure 2: Arrow from root with space before horizontal line
|
|
509
|
+
return (
|
|
510
|
+
<svg
|
|
511
|
+
style={{
|
|
512
|
+
position: 'absolute',
|
|
513
|
+
top: 0,
|
|
514
|
+
left: `${svgLeft}px`,
|
|
515
|
+
width: `${svgWidth}px`,
|
|
516
|
+
height: '210px',
|
|
517
|
+
pointerEvents: 'none',
|
|
518
|
+
zIndex: 5,
|
|
519
|
+
}}
|
|
520
|
+
viewBox={`${svgLeft} 0 ${svgWidth} 210`}
|
|
521
|
+
>
|
|
522
|
+
{/* Arrow from root node bottom center */}
|
|
523
|
+
<g>
|
|
524
|
+
{/* Arrow shaft */}
|
|
525
|
+
<line
|
|
526
|
+
x1={nodeCenterX}
|
|
527
|
+
y1="60" // Bottom of root node
|
|
528
|
+
x2={nodeCenterX}
|
|
529
|
+
y2="110" // Extended down with space
|
|
530
|
+
stroke="#666"
|
|
531
|
+
strokeWidth="2"
|
|
532
|
+
/>
|
|
533
|
+
{/* Arrow head pointing down */}
|
|
534
|
+
<polygon
|
|
535
|
+
points={`${nodeCenterX},110 ${nodeCenterX - 6},104 ${nodeCenterX + 6},104`}
|
|
536
|
+
fill="#666"
|
|
537
|
+
/>
|
|
538
|
+
</g>
|
|
539
|
+
|
|
540
|
+
{/* Dynamic horizontal line connecting all child nodes with space from arrow */}
|
|
541
|
+
{childNodes.length > 0 && (() => {
|
|
542
|
+
const leftmostChild = Math.min(...childNodes.map(n => {
|
|
543
|
+
const relativePos = n.data.relativePosition as { x: number; y: number };
|
|
544
|
+
const childWidth = n.measured?.width || n.width || 120;
|
|
545
|
+
return relativePos ? nodeCenterX + relativePos.x + (childWidth / 2) : 0;
|
|
546
|
+
}));
|
|
547
|
+
const rightmostChild = Math.max(...childNodes.map(n => {
|
|
548
|
+
const relativePos = n.data.relativePosition as { x: number; y: number };
|
|
549
|
+
const childWidth = n.measured?.width || n.width || 120;
|
|
550
|
+
return relativePos ? nodeCenterX + relativePos.x + (childWidth / 2) : 0;
|
|
551
|
+
}));
|
|
552
|
+
|
|
553
|
+
return (
|
|
554
|
+
<line
|
|
555
|
+
x1={leftmostChild}
|
|
556
|
+
y1="110" // Space below the arrow
|
|
557
|
+
x2={rightmostChild}
|
|
558
|
+
y2="110" // Same y
|
|
559
|
+
stroke="#666"
|
|
560
|
+
strokeWidth="2"
|
|
561
|
+
/>
|
|
562
|
+
);
|
|
563
|
+
})()}
|
|
564
|
+
|
|
565
|
+
{/* Dynamic vertical lines and arrows for each child node */}
|
|
566
|
+
{childNodes.map((childNode, index) => {
|
|
567
|
+
const relativePos = childNode.data.relativePosition as { x: number; y: number };
|
|
568
|
+
if (!relativePos) return null;
|
|
569
|
+
|
|
570
|
+
const childWidth = childNode.measured?.width || childNode.width || 120;
|
|
571
|
+
const childX = nodeCenterX + relativePos.x + (childWidth / 2);
|
|
572
|
+
|
|
573
|
+
return (
|
|
574
|
+
<g key={childNode.id}>
|
|
575
|
+
{/* Vertical line down to child node - connect directly to node */}
|
|
576
|
+
<line
|
|
577
|
+
x1={childX}
|
|
578
|
+
y1="110" // From horizontal line
|
|
579
|
+
x2={childX}
|
|
580
|
+
y2="145" // Connect directly to child node top
|
|
581
|
+
stroke="#666"
|
|
582
|
+
strokeWidth="2"
|
|
583
|
+
/>
|
|
584
|
+
|
|
585
|
+
{/* Arrow head pointing down to child node - positioned at node top */}
|
|
586
|
+
<polygon
|
|
587
|
+
points={`${childX},150 ${childX - 6},144 ${childX + 6},144`}
|
|
588
|
+
fill="#666"
|
|
589
|
+
/>
|
|
590
|
+
</g>
|
|
591
|
+
);
|
|
592
|
+
})}
|
|
593
|
+
</svg>
|
|
594
|
+
);
|
|
595
|
+
} else if (structureType === 'structure3') {
|
|
596
|
+
// Structure 3: Normal root line with circle center point for child connections
|
|
597
|
+
return (
|
|
598
|
+
<svg
|
|
599
|
+
style={{
|
|
600
|
+
position: 'absolute',
|
|
601
|
+
top: 0,
|
|
602
|
+
left: `${svgLeft}px`,
|
|
603
|
+
width: `${svgWidth}px`,
|
|
604
|
+
height: '210px',
|
|
605
|
+
pointerEvents: 'none',
|
|
606
|
+
zIndex: 5,
|
|
607
|
+
}}
|
|
608
|
+
viewBox={`${svgLeft} 0 ${svgWidth} 210`}
|
|
609
|
+
>
|
|
610
|
+
{/* Vertical line from root node bottom center */}
|
|
611
|
+
<line
|
|
612
|
+
x1={nodeCenterX}
|
|
613
|
+
y1="60" // Bottom of root node
|
|
614
|
+
x2={nodeCenterX}
|
|
615
|
+
y2="90" // Fixed distance down
|
|
616
|
+
stroke="#666"
|
|
617
|
+
strokeWidth="2"
|
|
618
|
+
/>
|
|
619
|
+
|
|
620
|
+
{/* Circle center point for child connections */}
|
|
621
|
+
{childNodes.length > 0 && (
|
|
622
|
+
<circle
|
|
623
|
+
cx={nodeCenterX}
|
|
624
|
+
cy="90"
|
|
625
|
+
r="8"
|
|
626
|
+
fill="white"
|
|
627
|
+
stroke="white"
|
|
628
|
+
strokeWidth="2"
|
|
629
|
+
/>
|
|
630
|
+
)}
|
|
631
|
+
|
|
632
|
+
{/* Dynamic lines from circle to each child node */}
|
|
633
|
+
{childNodes.map((childNode, index) => {
|
|
634
|
+
const relativePos = childNode.data.relativePosition as { x: number; y: number };
|
|
635
|
+
if (!relativePos) return null;
|
|
636
|
+
|
|
637
|
+
const childWidth = childNode.measured?.width || childNode.width || 120;
|
|
638
|
+
const childX = nodeCenterX + relativePos.x + (childWidth / 2);
|
|
639
|
+
const childY = 160; // Child nodes start at y=160
|
|
640
|
+
|
|
641
|
+
// Calculate angle from circle center to child node
|
|
642
|
+
const deltaX = childX - nodeCenterX;
|
|
643
|
+
const deltaY = childY - 90;
|
|
644
|
+
const angle = Math.atan2(deltaY, deltaX);
|
|
645
|
+
|
|
646
|
+
// Calculate circle edge point
|
|
647
|
+
const circleRadius = 8;
|
|
648
|
+
const circleEdgeX = nodeCenterX + circleRadius * Math.cos(angle);
|
|
649
|
+
const circleEdgeY = 90 + circleRadius * Math.sin(angle);
|
|
650
|
+
|
|
651
|
+
return (
|
|
652
|
+
<g key={childNode.id}>
|
|
653
|
+
{/* Line from circle edge to child node */}
|
|
654
|
+
<line
|
|
655
|
+
x1={circleEdgeX}
|
|
656
|
+
y1={circleEdgeY}
|
|
657
|
+
x2={childX}
|
|
658
|
+
y2="145" // Connect directly to child node top
|
|
659
|
+
stroke="#666"
|
|
660
|
+
strokeWidth="2"
|
|
661
|
+
/>
|
|
662
|
+
|
|
663
|
+
{/* Arrow head pointing down to child node */}
|
|
664
|
+
<polygon
|
|
665
|
+
points={`${childX},150 ${childX - 6},144 ${childX + 6},144`}
|
|
666
|
+
fill="#666"
|
|
667
|
+
/>
|
|
668
|
+
</g>
|
|
669
|
+
);
|
|
670
|
+
})}
|
|
671
|
+
</svg>
|
|
672
|
+
);
|
|
673
|
+
} else {
|
|
674
|
+
// Structure 1: Original design with connected lines
|
|
675
|
+
return (
|
|
676
|
+
<svg
|
|
677
|
+
style={{
|
|
678
|
+
position: 'absolute',
|
|
679
|
+
top: 0,
|
|
680
|
+
left: `${svgLeft}px`,
|
|
681
|
+
width: `${svgWidth}px`,
|
|
682
|
+
height: '210px',
|
|
683
|
+
pointerEvents: 'none',
|
|
684
|
+
zIndex: 5,
|
|
685
|
+
}}
|
|
686
|
+
viewBox={`0 0 ${svgWidth} 210`}
|
|
687
|
+
>
|
|
688
|
+
{/* Vertical line from current node bottom center */}
|
|
689
|
+
<line
|
|
690
|
+
x1={nodeCenterX - svgLeft}
|
|
691
|
+
y1="60" // Bottom of current node
|
|
692
|
+
x2={nodeCenterX - svgLeft}
|
|
693
|
+
y2="90" // Fixed distance down
|
|
694
|
+
stroke="#666"
|
|
695
|
+
strokeWidth="2"
|
|
696
|
+
/>
|
|
697
|
+
|
|
698
|
+
{/* Dynamic horizontal line connecting all child nodes */}
|
|
699
|
+
{childNodes.length > 0 && (() => {
|
|
700
|
+
const leftmostChild = Math.min(...childNodes.map(n => {
|
|
701
|
+
const childWidth = n.measured?.width || n.width || 120;
|
|
702
|
+
return n.position.x + (childWidth / 2) - currentNode.position.x;
|
|
703
|
+
}));
|
|
704
|
+
const rightmostChild = Math.max(...childNodes.map(n => {
|
|
705
|
+
const childWidth = n.measured?.width || n.width || 120;
|
|
706
|
+
return n.position.x + (childWidth / 2) - currentNode.position.x;
|
|
707
|
+
}));
|
|
708
|
+
|
|
709
|
+
return (
|
|
710
|
+
<line
|
|
711
|
+
x1={leftmostChild - svgLeft}
|
|
712
|
+
y1="90" // Same y as vertical line end
|
|
713
|
+
x2={rightmostChild - svgLeft}
|
|
714
|
+
y2="90" // Same y
|
|
715
|
+
stroke="#666"
|
|
716
|
+
strokeWidth="2"
|
|
717
|
+
/>
|
|
718
|
+
);
|
|
719
|
+
})()}
|
|
720
|
+
|
|
721
|
+
{/* Dynamic vertical lines and arrows for each child node */}
|
|
722
|
+
{childNodes.map((childNode, index) => {
|
|
723
|
+
const childWidth = childNode.measured?.width || childNode.width || 120;
|
|
724
|
+
const childX = childNode.position.x + (childWidth / 2) - currentNode.position.x;
|
|
725
|
+
|
|
726
|
+
return (
|
|
727
|
+
<g key={childNode.id}>
|
|
728
|
+
{/* Vertical line down to child node - connect directly to node */}
|
|
729
|
+
<line
|
|
730
|
+
x1={childX - svgLeft}
|
|
731
|
+
y1="90" // From horizontal line
|
|
732
|
+
x2={childX - svgLeft}
|
|
733
|
+
y2="145" // Connect directly to child node top
|
|
734
|
+
stroke="#666"
|
|
735
|
+
strokeWidth="2"
|
|
736
|
+
/>
|
|
737
|
+
|
|
738
|
+
{/* Arrow head pointing down to child node - positioned at node top */}
|
|
739
|
+
<polygon
|
|
740
|
+
points={`${childX - svgLeft},150 ${childX - svgLeft - 6},144 ${childX - svgLeft + 6},144`}
|
|
741
|
+
fill="#666"
|
|
742
|
+
/>
|
|
743
|
+
</g>
|
|
744
|
+
);
|
|
745
|
+
})}
|
|
746
|
+
</svg>
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
})()}
|
|
750
|
+
</div>
|
|
751
|
+
)
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
export default memo(TreeSystemNode)
|
|
755
|
+
|