@motiadev/workbench 0.0.6 → 0.0.8

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.
Files changed (192) hide show
  1. package/dist/README.md +50 -0
  2. package/dist/index.d.ts +0 -1
  3. package/{index.html → dist/index.html} +1 -1
  4. package/dist/middleware.d.ts +2 -2
  5. package/dist/middleware.js +10 -12
  6. package/dist/package.json +58 -0
  7. package/dist/src/components/app-sidebar.d.ts +0 -1
  8. package/dist/src/components/app-sidebar.js +5 -6
  9. package/dist/src/components/log-console.d.ts +0 -1
  10. package/dist/src/components/log-level-badge.d.ts +0 -1
  11. package/dist/src/components/ui/badge.d.ts +1 -2
  12. package/dist/src/components/ui/button.d.ts +1 -2
  13. package/dist/src/components/ui/collapsible.d.ts +0 -1
  14. package/dist/src/components/ui/dialog.d.ts +0 -1
  15. package/dist/src/components/ui/input.d.ts +0 -1
  16. package/dist/src/components/ui/label.d.ts +0 -1
  17. package/dist/src/components/ui/select.d.ts +0 -1
  18. package/dist/src/components/ui/separator.d.ts +0 -1
  19. package/dist/src/components/ui/sheet.d.ts +1 -2
  20. package/dist/src/components/ui/sidebar.d.ts +0 -1
  21. package/dist/src/components/ui/skeleton.d.ts +0 -1
  22. package/dist/src/components/ui/switch.d.ts +0 -1
  23. package/dist/src/components/ui/table.d.ts +0 -1
  24. package/dist/src/components/ui/textarea.d.ts +0 -1
  25. package/dist/src/components/ui/tooltip.d.ts +0 -1
  26. package/dist/src/hooks/use-list-flows.d.ts +0 -1
  27. package/dist/src/hooks/use-log-listener.d.ts +0 -1
  28. package/dist/src/hooks/use-mobile.d.ts +0 -1
  29. package/dist/src/lib/utils.d.ts +0 -1
  30. package/dist/src/main.d.ts +0 -8
  31. package/dist/src/main.js +6 -7
  32. package/dist/src/publicComponents/api-node.d.ts +0 -1
  33. package/dist/src/publicComponents/base-handle.d.ts +0 -1
  34. package/dist/src/publicComponents/base-node.d.ts +0 -1
  35. package/dist/src/publicComponents/emits.d.ts +0 -1
  36. package/dist/src/publicComponents/event-node.d.ts +0 -1
  37. package/dist/src/publicComponents/node-props.d.ts +0 -1
  38. package/dist/src/publicComponents/noop-node.d.ts +0 -1
  39. package/dist/src/publicComponents/subscribe.d.ts +0 -1
  40. package/dist/src/route-wrapper.d.ts +0 -1
  41. package/dist/src/routes/flow.d.ts +1 -0
  42. package/dist/src/routes/flow.js +16 -0
  43. package/dist/src/routes/index.d.ts +1 -2
  44. package/dist/src/routes/index.js +2 -6
  45. package/dist/src/stores/use-logs.d.ts +0 -1
  46. package/dist/src/views/flow/arrow-head.d.ts +0 -1
  47. package/dist/src/views/flow/base-edge.d.ts +0 -1
  48. package/dist/src/views/flow/flow-loader.d.ts +0 -1
  49. package/dist/src/views/flow/flow-view.d.ts +0 -1
  50. package/dist/src/views/flow/hooks/use-get-flow-state.d.ts +0 -1
  51. package/dist/src/views/flow/hooks/use-organize-nodes.d.ts +0 -1
  52. package/dist/src/views/flow/legend.d.ts +0 -1
  53. package/dist/src/views/flow/node-organizer.d.ts +0 -1
  54. package/dist/src/views/flow/nodes/api-flow-node.d.ts +0 -1
  55. package/dist/src/views/flow/nodes/event-flow-node.d.ts +0 -1
  56. package/dist/src/views/flow/nodes/json-schema-form.d.ts +0 -1
  57. package/dist/src/views/flow/nodes/language-indicator.d.ts +0 -1
  58. package/dist/src/views/flow/nodes/nodes.types.d.ts +0 -1
  59. package/dist/src/views/flow/nodes/noop-flow-node.d.ts +0 -1
  60. package/dist/tailwind.config.d.ts +0 -1
  61. package/dist/tsconfig.app.tsbuildinfo +1 -1
  62. package/dist/tsconfig.node.tsbuildinfo +1 -1
  63. package/dist/vite.config.d.ts +1 -10
  64. package/dist/vite.config.js +4 -5
  65. package/package.json +3 -3
  66. package/dist/index.d.ts.map +0 -1
  67. package/dist/middleware.d.ts.map +0 -1
  68. package/dist/src/components/app-sidebar.d.ts.map +0 -1
  69. package/dist/src/components/log-console.d.ts.map +0 -1
  70. package/dist/src/components/log-level-badge.d.ts.map +0 -1
  71. package/dist/src/components/ui/badge.d.ts.map +0 -1
  72. package/dist/src/components/ui/button.d.ts.map +0 -1
  73. package/dist/src/components/ui/collapsible.d.ts.map +0 -1
  74. package/dist/src/components/ui/dialog.d.ts.map +0 -1
  75. package/dist/src/components/ui/input.d.ts.map +0 -1
  76. package/dist/src/components/ui/label.d.ts.map +0 -1
  77. package/dist/src/components/ui/select.d.ts.map +0 -1
  78. package/dist/src/components/ui/separator.d.ts.map +0 -1
  79. package/dist/src/components/ui/sheet.d.ts.map +0 -1
  80. package/dist/src/components/ui/sidebar.d.ts.map +0 -1
  81. package/dist/src/components/ui/skeleton.d.ts.map +0 -1
  82. package/dist/src/components/ui/switch.d.ts.map +0 -1
  83. package/dist/src/components/ui/table.d.ts.map +0 -1
  84. package/dist/src/components/ui/textarea.d.ts.map +0 -1
  85. package/dist/src/components/ui/tooltip.d.ts.map +0 -1
  86. package/dist/src/hooks/use-list-flows.d.ts.map +0 -1
  87. package/dist/src/hooks/use-log-listener.d.ts.map +0 -1
  88. package/dist/src/hooks/use-mobile.d.ts.map +0 -1
  89. package/dist/src/lib/utils.d.ts.map +0 -1
  90. package/dist/src/main.d.ts.map +0 -1
  91. package/dist/src/publicComponents/api-node.d.ts.map +0 -1
  92. package/dist/src/publicComponents/base-handle.d.ts.map +0 -1
  93. package/dist/src/publicComponents/base-node.d.ts.map +0 -1
  94. package/dist/src/publicComponents/emits.d.ts.map +0 -1
  95. package/dist/src/publicComponents/event-node.d.ts.map +0 -1
  96. package/dist/src/publicComponents/node-props.d.ts.map +0 -1
  97. package/dist/src/publicComponents/noop-node.d.ts.map +0 -1
  98. package/dist/src/publicComponents/subscribe.d.ts.map +0 -1
  99. package/dist/src/route-wrapper.d.ts.map +0 -1
  100. package/dist/src/routeTree.gen.d.ts +0 -53
  101. package/dist/src/routeTree.gen.d.ts.map +0 -1
  102. package/dist/src/routeTree.gen.js +0 -45
  103. package/dist/src/routes/__root.d.ts +0 -2
  104. package/dist/src/routes/__root.d.ts.map +0 -1
  105. package/dist/src/routes/__root.js +0 -15
  106. package/dist/src/routes/flow/$id.d.ts +0 -4
  107. package/dist/src/routes/flow/$id.d.ts.map +0 -1
  108. package/dist/src/routes/flow/$id.js +0 -15
  109. package/dist/src/routes/index.d.ts.map +0 -1
  110. package/dist/src/stores/use-logs.d.ts.map +0 -1
  111. package/dist/src/views/flow/arrow-head.d.ts.map +0 -1
  112. package/dist/src/views/flow/base-edge.d.ts.map +0 -1
  113. package/dist/src/views/flow/flow-loader.d.ts.map +0 -1
  114. package/dist/src/views/flow/flow-view.d.ts.map +0 -1
  115. package/dist/src/views/flow/hooks/use-get-flow-state.d.ts.map +0 -1
  116. package/dist/src/views/flow/hooks/use-organize-nodes.d.ts.map +0 -1
  117. package/dist/src/views/flow/legend.d.ts.map +0 -1
  118. package/dist/src/views/flow/node-organizer.d.ts.map +0 -1
  119. package/dist/src/views/flow/nodes/api-flow-node.d.ts.map +0 -1
  120. package/dist/src/views/flow/nodes/event-flow-node.d.ts.map +0 -1
  121. package/dist/src/views/flow/nodes/json-schema-form.d.ts.map +0 -1
  122. package/dist/src/views/flow/nodes/language-indicator.d.ts.map +0 -1
  123. package/dist/src/views/flow/nodes/nodes.types.d.ts.map +0 -1
  124. package/dist/src/views/flow/nodes/noop-flow-node.d.ts.map +0 -1
  125. package/dist/tailwind.config.d.ts.map +0 -1
  126. package/dist/vite.config.d.ts.map +0 -1
  127. package/eslint.config.js +0 -28
  128. package/index.tsx +0 -10
  129. package/middleware.ts +0 -48
  130. package/src/assets/.empty +0 -0
  131. package/src/components/app-sidebar.tsx +0 -55
  132. package/src/components/log-console.tsx +0 -76
  133. package/src/components/log-level-badge.tsx +0 -12
  134. package/src/components/ui/badge.tsx +0 -31
  135. package/src/components/ui/button.tsx +0 -47
  136. package/src/components/ui/collapsible.tsx +0 -9
  137. package/src/components/ui/dialog.tsx +0 -120
  138. package/src/components/ui/input.tsx +0 -21
  139. package/src/components/ui/label.tsx +0 -26
  140. package/src/components/ui/select.tsx +0 -157
  141. package/src/components/ui/separator.tsx +0 -22
  142. package/src/components/ui/sheet.tsx +0 -106
  143. package/src/components/ui/sidebar.tsx +0 -637
  144. package/src/components/ui/skeleton.tsx +0 -7
  145. package/src/components/ui/switch.tsx +0 -27
  146. package/src/components/ui/table.tsx +0 -76
  147. package/src/components/ui/textarea.tsx +0 -22
  148. package/src/components/ui/tooltip.tsx +0 -32
  149. package/src/hooks/use-list-flows.tsx +0 -20
  150. package/src/hooks/use-log-listener.tsx +0 -32
  151. package/src/hooks/use-mobile.tsx +0 -19
  152. package/src/lib/utils.ts +0 -6
  153. package/src/main.tsx +0 -28
  154. package/src/publicComponents/api-node.tsx +0 -28
  155. package/src/publicComponents/base-handle.tsx +0 -43
  156. package/src/publicComponents/base-node.tsx +0 -57
  157. package/src/publicComponents/emits.tsx +0 -22
  158. package/src/publicComponents/event-node.tsx +0 -36
  159. package/src/publicComponents/node-props.tsx +0 -15
  160. package/src/publicComponents/noop-node.tsx +0 -21
  161. package/src/publicComponents/subscribe.tsx +0 -19
  162. package/src/route-wrapper.tsx +0 -9
  163. package/src/routeTree.gen.ts +0 -109
  164. package/src/routes/__root.tsx +0 -26
  165. package/src/routes/flow/$id.tsx +0 -21
  166. package/src/routes/index.tsx +0 -13
  167. package/src/stores/use-logs.ts +0 -22
  168. package/src/views/flow/arrow-head.tsx +0 -13
  169. package/src/views/flow/base-edge.tsx +0 -31
  170. package/src/views/flow/flow-loader.tsx +0 -3
  171. package/src/views/flow/flow-view.tsx +0 -72
  172. package/src/views/flow/hooks/use-get-flow-state.tsx +0 -93
  173. package/src/views/flow/hooks/use-organize-nodes.ts +0 -60
  174. package/src/views/flow/legend.tsx +0 -96
  175. package/src/views/flow/node-organizer.tsx +0 -70
  176. package/src/views/flow/nodes/api-flow-node.tsx +0 -6
  177. package/src/views/flow/nodes/event-flow-node.tsx +0 -6
  178. package/src/views/flow/nodes/json-schema-form.tsx +0 -110
  179. package/src/views/flow/nodes/language-indicator.tsx +0 -74
  180. package/src/views/flow/nodes/nodes.types.ts +0 -36
  181. package/src/views/flow/nodes/noop-flow-node.tsx +0 -6
  182. package/src/vite-env.d.ts +0 -1
  183. package/tailwind.config.ts +0 -75
  184. package/tsconfig.app.json +0 -32
  185. package/tsconfig.json +0 -14
  186. package/tsconfig.node.json +0 -32
  187. package/tsconfig.node.tsbuildinfo +0 -1
  188. package/vite.config.ts +0 -14
  189. /package/{components.json → dist/components.json} +0 -0
  190. /package/{postcss.config.js → dist/postcss.config.js} +0 -0
  191. /package/{public → dist/public}/.empty +0 -0
  192. /package/{src → dist/src}/index.css +0 -0
@@ -1,22 +0,0 @@
1
- import { create } from 'zustand'
2
-
3
- export type Log = {
4
- level: string
5
- time: number
6
- msg: string
7
- traceId: string
8
- flows: string[]
9
- [key: string]: any
10
- }
11
-
12
- export type LogsState = {
13
- logs: Log[]
14
- addLog: (log: Log) => void
15
- resetLogs: () => void
16
- }
17
-
18
- export const useLogs = create<LogsState>()((set) => ({
19
- logs: [],
20
- addLog: (log) => set((state) => ({ ...state, logs: [...state.logs, log] })),
21
- resetLogs: () => set({ logs: [] }),
22
- }))
@@ -1,13 +0,0 @@
1
- import React from 'react'
2
-
3
- type Props = {
4
- color: string
5
- id: string
6
- }
7
-
8
- export const ArrowHead: React.FC<Props> = (props) => (
9
- <marker id={props.id} viewBox="-5 -5 10 10" markerUnits="strokeWidth" markerWidth="10" markerHeight="10">
10
- <line x1={0} y1={0} x2={2} y2={-2} stroke={props.color} strokeWidth="1" strokeOpacity="1" strokeLinecap="round" />
11
- <line x1={-2} y1={-2} x2={0} y2={0} stroke={props.color} strokeWidth="1" strokeOpacity="1" strokeLinecap="round" />
12
- </marker>
13
- )
@@ -1,31 +0,0 @@
1
- import { BaseEdge as BaseReactFlowEdge, EdgeProps, getSmoothStepPath } from '@xyflow/react'
2
- import React from 'react'
3
-
4
- export const BaseEdge: React.FC<EdgeProps> = (props) => {
5
- const { sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data } = props
6
-
7
- const [edgePath] = getSmoothStepPath({
8
- sourceX,
9
- sourceY,
10
- targetX,
11
- targetY,
12
- sourcePosition,
13
- targetPosition,
14
- borderRadius: 20,
15
- offset: 10,
16
- })
17
-
18
- return (
19
- <BaseReactFlowEdge
20
- path={edgePath}
21
- style={{
22
- stroke: data?.variant === 'virtual' ? 'rgb(147, 169, 197)' : 'rgb(133, 176, 132)',
23
- strokeWidth: 0.5,
24
- shapeRendering: 'geometricPrecision',
25
- fill: 'none',
26
- mixBlendMode: 'screen',
27
- }}
28
- className="edge-animated"
29
- />
30
- )
31
- }
@@ -1,3 +0,0 @@
1
- export const FlowLoader = () => {
2
- return <div className="absolute z-10 inset-0 w-full h-full bg-[#060911]" />
3
- }
@@ -1,72 +0,0 @@
1
- import { Background, BackgroundVariant, ReactFlow } from '@xyflow/react'
2
- import '@xyflow/react/dist/style.css'
3
- import { BaseEdge } from './base-edge'
4
- import { ArrowHead } from './arrow-head'
5
- import { useGetFlowState, FlowResponse } from './hooks/use-get-flow-state'
6
- import { useCallback, useEffect, useState } from 'react'
7
- import { NodeOrganizer } from './node-organizer'
8
- import { FlowLoader } from './flow-loader'
9
- import { useLogListener } from '@/hooks/use-log-listener'
10
- import { LogConsole } from '@/components/log-console'
11
- import { Legend } from './legend'
12
-
13
- const edgeTypes = {
14
- base: BaseEdge,
15
- }
16
-
17
- type Props = {
18
- flow: FlowResponse
19
- }
20
-
21
- export const FlowView: React.FC<Props> = ({ flow }) => {
22
- const { nodes, edges, onNodesChange, onEdgesChange, nodeTypes } = useGetFlowState(flow)
23
- const [initialized, setInitialized] = useState(false)
24
- const [hoveredType, setHoveredType] = useState<string | null>(null)
25
-
26
- useLogListener()
27
-
28
- useEffect(() => setInitialized(false), [flow])
29
- const onInitialized = useCallback(() => {
30
- setTimeout(() => setInitialized(true), 10)
31
- }, [])
32
-
33
- const highlightClass = (nodeType?: string) => {
34
- if (!hoveredType) return ''
35
- return nodeType === hoveredType
36
- ? 'shadow-[0_0_15px_rgba(255,255,255,0.15)] border border-white/30 scale-[1.02] transition-all duration-300'
37
- : 'opacity-30 transition-all duration-300'
38
- }
39
-
40
- const nodesWithHighlights = nodes.map((node) => ({
41
- ...node,
42
- className: highlightClass(node.data.type), // Access type from `data.type`
43
- }))
44
-
45
- if (!nodeTypes) {
46
- return null
47
- }
48
-
49
- return (
50
- <div className="w-full h-full relative bg-black">
51
- {!initialized && <FlowLoader />}
52
- <Legend onHover={setHoveredType} />
53
- <ReactFlow
54
- nodes={nodesWithHighlights}
55
- edges={edges}
56
- nodeTypes={nodeTypes}
57
- edgeTypes={edgeTypes}
58
- onNodesChange={onNodesChange}
59
- onEdgesChange={onEdgesChange}
60
- >
61
- <Background variant={BackgroundVariant.Dots} gap={20} size={1} color="#444" />
62
- <NodeOrganizer onInitialized={onInitialized} />
63
- <svg>
64
- <defs>
65
- <ArrowHead color="#B3B3B3" id="arrowhead" />
66
- </defs>
67
- </svg>
68
- </ReactFlow>
69
- <LogConsole />
70
- </div>
71
- )
72
- }
@@ -1,93 +0,0 @@
1
- import { Edge, Node, useEdgesState, useNodesState } from '@xyflow/react'
2
- import { useEffect, useState } from 'react'
3
- import type { EdgeData, NodeData } from '../nodes/nodes.types'
4
- import { ApiFlowNode } from '../nodes/api-flow-node'
5
- import { NoopFlowNode } from '../nodes/noop-flow-node'
6
- import { EventFlowNode } from '../nodes/event-flow-node'
7
-
8
- type Emit = string | { type: string; label?: string }
9
-
10
- type FlowStep = {
11
- id: string
12
- name: string
13
- type: 'event' | 'api' | 'noop'
14
- description?: string
15
- subscribes?: string[]
16
- emits: Emit[]
17
- virtualEmits?: Emit[]
18
- action?: 'webhook'
19
- webhookUrl?: string
20
- language?: string
21
- nodeComponentPath?: string
22
- }
23
-
24
- export type FlowResponse = {
25
- id: string
26
- name: string
27
- steps: FlowStep[]
28
- edges: FlowEdge[]
29
- }
30
-
31
- type FlowEdge = {
32
- id: string
33
- source: string
34
- target: string
35
- data: EdgeData
36
- }
37
-
38
- type FlowState = {
39
- nodes: Node<NodeData>[]
40
- edges: Edge<EdgeData>[]
41
- nodeTypes: Record<string, React.ComponentType<any>>
42
- }
43
-
44
- async function importFlow(flow: FlowResponse): Promise<FlowState> {
45
- const nodeTypes: Record<string, React.ComponentType<any>> = {
46
- event: EventFlowNode,
47
- api: ApiFlowNode,
48
- noop: NoopFlowNode,
49
- }
50
-
51
- // Load custom node components if they exist
52
- for (const step of flow.steps) {
53
- if (step.nodeComponentPath) {
54
- const module = await import(/* @vite-ignore */ step.nodeComponentPath)
55
- nodeTypes[step.nodeComponentPath] = module.default
56
- }
57
- }
58
-
59
- // Create nodes from steps
60
- const nodes: Node<NodeData>[] = flow.steps.map((step) => ({
61
- id: step.id,
62
- type: step.nodeComponentPath ? step.nodeComponentPath : step.type,
63
- position: { x: 0, y: 0 },
64
- data: step,
65
- language: step.language,
66
- }))
67
-
68
- // Use the edges provided by the API, adding required ReactFlow properties
69
- const edges: Edge<EdgeData>[] = flow.edges.map((edge) => ({
70
- ...edge,
71
- type: 'base',
72
- }))
73
-
74
- return { nodes, edges, nodeTypes }
75
- }
76
-
77
- export const useGetFlowState = (flow: FlowResponse) => {
78
- const [nodeTypes, setNodeTypes] = useState<Record<string, React.ComponentType<any>>>()
79
- const [nodes, setNodes, onNodesChange] = useNodesState<Node<NodeData>>([])
80
- const [edges, setEdges, onEdgesChange] = useEdgesState<Edge<EdgeData>>([])
81
-
82
- useEffect(() => {
83
- if (!flow) return
84
-
85
- importFlow(flow).then(({ nodes, edges, nodeTypes }) => {
86
- setNodes(nodes)
87
- setEdges(edges)
88
- setNodeTypes(nodeTypes)
89
- })
90
- }, [flow])
91
-
92
- return { nodes, edges, onNodesChange, onEdgesChange, nodeTypes }
93
- }
@@ -1,60 +0,0 @@
1
- import { Edge, Node } from '@xyflow/react'
2
- import dagre from 'dagre'
3
- import { useEffect, useRef } from 'react'
4
- import { EventNodeData, EdgeData, ApiNodeData } from '../nodes/nodes.types'
5
-
6
- const organizeNodes = (
7
- nodes: Node<EventNodeData | ApiNodeData>[],
8
- edges: Edge<EdgeData>[],
9
- ): Node<EventNodeData | ApiNodeData>[] => {
10
- const dagreGraph = new dagre.graphlib.Graph({ compound: true })
11
- dagreGraph.setDefaultEdgeLabel(() => ({}))
12
-
13
- // Top-to-bottom layout
14
- dagreGraph.setGraph({ rankdir: 'TB', ranksep: 80, nodesep: 60, edgesep: 20, ranker: 'tight-tree' })
15
-
16
- nodes.forEach((node) => {
17
- dagreGraph.setNode(node.id, { width: node.measured?.width, height: node.measured?.height })
18
- })
19
-
20
- edges.forEach((edge) => {
21
- if (typeof edge.label === 'string') {
22
- dagreGraph.setEdge(edge.source, edge.target, {
23
- label: edge.label ?? '',
24
- width: edge.label.length * 40, // Add width for the label
25
- height: 30, // Add height for the label
26
- labelpos: 'c', // Position label in center
27
- })
28
- } else {
29
- dagreGraph.setEdge(edge.source, edge.target)
30
- }
31
- })
32
-
33
- dagre.layout(dagreGraph)
34
-
35
- return nodes.map((node) => {
36
- const { x, y } = dagreGraph.node(node.id)
37
- const position = {
38
- x: x - (node.measured?.width ?? 0) / 2,
39
- y: y - (node.measured?.height ?? 0) / 2,
40
- }
41
-
42
- return { ...node, position }
43
- })
44
- }
45
-
46
- export const useOrganizeNodes = (
47
- nodes: Node<EventNodeData | ApiNodeData>[],
48
- edges: Edge<EdgeData>[],
49
- setNodes: (nodes: Node<EventNodeData | ApiNodeData>[]) => void,
50
- ) => {
51
- const organizedRef = useRef<boolean>(false)
52
-
53
- useEffect(() => {
54
- if (!nodes.length || !edges.length || !nodes[0].measured || organizedRef.current) return
55
-
56
- const layoutedNodes = organizeNodes(nodes, edges)
57
- setNodes(layoutedNodes)
58
- organizedRef.current = true
59
- }, [nodes, edges, setNodes])
60
- }
@@ -1,96 +0,0 @@
1
- export const Legend = ({ onHover }: { onHover: (type: string | null) => void }) => {
2
- const legendItems = [
3
- {
4
- label: 'Event (Core)',
5
- type: 'event',
6
- bgColor: 'bg-green-950/40',
7
- description: 'Core logic components that process events.',
8
- },
9
- {
10
- label: 'API',
11
- type: 'api',
12
- bgColor: 'bg-blue-950/40',
13
- description: 'HTTP endpoints that trigger flows.',
14
- },
15
- {
16
- label: 'Noop (Non-Operation)',
17
- type: 'noop',
18
- bgColor: 'bg-zinc-950/40',
19
- description: 'Placeholder nodes for external processes.',
20
- },
21
- ]
22
-
23
- const edgeLegendItems = [
24
- {
25
- label: 'Event Edge',
26
- color: 'rgb(133, 176, 132)', // Solid green line
27
- description: 'Represents an event emitted and subscribed by steps.',
28
- dashed: true,
29
- },
30
- {
31
- label: 'Virtual Edge',
32
- color: 'rgb(147, 169, 197)', // Dotted blue line
33
- description: 'Represents virtual connections.',
34
- dashed: true,
35
- },
36
- ]
37
-
38
- const renderSwatch = (bgColor: string) => (
39
- <div className="relative group">
40
- <div className="absolute -inset-[1px] rounded bg-gradient-to-r from-white/20 to-white/10" />
41
- <div className={`relative ${bgColor} w-8 h-8 rounded border border-white/10`} />
42
- <div className="absolute inset-0 -z-10 translate-y-0.5 translate-x-0.5 bg-black/20 rounded border border-white/5" />
43
- </div>
44
- )
45
-
46
- const renderEdgeSwatch = (color: string, dashed: boolean) => (
47
- <svg width="48" height="10" viewBox="0 0 48 10" xmlns="http://www.w3.org/2000/svg">
48
- <line
49
- x1="0"
50
- y1="5"
51
- x2="48"
52
- y2="5"
53
- stroke={color}
54
- strokeWidth=".8"
55
- strokeDasharray={dashed ? '4 3' : 'none'} // Match the dashed or solid style
56
- strokeLinecap="round" // Rounded edges
57
- />
58
- </svg>
59
- )
60
-
61
- return (
62
- <div className="absolute right-4 top-4 font-mono rounded-lg border border-white/20 p-4 z-10 shadow-xl">
63
- <div className="text-sm text-white mb-3 font-semibold">Flow Legend</div>
64
- <div className="flex flex-col gap-3">
65
- {legendItems.map((item) => (
66
- <div
67
- key={item.type}
68
- onMouseEnter={() => onHover(item.type)}
69
- onMouseLeave={() => onHover(null)}
70
- className="group cursor-pointer transition-all hover:bg-white/5 rounded p-1 -mx-1"
71
- >
72
- <div className="flex items-start gap-3">
73
- {renderSwatch(item.bgColor)}
74
- <div className="flex-1">
75
- <div className="text-white text-xs font-medium">{item.label}</div>
76
- <div className="text-white/60 text-xs mt-0.5">{item.description}</div>
77
- </div>
78
- </div>
79
- </div>
80
- ))}
81
- </div>
82
- <div className="text-sm text-white mt-4 mb-3 font-semibold">Edge Legend</div>
83
- <div className="flex flex-col gap-3">
84
- {edgeLegendItems.map((item) => (
85
- <div key={item.label} className="flex items-start gap-3">
86
- {renderEdgeSwatch(item.color, item.dashed)}
87
- <div className="flex-1">
88
- <div className="text-white text-xs font-medium">{item.label}</div>
89
- <div className="text-white/60 text-xs mt-0.5">{item.description}</div>
90
- </div>
91
- </div>
92
- ))}
93
- </div>
94
- </div>
95
- )
96
- }
@@ -1,70 +0,0 @@
1
- import { Edge, Node, useNodesInitialized, useReactFlow } from '@xyflow/react'
2
- import dagre from 'dagre'
3
- import { useEffect } from 'react'
4
- import { EventNodeData, EdgeData, ApiNodeData } from './nodes/nodes.types'
5
-
6
- const organizeNodes = (
7
- nodes: Node<EventNodeData | ApiNodeData>[],
8
- edges: Edge<EdgeData>[],
9
- ): Node<EventNodeData | ApiNodeData>[] => {
10
- const dagreGraph = new dagre.graphlib.Graph({ compound: true })
11
- dagreGraph.setDefaultEdgeLabel(() => ({}))
12
-
13
- // Top-to-bottom layout
14
- dagreGraph.setGraph({ rankdir: 'TB', ranksep: 80, nodesep: 60, edgesep: 20, ranker: 'tight-tree' })
15
-
16
- nodes.forEach((node) => {
17
- dagreGraph.setNode(node.id, { width: node.measured?.width, height: node.measured?.height })
18
- })
19
-
20
- edges.forEach((edge) => {
21
- if (typeof edge.label === 'string') {
22
- dagreGraph.setEdge(edge.source, edge.target, {
23
- label: edge.label ?? '',
24
- width: edge.label.length * 40, // Add width for the label
25
- height: 30, // Add height for the label
26
- labelpos: 'c', // Position label in center
27
- })
28
- } else {
29
- dagreGraph.setEdge(edge.source, edge.target)
30
- }
31
- })
32
-
33
- dagre.layout(dagreGraph)
34
-
35
- return nodes.map((node) => {
36
- const { x, y } = dagreGraph.node(node.id)
37
- const position = {
38
- x: x - (node.measured?.width ?? 0) / 2,
39
- y: y - (node.measured?.height ?? 0) / 2,
40
- }
41
-
42
- return { ...node, position }
43
- })
44
- }
45
-
46
- type Props = {
47
- onInitialized: () => void
48
- }
49
-
50
- export const NodeOrganizer: React.FC<Props> = ({ onInitialized }) => {
51
- const { setNodes, getNodes, getEdges, fitView } = useReactFlow()
52
- const nodesInitialized = useNodesInitialized()
53
-
54
- useEffect(() => {
55
- if (nodesInitialized) {
56
- const nodes = getNodes() as Node<EventNodeData | ApiNodeData>[]
57
- const edges = getEdges() as Edge<EdgeData>[]
58
- const organizedNodes = organizeNodes(nodes, edges)
59
-
60
- setNodes(organizedNodes)
61
- onInitialized()
62
-
63
- setTimeout(async () => {
64
- await fitView()
65
- }, 1)
66
- }
67
- }, [nodesInitialized, onInitialized])
68
-
69
- return null
70
- }
@@ -1,6 +0,0 @@
1
- import { ApiNode } from '../../../publicComponents/api-node'
2
- import { ApiNodeData } from './nodes.types'
3
-
4
- export const ApiFlowNode = ({ data }: { data: ApiNodeData }) => {
5
- return <ApiNode data={data} />
6
- }
@@ -1,6 +0,0 @@
1
- import { EventNode } from '../../../publicComponents/event-node'
2
- import { EventNodeProps } from '../../../publicComponents/node-props'
3
-
4
- export const EventFlowNode = ({ data }: EventNodeProps) => {
5
- return <EventNode className="relative" data={data}></EventNode>
6
- }
@@ -1,110 +0,0 @@
1
- import { useEffect, useState } from 'react'
2
- import { JSONSchema7 } from 'json-schema'
3
- import { Input } from '@/components/ui/input'
4
- import { Label } from '@/components/ui/label'
5
- import { Switch } from '@/components/ui/switch'
6
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
7
- import { Textarea } from '@/components/ui/textarea'
8
-
9
- interface JsonSchemaFormProps {
10
- schema: JSONSchema7
11
- formData?: any
12
- onChange?: (data: any) => void
13
- }
14
-
15
- export const JsonSchemaForm: React.FC<JsonSchemaFormProps> = ({ schema, formData = {}, onChange }) => {
16
- const [values, setValues] = useState(formData)
17
-
18
- useEffect(() => {
19
- onChange?.(values)
20
- }, [values, onChange])
21
-
22
- const renderField = (propertyName: string, propertySchema: JSONSchema7) => {
23
- const value = values[propertyName]
24
-
25
- switch (propertySchema.type) {
26
- case 'string':
27
- if (propertySchema.enum) {
28
- return (
29
- <div className="space-y-2" key={propertyName}>
30
- <Label>{propertySchema.title || propertyName}</Label>
31
- <Select value={value} onValueChange={(newValue) => setValues({ ...values, [propertyName]: newValue })}>
32
- <SelectTrigger>
33
- <SelectValue placeholder={propertySchema.description || `Select ${propertyName}`} />
34
- </SelectTrigger>
35
- <SelectContent>
36
- {propertySchema.enum.map((option) => (
37
- <SelectItem key={String(option)} value={String(option)}>
38
- {String(option)}
39
- </SelectItem>
40
- ))}
41
- </SelectContent>
42
- </Select>
43
- </div>
44
- )
45
- }
46
-
47
- if (propertySchema.format === 'textarea') {
48
- return (
49
- <div className="space-y-2" key={propertyName}>
50
- <Label>{propertySchema.title || propertyName}</Label>
51
- <Textarea
52
- placeholder={propertySchema.description}
53
- value={value || ''}
54
- onChange={(e) => setValues({ ...values, [propertyName]: e.target.value })}
55
- />
56
- </div>
57
- )
58
- }
59
-
60
- return (
61
- <div className="space-y-2" key={propertyName}>
62
- <Label>{propertySchema.title || propertyName}</Label>
63
- <Input
64
- type="text"
65
- placeholder={propertySchema.description}
66
- value={value || ''}
67
- onChange={(e) => setValues({ ...values, [propertyName]: e.target.value })}
68
- />
69
- </div>
70
- )
71
-
72
- case 'number':
73
- case 'integer':
74
- return (
75
- <div className="space-y-2" key={propertyName}>
76
- <Label>{propertySchema.title || propertyName}</Label>
77
- <Input
78
- type="number"
79
- placeholder={propertySchema.description}
80
- value={value || ''}
81
- onChange={(e) => setValues({ ...values, [propertyName]: Number(e.target.value) })}
82
- />
83
- </div>
84
- )
85
-
86
- case 'boolean':
87
- return (
88
- <div className="flex items-center space-x-2" key={propertyName}>
89
- <Switch
90
- checked={value || false}
91
- onCheckedChange={(checked) => setValues({ ...values, [propertyName]: checked })}
92
- />
93
- <Label>{propertySchema.title || propertyName}</Label>
94
- </div>
95
- )
96
-
97
- default:
98
- return null
99
- }
100
- }
101
-
102
- return (
103
- <form className="space-y-4">
104
- {schema.properties &&
105
- Object.entries(schema.properties).map(([propertyName, propertySchema]) =>
106
- renderField(propertyName, propertySchema as JSONSchema7),
107
- )}
108
- </form>
109
- )
110
- }