You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. 'use client'
  2. import {
  3. useCallback,
  4. useState,
  5. } from 'react'
  6. import ReactFlow, {
  7. Background,
  8. MiniMap,
  9. ReactFlowProvider,
  10. SelectionMode,
  11. applyEdgeChanges,
  12. applyNodeChanges,
  13. } from 'reactflow'
  14. import type {
  15. EdgeChange,
  16. NodeChange,
  17. Viewport,
  18. } from 'reactflow'
  19. import 'reactflow/dist/style.css'
  20. import '../style.css'
  21. import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants'
  22. import { CUSTOM_LOOP_START_NODE } from '@/app/components/workflow/nodes/loop-start/constants'
  23. import { CUSTOM_SIMPLE_NODE } from '@/app/components/workflow/simple-node/constants'
  24. import CustomConnectionLine from '@/app/components/workflow/custom-connection-line'
  25. import {
  26. CUSTOM_EDGE,
  27. CUSTOM_NODE,
  28. ITERATION_CHILDREN_Z_INDEX,
  29. } from '@/app/components/workflow/constants'
  30. import cn from '@/utils/classnames'
  31. import {
  32. initialEdges,
  33. initialNodes,
  34. } from '@/app/components/workflow/utils/workflow-init'
  35. import type {
  36. Edge,
  37. Node,
  38. } from '@/app/components/workflow/types'
  39. import { CUSTOM_NOTE_NODE } from '@/app/components/workflow/note-node/constants'
  40. import CustomNode from './components/nodes'
  41. import CustomEdge from './components/custom-edge'
  42. import ZoomInOut from './components/zoom-in-out'
  43. import IterationStartNode from './components/nodes/iteration-start'
  44. import LoopStartNode from './components/nodes/loop-start'
  45. import CustomNoteNode from './components/note-node'
  46. const nodeTypes = {
  47. [CUSTOM_NODE]: CustomNode,
  48. [CUSTOM_NOTE_NODE]: CustomNoteNode,
  49. [CUSTOM_SIMPLE_NODE]: CustomNode,
  50. [CUSTOM_ITERATION_START_NODE]: IterationStartNode,
  51. [CUSTOM_LOOP_START_NODE]: LoopStartNode,
  52. }
  53. const edgeTypes = {
  54. [CUSTOM_EDGE]: CustomEdge,
  55. }
  56. type WorkflowPreviewProps = {
  57. nodes: Node[]
  58. edges: Edge[]
  59. viewport: Viewport
  60. className?: string
  61. }
  62. const WorkflowPreview = ({
  63. nodes,
  64. edges,
  65. viewport,
  66. className,
  67. }: WorkflowPreviewProps) => {
  68. const [nodesData, setNodesData] = useState(initialNodes(nodes, edges))
  69. const [edgesData, setEdgesData] = useState(initialEdges(edges, nodes))
  70. const onNodesChange = useCallback(
  71. (changes: NodeChange[]) => setNodesData(nds => applyNodeChanges(changes, nds)),
  72. [],
  73. )
  74. const onEdgesChange = useCallback(
  75. (changes: EdgeChange[]) => setEdgesData(eds => applyEdgeChanges(changes, eds)),
  76. [],
  77. )
  78. return (
  79. <div
  80. id='workflow-container'
  81. className={cn(
  82. 'relative h-full w-full',
  83. className,
  84. )}
  85. >
  86. <>
  87. <MiniMap
  88. pannable
  89. zoomable
  90. style={{
  91. width: 102,
  92. height: 72,
  93. }}
  94. maskColor='var(--color-workflow-minimap-bg)'
  95. className='!absolute !bottom-14 !left-4 z-[9] !m-0 !h-[72px] !w-[102px] !rounded-lg !border-[0.5px]
  96. !border-divider-subtle !bg-background-default-subtle !shadow-md !shadow-shadow-shadow-5'
  97. />
  98. <div className='absolute bottom-4 left-4 z-[9] mt-1 flex items-center gap-2'>
  99. <ZoomInOut />
  100. </div>
  101. </>
  102. <ReactFlow
  103. nodeTypes={nodeTypes}
  104. edgeTypes={edgeTypes}
  105. nodes={nodesData}
  106. onNodesChange={onNodesChange}
  107. edges={edgesData}
  108. onEdgesChange={onEdgesChange}
  109. connectionLineComponent={CustomConnectionLine}
  110. connectionLineContainerStyle={{ zIndex: ITERATION_CHILDREN_Z_INDEX }}
  111. defaultViewport={viewport}
  112. multiSelectionKeyCode={null}
  113. deleteKeyCode={null}
  114. nodesDraggable
  115. nodesConnectable={false}
  116. nodesFocusable={false}
  117. edgesFocusable={false}
  118. panOnScroll={false}
  119. selectionKeyCode={null}
  120. selectionMode={SelectionMode.Partial}
  121. minZoom={0.25}
  122. >
  123. <Background
  124. gap={[14, 14]}
  125. size={2}
  126. className='bg-workflow-canvas-workflow-bg'
  127. color='var(--color-workflow-canvas-workflow-dot-color)'
  128. />
  129. </ReactFlow>
  130. </div>
  131. )
  132. }
  133. const WorkflowPreviewWrapper = (props: WorkflowPreviewProps) => {
  134. return (
  135. <ReactFlowProvider>
  136. <WorkflowPreview {...props} />
  137. </ReactFlowProvider>
  138. )
  139. }
  140. export default WorkflowPreviewWrapper