@motiadev/workbench 0.14.0-beta.165-285707 → 0.15.0-beta.165

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 (236) hide show
  1. package/dist/index.d.ts +189 -10
  2. package/dist/index.html +1 -1
  3. package/dist/index.js +1065 -7
  4. package/dist/middleware.d.ts +66 -8
  5. package/dist/middleware.js +694 -86
  6. package/dist/motia-plugin/__tests__/generator.test.ts +129 -0
  7. package/dist/motia-plugin/__tests__/resolver.test.ts +82 -0
  8. package/dist/motia-plugin/__tests__/validator.test.ts +71 -0
  9. package/dist/motia-plugin/{generator.js → generator.ts} +37 -35
  10. package/dist/motia-plugin/hmr.ts +123 -0
  11. package/dist/motia-plugin/index.ts +183 -0
  12. package/dist/motia-plugin/{resolver.d.ts → resolver.ts} +38 -5
  13. package/dist/motia-plugin/types.ts +198 -0
  14. package/dist/motia-plugin/{utils.d.ts → utils.ts} +17 -4
  15. package/dist/motia-plugin/validator.ts +197 -0
  16. package/dist/src/App.tsx +41 -0
  17. package/dist/src/components/NotFoundPage.tsx +11 -0
  18. package/dist/src/components/bottom-panel.tsx +39 -0
  19. package/dist/src/components/flow/base-edge.tsx +61 -0
  20. package/dist/src/components/flow/flow-loader.tsx +3 -0
  21. package/dist/src/components/flow/flow-page.tsx +75 -0
  22. package/dist/src/components/flow/flow-tab-menu-item.tsx +52 -0
  23. package/dist/src/components/flow/flow-view.tsx +66 -0
  24. package/dist/src/components/flow/hooks/use-get-flow-state.tsx +171 -0
  25. package/dist/src/components/flow/hooks/use-save-workflow-config.ts +25 -0
  26. package/dist/src/components/flow/node-organizer.tsx +103 -0
  27. package/dist/src/components/flow/nodes/api-flow-node.tsx +6 -0
  28. package/dist/src/components/flow/nodes/cron-flow-node.tsx +6 -0
  29. package/dist/src/components/flow/nodes/event-flow-node.tsx +6 -0
  30. package/dist/src/components/flow/nodes/noop-flow-node.tsx +6 -0
  31. package/dist/src/components/header/deploy-button.tsx +110 -0
  32. package/dist/src/components/header/header.tsx +39 -0
  33. package/dist/src/components/root-motia.tsx +10 -0
  34. package/dist/src/components/top-panel.tsx +40 -0
  35. package/dist/src/components/tutorial/engine/tutorial-engine.ts +26 -0
  36. package/dist/src/components/tutorial/engine/tutorial-types.ts +26 -0
  37. package/dist/src/components/tutorial/engine/workbench-xpath.ts +53 -0
  38. package/dist/src/components/tutorial/hooks/tutorial-utils.ts +26 -0
  39. package/dist/src/components/tutorial/hooks/use-tutorial-engine.ts +213 -0
  40. package/dist/src/components/tutorial/hooks/use-tutorial.ts +14 -0
  41. package/dist/src/components/tutorial/tutorial-button.tsx +46 -0
  42. package/dist/src/components/tutorial/tutorial-step.tsx +82 -0
  43. package/dist/src/components/tutorial/tutorial.tsx +59 -0
  44. package/dist/src/components/ui/json-editor.tsx +68 -0
  45. package/dist/src/components/ui/table.tsx +75 -0
  46. package/dist/src/components/ui/theme-toggle.tsx +54 -0
  47. package/dist/src/components/ui/tooltip.tsx +26 -0
  48. package/dist/src/hooks/use-debounced.ts +22 -0
  49. package/dist/src/hooks/use-fetch-flows.ts +33 -0
  50. package/dist/src/hooks/use-mobile.ts +19 -0
  51. package/dist/src/hooks/use-update-handle-positions.ts +42 -0
  52. package/dist/src/index.css +5 -5
  53. package/dist/src/lib/__tests__/utils.test.ts +110 -0
  54. package/dist/src/lib/motia-analytics.ts +140 -0
  55. package/dist/src/lib/plugins.tsx +132 -0
  56. package/dist/src/lib/utils.ts +37 -0
  57. package/dist/src/main.tsx +30 -0
  58. package/dist/src/project-view-mode.tsx +32 -0
  59. package/dist/src/publicComponents/api-node.tsx +26 -0
  60. package/dist/src/publicComponents/base-node/base-handle.tsx +50 -0
  61. package/dist/src/publicComponents/base-node/base-node.tsx +114 -0
  62. package/dist/src/publicComponents/base-node/code-display.tsx +119 -0
  63. package/dist/src/publicComponents/base-node/emits.tsx +17 -0
  64. package/dist/src/publicComponents/base-node/feature-card.tsx +32 -0
  65. package/dist/src/publicComponents/base-node/language-indicator.tsx +131 -0
  66. package/dist/src/publicComponents/base-node/node-header.tsx +49 -0
  67. package/dist/src/publicComponents/base-node/node-sidebar.tsx +41 -0
  68. package/dist/src/publicComponents/base-node/subscribe.tsx +13 -0
  69. package/dist/src/publicComponents/cron-node.tsx +24 -0
  70. package/dist/src/publicComponents/event-node.tsx +20 -0
  71. package/dist/src/publicComponents/node-props.tsx +15 -0
  72. package/dist/src/publicComponents/noop-node.tsx +19 -0
  73. package/dist/src/setupTests.ts +1 -0
  74. package/dist/src/stores/use-app-tabs-store.ts +49 -0
  75. package/dist/src/stores/use-flow-store.ts +31 -0
  76. package/dist/src/stores/use-global-store.ts +24 -0
  77. package/dist/src/stores/use-motia-config-store.ts +36 -0
  78. package/dist/src/stores/use-tabs-store.ts +34 -0
  79. package/dist/src/system-view-mode.tsx +28 -0
  80. package/dist/src/types/endpoint.ts +12 -0
  81. package/dist/src/types/file.ts +7 -0
  82. package/dist/src/types/flow.ts +103 -0
  83. package/eslint.config.cjs +22 -0
  84. package/jest.config.cjs +68 -0
  85. package/package.json +53 -51
  86. package/dist/motia-plugin/__tests__/generator.test.d.ts +0 -1
  87. package/dist/motia-plugin/__tests__/generator.test.js +0 -97
  88. package/dist/motia-plugin/__tests__/resolver.test.d.ts +0 -1
  89. package/dist/motia-plugin/__tests__/resolver.test.js +0 -64
  90. package/dist/motia-plugin/__tests__/validator.test.d.ts +0 -1
  91. package/dist/motia-plugin/__tests__/validator.test.js +0 -59
  92. package/dist/motia-plugin/generator.d.ts +0 -78
  93. package/dist/motia-plugin/hmr.d.ts +0 -22
  94. package/dist/motia-plugin/hmr.js +0 -100
  95. package/dist/motia-plugin/index.d.ts +0 -3
  96. package/dist/motia-plugin/index.js +0 -153
  97. package/dist/motia-plugin/resolver.js +0 -92
  98. package/dist/motia-plugin/types.d.ts +0 -169
  99. package/dist/motia-plugin/types.js +0 -36
  100. package/dist/motia-plugin/utils.js +0 -75
  101. package/dist/motia-plugin/validator.d.ts +0 -19
  102. package/dist/motia-plugin/validator.js +0 -163
  103. package/dist/src/App.d.ts +0 -2
  104. package/dist/src/App.js +0 -35
  105. package/dist/src/components/NotFoundPage.d.ts +0 -1
  106. package/dist/src/components/NotFoundPage.js +0 -3
  107. package/dist/src/components/bottom-panel.d.ts +0 -1
  108. package/dist/src/components/bottom-panel.js +0 -15
  109. package/dist/src/components/flow/base-edge.d.ts +0 -3
  110. package/dist/src/components/flow/base-edge.js +0 -39
  111. package/dist/src/components/flow/flow-loader.d.ts +0 -1
  112. package/dist/src/components/flow/flow-loader.js +0 -4
  113. package/dist/src/components/flow/flow-page.d.ts +0 -1
  114. package/dist/src/components/flow/flow-page.js +0 -25
  115. package/dist/src/components/flow/flow-tab-menu-item.d.ts +0 -1
  116. package/dist/src/components/flow/flow-tab-menu-item.js +0 -18
  117. package/dist/src/components/flow/flow-view.d.ts +0 -12
  118. package/dist/src/components/flow/flow-view.js +0 -22
  119. package/dist/src/components/flow/hooks/use-get-flow-state.d.ts +0 -10
  120. package/dist/src/components/flow/hooks/use-get-flow-state.js +0 -133
  121. package/dist/src/components/flow/hooks/use-save-workflow-config.d.ts +0 -2
  122. package/dist/src/components/flow/hooks/use-save-workflow-config.js +0 -22
  123. package/dist/src/components/flow/node-organizer.d.ts +0 -10
  124. package/dist/src/components/flow/node-organizer.js +0 -82
  125. package/dist/src/components/flow/nodes/api-flow-node.d.ts +0 -2
  126. package/dist/src/components/flow/nodes/api-flow-node.js +0 -5
  127. package/dist/src/components/flow/nodes/cron-flow-node.d.ts +0 -2
  128. package/dist/src/components/flow/nodes/cron-flow-node.js +0 -5
  129. package/dist/src/components/flow/nodes/event-flow-node.d.ts +0 -2
  130. package/dist/src/components/flow/nodes/event-flow-node.js +0 -5
  131. package/dist/src/components/flow/nodes/noop-flow-node.d.ts +0 -2
  132. package/dist/src/components/flow/nodes/noop-flow-node.js +0 -5
  133. package/dist/src/components/header/deploy-button.d.ts +0 -1
  134. package/dist/src/components/header/deploy-button.js +0 -28
  135. package/dist/src/components/header/header.d.ts +0 -2
  136. package/dist/src/components/header/header.js +0 -23
  137. package/dist/src/components/root-motia.d.ts +0 -2
  138. package/dist/src/components/root-motia.js +0 -7
  139. package/dist/src/components/top-panel.d.ts +0 -1
  140. package/dist/src/components/top-panel.js +0 -15
  141. package/dist/src/components/tutorial/engine/tutorial-engine.d.ts +0 -12
  142. package/dist/src/components/tutorial/engine/tutorial-engine.js +0 -36
  143. package/dist/src/components/tutorial/engine/tutorial-types.d.ts +0 -22
  144. package/dist/src/components/tutorial/engine/tutorial-types.js +0 -1
  145. package/dist/src/components/tutorial/engine/workbench-xpath.d.ts +0 -45
  146. package/dist/src/components/tutorial/engine/workbench-xpath.js +0 -45
  147. package/dist/src/components/tutorial/hooks/tutorial-utils.d.ts +0 -1
  148. package/dist/src/components/tutorial/hooks/tutorial-utils.js +0 -17
  149. package/dist/src/components/tutorial/hooks/use-tutorial-engine.d.ts +0 -15
  150. package/dist/src/components/tutorial/hooks/use-tutorial-engine.js +0 -183
  151. package/dist/src/components/tutorial/hooks/use-tutorial.d.ts +0 -5
  152. package/dist/src/components/tutorial/hooks/use-tutorial.js +0 -10
  153. package/dist/src/components/tutorial/tutorial-button.d.ts +0 -2
  154. package/dist/src/components/tutorial/tutorial-button.js +0 -21
  155. package/dist/src/components/tutorial/tutorial-step.d.ts +0 -14
  156. package/dist/src/components/tutorial/tutorial-step.js +0 -19
  157. package/dist/src/components/tutorial/tutorial.d.ts +0 -2
  158. package/dist/src/components/tutorial/tutorial.js +0 -32
  159. package/dist/src/components/ui/json-editor.d.ts +0 -12
  160. package/dist/src/components/ui/json-editor.js +0 -35
  161. package/dist/src/components/ui/table.d.ts +0 -10
  162. package/dist/src/components/ui/table.js +0 -20
  163. package/dist/src/components/ui/theme-toggle.d.ts +0 -2
  164. package/dist/src/components/ui/theme-toggle.js +0 -19
  165. package/dist/src/components/ui/tooltip.d.ts +0 -6
  166. package/dist/src/components/ui/tooltip.js +0 -3
  167. package/dist/src/hooks/use-debounced.d.ts +0 -1
  168. package/dist/src/hooks/use-debounced.js +0 -18
  169. package/dist/src/hooks/use-fetch-flows.d.ts +0 -1
  170. package/dist/src/hooks/use-fetch-flows.js +0 -26
  171. package/dist/src/hooks/use-mobile.d.ts +0 -1
  172. package/dist/src/hooks/use-mobile.js +0 -15
  173. package/dist/src/hooks/use-update-handle-positions.d.ts +0 -10
  174. package/dist/src/hooks/use-update-handle-positions.js +0 -35
  175. package/dist/src/lib/__tests__/utils.test.d.ts +0 -1
  176. package/dist/src/lib/__tests__/utils.test.js +0 -94
  177. package/dist/src/lib/motia-analytics.d.ts +0 -38
  178. package/dist/src/lib/motia-analytics.js +0 -132
  179. package/dist/src/lib/plugins.d.ts +0 -2
  180. package/dist/src/lib/plugins.js +0 -105
  181. package/dist/src/lib/utils.d.ts +0 -7
  182. package/dist/src/lib/utils.js +0 -34
  183. package/dist/src/main.d.ts +0 -2
  184. package/dist/src/main.js +0 -17
  185. package/dist/src/project-view-mode.d.ts +0 -1
  186. package/dist/src/project-view-mode.js +0 -20
  187. package/dist/src/publicComponents/api-node.d.ts +0 -5
  188. package/dist/src/publicComponents/api-node.js +0 -5
  189. package/dist/src/publicComponents/base-node/base-handle.d.ts +0 -9
  190. package/dist/src/publicComponents/base-node/base-handle.js +0 -8
  191. package/dist/src/publicComponents/base-node/base-node.d.ts +0 -15
  192. package/dist/src/publicComponents/base-node/base-node.js +0 -30
  193. package/dist/src/publicComponents/base-node/code-display.d.ts +0 -9
  194. package/dist/src/publicComponents/base-node/code-display.js +0 -64
  195. package/dist/src/publicComponents/base-node/emits.d.ts +0 -5
  196. package/dist/src/publicComponents/base-node/emits.js +0 -5
  197. package/dist/src/publicComponents/base-node/feature-card.d.ts +0 -10
  198. package/dist/src/publicComponents/base-node/feature-card.js +0 -5
  199. package/dist/src/publicComponents/base-node/language-indicator.d.ts +0 -10
  200. package/dist/src/publicComponents/base-node/language-indicator.js +0 -29
  201. package/dist/src/publicComponents/base-node/node-header.d.ts +0 -13
  202. package/dist/src/publicComponents/base-node/node-header.js +0 -30
  203. package/dist/src/publicComponents/base-node/node-sidebar.d.ts +0 -14
  204. package/dist/src/publicComponents/base-node/node-sidebar.js +0 -9
  205. package/dist/src/publicComponents/base-node/subscribe.d.ts +0 -4
  206. package/dist/src/publicComponents/base-node/subscribe.js +0 -4
  207. package/dist/src/publicComponents/cron-node.d.ts +0 -4
  208. package/dist/src/publicComponents/cron-node.js +0 -6
  209. package/dist/src/publicComponents/event-node.d.ts +0 -4
  210. package/dist/src/publicComponents/event-node.js +0 -5
  211. package/dist/src/publicComponents/node-props.d.ts +0 -21
  212. package/dist/src/publicComponents/node-props.js +0 -1
  213. package/dist/src/publicComponents/noop-node.d.ts +0 -4
  214. package/dist/src/publicComponents/noop-node.js +0 -5
  215. package/dist/src/setupTests.d.ts +0 -1
  216. package/dist/src/setupTests.js +0 -1
  217. package/dist/src/stores/use-app-tabs-store.d.ts +0 -16
  218. package/dist/src/stores/use-app-tabs-store.js +0 -31
  219. package/dist/src/stores/use-flow-store.d.ts +0 -21
  220. package/dist/src/stores/use-flow-store.js +0 -16
  221. package/dist/src/stores/use-global-store.d.ts +0 -18
  222. package/dist/src/stores/use-global-store.js +0 -12
  223. package/dist/src/stores/use-motia-config-store.d.ts +0 -12
  224. package/dist/src/stores/use-motia-config-store.js +0 -24
  225. package/dist/src/stores/use-tabs-store.d.ts +0 -19
  226. package/dist/src/stores/use-tabs-store.js +0 -22
  227. package/dist/src/system-view-mode.d.ts +0 -1
  228. package/dist/src/system-view-mode.js +0 -10
  229. package/dist/src/types/endpoint.d.ts +0 -14
  230. package/dist/src/types/endpoint.js +0 -1
  231. package/dist/src/types/file.d.ts +0 -7
  232. package/dist/src/types/file.js +0 -1
  233. package/dist/src/types/flow.d.ts +0 -115
  234. package/dist/src/types/flow.js +0 -1
  235. package/dist/tsconfig.app.tsbuildinfo +0 -1
  236. package/dist/tsconfig.node.tsbuildinfo +0 -1
@@ -0,0 +1,17 @@
1
+ import type React from 'react'
2
+ import type { EventNodeData } from '../../types/flow'
3
+
4
+ const toTopic = (emit: string | { topic: string; label?: string; conditional?: boolean }) =>
5
+ typeof emit === 'string' ? emit : emit.topic
6
+
7
+ export const Emits: React.FC<{ emits: EventNodeData['emits'] }> = ({ emits }) => {
8
+ return (
9
+ <div className="flex flex-col gap-2">
10
+ {emits.map((emit) => (
11
+ <div key={toTopic(emit)} data-testid={`emits__${toTopic(emit)}`}>
12
+ {toTopic(emit)}
13
+ </div>
14
+ ))}
15
+ </div>
16
+ )
17
+ }
@@ -0,0 +1,32 @@
1
+ import { cn } from '@motiadev/ui'
2
+ import type React from 'react'
3
+ import type { Feature } from '../../types/file'
4
+
5
+ type Props = {
6
+ feature: Feature
7
+ highlighted: boolean
8
+ onClick: () => void
9
+ onHover: () => void
10
+ }
11
+
12
+ export const FeatureCard: React.FC<Props> = ({ feature, highlighted, onClick, onHover }) => {
13
+ return (
14
+ <div
15
+ data-feature-id={feature.id}
16
+ className={cn(
17
+ 'p-4 rounded-lg bg-card shadow-sm cursor-pointer hover:bg-card/50 border-2 border-transparent',
18
+ highlighted && 'border-2 border-accent-1000 bg-accent-100',
19
+ )}
20
+ onClick={onClick}
21
+ onMouseEnter={onHover}
22
+ >
23
+ <div className="text-md font-semibold text-foreground leading-tight whitespace-nowrap mb-2">{feature.title}</div>
24
+ <div className="text-sm font-medium text-muted-foreground leading-tight">{feature.description}</div>
25
+ {feature.link && (
26
+ <div className="text-sm font-medium text-muted-foreground leading-tight">
27
+ <a href={feature.link}>Learn more</a>
28
+ </div>
29
+ )}
30
+ </div>
31
+ )
32
+ }
@@ -0,0 +1,131 @@
1
+ import { cn } from '@motiadev/ui'
2
+ import type { FC } from 'react'
3
+ import type { EventNodeData } from '../../types/flow'
4
+
5
+ type Props = { language: EventNodeData['language']; className?: string; size?: number; showLabel?: boolean }
6
+
7
+ export const LanguageIndicator: FC<Props> = ({ language, className, size = 18, showLabel = false }) => {
8
+ const renderIcon = (language?: string) => {
9
+ if (language === 'typescript') {
10
+ return (
11
+ <>
12
+ {showLabel ? <>TypeScript</> : null}
13
+ <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none">
14
+ <path
15
+ d="M3 3V21H21V3H3ZM9 12H13.5V13.5H12V19.5H10.5V13.5H9V12ZM16.5 12H19.5V13.5H16.5V15H18C18.3975 15.0012 18.7783 15.1596 19.0593 15.4407C19.3404 15.7217 19.4988 16.1025 19.5 16.5V18C19.4988 18.3975 19.3404 18.7783 19.0593 19.0593C18.7783 19.3404 18.3975 19.4988 18 19.5H15V18H18V16.5H16.5C16.1025 16.4988 15.7217 16.3404 15.4407 16.0593C15.1596 15.7783 15.0012 15.3975 15 15V13.5C15.0012 13.1025 15.1596 12.7217 15.4407 12.4407C15.7217 12.1596 16.1025 12.0012 16.5 12Z"
16
+ fill="#0288D1"
17
+ />
18
+ </svg>
19
+ </>
20
+ )
21
+ }
22
+
23
+ if (language === 'javascript') {
24
+ return (
25
+ <>
26
+ {showLabel ? <>JavaScript</> : null}
27
+ <svg
28
+ width={size}
29
+ height={size}
30
+ viewBox="0 0 20 20"
31
+ fill="none"
32
+ xmlns="http://www.w3.org/2000/svg"
33
+ className={className}
34
+ >
35
+ <g clipPath="url(#clip0_42_2938)">
36
+ <path
37
+ d="M0 0H20V20H0V0ZM18.3617 15.23C18.2158 14.3175 17.6217 13.5508 15.8592 12.8358C15.2458 12.5483 14.5642 12.3483 14.3617 11.8858C14.2858 11.6108 14.2742 11.4608 14.3233 11.2983C14.4483 10.76 15.0858 10.5983 15.5858 10.7483C15.9108 10.8483 16.2108 11.0983 16.3992 11.4983C17.2608 10.935 17.2608 10.935 17.8617 10.5608C17.6367 10.2108 17.525 10.06 17.3733 9.91083C16.8483 9.32333 16.1492 9.02333 15.0117 9.04917L14.4242 9.12333C13.8608 9.26083 13.3242 9.56083 12.9992 9.96083C12.0492 11.0367 12.3233 12.9117 13.4733 13.6867C14.6108 14.5367 16.2742 14.7233 16.4867 15.5242C16.6867 16.4992 15.7617 16.8117 14.8483 16.6992C14.1725 16.5492 13.7983 16.2108 13.3858 15.5858L11.8608 16.4617C12.0358 16.8617 12.2358 17.0358 12.5358 17.3858C13.9858 18.8492 17.6108 18.7742 18.2617 16.5492C18.2858 16.4742 18.4617 15.9617 18.3233 15.1742L18.3617 15.23ZM10.8758 9.1925H9.0025C9.0025 10.8075 8.995 12.4125 8.995 14.03C8.995 15.0567 9.0475 15.9992 8.88 16.2892C8.605 16.8633 7.89667 16.79 7.575 16.6892C7.245 16.5258 7.0775 16.3008 6.88333 15.9767C6.83083 15.8892 6.79167 15.8133 6.7775 15.8133L5.25667 16.7508C5.51083 17.2758 5.88167 17.7275 6.36 18.015C7.0725 18.44 8.03 18.5775 9.0325 18.3525C9.685 18.1642 10.2475 17.7767 10.5417 17.1767C10.9667 16.4017 10.8767 15.4517 10.8725 14.3883C10.8825 12.6767 10.8725 10.9642 10.8725 9.23917L10.8758 9.1925Z"
38
+ fill="white"
39
+ />
40
+ </g>
41
+ <defs>
42
+ <clipPath id="clip0_42_2938">
43
+ <rect width="20" height="20" fill="white" />
44
+ </clipPath>
45
+ </defs>
46
+ </svg>
47
+ </>
48
+ )
49
+ }
50
+
51
+ if (language === 'python') {
52
+ return (
53
+ <>
54
+ {showLabel ? <>Python</> : null}
55
+ <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none">
56
+ <path
57
+ d="M9.86 2C9.10148 2 8.37403 2.30132 7.83767 2.83767C7.30132 3.37403 7 4.10148 7 4.86V6.54H11.29C11.68 6.54 12 7.11 12 7.5H4.86C4.10148 7.5 3.37403 7.80132 2.83767 8.33767C2.30132 8.87403 2 9.60148 2 10.36V14.141C2 14.8995 2.30132 15.627 2.83767 16.1633C3.37403 16.6997 4.10148 17.001 4.86 17.001H6.04V14.321C6.03868 13.9459 6.11143 13.5742 6.25407 13.2273C6.3967 12.8803 6.60642 12.565 6.8712 12.2993C7.13598 12.0336 7.45061 11.8227 7.79704 11.6789C8.14347 11.535 8.51489 11.461 8.89 11.461H14.14C15.72 11.461 17 10.19 17 8.61V4.86C17 4.10148 16.6987 3.37403 16.1623 2.83767C15.626 2.30132 14.8985 2 14.14 2H9.86ZM9.14 3.61C9.54 3.61 9.86 3.73 9.86 4.32C9.86 4.91 9.54 5.211 9.14 5.211C8.75 5.211 8.43 4.911 8.43 4.321C8.43 3.731 8.75 3.61 9.14 3.61Z"
58
+ fill="#0288D1"
59
+ />
60
+ <path
61
+ d="M17.959 7V9.68C17.9602 10.055 17.8873 10.4266 17.7446 10.7734C17.602 11.1202 17.3922 11.4355 17.1274 11.7011C16.8627 11.9667 16.5481 12.1774 16.2017 12.3212C15.8554 12.465 15.484 12.539 15.109 12.539H9.86C9.48489 12.5377 9.11321 12.6104 8.76628 12.7531C8.41935 12.8957 8.10399 13.1054 7.83828 13.3702C7.57257 13.635 7.36175 13.9496 7.2179 14.296C7.07405 14.6425 7 15.0139 7 15.389V19.139C7 19.8975 7.30132 20.625 7.83767 21.1613C8.37403 21.6977 9.10148 21.999 9.86 21.999H14.14C14.8983 21.999 15.6256 21.6978 16.162 21.1617C16.6983 20.6255 16.9997 19.8983 17 19.14V17.46H12.709C12.319 17.46 12 16.89 12 16.5H19.14C19.8985 16.5 20.626 16.1987 21.1623 15.6623C21.6987 15.126 22 14.3985 22 13.64V9.86C22 9.10148 21.6987 8.37403 21.1623 7.83767C20.626 7.30132 19.8985 7 19.14 7H17.959ZM8.32 11.513L8.316 11.517L8.354 11.513H8.32ZM14.86 18.789C15.25 18.789 15.57 19.089 15.57 19.679C15.57 19.7722 15.5516 19.8646 15.516 19.9507C15.4803 20.0368 15.428 20.1151 15.362 20.181C15.2961 20.247 15.2178 20.2993 15.1317 20.335C15.0456 20.3706 14.9532 20.389 14.86 20.389C14.46 20.389 14.14 20.269 14.14 19.679C14.14 19.089 14.46 18.789 14.86 18.789Z"
62
+ fill="#FDD835"
63
+ />
64
+ </svg>
65
+ </>
66
+ )
67
+ }
68
+
69
+ if (language === 'go') {
70
+ return (
71
+ <>
72
+ {showLabel ? <>Go</> : null}
73
+ <svg viewBox="0 0 128 128" width={size} height={size} className={className}>
74
+ <path d="M108.7 64.4c-1.6-1.2-3.8-1.9-6-1.9-.1-3.6-.2-7.2-.2-10.7-.1-9.5-.1-19.3-2.6-28.6 6.5-2.5 6.2-7.6 5.9-9.2-.7-3.8-4-7.9-9-7.9-1.9 0-3.9.6-5.8 1.9C83.4 1.6 73 .5 62.5.5 53 1.3 46.4 2.8 41 5.4c-2.3 1.1-4.2 2.4-6 3.9-1.8-1.1-3.7-1.7-5.5-1.7-5.1 0-8.8 4.1-9.4 8.1-.6 4 1.6 7.3 6 8.9-2.2 8.9-1.5 18.1-.7 27 .3 3.7.6 7.6.7 11.4h-.5c-2.3 0-4.6.7-6.3 1.9-.7.5-2.1 2-2 3.3 0 .4.2.9.9 1.3.2 2.1 1.5 2.4 2.3 2.4 1.6 0 3.4-1.1 3.9-1.5.5-.3.9-.5 1.2-.6l.5-.2c-.1 2.2-.3 4.5-.5 7-.9 11.7-2 25 3.9 34.6 1.2 1.9 2.6 3.6 4.3 5.1l-.9.6c-2.7 1.9-6.7 4.7-4.3 8.5v.1c.4.4.6.5.9.5h.1c.3.5.9 1.6 2.4 1.6.6 0 1.3-.2 2-.6 1.1-.6 2.1-1.4 3-2.2 1.5-1.3 3-2.6 5-2.9l.6-.1.7.3c6.4 2.6 12.9 3.3 17.3 3.4h2.6c7.7 0 14.8-1.2 20.5-3.5 1.2-.5 2.4-1.1 3.5-1.7 1.2.5 2.3 1.7 3.4 3 1.4 1.6 2.8 3.2 4.5 3.2.8 0 1.6-.4 2.4-1.1 1.2-.7 1.8-1.7 1.8-2.9 0-2.6-2.9-5.7-5.2-7.2 2-2 3.6-4.2 4.9-6.7 5.9-11.8 5-26.2 4.2-39l.5.3c.5.4 2.3 1.5 3.9 1.5.8 0 2.1-.3 2.3-2.4.7-.4.8-.9.9-1.3 0-1.3-1.4-2.8-2.1-3.3zm-17.1-56c1.7-1.1 3.4-1.7 5.2-1.7 4.4 0 7.7 3.7 8.3 7.3.6 3.7-1.4 6.8-5.4 8.4 0-.2-.1-.3-.2-.5l-.6-2.1-.3-.8-.9-2.4c0-.1 0-.1-.1-.2 0 0 0-.1-.1-.1-.4-.7-.7-1.4-1.1-2l-.2-.3-1.2-1.8c-.1-.1-.2-.2-.3-.4-.4-.5-.8-1-1.3-1.5-.1-.2-.3-.3-.5-.5l-1.2-1.2c.1.1 0-.1-.1-.2-.2zM26.3 23.9c-4-1.5-6.1-4.5-5.5-8.1.6-3.7 4-7.5 8.7-7.5 1.7 0 3.3.5 4.9 1.4l-.1.1-.3.3c-.5.5-1 1-1.4 1.5l-.3.3c-.5.6-1 1.2-1.5 1.9l-.2.3c-.5.7-.9 1.3-1.3 2 0 0 0 .1-.1.1-.4.7-.8 1.5-1.1 2.3 0 .2-.1.4-.1.5-.3.8-.7 1.6-.9 2.4 0 .1 0 .1-.1.2l-.6 2-.1.3zm-.9 45.2c-.3.1-.8.3-1.4.7-1 .7-2.4 1.4-3.5 1.4-.6 0-1.4-.2-1.6-1.7.5-.2 1-.4 1.4-.9.1-.2.1-.4-.1-.5-.2-.1-.4-.1-.5.1-.3.3-.6.5-1.1.6h-.1c-.3-.2-.5-.4-.6-.7.1-.9 1.1-2.1 1.8-2.7 1.6-1.2 3.7-1.8 5.9-1.8h.6v2.9l-.1 1c-.1 1.4-.2 1.4-.7 1.6zm15.8 52l.1.1c-1.9.5-3.4 1.7-4.8 2.9-.9.8-1.8 1.6-2.9 2.1-.6.4-1.1.5-1.6.5-1 0-1.5-.8-1.7-1.2.1-.8.5-1.5 1-2.2.3-.4.6-.9.8-1.4.1-.2 0-.4-.2-.5-.2-.1-.4 0-.5.2-.2.4-.5.8-.7 1.3-.4.7-.9 1.4-1.1 2.2h-.1c-.1 0-.2-.1-.4-.3-2-3.2 1.4-5.5 4.2-7.5l.9-.6h.2l.2.1 1.2.9.4.3c.4.3.8.6 1.3.9l.5.3 1.3.8.6.3c.4.3.8.5 1.3.8zm52.3-5.3c2.1 1.4 5 4.4 5 6.7 0 .8-.4 1.5-1.1 2-.1-.3-.2-.6-.4-.9-.3-.9-.7-1.9-1.5-2.6-.1-.1-.4-.1-.5 0-.1.1-.1.4 0 .5.7.6 1 1.5 1.3 2.4l.4 1.1c-.6.5-1.2.8-1.8.8-1.4 0-2.6-1.5-3.9-3-1-1.1-2-2.3-3.1-3l.3-.2c.3-.1.5-.3.7-.5l1.3-.9.8-.6 1.4-1.1c.2-.2.4-.4.7-.6.2.1.3 0 .4-.1zm4.7-7.5c-1.2 2.5-3.4 5.7-7.1 8.5l-.2.1c-.3.3-.7.5-1.1.8l-1.1.7-.2.1-1.6.9-.7.4c-5.4 2.8-12.8 4.8-23.2 4.8h-2.6c-8.1-.3-14.3-2-18.9-4.2h-.1c-1.1-.5-2.1-1.1-3.1-1.7-4.6-2.9-7.1-6.1-8.3-8-5.8-9.4-4.8-22.5-3.8-34.1.2-3 .5-5.7.6-8.4l.1-1.8.1-.1v-.1l-.1-.5V63c-.1-4-.4-7.7-.7-11.5-.8-9-1.5-18.4.9-27.4.2-.8.4-1.6.7-2.3v-.1l.1-.3c.1-.4.3-.8.5-1.2.1-.3.2-.5.3-.7l.3-.8.4-.8.3-.6c.1-.3.3-.6.4-.8.1-.2.2-.4.3-.5.2-.4.5-.8.7-1.1.2-.3.4-.6.6-.8.1-.2.2-.3.4-.5l.6-.8c.1-.1.2-.2.3-.4l.9-1 .1-.1 1.2-1.2.2-.2c7-6 17-7.8 27.1-8.6 5.9 0 13.5.3 20 2.7 3.2 1.2 6 2.8 8.4 4.9.3.3.6.6.9.8l.9.9 1 1.2.6.7 1 1.4.5.7.9 1.5.4.8c.3.6.5 1.3.7 2 0 .1.1.2.1.4.2.6.4 1.2.6 1.7l.1.3c3 9.9 3.1 20.2 3.1 30.4 0 3.5 0 7.4.2 10.4v.6c0 .9.1 1.8.1 2.5v.1l.1 1.9c0 .6.1 1.3.1 2v.3c.9 12.6 1.9 27.1-4 38.8zm11.2-40c-.5-.2-.9-.3-1.2-.7-.1-.2-.3-.2-.5-.1s-.2.3-.1.5c.4.5.9.7 1.4.9-.2 1.5-1 1.7-1.6 1.7-1.1 0-2.5-.7-3.5-1.4-.4-.3-.7-.4-1-.5l-.2-2.4c0-.4 0-.8-.1-1.1 0-.6-.1-1.3-.1-2 2.1.1 4.1.7 5.6 1.8.7.5 1.8 1.8 1.7 2.6.1.3-.1.6-.4.7zM77.7 7.2c-3.8 0-7.5 1.6-9.9 4.1-2.2 2.4-3.3 5.4-3.1 8.8v.1C66 27.4 72 30 76.8 30c4.2 0 8.1-1.8 10.4-4.7 2-2.5 2.7-5.8 1.8-9.3-1.5-6.4-6.8-8.8-11.3-8.8zm8.9 17.5c-2.1 2.7-5.9 4.3-9.9 4.3-2.7 0-5.2-.7-7.2-2.1-2.2-1.6-3.6-3.9-4.1-6.9-.2-3.2.8-6 2.9-8.2 2.3-2.5 5.8-3.9 9.4-3.9 4.2 0 9.2 2.1 10.6 8.1.8 3.4.2 6.4-1.7 8.7zm-27-5.5c-.4-7.3-6.2-10.6-11.8-10.6-4.1 0-7.9 1.7-10.3 4.5-2.1 2.6-2.8 5.9-2.1 9.6 1.6 6.3 7 8.5 11.5 8.5 3.8 0 7.4-1.5 9.8-4 2.1-2.2 3.1-5 2.9-8zM47 30.5c-4.2 0-9.3-2.1-10.8-8-.7-3.5 0-6.6 2-9 2.2-2.7 5.8-4.3 9.7-4.3 7.7 0 10.8 5.4 11.1 10 .2 2.9-.7 5.5-2.6 7.5-2.3 2.4-5.8 3.8-9.4 3.8zm-5.4-13.9c-1.9 0-3.5 1.7-3.5 3.8 0 2.1 1.6 3.8 3.5 3.8s3.5-1.7 3.5-3.8c0-2.1-1.6-3.8-3.5-3.8zm1.6 5.7c-.5 0-.8-.4-.8-1 0-.5.4-1 .8-1 .5 0 .8.4.8 1 0 .5-.4 1-.8 1zm27.9-6.6c-1.9 0-3.5 1.7-3.5 3.8 0 2.1 1.6 3.8 3.5 3.8s3.5-1.7 3.5-3.8c0-2.1-1.5-3.8-3.5-3.8zm1.6 5.6c-.5 0-.8-.4-.8-1 0-.5.4-1 .8-1 .5 0 .8.4.8 1s-.3 1-.8 1zm-4.2 9c.1-.3.1-.7 0-1.1-1.1-4.1-10.4-3.5-10.4 1.3 0-.4-.1-.6-.1-.8 0 .3.1.6.1.8-1.5.2-2.8 1.2-3.6 2.7-.7 1.4-.8 2.9-.1 4.2.6 1.1 1.6 1.7 2.8 1.7-.4 2.1 0 4.6 1 6 .5.7 1.2 1.1 1.8 1.1.9 0 1.9-.7 2.8-1.8.6 1 1.5 1.7 2.7 1.9h.2c.2-.1.4-.2.6-.2.7-.2 1.4-.5 1.9-1.3v-.1c.3-1.4.1-2.9 0-4.3l-.1-1.2c.5.2 1 .3 1.5.3 1 0 1.8-.4 2.5-1.2.9-1 1.2-2 1-3-.1-2.3-2.4-4-4.6-5zm-5.9 13.2c-.9 1.1-1.7 1.7-2.4 1.7-.5 0-.9-.3-1.3-.7-.9-1.2-1.3-3.7-.9-5.6l.5-.1h.2l.6-.1h.1l1.2-.4.6-.2c.1 0 .1 0 .2-.1.2-.1.3-.1.5-.1.2-.1.4-.1.7-.2h.2l-.1 1.3c-.1 1.3-.2 2.9-.1 4.5zm5.2-3.3c.1 1.3.2 2.7 0 4-.3.6-.8.7-1.5 1l-.6.2c-1-.2-1.8-.8-2.2-1.8-.2-1.5-.1-3 .1-4.6l.1-1.5h.1c1.1 0 2.1.5 3.1.9l.7.3c.1.4.2.9.2 1.5zm4.1-2.7c-.6.7-1.3 1-2 1-.6 0-1.1-.2-1.7-.4-.3-.1-.6-.2-.9-.4-1.1-.4-2.2-.9-3.4-.9h-1.3l-.4.1c-.1 0-.2 0-.3.1-.2 0-.3.1-.5.2-.1 0-.2 0-.2.1l-.8.3c-.1.1-.3.1-.4.1l-.3.1-.3.1c-.2.1-.3.1-.5.1-.1 0-.2 0-.3.1l-.5.1h-.2l-.6.1c-1 0-1.7-.4-2.2-1.3-.6-1-.6-2.3.1-3.5.7-1.2 1.9-2.1 3.1-2.3 1.2 2.5 8.1 2.2 9.9-.2 2 .9 4.2 2.5 4.5 4.2.2.7-.1 1.5-.8 2.3zM58 29.4z"></path>
75
+ </svg>
76
+ </>
77
+ )
78
+ }
79
+
80
+ if (language === 'ruby') {
81
+ return (
82
+ <>
83
+ {showLabel ? <>Ruby</> : null}
84
+ <svg
85
+ width={size}
86
+ height={size}
87
+ viewBox="0 0 20 20"
88
+ fill="none"
89
+ xmlns="http://www.w3.org/2000/svg"
90
+ className={className}
91
+ >
92
+ <g clipPath="url(#clip0_42_2969)">
93
+ <path
94
+ d="M16.7967 0.0691243C19.3242 0.506624 20.0408 2.23412 19.9875 4.04412L20 4.01829L18.8625 18.925L4.075 19.9383H4.08833C2.86083 19.8866 0.125 19.7741 0 15.9491L1.37083 13.4491L3.72 18.9375L4.13917 19.9141L6.47667 12.2941L6.45167 12.3L6.465 12.275L14.1775 14.7383L13.0142 10.2125L12.1892 6.96246L19.5392 6.48829L19.0267 6.06329L13.75 1.76162L16.7992 0.060791L16.7967 0.0691243ZM4.275 4.22746C7.2425 1.28329 11.0725 -0.456709 12.5433 1.02746C14.0117 2.50829 12.4558 6.11496 9.4825 9.05746C6.51333 12.0008 2.73 13.8358 1.2625 12.355C-0.209167 10.8741 1.3 7.17412 4.2725 4.22996L4.275 4.22746Z"
95
+ fill="white"
96
+ />
97
+ </g>
98
+ <defs>
99
+ <clipPath id="clip0_42_2969">
100
+ <rect width="20" height="20" fill="white" />
101
+ </clipPath>
102
+ </defs>
103
+ </svg>
104
+ </>
105
+ )
106
+ }
107
+
108
+ if (language === 'php') {
109
+ return (
110
+ <>
111
+ {showLabel ? <>PHP</> : null}
112
+ <svg viewBox="0 0 128 128" width={size} height={size} className={className}>
113
+ <path d="M64 30.332C28.654 30.332 0 45.407 0 64s28.654 33.668 64 33.668c35.345 0 64-15.075 64-33.668S99.346 30.332 64 30.332zm-5.982 9.81h7.293v.003l-1.745 8.968h6.496c4.087 0 6.908.714 8.458 2.139 1.553 1.427 2.017 2.017 3.737 3.737 5.946 1.719 2.209-2.209 2.209-5.928 0-8.137zm-51.051 51.372c0-3.757-1.072-5.686-3.214-5.791a6.03 6.03 0 00-2.495.409c-.646.231-1.082.461-1.311.692v8.968c1.371.86 2.588 1.26 3.649 1.197 2.247-.148 3.371-1.971 3.371-5.475zm2.643.157c0 1.909-.447 3.493-1.348 4.753-1.003 1.427-2.394 2.16-4.172 2.201-1.34.043-2.721-.378-4.142-1.258v8.151l-2.298-.82V107.14c.377-.462.862-.859 1.451-1.196 1.368-.798 3.031-1.207 4.987-1.228l.033.032c1.788-.022 3.166.712 4.134 2.201.902 1.366 1.355 3.117 1.355 5.257zm14.049 5.349c0 2.56-.257 4.333-.77 5.318-.516.986-1.497 1.773-2.945 2.359-1.174.463-2.444.714-3.808.757l-.38-1.448c1.386-.188 2.362-.378 2.928-.566 1.114-.377 1.878-.955 2.298-1.73.337-.631.503-1.835.503-3.618v-.599a11.809 11.809 0 01-4.941 1.068c-1.132 0-2.13-.354-2.99-1.068-.966-.777-1.449-1.764-1.449-2.958v-9.566l2.299-.787v9.63c0 1.028.332 1.82.996 2.376s1.524.822 2.578.803c1.054-.022 2.183-.431 3.382-1.228v-11.234h2.299v12.491zm8.973 1.479a9.457 9.457 0 01-.757.032c-1.3 0-2.314-.309-3.038-.93-.722-.622-1.084-1.479-1.084-2.573v-9.054h-1.574v-1.446h1.574v-3.84l2.296-.817v4.657h2.583v1.446h-2.583v8.991c0 .862.231 1.474.694 1.83.397.295 1.029.463 1.889.506v1.198zm13.917-.189h-2.298v-8.873c0-.902-.211-1.68-.631-2.329-.485-.734-1.159-1.102-2.024-1.102-1.054 0-2.372.556-3.954 1.668v10.636h-2.298V97.637l2.298-.725v9.659c1.469-1.068 3.073-1.604 4.816-1.604 1.218 0 2.203.41 2.958 1.228.757.817 1.134 1.836 1.134 3.053v9.597h-.001zm12.218-7.157c0-1.444-.274-2.636-.82-3.579-.649-1.149-1.657-1.756-3.021-1.818-2.52.146-3.778 1.951-3.778 5.412 0 1.587.262 2.912.79 3.976.674 1.356 1.685 2.024 3.033 2.002 2.531-.02 3.796-2.017 3.796-5.993zm2.518.015c0 2.055-.526 3.765-1.575 5.131-1.154 1.528-2.749 2.296-4.783 2.296-2.017 0-3.589-.768-4.723-2.296-1.028-1.366-1.542-3.076-1.542-5.131 0-1.932.556-3.556 1.668-4.879 1.174-1.403 2.718-2.107 4.627-2.107 1.909 0 3.463.704 4.66 2.107 1.111 1.323 1.668 2.947 1.668 4.879zm13.178 7.142h-2.299v-9.376c0-1.028-.31-1.831-.928-2.409-.619-.576-1.443-.855-2.472-.833-1.091.021-2.13.378-3.116 1.069v11.549h-2.299v-11.833c1.323-.963 2.54-1.592 3.652-1.886 1.049-.274 1.974-.41 2.771-.41.545 0 1.059.053 1.542.158.903.209 1.637.596 2.203 1.164.631.629.946 1.384.946 2.267v10.54z"></path>
114
+ </svg>
115
+ </>
116
+ )
117
+ }
118
+
119
+ return
120
+ }
121
+ return (
122
+ <div
123
+ className={cn('text-muted-foreground', {
124
+ 'text-sm flex items-center justify-center flex-row gap-2': showLabel,
125
+ 'font-mono text-xs': !showLabel,
126
+ })}
127
+ >
128
+ {renderIcon(language)}
129
+ </div>
130
+ )
131
+ }
@@ -0,0 +1,49 @@
1
+ import { cn } from '@motiadev/ui'
2
+ import { cva, type VariantProps } from 'class-variance-authority'
3
+ import { CalendarClock, CircleOff, Link2, Waypoints } from 'lucide-react'
4
+ import type React from 'react'
5
+ import type { PropsWithChildren } from 'react'
6
+
7
+ const baseIcon = cva('rounded-md p-2', {
8
+ variants: {
9
+ variant: {
10
+ event: 'bg-[rgba(30,118,231,0.2)] text-[rgb(30,118,231)]',
11
+ api: 'dark:bg-[rgba(192,255,17,0.2)] dark:text-[rgb(192,255,17)] bg-[rgb(231,255,166)] text-[rgb(94,125,11)]',
12
+ noop: 'bg-[rgba(239,18,229,0.2)] text-[rgb(239,18,229)]',
13
+ cron: 'bg-[rgba(241,105,15,0.2)] text-[rgb(241,105,15)]',
14
+ },
15
+ },
16
+ })
17
+
18
+ const NodeIcon = ({ variant }: { variant: VariantProps<typeof baseIcon>['variant'] }) => {
19
+ if (variant === 'cron') {
20
+ return <CalendarClock className="w-5 h-5" />
21
+ } else if (variant === 'api') {
22
+ return <Link2 className="w-5 h-5" />
23
+ } else if (variant === 'noop') {
24
+ return <CircleOff className="w-5 h-5" />
25
+ } else if (variant === 'event') {
26
+ return <Waypoints className="w-5 h-5" />
27
+ }
28
+ return <div className={cn(baseIcon({ variant }))}>Icon</div>
29
+ }
30
+
31
+ type Props = PropsWithChildren<{
32
+ text: string
33
+ variant: VariantProps<typeof baseIcon>['variant']
34
+ className?: string
35
+ }>
36
+
37
+ export const NodeHeader: React.FC<Props> = ({ text, variant, children, className }) => (
38
+ <div className={cn('flex items-center gap-2 p-2', className)}>
39
+ <div className={baseIcon({ variant })}>
40
+ <NodeIcon variant={variant} />
41
+ </div>
42
+ <div className="flex flex-1 justify-between items-start gap-4">
43
+ <div className="flex flex-col">
44
+ <div className="text-sm font-semibold leading-[1.25] tracking-[-0.25px]">{text}</div>
45
+ </div>
46
+ {children}
47
+ </div>
48
+ </div>
49
+ )
@@ -0,0 +1,41 @@
1
+ import { Sidebar } from '@motiadev/ui'
2
+ import { X } from 'lucide-react'
3
+ import type React from 'react'
4
+ import type { Feature } from '../../types/file'
5
+ import { CodeDisplay } from './code-display'
6
+
7
+ type NodeSidebarProps = {
8
+ content: string
9
+ features: Feature[]
10
+ title: string
11
+ subtitle?: string
12
+ variant: 'event' | 'api' | 'noop' | 'cron'
13
+ language?: string
14
+ isOpen: boolean
15
+ onClose: () => void
16
+ }
17
+
18
+ export const NodeSidebar: React.FC<NodeSidebarProps> = ({
19
+ content,
20
+ title,
21
+ subtitle,
22
+ language,
23
+ isOpen,
24
+ onClose,
25
+ features,
26
+ }) => {
27
+ if (!isOpen) return null
28
+
29
+ return (
30
+ <Sidebar
31
+ title={title}
32
+ subtitle={subtitle}
33
+ initialWidth={900}
34
+ contentClassName="p-0 h-full gap-0"
35
+ onClose={onClose}
36
+ actions={[{ icon: <X />, onClick: onClose, label: 'Close' }]}
37
+ >
38
+ <CodeDisplay code={content} language={language} features={features} />
39
+ </Sidebar>
40
+ )
41
+ }
@@ -0,0 +1,13 @@
1
+ import type React from 'react'
2
+
3
+ export const Subscribe: React.FC<{ subscribes: string[] }> = ({ subscribes }) => {
4
+ return (
5
+ <div className="flex flex-col gap-2">
6
+ {subscribes.map((subscribe) => (
7
+ <div key={subscribe} data-testid={`subscribes__${subscribe}`}>
8
+ {subscribe}
9
+ </div>
10
+ ))}
11
+ </div>
12
+ )
13
+ }
@@ -0,0 +1,24 @@
1
+ import { Clock } from 'lucide-react'
2
+ import type React from 'react'
3
+ import type { PropsWithChildren } from 'react'
4
+ import { BaseNode } from './base-node/base-node'
5
+ import type { CronNodeProps } from './node-props'
6
+
7
+ export const CronNode: React.FC<PropsWithChildren<CronNodeProps>> = ({ data, children }) => {
8
+ return (
9
+ <BaseNode
10
+ data={data}
11
+ variant="cron"
12
+ title={data.name}
13
+ subtitle={data.description}
14
+ language={data.language}
15
+ disableTargetHandle={!data.virtualSubscribes?.length}
16
+ disableSourceHandle={!data.virtualEmits?.length && !data.emits?.length}
17
+ >
18
+ <div className="text-xs text-muted-foreground flex items-center gap-2">
19
+ <Clock className="w-3 h-3" /> {data.cronExpression}
20
+ </div>
21
+ {children}
22
+ </BaseNode>
23
+ )
24
+ }
@@ -0,0 +1,20 @@
1
+ import type React from 'react'
2
+ import type { PropsWithChildren } from 'react'
3
+ import { BaseNode } from './base-node/base-node'
4
+ import type { EventNodeProps } from './node-props'
5
+
6
+ export const EventNode: React.FC<PropsWithChildren<EventNodeProps>> = ({ data, children }) => {
7
+ return (
8
+ <BaseNode
9
+ data={data}
10
+ variant="event"
11
+ title={data.name}
12
+ subtitle={data.description}
13
+ language={data.language}
14
+ disableSourceHandle={!data.emits?.length && !data.virtualEmits?.length}
15
+ disableTargetHandle={!data.subscribes?.length && !data.virtualSubscribes?.length}
16
+ >
17
+ {children}
18
+ </BaseNode>
19
+ )
20
+ }
@@ -0,0 +1,15 @@
1
+ import type { ApiNodeData, CronNodeData, EventNodeData, NoopNodeData } from '../types/flow'
2
+
3
+ export type NodeProps = EventNodeProps | NoopNodeProps | ApiNodeProps | CronNodeProps
4
+ export type BaseNodeProps = {
5
+ id: string
6
+ nodeConfig?: {
7
+ sourceHandlePosition?: 'bottom' | 'right'
8
+ targetHandlePosition?: 'top' | 'left'
9
+ }
10
+ }
11
+
12
+ export type EventNodeProps = { data: BaseNodeProps & EventNodeData }
13
+ export type NoopNodeProps = { data: BaseNodeProps & NoopNodeData }
14
+ export type ApiNodeProps = { data: BaseNodeProps & ApiNodeData }
15
+ export type CronNodeProps = { data: BaseNodeProps & CronNodeData }
@@ -0,0 +1,19 @@
1
+ import type React from 'react'
2
+ import type { PropsWithChildren } from 'react'
3
+ import { BaseNode } from './base-node/base-node'
4
+ import type { NoopNodeProps } from './node-props'
5
+
6
+ export const NoopNode: React.FC<PropsWithChildren<NoopNodeProps>> = ({ data, children }) => {
7
+ return (
8
+ <BaseNode
9
+ data={data}
10
+ variant="noop"
11
+ title={data.name}
12
+ subtitle={data.description}
13
+ disableSourceHandle={!data.virtualEmits.length}
14
+ disableTargetHandle={!data.subscribes?.length}
15
+ >
16
+ {children}
17
+ </BaseNode>
18
+ )
19
+ }
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom'
@@ -0,0 +1,49 @@
1
+ import { create } from 'zustand'
2
+
3
+ export enum TabLocation {
4
+ TOP = 'top',
5
+ BOTTOM = 'bottom',
6
+ }
7
+
8
+ export type AppTab = {
9
+ id: string
10
+ tabLabel: React.ElementType
11
+ content: React.ElementType
12
+ }
13
+
14
+ export interface AppTabsState {
15
+ tabs: Record<TabLocation, AppTab[]>
16
+ addTab: (position: TabLocation, tab: AppTab) => void
17
+ setTabs: (position: TabLocation, tabs: AppTab[]) => void
18
+ removeTab: (position: TabLocation, id: string) => void
19
+ }
20
+
21
+ const defaultTabs: Record<TabLocation, AppTab[]> = {
22
+ [TabLocation.TOP]: [],
23
+ [TabLocation.BOTTOM]: [],
24
+ }
25
+
26
+ export const useAppTabsStore = create<AppTabsState>((set) => ({
27
+ tabs: defaultTabs,
28
+ addTab: (position: TabLocation, tab: AppTab) =>
29
+ set((state) => ({
30
+ tabs: {
31
+ ...state.tabs,
32
+ [position]: [...state.tabs[position], tab],
33
+ },
34
+ })),
35
+ setTabs: (position: TabLocation, tabs: AppTab[]) =>
36
+ set((state) => ({
37
+ tabs: {
38
+ ...state.tabs,
39
+ [position]: tabs,
40
+ },
41
+ })),
42
+ removeTab: (position: TabLocation, id: string) =>
43
+ set((state) => ({
44
+ tabs: {
45
+ ...state.tabs,
46
+ [position]: state.tabs[position].filter((tab) => tab.id !== id),
47
+ },
48
+ })),
49
+ }))
@@ -0,0 +1,31 @@
1
+ import { create } from 'zustand'
2
+ import { createJSONStorage, persist } from 'zustand/middleware'
3
+
4
+ type UseFlowStore = {
5
+ selectedFlowId?: string
6
+ selectFlowId: (flowId: string) => void
7
+ clearSelectedFlowId: () => void
8
+ flows: string[]
9
+ setFlows: (flows: string[]) => void
10
+ }
11
+
12
+ export const useFlowStore = create(
13
+ persist<UseFlowStore>(
14
+ (set) => ({
15
+ flows: [],
16
+ setFlows: (flows) => set({ flows }),
17
+ selectFlowId: (flowId) =>
18
+ set((state) => {
19
+ if (state.selectedFlowId === flowId) {
20
+ return state
21
+ }
22
+ return { selectedFlowId: flowId }
23
+ }),
24
+ clearSelectedFlowId: () => set({ selectedFlowId: undefined }),
25
+ }),
26
+ {
27
+ name: 'motia-flow-storage',
28
+ storage: createJSONStorage(() => localStorage),
29
+ },
30
+ ),
31
+ )
@@ -0,0 +1,24 @@
1
+ import { create } from 'zustand'
2
+ import { createJSONStorage, persist } from 'zustand/middleware'
3
+
4
+ type UseGlobalStore = {
5
+ selectedEndpointId?: string
6
+ selectEndpointId: (endpointId?: string) => void
7
+ }
8
+
9
+ const select = (id: string | undefined, name: keyof UseGlobalStore) => (state: UseGlobalStore) => {
10
+ return id ? (state[name] === id ? state : { ...state, [name]: id }) : { ...state, [name]: undefined }
11
+ }
12
+
13
+ export const useGlobalStore = create(
14
+ persist<UseGlobalStore>(
15
+ (set) => ({
16
+ selectedEndpointId: undefined,
17
+ selectEndpointId: (endpointId) => set(select(endpointId, 'selectedEndpointId')),
18
+ }),
19
+ {
20
+ name: 'motia-global-storage',
21
+ storage: createJSONStorage(() => localStorage),
22
+ },
23
+ ),
24
+ )
@@ -0,0 +1,36 @@
1
+ import { create } from 'zustand'
2
+
3
+ interface MotiaConfig {
4
+ isDev: boolean
5
+ isTutorialDisabled: boolean
6
+ }
7
+
8
+ interface MotiaConfigState {
9
+ config: MotiaConfig | null
10
+ isLoading: boolean
11
+ error: Error | null
12
+ fetchConfig: () => Promise<void>
13
+ }
14
+
15
+ export const useMotiaConfigStore = create<MotiaConfigState>((set, get) => ({
16
+ config: null,
17
+ isLoading: false,
18
+ error: null,
19
+ fetchConfig: async () => {
20
+ const { config, isLoading } = get()
21
+ if (isLoading || config) return
22
+
23
+ set({ isLoading: true, error: null })
24
+ try {
25
+ const response = await fetch('/__motia')
26
+ if (!response.ok) {
27
+ throw new Error(`Failed to fetch Motia config: ${response.statusText}`)
28
+ }
29
+ const data = await response.json()
30
+ set({ config: data, isLoading: false })
31
+ } catch (error) {
32
+ console.error('Failed to fetch Motia config:', error)
33
+ set({ error: error as Error, isLoading: false })
34
+ }
35
+ },
36
+ }))
@@ -0,0 +1,34 @@
1
+ import { create } from 'zustand'
2
+ import { createJSONStorage, persist } from 'zustand/middleware'
3
+ import { motiaAnalytics } from '../lib/motia-analytics'
4
+
5
+ interface TabsState {
6
+ tab: Record<string, string>
7
+ setTopTab: (tab: string) => void
8
+ setBottomTab: (tab: string) => void
9
+ }
10
+
11
+ export const useTabsStore = create(
12
+ persist<TabsState>(
13
+ (set, get) => ({
14
+ tab: {
15
+ top: 'flow',
16
+ bottom: 'tracing',
17
+ },
18
+ setTopTab: (tab) => {
19
+ const currentTab = get().tab
20
+ motiaAnalytics.track('Top panel tab changed', { 'new.top': tab, tab: currentTab })
21
+ set((state) => ({ tab: { ...state.tab, top: tab } }))
22
+ },
23
+ setBottomTab: (tab) => {
24
+ const currentTab = get().tab
25
+ motiaAnalytics.track('Bottom panel tab changed', { 'new.bottom': tab, tab: currentTab })
26
+ set((state) => ({ tab: { ...state.tab, bottom: tab } }))
27
+ },
28
+ }),
29
+ {
30
+ name: 'motia-tabs-storage',
31
+ storage: createJSONStorage(() => localStorage),
32
+ },
33
+ ),
34
+ )
@@ -0,0 +1,28 @@
1
+ import { APP_SIDEBAR_CONTAINER_ID, CollapsiblePanelGroup } from '@motiadev/ui'
2
+ import { memo } from 'react'
3
+ import { BottomPanel } from './components/bottom-panel'
4
+ import { Header } from './components/header/header'
5
+ import { TopPanel } from './components/top-panel'
6
+
7
+ export const SystemViewMode = memo(() => {
8
+ return (
9
+ <div className="grid grid-rows-[auto_1fr] grid-cols-[1fr_auto] bg-background text-foreground h-screen">
10
+ <div className="col-span-2">
11
+ <Header />
12
+ </div>
13
+ <main className="m-2 overflow-hidden">
14
+ <CollapsiblePanelGroup
15
+ autoSaveId="app-panel"
16
+ direction="vertical"
17
+ className="gap-1 h-full"
18
+ aria-label="Workbench panels"
19
+ >
20
+ <TopPanel />
21
+ <BottomPanel />
22
+ </CollapsiblePanelGroup>
23
+ </main>
24
+ <div id={APP_SIDEBAR_CONTAINER_ID} />
25
+ </div>
26
+ )
27
+ })
28
+ SystemViewMode.displayName = 'SystemViewMode'
@@ -0,0 +1,12 @@
1
+ export type ApiRouteMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD'
2
+ export type QueryParam = { name: string; description: string }
3
+
4
+ export type ApiEndpoint = {
5
+ id: string
6
+ method: ApiRouteMethod
7
+ path: string
8
+ description?: string
9
+ queryParams?: QueryParam[]
10
+ responseSchema?: Record<string, any> // eslint-disable-line @typescript-eslint/no-explicit-any
11
+ bodySchema?: Record<string, Record<string, any>> // eslint-disable-line @typescript-eslint/no-explicit-any
12
+ }
@@ -0,0 +1,7 @@
1
+ export type Feature = {
2
+ id?: string
3
+ title: string
4
+ description: string
5
+ lines: string[]
6
+ link?: string
7
+ }