@brainfish-ai/devdoc 0.1.42 → 0.1.44

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 (398) hide show
  1. package/dist/cli/commands/create.js +2 -2
  2. package/dist/cli/commands/dev.js +19 -10
  3. package/package.json +3 -2
  4. package/renderer/app/api/assets/[...path]/route.js +108 -0
  5. package/renderer/app/api/assets/route.js +114 -0
  6. package/renderer/app/api/assets/upload/route.js +163 -0
  7. package/renderer/app/api/auth-schemes/route.js +58 -0
  8. package/renderer/app/api/chat/route.js +759 -0
  9. package/renderer/app/api/codegen/route.js +52 -0
  10. package/renderer/app/api/collections/route.js +706 -0
  11. package/renderer/app/api/debug/route.js +47 -0
  12. package/renderer/app/api/deploy/route.js +199 -0
  13. package/renderer/app/api/device/route.js +36 -0
  14. package/renderer/app/api/docs/route.js +205 -0
  15. package/renderer/app/api/domains/add/route.js +121 -0
  16. package/renderer/app/api/domains/lookup/route.js +43 -0
  17. package/renderer/app/api/domains/remove/route.js +89 -0
  18. package/renderer/app/api/domains/status/route.js +140 -0
  19. package/renderer/app/api/domains/verify/route.js +168 -0
  20. package/renderer/app/api/keys/regenerate/route.js +71 -0
  21. package/renderer/app/api/local-assets/[...path]/route.js +108 -0
  22. package/renderer/app/api/openapi-spec/route.js +73 -0
  23. package/renderer/app/api/projects/[slug]/route.js +129 -0
  24. package/renderer/app/api/projects/[slug]/stats/route.js +80 -0
  25. package/renderer/app/api/projects/register/route.js +176 -0
  26. package/renderer/app/api/proxy/route.js +139 -0
  27. package/renderer/app/api/proxy-stream/route.js +156 -0
  28. package/renderer/app/api/redirects/route.js +35 -0
  29. package/renderer/app/api/schema/route.js +85 -0
  30. package/renderer/app/api/subdomains/check/route.js +158 -0
  31. package/renderer/app/api/suggestions/route.js +195 -0
  32. package/renderer/app/globals.css +69 -0
  33. package/renderer/app/layout.js +47 -0
  34. package/renderer/app/llms-full.txt/route.js +266 -0
  35. package/renderer/app/llms.txt/route.js +228 -0
  36. package/renderer/app/page.js +12 -0
  37. package/renderer/app/robots.txt/route.js +66 -0
  38. package/renderer/app/sitemap.xml/route.js +155 -0
  39. package/renderer/components/docs/index.js +8 -0
  40. package/renderer/components/docs/mdx/accordion.js +113 -0
  41. package/renderer/components/docs/mdx/badge.js +72 -0
  42. package/renderer/components/docs/mdx/callouts.js +137 -0
  43. package/renderer/components/docs/mdx/cards.js +175 -0
  44. package/renderer/components/docs/mdx/changelog.js +100 -0
  45. package/renderer/components/docs/mdx/code-block.js +147 -0
  46. package/renderer/components/docs/mdx/code-group.js +287 -0
  47. package/renderer/components/docs/mdx/file-embeds.js +82 -0
  48. package/renderer/components/docs/mdx/frame.js +59 -0
  49. package/renderer/components/docs/mdx/highlight.js +90 -0
  50. package/renderer/components/docs/mdx/iframe.js +69 -0
  51. package/renderer/components/docs/mdx/image.js +135 -0
  52. package/renderer/components/docs/mdx/index.js +134 -0
  53. package/renderer/components/docs/mdx/landing.js +317 -0
  54. package/renderer/components/docs/mdx/mermaid.js +212 -0
  55. package/renderer/components/docs/mdx/param-field.js +112 -0
  56. package/renderer/components/docs/mdx/steps.js +74 -0
  57. package/renderer/components/docs/mdx/tabs.js +50 -0
  58. package/renderer/components/docs/mdx-renderer.js +77 -0
  59. package/renderer/components/docs/navigation/breadcrumbs.js +64 -0
  60. package/renderer/components/docs/navigation/index.js +6 -0
  61. package/renderer/components/docs/navigation/page-nav.js +57 -0
  62. package/renderer/components/docs/navigation/sidebar.js +375 -0
  63. package/renderer/components/docs/navigation/toc.js +89 -0
  64. package/renderer/components/docs/notice.js +77 -0
  65. package/renderer/components/docs-header.js +202 -0
  66. package/renderer/components/docs-viewer/agent/agent-chat.js +1831 -0
  67. package/renderer/components/docs-viewer/agent/agent-popup-button.js +99 -0
  68. package/renderer/components/docs-viewer/agent/cards/debug-context-card.js +107 -0
  69. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.js +57 -0
  70. package/renderer/components/docs-viewer/agent/cards/index.js +45 -0
  71. package/renderer/components/docs-viewer/agent/cards/response-options-card.js +154 -0
  72. package/renderer/components/docs-viewer/agent/cards/types.js +22 -0
  73. package/renderer/components/docs-viewer/agent/chat-message.js +2 -0
  74. package/renderer/components/docs-viewer/agent/index.js +7 -0
  75. package/renderer/components/docs-viewer/agent/messages/assistant-message.js +108 -0
  76. package/renderer/components/docs-viewer/agent/messages/chat-message.js +34 -0
  77. package/renderer/components/docs-viewer/agent/messages/index.js +6 -0
  78. package/renderer/components/docs-viewer/agent/messages/tool-call-display.js +1065 -0
  79. package/renderer/components/docs-viewer/agent/messages/types.js +2 -0
  80. package/renderer/components/docs-viewer/agent/messages/typing-indicator.js +26 -0
  81. package/renderer/components/docs-viewer/agent/messages/user-message.js +37 -0
  82. package/renderer/components/docs-viewer/code-editor/{index.tsx → index.js} +1 -1
  83. package/renderer/components/docs-viewer/code-editor/notes-mode.js +1338 -0
  84. package/renderer/components/docs-viewer/content/changelog-page.js +297 -0
  85. package/renderer/components/docs-viewer/content/content-router.js +182 -0
  86. package/renderer/components/docs-viewer/content/doc-page.js +290 -0
  87. package/renderer/components/docs-viewer/content/documentation-viewer.js +14 -0
  88. package/renderer/components/docs-viewer/content/index.js +31 -0
  89. package/renderer/components/docs-viewer/content/not-found-page.js +300 -0
  90. package/renderer/components/docs-viewer/content/request-details.js +528 -0
  91. package/renderer/components/docs-viewer/content/sections/auth.js +108 -0
  92. package/renderer/components/docs-viewer/content/sections/body.js +80 -0
  93. package/renderer/components/docs-viewer/content/sections/headers.js +64 -0
  94. package/renderer/components/docs-viewer/content/sections/overview.js +56 -0
  95. package/renderer/components/docs-viewer/content/sections/parameters.js +64 -0
  96. package/renderer/components/docs-viewer/content/sections/responses.js +91 -0
  97. package/renderer/components/docs-viewer/global-auth-modal.js +427 -0
  98. package/renderer/components/docs-viewer/index.js +1448 -0
  99. package/renderer/components/docs-viewer/playground/auth-editor.js +418 -0
  100. package/renderer/components/docs-viewer/playground/body-editor.js +240 -0
  101. package/renderer/components/docs-viewer/playground/code-editor.js +135 -0
  102. package/renderer/components/docs-viewer/playground/code-snippet.js +393 -0
  103. package/renderer/components/docs-viewer/playground/graphql-playground.js +936 -0
  104. package/renderer/components/docs-viewer/playground/index.js +682 -0
  105. package/renderer/components/docs-viewer/playground/key-value-editor.js +317 -0
  106. package/renderer/components/docs-viewer/playground/method-selector.js +65 -0
  107. package/renderer/components/docs-viewer/playground/request-builder.js +181 -0
  108. package/renderer/components/docs-viewer/playground/request-tabs.js +240 -0
  109. package/renderer/components/docs-viewer/playground/response-cards/idle-card.js +42 -0
  110. package/renderer/components/docs-viewer/playground/response-cards/index.js +72 -0
  111. package/renderer/components/docs-viewer/playground/response-cards/loading-card.js +24 -0
  112. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.js +28 -0
  113. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.js +308 -0
  114. package/renderer/components/docs-viewer/playground/response-cards/types.js +9 -0
  115. package/renderer/components/docs-viewer/playground/response-viewer.js +18 -0
  116. package/renderer/components/docs-viewer/search/index.js +2 -0
  117. package/renderer/components/docs-viewer/search/search-dialog.js +367 -0
  118. package/renderer/components/docs-viewer/search/use-search.js +89 -0
  119. package/renderer/components/docs-viewer/shared/markdown-renderer.js +423 -0
  120. package/renderer/components/docs-viewer/shared/method-badge.js +23 -0
  121. package/renderer/components/docs-viewer/shared/schema-viewer.js +321 -0
  122. package/renderer/components/docs-viewer/sidebar/collection-tree.js +222 -0
  123. package/renderer/components/docs-viewer/sidebar/endpoint-options.js +512 -0
  124. package/renderer/components/docs-viewer/sidebar/index.js +196 -0
  125. package/renderer/components/docs-viewer/sidebar/right-sidebar.js +159 -0
  126. package/renderer/components/docs-viewer/sidebar/sidebar-group.js +87 -0
  127. package/renderer/components/docs-viewer/sidebar/sidebar-item.js +172 -0
  128. package/renderer/components/docs-viewer/sidebar/sidebar-section.js +31 -0
  129. package/renderer/components/theme-provider.js +10 -0
  130. package/renderer/components/theme-toggle.js +86 -0
  131. package/renderer/components/ui/badge.js +29 -0
  132. package/renderer/components/ui/button.js +40 -0
  133. package/renderer/components/ui/dialog.js +50 -0
  134. package/renderer/components/ui/dropdown-menu.js +143 -0
  135. package/renderer/components/ui/input.js +12 -0
  136. package/renderer/components/ui/label.js +13 -0
  137. package/renderer/components/ui/navigation-menu.js +83 -0
  138. package/renderer/components/ui/select.js +116 -0
  139. package/renderer/components/ui/spinner.js +92 -0
  140. package/renderer/components/ui/tabs.js +34 -0
  141. package/renderer/components/ui/tooltip.js +43 -0
  142. package/renderer/hooks/use-code-copy.js +76 -0
  143. package/renderer/hooks/use-openapi-title.js +33 -0
  144. package/renderer/hooks/use-route-state.js +159 -0
  145. package/renderer/lib/api-docs/agent/index.js +4 -0
  146. package/renderer/lib/api-docs/agent/indexer.js +254 -0
  147. package/renderer/lib/api-docs/agent/spec-summary.js +227 -0
  148. package/renderer/lib/api-docs/agent/types.js +5 -0
  149. package/renderer/lib/api-docs/agent/use-suggestions.js +97 -0
  150. package/renderer/lib/api-docs/auth/auth-context.js +157 -0
  151. package/renderer/lib/api-docs/auth/auth-storage.js +66 -0
  152. package/renderer/lib/api-docs/auth/crypto.js +64 -0
  153. package/renderer/lib/api-docs/auth/index.js +3 -0
  154. package/renderer/lib/api-docs/code-editor/db.js +145 -0
  155. package/renderer/lib/api-docs/code-editor/hooks.js +254 -0
  156. package/renderer/lib/api-docs/code-editor/{index.ts → index.js} +3 -4
  157. package/renderer/lib/api-docs/code-editor/mode-context.js +126 -0
  158. package/renderer/lib/api-docs/code-editor/types.js +53 -0
  159. package/renderer/lib/api-docs/codegen/definitions.js +258 -0
  160. package/renderer/lib/api-docs/codegen/har.js +171 -0
  161. package/renderer/lib/api-docs/codegen/index.js +118 -0
  162. package/renderer/lib/api-docs/factories.js +136 -0
  163. package/renderer/lib/api-docs/{index.ts → index.js} +5 -10
  164. package/renderer/lib/api-docs/mobile-context.js +116 -0
  165. package/renderer/lib/api-docs/navigation-context.js +62 -0
  166. package/renderer/lib/api-docs/parsers/graphql/index.js +50 -0
  167. package/renderer/lib/api-docs/parsers/graphql/parser.js +350 -0
  168. package/renderer/lib/api-docs/parsers/graphql/transformer.js +215 -0
  169. package/renderer/lib/api-docs/parsers/graphql/types.js +46 -0
  170. package/renderer/lib/api-docs/parsers/openapi/dereferencer.js +43 -0
  171. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.js +486 -0
  172. package/renderer/lib/api-docs/parsers/openapi/extractors/body.js +295 -0
  173. package/renderer/lib/api-docs/parsers/openapi/extractors/index.js +132 -0
  174. package/renderer/lib/api-docs/parsers/openapi/index.js +127 -0
  175. package/renderer/lib/api-docs/parsers/openapi/transformer.js +192 -0
  176. package/renderer/lib/api-docs/parsers/openapi/validator.js +24 -0
  177. package/renderer/lib/api-docs/playground/context.js +65 -0
  178. package/renderer/lib/api-docs/playground/navigation-context.js +74 -0
  179. package/renderer/lib/api-docs/playground/request-builder.js +163 -0
  180. package/renderer/lib/api-docs/playground/request-runner.js +224 -0
  181. package/renderer/lib/api-docs/playground/types.js +5 -0
  182. package/renderer/lib/api-docs/types.js +23 -0
  183. package/renderer/lib/api-docs/utils.js +212 -0
  184. package/renderer/lib/cache.js +157 -0
  185. package/renderer/lib/docs/config/domain-schema.js +161 -0
  186. package/renderer/lib/docs/config/environment.js +38 -0
  187. package/renderer/lib/docs/config/index.js +6 -0
  188. package/renderer/lib/docs/config/loader.js +113 -0
  189. package/renderer/lib/docs/config/schema.js +281 -0
  190. package/renderer/lib/docs/index.js +8 -0
  191. package/renderer/lib/docs/mdx/compiler.js +131 -0
  192. package/renderer/lib/docs/mdx/frontmatter.js +73 -0
  193. package/renderer/lib/docs/mdx/index.js +10 -0
  194. package/renderer/lib/docs/mdx/remark-mermaid.js +63 -0
  195. package/renderer/lib/docs/navigation/generator.js +269 -0
  196. package/renderer/lib/docs/navigation/index.js +3 -0
  197. package/renderer/lib/docs/navigation/types.js +11 -0
  198. package/renderer/lib/docs-navigation-context.js +40 -0
  199. package/renderer/lib/docs-navigation.js +140 -0
  200. package/renderer/lib/multi-tenant/context.js +80 -0
  201. package/renderer/lib/storage/blob.js +767 -0
  202. package/renderer/lib/utils/icons.js +30 -0
  203. package/renderer/lib/utils.js +5 -0
  204. package/renderer/next.config.js +62 -0
  205. package/renderer/package.json +1 -0
  206. package/renderer/tsconfig.json +23 -5
  207. package/renderer/app/api/assets/[...path]/route.ts +0 -123
  208. package/renderer/app/api/assets/route.ts +0 -124
  209. package/renderer/app/api/assets/upload/route.ts +0 -177
  210. package/renderer/app/api/auth-schemes/route.ts +0 -77
  211. package/renderer/app/api/chat/route.ts +0 -858
  212. package/renderer/app/api/codegen/route.ts +0 -72
  213. package/renderer/app/api/collections/route.ts +0 -1002
  214. package/renderer/app/api/debug/route.ts +0 -53
  215. package/renderer/app/api/deploy/route.ts +0 -234
  216. package/renderer/app/api/device/route.ts +0 -42
  217. package/renderer/app/api/docs/route.ts +0 -201
  218. package/renderer/app/api/domains/add/route.ts +0 -132
  219. package/renderer/app/api/domains/lookup/route.ts +0 -43
  220. package/renderer/app/api/domains/remove/route.ts +0 -100
  221. package/renderer/app/api/domains/status/route.ts +0 -158
  222. package/renderer/app/api/domains/verify/route.ts +0 -181
  223. package/renderer/app/api/keys/regenerate/route.ts +0 -80
  224. package/renderer/app/api/local-assets/[...path]/route.ts +0 -122
  225. package/renderer/app/api/openapi-spec/route.ts +0 -151
  226. package/renderer/app/api/projects/[slug]/route.ts +0 -153
  227. package/renderer/app/api/projects/[slug]/stats/route.ts +0 -96
  228. package/renderer/app/api/projects/register/route.ts +0 -152
  229. package/renderer/app/api/proxy/route.ts +0 -149
  230. package/renderer/app/api/proxy-stream/route.ts +0 -168
  231. package/renderer/app/api/redirects/route.ts +0 -47
  232. package/renderer/app/api/schema/route.ts +0 -73
  233. package/renderer/app/api/subdomains/check/route.ts +0 -172
  234. package/renderer/app/api/suggestions/route.ts +0 -144
  235. package/renderer/app/layout.tsx +0 -54
  236. package/renderer/app/llms-full.txt/route.ts +0 -346
  237. package/renderer/app/llms.txt/route.ts +0 -279
  238. package/renderer/app/page.tsx +0 -14
  239. package/renderer/app/robots.txt/route.ts +0 -84
  240. package/renderer/app/sitemap.xml/route.ts +0 -199
  241. package/renderer/components/docs/index.ts +0 -12
  242. package/renderer/components/docs/mdx/accordion.tsx +0 -169
  243. package/renderer/components/docs/mdx/badge.tsx +0 -132
  244. package/renderer/components/docs/mdx/callouts.tsx +0 -154
  245. package/renderer/components/docs/mdx/cards.tsx +0 -241
  246. package/renderer/components/docs/mdx/changelog.tsx +0 -120
  247. package/renderer/components/docs/mdx/code-block.tsx +0 -186
  248. package/renderer/components/docs/mdx/code-group.tsx +0 -421
  249. package/renderer/components/docs/mdx/file-embeds.tsx +0 -105
  250. package/renderer/components/docs/mdx/frame.tsx +0 -112
  251. package/renderer/components/docs/mdx/highlight.tsx +0 -151
  252. package/renderer/components/docs/mdx/iframe.tsx +0 -134
  253. package/renderer/components/docs/mdx/image.tsx +0 -235
  254. package/renderer/components/docs/mdx/index.ts +0 -237
  255. package/renderer/components/docs/mdx/landing.tsx +0 -684
  256. package/renderer/components/docs/mdx/mermaid.tsx +0 -240
  257. package/renderer/components/docs/mdx/param-field.tsx +0 -200
  258. package/renderer/components/docs/mdx/steps.tsx +0 -113
  259. package/renderer/components/docs/mdx/tabs.tsx +0 -86
  260. package/renderer/components/docs/mdx-renderer.tsx +0 -100
  261. package/renderer/components/docs/navigation/breadcrumbs.tsx +0 -76
  262. package/renderer/components/docs/navigation/index.ts +0 -8
  263. package/renderer/components/docs/navigation/page-nav.tsx +0 -64
  264. package/renderer/components/docs/navigation/sidebar.tsx +0 -515
  265. package/renderer/components/docs/navigation/toc.tsx +0 -113
  266. package/renderer/components/docs/notice.tsx +0 -105
  267. package/renderer/components/docs-header.tsx +0 -278
  268. package/renderer/components/docs-viewer/agent/agent-chat.tsx +0 -2076
  269. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +0 -90
  270. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +0 -49
  271. package/renderer/components/docs-viewer/agent/cards/index.tsx +0 -50
  272. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +0 -212
  273. package/renderer/components/docs-viewer/agent/cards/types.ts +0 -84
  274. package/renderer/components/docs-viewer/agent/chat-message.tsx +0 -17
  275. package/renderer/components/docs-viewer/agent/index.tsx +0 -6
  276. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +0 -119
  277. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +0 -46
  278. package/renderer/components/docs-viewer/agent/messages/index.ts +0 -17
  279. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +0 -721
  280. package/renderer/components/docs-viewer/agent/messages/types.ts +0 -61
  281. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +0 -24
  282. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +0 -51
  283. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +0 -1283
  284. package/renderer/components/docs-viewer/content/changelog-page.tsx +0 -331
  285. package/renderer/components/docs-viewer/content/doc-page.tsx +0 -367
  286. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +0 -17
  287. package/renderer/components/docs-viewer/content/index.tsx +0 -29
  288. package/renderer/components/docs-viewer/content/not-found-page.tsx +0 -330
  289. package/renderer/components/docs-viewer/content/request-details.tsx +0 -330
  290. package/renderer/components/docs-viewer/content/sections/auth.tsx +0 -69
  291. package/renderer/components/docs-viewer/content/sections/body.tsx +0 -66
  292. package/renderer/components/docs-viewer/content/sections/headers.tsx +0 -43
  293. package/renderer/components/docs-viewer/content/sections/overview.tsx +0 -40
  294. package/renderer/components/docs-viewer/content/sections/parameters.tsx +0 -43
  295. package/renderer/components/docs-viewer/content/sections/responses.tsx +0 -87
  296. package/renderer/components/docs-viewer/global-auth-modal.tsx +0 -352
  297. package/renderer/components/docs-viewer/index.tsx +0 -1670
  298. package/renderer/components/docs-viewer/playground/auth-editor.tsx +0 -280
  299. package/renderer/components/docs-viewer/playground/body-editor.tsx +0 -221
  300. package/renderer/components/docs-viewer/playground/code-editor.tsx +0 -224
  301. package/renderer/components/docs-viewer/playground/code-snippet.tsx +0 -387
  302. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +0 -745
  303. package/renderer/components/docs-viewer/playground/index.tsx +0 -671
  304. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +0 -261
  305. package/renderer/components/docs-viewer/playground/method-selector.tsx +0 -60
  306. package/renderer/components/docs-viewer/playground/request-builder.tsx +0 -179
  307. package/renderer/components/docs-viewer/playground/request-tabs.tsx +0 -237
  308. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +0 -21
  309. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +0 -93
  310. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +0 -16
  311. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +0 -23
  312. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +0 -268
  313. package/renderer/components/docs-viewer/playground/response-cards/types.ts +0 -82
  314. package/renderer/components/docs-viewer/playground/response-viewer.tsx +0 -43
  315. package/renderer/components/docs-viewer/search/index.ts +0 -2
  316. package/renderer/components/docs-viewer/search/search-dialog.tsx +0 -331
  317. package/renderer/components/docs-viewer/search/use-search.ts +0 -117
  318. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +0 -431
  319. package/renderer/components/docs-viewer/shared/method-badge.tsx +0 -41
  320. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +0 -349
  321. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +0 -259
  322. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +0 -316
  323. package/renderer/components/docs-viewer/sidebar/index.tsx +0 -282
  324. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +0 -202
  325. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +0 -118
  326. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +0 -212
  327. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +0 -38
  328. package/renderer/components/theme-provider.tsx +0 -11
  329. package/renderer/components/theme-toggle.tsx +0 -76
  330. package/renderer/components/ui/badge.tsx +0 -46
  331. package/renderer/components/ui/button.tsx +0 -59
  332. package/renderer/components/ui/dialog.tsx +0 -118
  333. package/renderer/components/ui/dropdown-menu.tsx +0 -257
  334. package/renderer/components/ui/input.tsx +0 -21
  335. package/renderer/components/ui/label.tsx +0 -24
  336. package/renderer/components/ui/navigation-menu.tsx +0 -168
  337. package/renderer/components/ui/select.tsx +0 -190
  338. package/renderer/components/ui/spinner.tsx +0 -114
  339. package/renderer/components/ui/tabs.tsx +0 -66
  340. package/renderer/components/ui/tooltip.tsx +0 -61
  341. package/renderer/hooks/use-code-copy.ts +0 -88
  342. package/renderer/hooks/use-openapi-title.ts +0 -44
  343. package/renderer/lib/api-docs/agent/index.ts +0 -6
  344. package/renderer/lib/api-docs/agent/indexer.ts +0 -323
  345. package/renderer/lib/api-docs/agent/spec-summary.ts +0 -335
  346. package/renderer/lib/api-docs/agent/types.ts +0 -116
  347. package/renderer/lib/api-docs/auth/auth-context.tsx +0 -225
  348. package/renderer/lib/api-docs/auth/auth-storage.ts +0 -87
  349. package/renderer/lib/api-docs/auth/crypto.ts +0 -89
  350. package/renderer/lib/api-docs/auth/index.ts +0 -4
  351. package/renderer/lib/api-docs/code-editor/db.ts +0 -164
  352. package/renderer/lib/api-docs/code-editor/hooks.ts +0 -266
  353. package/renderer/lib/api-docs/code-editor/mode-context.tsx +0 -207
  354. package/renderer/lib/api-docs/code-editor/types.ts +0 -105
  355. package/renderer/lib/api-docs/codegen/definitions.ts +0 -297
  356. package/renderer/lib/api-docs/codegen/har.ts +0 -251
  357. package/renderer/lib/api-docs/codegen/index.ts +0 -159
  358. package/renderer/lib/api-docs/factories.ts +0 -170
  359. package/renderer/lib/api-docs/mobile-context.tsx +0 -112
  360. package/renderer/lib/api-docs/navigation-context.tsx +0 -88
  361. package/renderer/lib/api-docs/parsers/graphql/README.md +0 -129
  362. package/renderer/lib/api-docs/parsers/graphql/index.ts +0 -91
  363. package/renderer/lib/api-docs/parsers/graphql/parser.ts +0 -491
  364. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +0 -246
  365. package/renderer/lib/api-docs/parsers/graphql/types.ts +0 -283
  366. package/renderer/lib/api-docs/parsers/openapi/README.md +0 -32
  367. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +0 -60
  368. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +0 -574
  369. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +0 -403
  370. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +0 -232
  371. package/renderer/lib/api-docs/parsers/openapi/index.ts +0 -171
  372. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +0 -278
  373. package/renderer/lib/api-docs/parsers/openapi/validator.ts +0 -31
  374. package/renderer/lib/api-docs/playground/context.tsx +0 -107
  375. package/renderer/lib/api-docs/playground/navigation-context.tsx +0 -124
  376. package/renderer/lib/api-docs/playground/request-builder.ts +0 -223
  377. package/renderer/lib/api-docs/playground/request-runner.ts +0 -282
  378. package/renderer/lib/api-docs/playground/types.ts +0 -35
  379. package/renderer/lib/api-docs/types.ts +0 -269
  380. package/renderer/lib/api-docs/utils.ts +0 -311
  381. package/renderer/lib/cache.ts +0 -193
  382. package/renderer/lib/docs/config/domain-schema.ts +0 -260
  383. package/renderer/lib/docs/config/index.ts +0 -43
  384. package/renderer/lib/docs/config/loader.ts +0 -142
  385. package/renderer/lib/docs/config/schema.ts +0 -308
  386. package/renderer/lib/docs/index.ts +0 -12
  387. package/renderer/lib/docs/mdx/compiler.ts +0 -176
  388. package/renderer/lib/docs/mdx/frontmatter.ts +0 -91
  389. package/renderer/lib/docs/mdx/index.ts +0 -26
  390. package/renderer/lib/docs/navigation/generator.ts +0 -348
  391. package/renderer/lib/docs/navigation/index.ts +0 -12
  392. package/renderer/lib/docs/navigation/types.ts +0 -123
  393. package/renderer/lib/docs-navigation-context.tsx +0 -80
  394. package/renderer/lib/multi-tenant/context.ts +0 -105
  395. package/renderer/lib/storage/blob.ts +0 -1083
  396. package/renderer/lib/utils/icons.ts +0 -48
  397. package/renderer/lib/utils.ts +0 -6
  398. package/renderer/next.config.ts +0 -76
@@ -0,0 +1,1338 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import React, { useState, useCallback, useEffect, useRef, useMemo } from 'react';
4
+ import Editor from '@monaco-editor/react';
5
+ import { File, Folder, FolderOpen, X, FloppyDisk, CaretRight, CaretDown, Spinner, Plus, Minus, Eye, Code, Trash, ArrowsOut, ArrowClockwise } from '@phosphor-icons/react';
6
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
7
+ import { Button } from '@/components/ui/button';
8
+ import { cn } from '@/lib/utils';
9
+ import { useModeContext, useWorkspace, useNotes, useEditorState, getMonacoLanguage, getFileType, supportsPreview } from '@/lib/api-docs/code-editor';
10
+ // VSCode-style file icon with color coding
11
+ function FileIcon({ path, className }) {
12
+ const type = getFileType(path);
13
+ const colorMap = {
14
+ 'javascript': 'text-yellow-400',
15
+ 'typescript': 'text-blue-400',
16
+ 'python': 'text-green-500',
17
+ 'go': 'text-cyan-400',
18
+ 'ruby': 'text-red-400',
19
+ 'php': 'text-purple-400',
20
+ 'shell': 'text-green-400',
21
+ 'markdown': 'text-blue-300',
22
+ 'mermaid': 'text-pink-400',
23
+ 'json': 'text-yellow-500',
24
+ 'yaml': 'text-red-300',
25
+ 'text': 'text-zinc-400'
26
+ };
27
+ return /*#__PURE__*/ _jsx(File, {
28
+ className: cn('h-4 w-4 flex-shrink-0', colorMap[type] || 'text-zinc-400', className),
29
+ weight: "fill"
30
+ });
31
+ }
32
+ function buildFileTree(files) {
33
+ const root = [];
34
+ // Filter out .folder placeholder files - they're only used internally to create folder structure
35
+ const visibleFiles = files.filter((f)=>!f.path.endsWith('.folder') && !f.path.includes('/.folder'));
36
+ const sortedFiles = [
37
+ ...visibleFiles
38
+ ].sort((a, b)=>a.path.localeCompare(b.path));
39
+ for (const file of sortedFiles){
40
+ const parts = file.path.split('/');
41
+ let current = root;
42
+ for(let i = 0; i < parts.length; i++){
43
+ const part = parts[i];
44
+ const isLastPart = i === parts.length - 1;
45
+ const currentPath = parts.slice(0, i + 1).join('/');
46
+ let existing = current.find((n)=>n.name === part);
47
+ if (!existing) {
48
+ existing = {
49
+ name: part,
50
+ path: currentPath,
51
+ isFolder: !isLastPart,
52
+ children: isLastPart ? undefined : [],
53
+ file: isLastPart ? file : undefined
54
+ };
55
+ current.push(existing);
56
+ }
57
+ if (!isLastPart && existing.children) {
58
+ current = existing.children;
59
+ }
60
+ }
61
+ }
62
+ // Sort: folders first, then alphabetically
63
+ const sortNodes = (nodes)=>{
64
+ return nodes.sort((a, b)=>{
65
+ if (a.isFolder !== b.isFolder) return a.isFolder ? -1 : 1;
66
+ return a.name.localeCompare(b.name);
67
+ }).map((node)=>({
68
+ ...node,
69
+ children: node.children ? sortNodes(node.children) : undefined
70
+ }));
71
+ };
72
+ return sortNodes(root);
73
+ }
74
+ function FileTreeItem({ node, depth, activeFile, expandedFolders, onFileClick, onFolderToggle, onDelete }) {
75
+ const isExpanded = expandedFolders.has(node.path);
76
+ const isActive = activeFile === node.path;
77
+ const [showContextMenu, setShowContextMenu] = useState(null);
78
+ // Close context menu
79
+ useEffect(()=>{
80
+ if (showContextMenu) {
81
+ const handleClick = ()=>setShowContextMenu(null);
82
+ const handleKeyDown = (e)=>{
83
+ if (e.key === 'Escape') setShowContextMenu(null);
84
+ };
85
+ document.addEventListener('click', handleClick);
86
+ document.addEventListener('keydown', handleKeyDown);
87
+ return ()=>{
88
+ document.removeEventListener('click', handleClick);
89
+ document.removeEventListener('keydown', handleKeyDown);
90
+ };
91
+ }
92
+ }, [
93
+ showContextMenu
94
+ ]);
95
+ const handleClick = (e)=>{
96
+ e.preventDefault();
97
+ if (node.isFolder) {
98
+ onFolderToggle(node.path);
99
+ } else {
100
+ onFileClick(node.path);
101
+ }
102
+ };
103
+ const handleContextMenu = (e)=>{
104
+ e.preventDefault();
105
+ setShowContextMenu({
106
+ x: e.clientX,
107
+ y: e.clientY
108
+ });
109
+ };
110
+ return /*#__PURE__*/ _jsxs("div", {
111
+ className: "relative",
112
+ children: [
113
+ /*#__PURE__*/ _jsxs("button", {
114
+ onClick: handleClick,
115
+ onContextMenu: handleContextMenu,
116
+ className: cn('w-full flex items-center gap-1 text-[13px] text-left transition-colors group', isActive && 'sandbox-file-active', !isActive && 'sandbox-file-hover'),
117
+ style: {
118
+ height: '22px',
119
+ paddingLeft: `${depth * 8 + 4}px`,
120
+ paddingRight: '8px'
121
+ },
122
+ children: [
123
+ /*#__PURE__*/ _jsx("span", {
124
+ className: "w-4 h-4 flex items-center justify-center flex-shrink-0",
125
+ children: node.isFolder && (isExpanded ? /*#__PURE__*/ _jsx(CaretDown, {
126
+ className: "h-3 w-3 text-zinc-400",
127
+ weight: "bold"
128
+ }) : /*#__PURE__*/ _jsx(CaretRight, {
129
+ className: "h-3 w-3 text-zinc-400",
130
+ weight: "bold"
131
+ }))
132
+ }),
133
+ node.isFolder ? isExpanded ? /*#__PURE__*/ _jsx(FolderOpen, {
134
+ className: "h-4 w-4 text-amber-400 flex-shrink-0",
135
+ weight: "fill"
136
+ }) : /*#__PURE__*/ _jsx(Folder, {
137
+ className: "h-4 w-4 text-amber-400 flex-shrink-0",
138
+ weight: "fill"
139
+ }) : /*#__PURE__*/ _jsx(FileIcon, {
140
+ path: node.path
141
+ }),
142
+ /*#__PURE__*/ _jsx("span", {
143
+ className: cn('truncate ml-1', isActive && 'text-white', !isActive && 'text-zinc-300'),
144
+ children: node.name
145
+ })
146
+ ]
147
+ }),
148
+ showContextMenu && !node.isFolder && /*#__PURE__*/ _jsx("div", {
149
+ className: "fixed z-50 min-w-[140px] py-1 sandbox-context-menu rounded shadow-xl",
150
+ style: {
151
+ left: showContextMenu.x,
152
+ top: showContextMenu.y
153
+ },
154
+ onClick: (e)=>e.stopPropagation(),
155
+ children: /*#__PURE__*/ _jsxs("button", {
156
+ onClick: ()=>{
157
+ onDelete?.(node.path);
158
+ setShowContextMenu(null);
159
+ },
160
+ className: "w-full flex items-center gap-2 px-3 py-1.5 text-[13px] sandbox-context-menu-delete text-left",
161
+ children: [
162
+ /*#__PURE__*/ _jsx(Trash, {
163
+ className: "h-4 w-4"
164
+ }),
165
+ "Delete"
166
+ ]
167
+ })
168
+ }),
169
+ node.isFolder && isExpanded && node.children && /*#__PURE__*/ _jsx("div", {
170
+ children: node.children.map((child)=>/*#__PURE__*/ _jsx(FileTreeItem, {
171
+ node: child,
172
+ depth: depth + 1,
173
+ activeFile: activeFile,
174
+ expandedFolders: expandedFolders,
175
+ onFileClick: onFileClick,
176
+ onFolderToggle: onFolderToggle,
177
+ onDelete: onDelete
178
+ }, child.path))
179
+ })
180
+ ]
181
+ });
182
+ }
183
+ // Editor tabs
184
+ function EditorTabs({ tabs, activeTab, onTabClick, onTabClose }) {
185
+ if (tabs.length === 0) return null;
186
+ return /*#__PURE__*/ _jsxs("div", {
187
+ className: "flex items-center h-[35px] sandbox-tabs overflow-x-auto",
188
+ children: [
189
+ tabs.map((path)=>{
190
+ const fileName = path.split('/').pop() || path;
191
+ const isActive = path === activeTab;
192
+ return /*#__PURE__*/ _jsxs("div", {
193
+ className: cn('relative flex items-center gap-1.5 px-3 h-full text-[13px] cursor-pointer group min-w-0', isActive ? 'sandbox-tab-active' : 'sandbox-tab-inactive'),
194
+ onClick: ()=>onTabClick(path),
195
+ children: [
196
+ isActive && /*#__PURE__*/ _jsx("div", {
197
+ className: "absolute top-0 left-0 right-0 h-[2px] sandbox-tab-indicator"
198
+ }),
199
+ /*#__PURE__*/ _jsx(FileIcon, {
200
+ path: path,
201
+ className: "h-4 w-4 flex-shrink-0"
202
+ }),
203
+ /*#__PURE__*/ _jsx("span", {
204
+ className: "truncate",
205
+ children: fileName
206
+ }),
207
+ /*#__PURE__*/ _jsx("button", {
208
+ onClick: (e)=>{
209
+ e.stopPropagation();
210
+ onTabClose(path);
211
+ },
212
+ className: cn('p-0.5 rounded flex-shrink-0 ml-1 sandbox-tab-close', isActive ? '' : 'opacity-0 group-hover:opacity-100'),
213
+ children: /*#__PURE__*/ _jsx(X, {
214
+ className: "h-3 w-3"
215
+ })
216
+ })
217
+ ]
218
+ }, path);
219
+ }),
220
+ /*#__PURE__*/ _jsx("div", {
221
+ className: "flex-1 h-full sandbox-tabs"
222
+ })
223
+ ]
224
+ });
225
+ }
226
+ // Note type templates
227
+ const noteTemplates = [
228
+ {
229
+ ext: '.py',
230
+ name: 'Python',
231
+ color: 'text-green-400',
232
+ bg: 'bg-green-500/10 hover:bg-green-500/20 border-green-500/30',
233
+ desc: 'Python script'
234
+ },
235
+ {
236
+ ext: '.ts',
237
+ name: 'TypeScript',
238
+ color: 'text-blue-400',
239
+ bg: 'bg-blue-500/10 hover:bg-blue-500/20 border-blue-500/30',
240
+ desc: 'TypeScript code'
241
+ },
242
+ {
243
+ ext: '.js',
244
+ name: 'JavaScript',
245
+ color: 'text-yellow-400',
246
+ bg: 'bg-yellow-500/10 hover:bg-yellow-500/20 border-yellow-500/30',
247
+ desc: 'JavaScript code'
248
+ },
249
+ {
250
+ ext: '.md',
251
+ name: 'Markdown',
252
+ color: 'text-blue-300',
253
+ bg: 'bg-blue-400/10 hover:bg-blue-400/20 border-blue-400/30',
254
+ desc: 'Documentation'
255
+ },
256
+ {
257
+ ext: '.mmd',
258
+ name: 'Mermaid',
259
+ color: 'text-pink-400',
260
+ bg: 'bg-pink-500/10 hover:bg-pink-500/20 border-pink-500/30',
261
+ desc: 'Diagrams'
262
+ },
263
+ {
264
+ ext: '.json',
265
+ name: 'JSON',
266
+ color: 'text-yellow-500',
267
+ bg: 'bg-yellow-500/10 hover:bg-yellow-500/20 border-yellow-500/30',
268
+ desc: 'Data/Config'
269
+ },
270
+ {
271
+ ext: '.go',
272
+ name: 'Go',
273
+ color: 'text-cyan-400',
274
+ bg: 'bg-cyan-500/10 hover:bg-cyan-500/20 border-cyan-500/30',
275
+ desc: 'Go code'
276
+ },
277
+ {
278
+ ext: '.rb',
279
+ name: 'Ruby',
280
+ color: 'text-red-400',
281
+ bg: 'bg-red-500/10 hover:bg-red-500/20 border-red-500/30',
282
+ desc: 'Ruby script'
283
+ }
284
+ ];
285
+ // New file dialog - VSCode style command palette
286
+ function NewNoteDialog({ open, onOpenChange, onCreateNote }) {
287
+ const [fileName, setFileName] = useState('');
288
+ const [selectedTemplate, setSelectedTemplate] = useState(null);
289
+ const inputRef = useRef(null);
290
+ // Reset on open
291
+ useEffect(()=>{
292
+ if (open) {
293
+ setFileName('');
294
+ setSelectedTemplate(null);
295
+ setTimeout(()=>inputRef.current?.focus(), 50);
296
+ }
297
+ }, [
298
+ open
299
+ ]);
300
+ // Detect file type from name
301
+ const detectedType = useMemo(()=>{
302
+ const ext = fileName.match(/\.[^.]+$/)?.[0];
303
+ return noteTemplates.find((t)=>t.ext === ext) || null;
304
+ }, [
305
+ fileName
306
+ ]);
307
+ const handleCreate = ()=>{
308
+ if (!fileName.trim()) return;
309
+ let finalName = fileName.trim();
310
+ // Add extension if not present and template selected
311
+ if (selectedTemplate && !finalName.includes('.')) {
312
+ finalName += selectedTemplate.ext;
313
+ }
314
+ onCreateNote(finalName);
315
+ setFileName('');
316
+ setSelectedTemplate(null);
317
+ onOpenChange(false);
318
+ };
319
+ const handleTemplateClick = (template)=>{
320
+ setSelectedTemplate(template);
321
+ // Update file name with new extension
322
+ const baseName = fileName.replace(/\.[^.]+$/, '') || 'untitled';
323
+ setFileName(baseName + template.ext);
324
+ inputRef.current?.focus();
325
+ };
326
+ const handleKeyDown = (e)=>{
327
+ if (e.key === 'Enter' && fileName.trim()) {
328
+ handleCreate();
329
+ }
330
+ if (e.key === 'Escape') {
331
+ onOpenChange(false);
332
+ }
333
+ };
334
+ const activeTemplate = detectedType || selectedTemplate;
335
+ if (!open) return null;
336
+ return /*#__PURE__*/ _jsxs("div", {
337
+ className: "fixed inset-0 z-50 flex items-start justify-center pt-[15vh]",
338
+ children: [
339
+ /*#__PURE__*/ _jsx("div", {
340
+ className: "absolute inset-0 bg-black/50",
341
+ onClick: ()=>onOpenChange(false)
342
+ }),
343
+ /*#__PURE__*/ _jsxs("div", {
344
+ className: "relative w-full max-w-lg mx-4 bg-[#1e1e1e] border border-[#454545] rounded-lg shadow-2xl overflow-hidden",
345
+ children: [
346
+ /*#__PURE__*/ _jsxs("div", {
347
+ className: "flex items-center gap-3 p-3 border-b border-[#3c3c3c]",
348
+ children: [
349
+ /*#__PURE__*/ _jsx("div", {
350
+ className: cn("w-8 h-8 rounded flex items-center justify-center flex-shrink-0 transition-colors", activeTemplate ? activeTemplate.bg : "bg-[#2d2d2d]"),
351
+ children: /*#__PURE__*/ _jsx(File, {
352
+ className: cn("h-4 w-4", activeTemplate?.color || "text-zinc-400"),
353
+ weight: "fill"
354
+ })
355
+ }),
356
+ /*#__PURE__*/ _jsx("input", {
357
+ ref: inputRef,
358
+ type: "text",
359
+ value: fileName,
360
+ onChange: (e)=>setFileName(e.target.value),
361
+ onKeyDown: handleKeyDown,
362
+ placeholder: "Enter file name...",
363
+ className: "flex-1 bg-transparent text-sm text-zinc-100 placeholder:text-zinc-500 outline-none"
364
+ }),
365
+ fileName.trim() && /*#__PURE__*/ _jsx("button", {
366
+ onClick: handleCreate,
367
+ className: "px-3 py-1.5 text-xs font-medium bg-[#007acc] hover:bg-[#006bb3] text-white rounded transition-colors",
368
+ children: "Create"
369
+ })
370
+ ]
371
+ }),
372
+ /*#__PURE__*/ _jsxs("div", {
373
+ className: "p-3",
374
+ children: [
375
+ /*#__PURE__*/ _jsx("p", {
376
+ className: "text-[11px] uppercase tracking-wider text-zinc-500 mb-2 px-1",
377
+ children: "Select type"
378
+ }),
379
+ /*#__PURE__*/ _jsx("div", {
380
+ className: "grid grid-cols-4 gap-2",
381
+ children: noteTemplates.map((template)=>{
382
+ const isActive = activeTemplate?.ext === template.ext;
383
+ return /*#__PURE__*/ _jsxs("button", {
384
+ onClick: ()=>handleTemplateClick(template),
385
+ className: cn("flex flex-col items-center gap-1.5 p-3 rounded-lg border transition-all", isActive ? `${template.bg} border-current` : "bg-[#2d2d2d] border-[#3c3c3c] hover:bg-[#333333] hover:border-[#4c4c4c]"),
386
+ children: [
387
+ /*#__PURE__*/ _jsx(File, {
388
+ className: cn("h-5 w-5", template.color),
389
+ weight: "fill"
390
+ }),
391
+ /*#__PURE__*/ _jsx("span", {
392
+ className: cn("text-[11px] font-medium", isActive ? template.color : "text-zinc-300"),
393
+ children: template.name
394
+ })
395
+ ]
396
+ }, template.ext);
397
+ })
398
+ })
399
+ ]
400
+ }),
401
+ /*#__PURE__*/ _jsxs("div", {
402
+ className: "px-4 py-2.5 bg-[#252526] border-t border-[#3c3c3c] flex items-center justify-between",
403
+ children: [
404
+ /*#__PURE__*/ _jsxs("p", {
405
+ className: "text-[11px] text-zinc-500",
406
+ children: [
407
+ "Tip: Use ",
408
+ /*#__PURE__*/ _jsx("code", {
409
+ className: "px-1 py-0.5 bg-[#3c3c3c] rounded text-zinc-400",
410
+ children: "folder/file.ext"
411
+ }),
412
+ " for nested files"
413
+ ]
414
+ }),
415
+ /*#__PURE__*/ _jsxs("div", {
416
+ className: "flex items-center gap-2 text-[11px] text-zinc-500",
417
+ children: [
418
+ /*#__PURE__*/ _jsx("span", {
419
+ className: "px-1.5 py-0.5 bg-[#3c3c3c] rounded text-[10px]",
420
+ children: "↵"
421
+ }),
422
+ /*#__PURE__*/ _jsx("span", {
423
+ children: "Create"
424
+ }),
425
+ /*#__PURE__*/ _jsx("span", {
426
+ className: "px-1.5 py-0.5 bg-[#3c3c3c] rounded text-[10px]",
427
+ children: "Esc"
428
+ }),
429
+ /*#__PURE__*/ _jsx("span", {
430
+ children: "Cancel"
431
+ })
432
+ ]
433
+ })
434
+ ]
435
+ })
436
+ ]
437
+ })
438
+ ]
439
+ });
440
+ }
441
+ // Error Boundary for Mermaid Preview
442
+ class MermaidErrorBoundary extends React.Component {
443
+ static getDerivedStateFromError(error) {
444
+ return {
445
+ hasError: true,
446
+ error: error.message
447
+ };
448
+ }
449
+ componentDidCatch(error, errorInfo) {
450
+ console.error('[MermaidErrorBoundary] Error:', error, errorInfo);
451
+ }
452
+ // Reset error when code changes
453
+ componentDidUpdate(prevProps) {
454
+ if (prevProps.code !== this.props.code && this.state.hasError) {
455
+ this.setState({
456
+ hasError: false,
457
+ error: null
458
+ });
459
+ }
460
+ }
461
+ render() {
462
+ if (this.state.hasError) {
463
+ return /*#__PURE__*/ _jsxs("div", {
464
+ className: "flex flex-col items-center justify-center h-full text-zinc-400 text-sm p-4 gap-4",
465
+ children: [
466
+ /*#__PURE__*/ _jsxs("p", {
467
+ className: "text-red-400",
468
+ children: [
469
+ "Render Error: ",
470
+ this.state.error
471
+ ]
472
+ }),
473
+ /*#__PURE__*/ _jsxs("div", {
474
+ className: "w-full max-w-lg",
475
+ children: [
476
+ /*#__PURE__*/ _jsx("p", {
477
+ className: "text-xs text-zinc-500 mb-2",
478
+ children: "Source:"
479
+ }),
480
+ /*#__PURE__*/ _jsx("pre", {
481
+ className: "p-4 bg-[#2d2d2d] rounded text-xs overflow-auto max-h-[200px] text-zinc-300",
482
+ children: this.props.code
483
+ })
484
+ ]
485
+ })
486
+ ]
487
+ });
488
+ }
489
+ return this.props.children;
490
+ }
491
+ constructor(props){
492
+ super(props);
493
+ this.state = {
494
+ hasError: false,
495
+ error: null
496
+ };
497
+ }
498
+ }
499
+ // Mermaid preview component with zoom/pan
500
+ function MermaidPreviewInner({ code }) {
501
+ const containerRef = useRef(null);
502
+ const contentRef = useRef(null);
503
+ const [svg, setSvg] = useState('');
504
+ const [error, setError] = useState(null);
505
+ const [loading, setLoading] = useState(true);
506
+ const renderIdRef = useRef(0);
507
+ // Zoom and pan state
508
+ const [scale, setScale] = useState(1);
509
+ const [position, setPosition] = useState({
510
+ x: 0,
511
+ y: 0
512
+ });
513
+ const [isDragging, setIsDragging] = useState(false);
514
+ const dragStart = useRef({
515
+ x: 0,
516
+ y: 0
517
+ });
518
+ const positionStart = useRef({
519
+ x: 0,
520
+ y: 0
521
+ });
522
+ useEffect(()=>{
523
+ if (!code.trim()) {
524
+ setLoading(false);
525
+ setSvg('');
526
+ setError(null);
527
+ return;
528
+ }
529
+ const currentRenderId = ++renderIdRef.current;
530
+ setLoading(true);
531
+ setError(null);
532
+ const renderDiagram = async ()=>{
533
+ try {
534
+ const mermaid = (await import('mermaid')).default;
535
+ mermaid.initialize({
536
+ startOnLoad: false,
537
+ theme: 'dark',
538
+ themeVariables: {
539
+ // Force dark backgrounds everywhere
540
+ background: '#1e1e1e',
541
+ primaryColor: '#3b82f6',
542
+ primaryTextColor: '#ffffff',
543
+ primaryBorderColor: '#60a5fa',
544
+ secondaryColor: '#3b82f6',
545
+ secondaryTextColor: '#ffffff',
546
+ secondaryBorderColor: '#60a5fa',
547
+ tertiaryColor: '#3b82f6',
548
+ tertiaryTextColor: '#ffffff',
549
+ tertiaryBorderColor: '#60a5fa',
550
+ // Node backgrounds - force blue
551
+ mainBkg: '#3b82f6',
552
+ nodeBkg: '#3b82f6',
553
+ nodeBorder: '#60a5fa',
554
+ nodeTextColor: '#ffffff',
555
+ // Cluster styling
556
+ clusterBkg: '#27272a',
557
+ clusterBorder: '#52525b',
558
+ titleColor: '#ffffff',
559
+ // Lines
560
+ lineColor: '#94a3b8',
561
+ // Font
562
+ fontFamily: 'system-ui, sans-serif',
563
+ fontSize: '14px'
564
+ },
565
+ flowchart: {
566
+ htmlLabels: true,
567
+ useMaxWidth: true
568
+ }
569
+ });
570
+ // Use unique ID to avoid conflicts
571
+ const { svg: renderedSvg } = await mermaid.render(`mermaid-${currentRenderId}-${Date.now()}`, code);
572
+ // Only update if this is still the latest render
573
+ if (currentRenderId === renderIdRef.current) {
574
+ setSvg(renderedSvg);
575
+ setError(null);
576
+ // Reset zoom/pan when diagram changes
577
+ setScale(1);
578
+ setPosition({
579
+ x: 0,
580
+ y: 0
581
+ });
582
+ }
583
+ } catch (err) {
584
+ if (currentRenderId === renderIdRef.current) {
585
+ // Extract meaningful error message from mermaid errors
586
+ let errorMessage = 'Failed to render diagram';
587
+ if (err instanceof Error) {
588
+ // Mermaid errors often have detailed messages
589
+ errorMessage = err.message;
590
+ // Clean up common mermaid error prefixes
591
+ if (errorMessage.includes('Parse error')) {
592
+ const match = errorMessage.match(/Parse error on line (\d+)/);
593
+ if (match) {
594
+ errorMessage = `Syntax error on line ${match[1]}`;
595
+ }
596
+ }
597
+ } else if (typeof err === 'string') {
598
+ errorMessage = err;
599
+ } else if (err && typeof err === 'object' && 'str' in err) {
600
+ // Mermaid sometimes returns {str: "error message"}
601
+ errorMessage = String(err.str);
602
+ }
603
+ setError(errorMessage);
604
+ setSvg(''); // Clear any previous SVG
605
+ }
606
+ } finally{
607
+ if (currentRenderId === renderIdRef.current) {
608
+ setLoading(false);
609
+ }
610
+ }
611
+ };
612
+ // Debounce rendering
613
+ const timer = setTimeout(renderDiagram, 300);
614
+ return ()=>clearTimeout(timer);
615
+ }, [
616
+ code
617
+ ]);
618
+ // Handle mouse wheel zoom
619
+ const handleWheel = useCallback((e)=>{
620
+ e.preventDefault();
621
+ const delta = e.deltaY > 0 ? -0.1 : 0.1;
622
+ setScale((prev)=>Math.min(Math.max(0.25, prev + delta), 3));
623
+ }, []);
624
+ // Handle mouse down for pan
625
+ const handleMouseDown = useCallback((e)=>{
626
+ if (e.button !== 0) return; // Only left click
627
+ setIsDragging(true);
628
+ dragStart.current = {
629
+ x: e.clientX,
630
+ y: e.clientY
631
+ };
632
+ positionStart.current = position;
633
+ }, [
634
+ position
635
+ ]);
636
+ // Handle mouse move for pan
637
+ const handleMouseMove = useCallback((e)=>{
638
+ if (!isDragging) return;
639
+ const dx = e.clientX - dragStart.current.x;
640
+ const dy = e.clientY - dragStart.current.y;
641
+ setPosition({
642
+ x: positionStart.current.x + dx,
643
+ y: positionStart.current.y + dy
644
+ });
645
+ }, [
646
+ isDragging
647
+ ]);
648
+ // Handle mouse up
649
+ const handleMouseUp = useCallback(()=>{
650
+ setIsDragging(false);
651
+ }, []);
652
+ // Handle zoom controls
653
+ const zoomIn = useCallback(()=>setScale((prev)=>Math.min(prev + 0.25, 3)), []);
654
+ const zoomOut = useCallback(()=>setScale((prev)=>Math.max(prev - 0.25, 0.25)), []);
655
+ const resetView = useCallback(()=>{
656
+ setScale(1);
657
+ setPosition({
658
+ x: 0,
659
+ y: 0
660
+ });
661
+ }, []);
662
+ if (loading) {
663
+ return /*#__PURE__*/ _jsxs("div", {
664
+ className: "flex items-center justify-center h-full text-zinc-500 text-sm",
665
+ children: [
666
+ /*#__PURE__*/ _jsx(Spinner, {
667
+ className: "h-5 w-5 animate-spin mr-2"
668
+ }),
669
+ "Rendering diagram..."
670
+ ]
671
+ });
672
+ }
673
+ if (error) {
674
+ return /*#__PURE__*/ _jsxs("div", {
675
+ className: "flex flex-col items-center justify-center h-full text-zinc-400 text-sm p-4 gap-4",
676
+ children: [
677
+ /*#__PURE__*/ _jsxs("p", {
678
+ className: "text-red-400",
679
+ children: [
680
+ "Syntax Error: ",
681
+ error
682
+ ]
683
+ }),
684
+ /*#__PURE__*/ _jsxs("div", {
685
+ className: "w-full max-w-lg",
686
+ children: [
687
+ /*#__PURE__*/ _jsx("p", {
688
+ className: "text-xs text-zinc-500 mb-2",
689
+ children: "Source:"
690
+ }),
691
+ /*#__PURE__*/ _jsx("pre", {
692
+ className: "p-4 bg-[#2d2d2d] rounded text-xs overflow-auto max-h-[200px] text-zinc-300",
693
+ children: code
694
+ })
695
+ ]
696
+ })
697
+ ]
698
+ });
699
+ }
700
+ return /*#__PURE__*/ _jsxs("div", {
701
+ className: "relative h-full w-full bg-[#1e1e1e]",
702
+ children: [
703
+ /*#__PURE__*/ _jsxs("div", {
704
+ className: "absolute top-3 right-3 z-10 flex items-center gap-1 bg-[#2d2d2d] rounded-md border border-[#3c3c3c] p-1",
705
+ children: [
706
+ /*#__PURE__*/ _jsx("button", {
707
+ onClick: zoomOut,
708
+ className: "p-1.5 hover:bg-[#3c3c3c] rounded text-zinc-400 hover:text-zinc-200 transition-colors",
709
+ title: "Zoom out",
710
+ children: /*#__PURE__*/ _jsx(Minus, {
711
+ className: "h-4 w-4"
712
+ })
713
+ }),
714
+ /*#__PURE__*/ _jsxs("span", {
715
+ className: "text-xs text-zinc-400 min-w-[3rem] text-center",
716
+ children: [
717
+ Math.round(scale * 100),
718
+ "%"
719
+ ]
720
+ }),
721
+ /*#__PURE__*/ _jsx("button", {
722
+ onClick: zoomIn,
723
+ className: "p-1.5 hover:bg-[#3c3c3c] rounded text-zinc-400 hover:text-zinc-200 transition-colors",
724
+ title: "Zoom in",
725
+ children: /*#__PURE__*/ _jsx(Plus, {
726
+ className: "h-4 w-4"
727
+ })
728
+ }),
729
+ /*#__PURE__*/ _jsx("div", {
730
+ className: "w-px h-4 bg-[#3c3c3c] mx-1"
731
+ }),
732
+ /*#__PURE__*/ _jsx("button", {
733
+ onClick: resetView,
734
+ className: "p-1.5 hover:bg-[#3c3c3c] rounded text-zinc-400 hover:text-zinc-200 transition-colors",
735
+ title: "Reset view",
736
+ children: /*#__PURE__*/ _jsx(ArrowsOut, {
737
+ className: "h-4 w-4"
738
+ })
739
+ })
740
+ ]
741
+ }),
742
+ /*#__PURE__*/ _jsx("div", {
743
+ ref: containerRef,
744
+ className: "h-full w-full overflow-hidden cursor-grab active:cursor-grabbing",
745
+ onWheel: handleWheel,
746
+ onMouseDown: handleMouseDown,
747
+ onMouseMove: handleMouseMove,
748
+ onMouseUp: handleMouseUp,
749
+ onMouseLeave: handleMouseUp,
750
+ children: /*#__PURE__*/ _jsx("div", {
751
+ ref: contentRef,
752
+ className: "h-full w-full flex items-center justify-center [&_svg]:max-w-none",
753
+ style: {
754
+ transform: `translate(${position.x}px, ${position.y}px) scale(${scale})`,
755
+ transformOrigin: 'center center',
756
+ transition: isDragging ? 'none' : 'transform 0.1s ease-out'
757
+ },
758
+ dangerouslySetInnerHTML: {
759
+ __html: svg
760
+ }
761
+ })
762
+ }),
763
+ /*#__PURE__*/ _jsx("div", {
764
+ className: "absolute bottom-3 left-3 text-[10px] text-zinc-600",
765
+ children: "Scroll to zoom • Drag to pan"
766
+ })
767
+ ]
768
+ });
769
+ }
770
+ // Mermaid preview with error boundary wrapper
771
+ function MermaidPreview({ code }) {
772
+ return /*#__PURE__*/ _jsx(MermaidErrorBoundary, {
773
+ code: code,
774
+ children: /*#__PURE__*/ _jsx(MermaidPreviewInner, {
775
+ code: code
776
+ })
777
+ });
778
+ }
779
+ // Main Notes Mode component
780
+ export function NotesMode({ apiSpecUrl, apiName }) {
781
+ const { activeFilePath, setActiveFilePath, streamingContent, setStreamingContent, notesRefreshTrigger } = useModeContext();
782
+ const { workspace, loading: workspaceLoading } = useWorkspace(apiSpecUrl, apiName);
783
+ const { notes, loading: notesLoading, createNote, readNote, updateNote, deleteNote, refresh } = useNotes(workspace?.id || null);
784
+ const { state: editorState, openTab, closeTab, setActiveTab, clearAllTabs } = useEditorState(workspace?.id || null);
785
+ // Editor refs
786
+ const editorRef = useRef(null);
787
+ // Local state
788
+ const [fileContent, setFileContent] = useState('');
789
+ const [isModified, setIsModified] = useState(false);
790
+ const [isSaving, setIsSaving] = useState(false);
791
+ const [isLoadingContent, setIsLoadingContent] = useState(false);
792
+ const [expandedFolders, setExpandedFolders] = useState(new Set());
793
+ const [showNewNote, setShowNewNote] = useState(false);
794
+ const [showPreview, setShowPreview] = useState(false);
795
+ // Build file tree
796
+ const fileTree = useMemo(()=>buildFileTree(notes), [
797
+ notes
798
+ ]);
799
+ // Refresh notes when triggered by agent (delete, update operations)
800
+ useEffect(()=>{
801
+ if (notesRefreshTrigger > 0) {
802
+ refresh();
803
+ }
804
+ }, [
805
+ notesRefreshTrigger,
806
+ refresh
807
+ ]);
808
+ // Clear tabs when all notes are deleted
809
+ useEffect(()=>{
810
+ if (!notesLoading && notes.length === 0 && editorState?.openTabs && editorState.openTabs.length > 0) {
811
+ clearAllTabs();
812
+ setFileContent('');
813
+ }
814
+ }, [
815
+ notes.length,
816
+ notesLoading,
817
+ editorState?.openTabs,
818
+ clearAllTabs
819
+ ]);
820
+ // State validation: Clean up orphaned tabs (pointing to deleted files)
821
+ useEffect(()=>{
822
+ if (notesLoading || !editorState?.openTabs || editorState.openTabs.length === 0) return;
823
+ const notePaths = new Set(notes.map((n)=>n.path));
824
+ const orphanedTabs = editorState.openTabs.filter((tab)=>!notePaths.has(tab));
825
+ if (orphanedTabs.length > 0) {
826
+ console.log('[NotesMode] Cleaning up orphaned tabs:', orphanedTabs);
827
+ // Close each orphaned tab
828
+ orphanedTabs.forEach((tab)=>closeTab(tab));
829
+ }
830
+ }, [
831
+ notes,
832
+ notesLoading,
833
+ editorState?.openTabs,
834
+ closeTab
835
+ ]);
836
+ // State validation: Clear stuck streaming state (no active streaming after 30s)
837
+ useEffect(()=>{
838
+ if (!streamingContent?.isStreaming) return;
839
+ const timeout = setTimeout(()=>{
840
+ if (streamingContent?.isStreaming) {
841
+ console.log('[NotesMode] Clearing stuck streaming state');
842
+ setStreamingContent(null);
843
+ }
844
+ }, 30000) // 30 second timeout
845
+ ;
846
+ return ()=>clearTimeout(timeout);
847
+ }, [
848
+ streamingContent?.isStreaming,
849
+ setStreamingContent
850
+ ]);
851
+ // Load file content when active tab changes
852
+ useEffect(()=>{
853
+ if (!editorState?.activeTab) {
854
+ setFileContent('');
855
+ setIsLoadingContent(false);
856
+ return;
857
+ }
858
+ setIsLoadingContent(true);
859
+ const loadContent = async ()=>{
860
+ const content = await readNote(editorState.activeTab);
861
+ setFileContent(content);
862
+ setIsModified(false);
863
+ setIsLoadingContent(false);
864
+ };
865
+ loadContent();
866
+ }, [
867
+ editorState?.activeTab,
868
+ readNote
869
+ ]);
870
+ // Track last processed path to avoid re-processing
871
+ const lastProcessedPath = useRef(null);
872
+ // Handle file navigation from agent
873
+ useEffect(()=>{
874
+ if (activeFilePath && workspace) {
875
+ // Strip timestamp from path if present (used to force refresh)
876
+ const cleanPath = activeFilePath.split('?')[0];
877
+ const hasTimestamp = activeFilePath.includes('?t=');
878
+ // Skip if we've already processed this path (unless it has a timestamp for force refresh)
879
+ if (lastProcessedPath.current === cleanPath && !hasTimestamp) {
880
+ return;
881
+ }
882
+ lastProcessedPath.current = cleanPath;
883
+ // Refresh notes first to ensure file is in the list
884
+ refresh().then(async ()=>{
885
+ openTab(cleanPath);
886
+ // Auto-enable preview for mermaid files
887
+ if (cleanPath.endsWith('.mmd')) {
888
+ setShowPreview(true);
889
+ }
890
+ // If this was a write operation (has timestamp), force content reload
891
+ if (hasTimestamp) {
892
+ setIsLoadingContent(true);
893
+ const content = await readNote(cleanPath);
894
+ setFileContent(content);
895
+ setIsModified(false);
896
+ setIsLoadingContent(false);
897
+ // Clear streaming content after file is loaded (prevents flash of empty content)
898
+ if (streamingContent?.path === cleanPath) {
899
+ setStreamingContent(null);
900
+ }
901
+ }
902
+ // Expand parent folders
903
+ const parts = cleanPath.split('/');
904
+ if (parts.length > 1) {
905
+ const foldersToExpand = parts.slice(0, -1).map((_, i)=>parts.slice(0, i + 1).join('/'));
906
+ setExpandedFolders((prev)=>{
907
+ const next = new Set(prev);
908
+ foldersToExpand.forEach((f)=>next.add(f));
909
+ return next;
910
+ });
911
+ }
912
+ });
913
+ }
914
+ }, [
915
+ activeFilePath,
916
+ workspace,
917
+ openTab,
918
+ refresh,
919
+ readNote,
920
+ streamingContent,
921
+ setStreamingContent
922
+ ]);
923
+ // Handle folder toggle
924
+ const handleFolderToggle = useCallback((path)=>{
925
+ setExpandedFolders((prev)=>{
926
+ const next = new Set(prev);
927
+ if (next.has(path)) {
928
+ next.delete(path);
929
+ } else {
930
+ next.add(path);
931
+ }
932
+ return next;
933
+ });
934
+ }, []);
935
+ // Handle content change
936
+ const handleContentChange = useCallback((value)=>{
937
+ if (value !== undefined) {
938
+ setFileContent(value);
939
+ setIsModified(true);
940
+ }
941
+ }, []);
942
+ // Handle save
943
+ const handleSave = useCallback(async ()=>{
944
+ if (!editorState?.activeTab || !isModified) return;
945
+ setIsSaving(true);
946
+ try {
947
+ await updateNote(editorState.activeTab, fileContent);
948
+ setIsModified(false);
949
+ } finally{
950
+ setIsSaving(false);
951
+ }
952
+ }, [
953
+ editorState?.activeTab,
954
+ fileContent,
955
+ isModified,
956
+ updateNote
957
+ ]);
958
+ // Keyboard shortcuts
959
+ useEffect(()=>{
960
+ const handleKeyDown = (e)=>{
961
+ if ((e.metaKey || e.ctrlKey) && e.key === 's') {
962
+ e.preventDefault();
963
+ handleSave();
964
+ }
965
+ if ((e.metaKey || e.ctrlKey) && e.key === 'n') {
966
+ e.preventDefault();
967
+ setShowNewNote(true);
968
+ }
969
+ };
970
+ window.addEventListener('keydown', handleKeyDown);
971
+ return ()=>window.removeEventListener('keydown', handleKeyDown);
972
+ }, [
973
+ handleSave
974
+ ]);
975
+ // Handle create note
976
+ const handleCreateNote = useCallback(async (path)=>{
977
+ await createNote(path, '');
978
+ await refresh();
979
+ await openTab(path);
980
+ }, [
981
+ createNote,
982
+ refresh,
983
+ openTab
984
+ ]);
985
+ // Handle delete note
986
+ const handleDeleteNote = useCallback(async (path)=>{
987
+ await deleteNote(path);
988
+ closeTab(path);
989
+ await refresh();
990
+ }, [
991
+ deleteNote,
992
+ closeTab,
993
+ refresh
994
+ ]);
995
+ // Handle reset workspace (clears all state)
996
+ const handleResetWorkspace = useCallback(async ()=>{
997
+ if (!window.confirm('Reset workspace? This will clear all notes and tabs.')) {
998
+ return;
999
+ }
1000
+ try {
1001
+ // Clear all notes from IndexedDB
1002
+ for (const note of notes){
1003
+ await deleteNote(note.path);
1004
+ }
1005
+ // Clear all tabs
1006
+ clearAllTabs();
1007
+ // Clear streaming content
1008
+ setStreamingContent(null);
1009
+ // Clear file content
1010
+ setFileContent('');
1011
+ setIsModified(false);
1012
+ // Refresh notes list
1013
+ await refresh();
1014
+ console.log('[NotesMode] Workspace reset complete');
1015
+ } catch (err) {
1016
+ console.error('[NotesMode] Failed to reset workspace:', err);
1017
+ }
1018
+ }, [
1019
+ notes,
1020
+ deleteNote,
1021
+ clearAllTabs,
1022
+ setStreamingContent,
1023
+ refresh
1024
+ ]);
1025
+ // Handle editor mount
1026
+ const handleEditorMount = (editor)=>{
1027
+ editorRef.current = editor;
1028
+ };
1029
+ // Check if current file supports preview
1030
+ const currentFileSupportsPreview = editorState?.activeTab ? supportsPreview(editorState.activeTab) : false;
1031
+ const currentFileType = editorState?.activeTab ? getFileType(editorState.activeTab) : null;
1032
+ // Auto-enable preview for mermaid files when tab changes
1033
+ useEffect(()=>{
1034
+ if (editorState?.activeTab?.endsWith('.mmd')) {
1035
+ setShowPreview(true);
1036
+ }
1037
+ }, [
1038
+ editorState?.activeTab
1039
+ ]);
1040
+ // Auto-scroll editor to end while streaming
1041
+ useEffect(()=>{
1042
+ if (streamingContent?.isStreaming && editorRef.current) {
1043
+ const model = editorRef.current.getModel();
1044
+ if (model) {
1045
+ const lineCount = model.getLineCount();
1046
+ editorRef.current.revealLine(lineCount);
1047
+ // Also position cursor at the end
1048
+ editorRef.current.setPosition({
1049
+ lineNumber: lineCount,
1050
+ column: 1
1051
+ });
1052
+ }
1053
+ }
1054
+ }, [
1055
+ streamingContent?.content,
1056
+ streamingContent?.isStreaming
1057
+ ]);
1058
+ // Loading state
1059
+ if (workspaceLoading || notesLoading) {
1060
+ return /*#__PURE__*/ _jsx("div", {
1061
+ className: "flex items-center justify-center h-full sandbox-bg",
1062
+ children: /*#__PURE__*/ _jsx(Spinner, {
1063
+ className: "h-6 w-6 animate-spin sandbox-text-muted"
1064
+ })
1065
+ });
1066
+ }
1067
+ return /*#__PURE__*/ _jsxs("div", {
1068
+ className: "flex flex-col h-full sandbox-bg",
1069
+ children: [
1070
+ /*#__PURE__*/ _jsxs("div", {
1071
+ className: "flex items-center justify-between px-3 py-1.5 sandbox-header",
1072
+ children: [
1073
+ /*#__PURE__*/ _jsxs("div", {
1074
+ className: "flex items-center gap-2",
1075
+ children: [
1076
+ /*#__PURE__*/ _jsx("span", {
1077
+ className: "text-xs sandbox-text-secondary",
1078
+ children: workspace?.name || 'Notes'
1079
+ }),
1080
+ isModified && /*#__PURE__*/ _jsx("span", {
1081
+ className: "text-[11px] sandbox-text-warning font-medium",
1082
+ children: "● Unsaved"
1083
+ })
1084
+ ]
1085
+ }),
1086
+ /*#__PURE__*/ _jsxs("div", {
1087
+ className: "flex items-center gap-1.5",
1088
+ children: [
1089
+ currentFileSupportsPreview && /*#__PURE__*/ _jsxs(Button, {
1090
+ variant: "ghost",
1091
+ size: "sm",
1092
+ onClick: ()=>setShowPreview(!showPreview),
1093
+ className: cn("h-7 px-2 sandbox-btn", showPreview ? "sandbox-btn-active" : ""),
1094
+ children: [
1095
+ showPreview ? /*#__PURE__*/ _jsx(Code, {
1096
+ className: "h-3.5 w-3.5 mr-1"
1097
+ }) : /*#__PURE__*/ _jsx(Eye, {
1098
+ className: "h-3.5 w-3.5 mr-1"
1099
+ }),
1100
+ /*#__PURE__*/ _jsx("span", {
1101
+ className: "text-xs",
1102
+ children: showPreview ? 'Code' : 'Preview'
1103
+ })
1104
+ ]
1105
+ }),
1106
+ /*#__PURE__*/ _jsxs(Button, {
1107
+ variant: "ghost",
1108
+ size: "sm",
1109
+ onClick: ()=>setShowNewNote(true),
1110
+ className: "sandbox-btn h-7 px-2",
1111
+ children: [
1112
+ /*#__PURE__*/ _jsx(Plus, {
1113
+ className: "h-3.5 w-3.5 mr-1"
1114
+ }),
1115
+ /*#__PURE__*/ _jsx("span", {
1116
+ className: "text-xs",
1117
+ children: "New"
1118
+ })
1119
+ ]
1120
+ }),
1121
+ /*#__PURE__*/ _jsxs(Button, {
1122
+ variant: "ghost",
1123
+ size: "sm",
1124
+ onClick: handleSave,
1125
+ disabled: !isModified || isSaving,
1126
+ className: "sandbox-btn h-7 px-2 disabled:opacity-40",
1127
+ children: [
1128
+ /*#__PURE__*/ _jsx(FloppyDisk, {
1129
+ className: "h-3.5 w-3.5 mr-1"
1130
+ }),
1131
+ /*#__PURE__*/ _jsx("span", {
1132
+ className: "text-xs",
1133
+ children: "Save"
1134
+ })
1135
+ ]
1136
+ }),
1137
+ (notes.length > 0 || (editorState?.openTabs?.length ?? 0) > 0) && /*#__PURE__*/ _jsxs(Tooltip, {
1138
+ children: [
1139
+ /*#__PURE__*/ _jsx(TooltipTrigger, {
1140
+ asChild: true,
1141
+ children: /*#__PURE__*/ _jsx(Button, {
1142
+ variant: "ghost",
1143
+ size: "sm",
1144
+ onClick: handleResetWorkspace,
1145
+ className: "sandbox-btn-danger h-7 w-7 p-0",
1146
+ children: /*#__PURE__*/ _jsx(ArrowClockwise, {
1147
+ className: "h-3.5 w-3.5"
1148
+ })
1149
+ })
1150
+ }),
1151
+ /*#__PURE__*/ _jsx(TooltipContent, {
1152
+ side: "bottom",
1153
+ children: "Reset workspace"
1154
+ })
1155
+ ]
1156
+ })
1157
+ ]
1158
+ })
1159
+ ]
1160
+ }),
1161
+ /*#__PURE__*/ _jsxs("div", {
1162
+ className: "flex flex-1 overflow-hidden",
1163
+ children: [
1164
+ /*#__PURE__*/ _jsxs("div", {
1165
+ className: "w-52 flex-shrink-0 border-r border-[#3c3c3c] flex flex-col bg-[#181818]",
1166
+ children: [
1167
+ /*#__PURE__*/ _jsx("div", {
1168
+ className: "px-2.5 py-1.5 border-b border-[#3c3c3c] bg-[#252526]",
1169
+ children: /*#__PURE__*/ _jsx("span", {
1170
+ className: "text-[11px] font-medium uppercase tracking-wider text-zinc-400",
1171
+ children: "Notes"
1172
+ })
1173
+ }),
1174
+ /*#__PURE__*/ _jsx("div", {
1175
+ className: "flex-1 overflow-y-auto",
1176
+ children: notes.length === 0 ? /*#__PURE__*/ _jsxs("div", {
1177
+ className: "px-3 py-4 text-xs text-zinc-500 text-center",
1178
+ children: [
1179
+ /*#__PURE__*/ _jsx("p", {
1180
+ className: "mb-2",
1181
+ children: "No notes yet"
1182
+ }),
1183
+ /*#__PURE__*/ _jsx(Button, {
1184
+ variant: "link",
1185
+ size: "sm",
1186
+ className: "text-xs text-blue-400 hover:text-blue-300",
1187
+ onClick: ()=>setShowNewNote(true),
1188
+ children: "Create your first note"
1189
+ })
1190
+ ]
1191
+ }) : fileTree.map((node)=>/*#__PURE__*/ _jsx(FileTreeItem, {
1192
+ node: node,
1193
+ depth: 0,
1194
+ activeFile: editorState?.activeTab || null,
1195
+ expandedFolders: expandedFolders,
1196
+ onFileClick: (path)=>{
1197
+ openTab(path);
1198
+ setActiveFilePath(path); // Update URL
1199
+ },
1200
+ onFolderToggle: handleFolderToggle,
1201
+ onDelete: handleDeleteNote
1202
+ }, node.path))
1203
+ })
1204
+ ]
1205
+ }),
1206
+ /*#__PURE__*/ _jsxs("div", {
1207
+ className: "flex-1 flex flex-col overflow-hidden bg-[#1e1e1e]",
1208
+ children: [
1209
+ /*#__PURE__*/ _jsx(EditorTabs, {
1210
+ tabs: editorState?.openTabs || [],
1211
+ activeTab: editorState?.activeTab || null,
1212
+ onTabClick: (path)=>{
1213
+ setActiveTab(path);
1214
+ setActiveFilePath(path); // Update URL
1215
+ },
1216
+ onTabClose: closeTab
1217
+ }),
1218
+ /*#__PURE__*/ _jsxs("div", {
1219
+ className: "flex-1 overflow-hidden relative",
1220
+ children: [
1221
+ isLoadingContent && !streamingContent?.isStreaming && /*#__PURE__*/ _jsx("div", {
1222
+ className: "absolute inset-0 bg-[#1e1e1e] z-10 flex items-center justify-center",
1223
+ children: /*#__PURE__*/ _jsxs("div", {
1224
+ className: "flex items-center gap-2 text-zinc-400",
1225
+ children: [
1226
+ /*#__PURE__*/ _jsx(Spinner, {
1227
+ className: "h-5 w-5 animate-spin"
1228
+ }),
1229
+ /*#__PURE__*/ _jsx("span", {
1230
+ className: "text-sm",
1231
+ children: "Loading content..."
1232
+ })
1233
+ ]
1234
+ })
1235
+ }),
1236
+ streamingContent?.isStreaming && streamingContent.path === editorState?.activeTab && /*#__PURE__*/ _jsxs("div", {
1237
+ className: "absolute top-2 right-2 z-10 flex items-center gap-2 px-2 py-1 rounded bg-blue-600/80 text-white text-xs",
1238
+ children: [
1239
+ /*#__PURE__*/ _jsx(Spinner, {
1240
+ className: "h-3 w-3 animate-spin"
1241
+ }),
1242
+ /*#__PURE__*/ _jsx("span", {
1243
+ children: "AI writing..."
1244
+ })
1245
+ ]
1246
+ }),
1247
+ editorState?.activeTab ? showPreview && currentFileType === 'mermaid' ? /*#__PURE__*/ _jsx(MermaidPreview, {
1248
+ code: streamingContent?.isStreaming && streamingContent.path === editorState.activeTab ? streamingContent.content : fileContent
1249
+ }) : /*#__PURE__*/ _jsx(Editor, {
1250
+ height: "100%",
1251
+ language: getMonacoLanguage(editorState.activeTab),
1252
+ value: streamingContent?.isStreaming && streamingContent.path === editorState.activeTab ? streamingContent.content : fileContent,
1253
+ onChange: handleContentChange,
1254
+ onMount: handleEditorMount,
1255
+ options: {
1256
+ minimap: {
1257
+ enabled: false
1258
+ },
1259
+ fontSize: 13,
1260
+ fontFamily: "'JetBrains Mono', 'Fira Code', monospace",
1261
+ lineNumbers: 'on',
1262
+ scrollBeyondLastLine: false,
1263
+ wordWrap: 'on',
1264
+ tabSize: 2,
1265
+ automaticLayout: true,
1266
+ padding: {
1267
+ top: 8,
1268
+ bottom: 8
1269
+ },
1270
+ renderWhitespace: 'selection',
1271
+ bracketPairColorization: {
1272
+ enabled: true
1273
+ },
1274
+ cursorBlinking: 'smooth',
1275
+ smoothScrolling: true,
1276
+ lineHeight: 20,
1277
+ readOnly: streamingContent?.isStreaming && streamingContent.path === editorState.activeTab
1278
+ },
1279
+ theme: "vs-dark"
1280
+ }) : /*#__PURE__*/ _jsx("div", {
1281
+ className: "flex items-center justify-center h-full",
1282
+ children: /*#__PURE__*/ _jsxs("div", {
1283
+ className: "text-center",
1284
+ children: [
1285
+ /*#__PURE__*/ _jsx("div", {
1286
+ className: "w-16 h-16 mx-auto mb-4 rounded-lg bg-[#2d2d2d] flex items-center justify-center",
1287
+ children: /*#__PURE__*/ _jsx(File, {
1288
+ className: "h-8 w-8 text-zinc-600"
1289
+ })
1290
+ }),
1291
+ /*#__PURE__*/ _jsx("p", {
1292
+ className: "text-sm text-zinc-500 mb-1",
1293
+ children: "No file open"
1294
+ }),
1295
+ /*#__PURE__*/ _jsx("p", {
1296
+ className: "text-xs text-zinc-600",
1297
+ children: "Create a note or select one from the sidebar"
1298
+ })
1299
+ ]
1300
+ })
1301
+ })
1302
+ ]
1303
+ })
1304
+ ]
1305
+ })
1306
+ ]
1307
+ }),
1308
+ /*#__PURE__*/ _jsxs("div", {
1309
+ className: "flex items-center justify-between h-[22px] px-2.5 border-t border-[#3c3c3c] bg-[#007acc] text-white text-[11px]",
1310
+ children: [
1311
+ /*#__PURE__*/ _jsx("div", {
1312
+ className: "flex items-center gap-3",
1313
+ children: editorState?.activeTab && /*#__PURE__*/ _jsx("span", {
1314
+ className: "opacity-90",
1315
+ children: getFileType(editorState.activeTab)
1316
+ })
1317
+ }),
1318
+ /*#__PURE__*/ _jsx("div", {
1319
+ className: "flex items-center gap-3",
1320
+ children: /*#__PURE__*/ _jsxs("span", {
1321
+ className: "opacity-70",
1322
+ children: [
1323
+ notes.length,
1324
+ " note",
1325
+ notes.length !== 1 ? 's' : ''
1326
+ ]
1327
+ })
1328
+ })
1329
+ ]
1330
+ }),
1331
+ /*#__PURE__*/ _jsx(NewNoteDialog, {
1332
+ open: showNewNote,
1333
+ onOpenChange: setShowNewNote,
1334
+ onCreateNote: handleCreateNote
1335
+ })
1336
+ ]
1337
+ });
1338
+ }