@brainfish-ai/devdoc 0.1.41 → 0.1.43

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 (400) hide show
  1. package/ai-agents/.claude/skills/bootstrap-docs/SKILL.md +710 -79
  2. package/ai-agents/.claude/skills/check-docs/SKILL.md +83 -8
  3. package/ai-agents/.claude/skills/create-doc/SKILL.md +267 -55
  4. package/ai-agents/.claude/skills/update-doc/SKILL.md +162 -63
  5. package/ai-agents/.cursor/rules/devdoc-bootstrap.mdc +145 -15
  6. package/ai-agents/.cursor/rules/devdoc-create.mdc +108 -57
  7. package/ai-agents/.cursor/rules/devdoc-update.mdc +93 -70
  8. package/ai-agents/.cursor/rules/devdoc.mdc +21 -0
  9. package/ai-agents/schemas/docs.schema.json +332 -0
  10. package/ai-agents/schemas/theme.schema.json +243 -0
  11. package/dist/cli/commands/create.js +4 -9
  12. package/dist/cli/commands/deploy.js +50 -25
  13. package/dist/cli/commands/dev.js +19 -10
  14. package/package.json +3 -2
  15. package/renderer/app/api/assets/[...path]/route.js +108 -0
  16. package/renderer/app/api/assets/route.js +114 -0
  17. package/renderer/app/api/assets/upload/route.js +163 -0
  18. package/renderer/app/api/auth-schemes/route.js +58 -0
  19. package/renderer/app/api/chat/route.js +759 -0
  20. package/renderer/app/api/codegen/route.js +52 -0
  21. package/renderer/app/api/collections/route.js +675 -0
  22. package/renderer/app/api/debug/route.js +47 -0
  23. package/renderer/app/api/deploy/route.js +199 -0
  24. package/renderer/app/api/device/route.js +36 -0
  25. package/renderer/app/api/docs/route.js +205 -0
  26. package/renderer/app/api/domains/add/route.js +121 -0
  27. package/renderer/app/api/domains/lookup/route.js +43 -0
  28. package/renderer/app/api/domains/remove/route.js +89 -0
  29. package/renderer/app/api/domains/status/route.js +140 -0
  30. package/renderer/app/api/domains/verify/route.js +168 -0
  31. package/renderer/app/api/keys/regenerate/route.js +71 -0
  32. package/renderer/app/api/local-assets/[...path]/route.js +108 -0
  33. package/renderer/app/api/openapi-spec/route.js +73 -0
  34. package/renderer/app/api/projects/[slug]/route.js +129 -0
  35. package/renderer/app/api/projects/[slug]/stats/route.js +80 -0
  36. package/renderer/app/api/projects/register/route.js +176 -0
  37. package/renderer/app/api/proxy/route.js +139 -0
  38. package/renderer/app/api/proxy-stream/route.js +156 -0
  39. package/renderer/app/api/redirects/route.js +35 -0
  40. package/renderer/app/api/schema/route.js +85 -0
  41. package/renderer/app/api/subdomains/check/route.js +158 -0
  42. package/renderer/app/api/suggestions/route.js +175 -0
  43. package/renderer/app/layout.js +47 -0
  44. package/renderer/app/llms-full.txt/route.js +257 -0
  45. package/renderer/app/llms.txt/route.js +219 -0
  46. package/renderer/app/page.js +12 -0
  47. package/renderer/app/robots.txt/route.js +66 -0
  48. package/renderer/app/sitemap.xml/route.js +145 -0
  49. package/renderer/components/docs/index.js +8 -0
  50. package/renderer/components/docs/mdx/accordion.js +113 -0
  51. package/renderer/components/docs/mdx/badge.js +72 -0
  52. package/renderer/components/docs/mdx/callouts.js +137 -0
  53. package/renderer/components/docs/mdx/cards.js +175 -0
  54. package/renderer/components/docs/mdx/changelog.js +100 -0
  55. package/renderer/components/docs/mdx/code-block.js +147 -0
  56. package/renderer/components/docs/mdx/code-group.js +287 -0
  57. package/renderer/components/docs/mdx/file-embeds.js +82 -0
  58. package/renderer/components/docs/mdx/frame.js +59 -0
  59. package/renderer/components/docs/mdx/highlight.js +90 -0
  60. package/renderer/components/docs/mdx/iframe.js +69 -0
  61. package/renderer/components/docs/mdx/image.js +135 -0
  62. package/renderer/components/docs/mdx/index.js +134 -0
  63. package/renderer/components/docs/mdx/landing.js +315 -0
  64. package/renderer/components/docs/mdx/mermaid.js +212 -0
  65. package/renderer/components/docs/mdx/param-field.js +112 -0
  66. package/renderer/components/docs/mdx/steps.js +74 -0
  67. package/renderer/components/docs/mdx/tabs.js +50 -0
  68. package/renderer/components/docs/mdx-renderer.js +77 -0
  69. package/renderer/components/docs/navigation/breadcrumbs.js +64 -0
  70. package/renderer/components/docs/navigation/index.js +6 -0
  71. package/renderer/components/docs/navigation/page-nav.js +57 -0
  72. package/renderer/components/docs/navigation/sidebar.js +375 -0
  73. package/renderer/components/docs/navigation/toc.js +89 -0
  74. package/renderer/components/docs/notice.js +77 -0
  75. package/renderer/components/docs-header.js +202 -0
  76. package/renderer/components/docs-viewer/agent/agent-chat.js +1930 -0
  77. package/renderer/components/docs-viewer/agent/cards/debug-context-card.js +107 -0
  78. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.js +57 -0
  79. package/renderer/components/docs-viewer/agent/cards/index.js +45 -0
  80. package/renderer/components/docs-viewer/agent/cards/response-options-card.js +154 -0
  81. package/renderer/components/docs-viewer/agent/cards/types.js +22 -0
  82. package/renderer/components/docs-viewer/agent/chat-message.js +2 -0
  83. package/renderer/components/docs-viewer/agent/index.js +4 -0
  84. package/renderer/components/docs-viewer/agent/messages/assistant-message.js +108 -0
  85. package/renderer/components/docs-viewer/agent/messages/chat-message.js +34 -0
  86. package/renderer/components/docs-viewer/agent/messages/index.js +6 -0
  87. package/renderer/components/docs-viewer/agent/messages/tool-call-display.js +1065 -0
  88. package/renderer/components/docs-viewer/agent/messages/types.js +2 -0
  89. package/renderer/components/docs-viewer/agent/messages/typing-indicator.js +26 -0
  90. package/renderer/components/docs-viewer/agent/messages/user-message.js +37 -0
  91. package/renderer/components/docs-viewer/code-editor/{index.tsx → index.js} +1 -1
  92. package/renderer/components/docs-viewer/code-editor/notes-mode.js +1338 -0
  93. package/renderer/components/docs-viewer/content/changelog-page.js +297 -0
  94. package/renderer/components/docs-viewer/content/doc-page.js +264 -0
  95. package/renderer/components/docs-viewer/content/documentation-viewer.js +14 -0
  96. package/renderer/components/docs-viewer/content/index.js +29 -0
  97. package/renderer/components/docs-viewer/content/not-found-page.js +300 -0
  98. package/renderer/components/docs-viewer/content/request-details.js +528 -0
  99. package/renderer/components/docs-viewer/content/sections/auth.js +108 -0
  100. package/renderer/components/docs-viewer/content/sections/body.js +80 -0
  101. package/renderer/components/docs-viewer/content/sections/headers.js +64 -0
  102. package/renderer/components/docs-viewer/content/sections/overview.js +56 -0
  103. package/renderer/components/docs-viewer/content/sections/parameters.js +64 -0
  104. package/renderer/components/docs-viewer/content/sections/responses.js +91 -0
  105. package/renderer/components/docs-viewer/global-auth-modal.js +427 -0
  106. package/renderer/components/docs-viewer/index.js +1552 -0
  107. package/renderer/components/docs-viewer/playground/auth-editor.js +418 -0
  108. package/renderer/components/docs-viewer/playground/body-editor.js +240 -0
  109. package/renderer/components/docs-viewer/playground/code-editor.js +135 -0
  110. package/renderer/components/docs-viewer/playground/code-snippet.js +393 -0
  111. package/renderer/components/docs-viewer/playground/graphql-playground.js +734 -0
  112. package/renderer/components/docs-viewer/playground/index.js +682 -0
  113. package/renderer/components/docs-viewer/playground/key-value-editor.js +317 -0
  114. package/renderer/components/docs-viewer/playground/method-selector.js +65 -0
  115. package/renderer/components/docs-viewer/playground/request-builder.js +181 -0
  116. package/renderer/components/docs-viewer/playground/request-tabs.js +240 -0
  117. package/renderer/components/docs-viewer/playground/response-cards/idle-card.js +42 -0
  118. package/renderer/components/docs-viewer/playground/response-cards/index.js +72 -0
  119. package/renderer/components/docs-viewer/playground/response-cards/loading-card.js +24 -0
  120. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.js +28 -0
  121. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.js +308 -0
  122. package/renderer/components/docs-viewer/playground/response-cards/types.js +9 -0
  123. package/renderer/components/docs-viewer/playground/response-viewer.js +18 -0
  124. package/renderer/components/docs-viewer/search/index.js +2 -0
  125. package/renderer/components/docs-viewer/search/search-dialog.js +367 -0
  126. package/renderer/components/docs-viewer/search/use-search.js +89 -0
  127. package/renderer/components/docs-viewer/shared/markdown-renderer.js +423 -0
  128. package/renderer/components/docs-viewer/shared/method-badge.js +23 -0
  129. package/renderer/components/docs-viewer/shared/schema-viewer.js +321 -0
  130. package/renderer/components/docs-viewer/sidebar/collection-tree.js +222 -0
  131. package/renderer/components/docs-viewer/sidebar/endpoint-options.js +512 -0
  132. package/renderer/components/docs-viewer/sidebar/index.js +196 -0
  133. package/renderer/components/docs-viewer/sidebar/right-sidebar.js +163 -0
  134. package/renderer/components/docs-viewer/sidebar/sidebar-group.js +87 -0
  135. package/renderer/components/docs-viewer/sidebar/sidebar-item.js +172 -0
  136. package/renderer/components/docs-viewer/sidebar/sidebar-section.js +31 -0
  137. package/renderer/components/theme-provider.js +10 -0
  138. package/renderer/components/theme-toggle.js +106 -0
  139. package/renderer/components/ui/badge.js +29 -0
  140. package/renderer/components/ui/button.js +40 -0
  141. package/renderer/components/ui/dialog.js +50 -0
  142. package/renderer/components/ui/dropdown-menu.js +143 -0
  143. package/renderer/components/ui/input.js +12 -0
  144. package/renderer/components/ui/label.js +13 -0
  145. package/renderer/components/ui/navigation-menu.js +83 -0
  146. package/renderer/components/ui/select.js +116 -0
  147. package/renderer/components/ui/spinner.js +92 -0
  148. package/renderer/components/ui/tabs.js +34 -0
  149. package/renderer/components/ui/tooltip.js +43 -0
  150. package/renderer/hooks/use-code-copy.js +76 -0
  151. package/renderer/hooks/use-openapi-title.js +33 -0
  152. package/renderer/lib/api-docs/agent/index.js +4 -0
  153. package/renderer/lib/api-docs/agent/indexer.js +254 -0
  154. package/renderer/lib/api-docs/agent/spec-summary.js +227 -0
  155. package/renderer/lib/api-docs/agent/types.js +5 -0
  156. package/renderer/lib/api-docs/auth/auth-context.js +157 -0
  157. package/renderer/lib/api-docs/auth/auth-storage.js +66 -0
  158. package/renderer/lib/api-docs/auth/crypto.js +64 -0
  159. package/renderer/lib/api-docs/auth/index.js +3 -0
  160. package/renderer/lib/api-docs/code-editor/db.js +145 -0
  161. package/renderer/lib/api-docs/code-editor/hooks.js +254 -0
  162. package/renderer/lib/api-docs/code-editor/{index.ts → index.js} +3 -4
  163. package/renderer/lib/api-docs/code-editor/mode-context.js +154 -0
  164. package/renderer/lib/api-docs/code-editor/types.js +53 -0
  165. package/renderer/lib/api-docs/codegen/definitions.js +258 -0
  166. package/renderer/lib/api-docs/codegen/har.js +171 -0
  167. package/renderer/lib/api-docs/codegen/index.js +118 -0
  168. package/renderer/lib/api-docs/factories.js +136 -0
  169. package/renderer/lib/api-docs/{index.ts → index.js} +5 -10
  170. package/renderer/lib/api-docs/mobile-context.js +79 -0
  171. package/renderer/lib/api-docs/navigation-context.js +62 -0
  172. package/renderer/lib/api-docs/parsers/graphql/index.js +50 -0
  173. package/renderer/lib/api-docs/parsers/graphql/parser.js +350 -0
  174. package/renderer/lib/api-docs/parsers/graphql/transformer.js +215 -0
  175. package/renderer/lib/api-docs/parsers/graphql/types.js +46 -0
  176. package/renderer/lib/api-docs/parsers/openapi/dereferencer.js +43 -0
  177. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.js +486 -0
  178. package/renderer/lib/api-docs/parsers/openapi/extractors/body.js +295 -0
  179. package/renderer/lib/api-docs/parsers/openapi/extractors/index.js +132 -0
  180. package/renderer/lib/api-docs/parsers/openapi/index.js +127 -0
  181. package/renderer/lib/api-docs/parsers/openapi/transformer.js +192 -0
  182. package/renderer/lib/api-docs/parsers/openapi/validator.js +24 -0
  183. package/renderer/lib/api-docs/playground/context.js +65 -0
  184. package/renderer/lib/api-docs/playground/navigation-context.js +74 -0
  185. package/renderer/lib/api-docs/playground/request-builder.js +163 -0
  186. package/renderer/lib/api-docs/playground/request-runner.js +224 -0
  187. package/renderer/lib/api-docs/playground/types.js +5 -0
  188. package/renderer/lib/api-docs/types.js +23 -0
  189. package/renderer/lib/api-docs/utils.js +212 -0
  190. package/renderer/lib/cache.js +157 -0
  191. package/renderer/lib/docs/config/domain-schema.js +161 -0
  192. package/renderer/lib/docs/config/index.js +5 -0
  193. package/renderer/lib/docs/config/loader.js +113 -0
  194. package/renderer/lib/docs/config/schema.js +269 -0
  195. package/renderer/lib/docs/index.js +8 -0
  196. package/renderer/lib/docs/mdx/compiler.js +128 -0
  197. package/renderer/lib/docs/mdx/frontmatter.js +73 -0
  198. package/renderer/lib/docs/mdx/index.js +8 -0
  199. package/renderer/lib/docs/navigation/generator.js +269 -0
  200. package/renderer/lib/docs/navigation/index.js +4 -0
  201. package/renderer/lib/docs/navigation/types.js +9 -0
  202. package/renderer/lib/docs-navigation-context.js +40 -0
  203. package/renderer/lib/multi-tenant/context.js +80 -0
  204. package/renderer/lib/storage/blob.js +767 -0
  205. package/renderer/lib/utils/icons.js +30 -0
  206. package/renderer/lib/utils.js +5 -0
  207. package/renderer/next.config.js +62 -0
  208. package/renderer/tsconfig.json +23 -5
  209. package/renderer/app/api/assets/[...path]/route.ts +0 -123
  210. package/renderer/app/api/assets/route.ts +0 -124
  211. package/renderer/app/api/assets/upload/route.ts +0 -177
  212. package/renderer/app/api/auth-schemes/route.ts +0 -77
  213. package/renderer/app/api/chat/route.ts +0 -858
  214. package/renderer/app/api/codegen/route.ts +0 -72
  215. package/renderer/app/api/collections/route.ts +0 -1002
  216. package/renderer/app/api/debug/route.ts +0 -53
  217. package/renderer/app/api/deploy/route.ts +0 -234
  218. package/renderer/app/api/device/route.ts +0 -42
  219. package/renderer/app/api/docs/route.ts +0 -201
  220. package/renderer/app/api/domains/add/route.ts +0 -132
  221. package/renderer/app/api/domains/lookup/route.ts +0 -43
  222. package/renderer/app/api/domains/remove/route.ts +0 -100
  223. package/renderer/app/api/domains/status/route.ts +0 -158
  224. package/renderer/app/api/domains/verify/route.ts +0 -181
  225. package/renderer/app/api/keys/regenerate/route.ts +0 -80
  226. package/renderer/app/api/local-assets/[...path]/route.ts +0 -122
  227. package/renderer/app/api/openapi-spec/route.ts +0 -151
  228. package/renderer/app/api/projects/[slug]/route.ts +0 -153
  229. package/renderer/app/api/projects/[slug]/stats/route.ts +0 -96
  230. package/renderer/app/api/projects/register/route.ts +0 -152
  231. package/renderer/app/api/proxy/route.ts +0 -149
  232. package/renderer/app/api/proxy-stream/route.ts +0 -168
  233. package/renderer/app/api/redirects/route.ts +0 -47
  234. package/renderer/app/api/schema/route.ts +0 -73
  235. package/renderer/app/api/subdomains/check/route.ts +0 -172
  236. package/renderer/app/api/suggestions/route.ts +0 -144
  237. package/renderer/app/layout.tsx +0 -54
  238. package/renderer/app/llms-full.txt/route.ts +0 -346
  239. package/renderer/app/llms.txt/route.ts +0 -279
  240. package/renderer/app/page.tsx +0 -14
  241. package/renderer/app/robots.txt/route.ts +0 -84
  242. package/renderer/app/sitemap.xml/route.ts +0 -199
  243. package/renderer/components/docs/index.ts +0 -12
  244. package/renderer/components/docs/mdx/accordion.tsx +0 -169
  245. package/renderer/components/docs/mdx/badge.tsx +0 -132
  246. package/renderer/components/docs/mdx/callouts.tsx +0 -154
  247. package/renderer/components/docs/mdx/cards.tsx +0 -241
  248. package/renderer/components/docs/mdx/changelog.tsx +0 -120
  249. package/renderer/components/docs/mdx/code-block.tsx +0 -186
  250. package/renderer/components/docs/mdx/code-group.tsx +0 -421
  251. package/renderer/components/docs/mdx/file-embeds.tsx +0 -105
  252. package/renderer/components/docs/mdx/frame.tsx +0 -112
  253. package/renderer/components/docs/mdx/highlight.tsx +0 -151
  254. package/renderer/components/docs/mdx/iframe.tsx +0 -134
  255. package/renderer/components/docs/mdx/image.tsx +0 -235
  256. package/renderer/components/docs/mdx/index.ts +0 -237
  257. package/renderer/components/docs/mdx/landing.tsx +0 -684
  258. package/renderer/components/docs/mdx/mermaid.tsx +0 -240
  259. package/renderer/components/docs/mdx/param-field.tsx +0 -200
  260. package/renderer/components/docs/mdx/steps.tsx +0 -113
  261. package/renderer/components/docs/mdx/tabs.tsx +0 -86
  262. package/renderer/components/docs/mdx-renderer.tsx +0 -100
  263. package/renderer/components/docs/navigation/breadcrumbs.tsx +0 -76
  264. package/renderer/components/docs/navigation/index.ts +0 -8
  265. package/renderer/components/docs/navigation/page-nav.tsx +0 -64
  266. package/renderer/components/docs/navigation/sidebar.tsx +0 -515
  267. package/renderer/components/docs/navigation/toc.tsx +0 -113
  268. package/renderer/components/docs/notice.tsx +0 -105
  269. package/renderer/components/docs-header.tsx +0 -278
  270. package/renderer/components/docs-viewer/agent/agent-chat.tsx +0 -2076
  271. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +0 -90
  272. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +0 -49
  273. package/renderer/components/docs-viewer/agent/cards/index.tsx +0 -50
  274. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +0 -212
  275. package/renderer/components/docs-viewer/agent/cards/types.ts +0 -84
  276. package/renderer/components/docs-viewer/agent/chat-message.tsx +0 -17
  277. package/renderer/components/docs-viewer/agent/index.tsx +0 -6
  278. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +0 -119
  279. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +0 -46
  280. package/renderer/components/docs-viewer/agent/messages/index.ts +0 -17
  281. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +0 -721
  282. package/renderer/components/docs-viewer/agent/messages/types.ts +0 -61
  283. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +0 -24
  284. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +0 -51
  285. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +0 -1283
  286. package/renderer/components/docs-viewer/content/changelog-page.tsx +0 -331
  287. package/renderer/components/docs-viewer/content/doc-page.tsx +0 -367
  288. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +0 -17
  289. package/renderer/components/docs-viewer/content/index.tsx +0 -29
  290. package/renderer/components/docs-viewer/content/not-found-page.tsx +0 -330
  291. package/renderer/components/docs-viewer/content/request-details.tsx +0 -330
  292. package/renderer/components/docs-viewer/content/sections/auth.tsx +0 -69
  293. package/renderer/components/docs-viewer/content/sections/body.tsx +0 -66
  294. package/renderer/components/docs-viewer/content/sections/headers.tsx +0 -43
  295. package/renderer/components/docs-viewer/content/sections/overview.tsx +0 -40
  296. package/renderer/components/docs-viewer/content/sections/parameters.tsx +0 -43
  297. package/renderer/components/docs-viewer/content/sections/responses.tsx +0 -87
  298. package/renderer/components/docs-viewer/global-auth-modal.tsx +0 -352
  299. package/renderer/components/docs-viewer/index.tsx +0 -1662
  300. package/renderer/components/docs-viewer/playground/auth-editor.tsx +0 -280
  301. package/renderer/components/docs-viewer/playground/body-editor.tsx +0 -221
  302. package/renderer/components/docs-viewer/playground/code-editor.tsx +0 -224
  303. package/renderer/components/docs-viewer/playground/code-snippet.tsx +0 -387
  304. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +0 -745
  305. package/renderer/components/docs-viewer/playground/index.tsx +0 -671
  306. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +0 -261
  307. package/renderer/components/docs-viewer/playground/method-selector.tsx +0 -60
  308. package/renderer/components/docs-viewer/playground/request-builder.tsx +0 -179
  309. package/renderer/components/docs-viewer/playground/request-tabs.tsx +0 -237
  310. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +0 -21
  311. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +0 -93
  312. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +0 -16
  313. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +0 -23
  314. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +0 -268
  315. package/renderer/components/docs-viewer/playground/response-cards/types.ts +0 -82
  316. package/renderer/components/docs-viewer/playground/response-viewer.tsx +0 -43
  317. package/renderer/components/docs-viewer/search/index.ts +0 -2
  318. package/renderer/components/docs-viewer/search/search-dialog.tsx +0 -331
  319. package/renderer/components/docs-viewer/search/use-search.ts +0 -117
  320. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +0 -431
  321. package/renderer/components/docs-viewer/shared/method-badge.tsx +0 -41
  322. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +0 -349
  323. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +0 -259
  324. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +0 -316
  325. package/renderer/components/docs-viewer/sidebar/index.tsx +0 -282
  326. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +0 -202
  327. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +0 -118
  328. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +0 -212
  329. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +0 -38
  330. package/renderer/components/theme-provider.tsx +0 -11
  331. package/renderer/components/theme-toggle.tsx +0 -76
  332. package/renderer/components/ui/badge.tsx +0 -46
  333. package/renderer/components/ui/button.tsx +0 -59
  334. package/renderer/components/ui/dialog.tsx +0 -118
  335. package/renderer/components/ui/dropdown-menu.tsx +0 -257
  336. package/renderer/components/ui/input.tsx +0 -21
  337. package/renderer/components/ui/label.tsx +0 -24
  338. package/renderer/components/ui/navigation-menu.tsx +0 -168
  339. package/renderer/components/ui/select.tsx +0 -190
  340. package/renderer/components/ui/spinner.tsx +0 -114
  341. package/renderer/components/ui/tabs.tsx +0 -66
  342. package/renderer/components/ui/tooltip.tsx +0 -61
  343. package/renderer/hooks/use-code-copy.ts +0 -88
  344. package/renderer/hooks/use-openapi-title.ts +0 -44
  345. package/renderer/lib/api-docs/agent/index.ts +0 -6
  346. package/renderer/lib/api-docs/agent/indexer.ts +0 -323
  347. package/renderer/lib/api-docs/agent/spec-summary.ts +0 -335
  348. package/renderer/lib/api-docs/agent/types.ts +0 -116
  349. package/renderer/lib/api-docs/auth/auth-context.tsx +0 -225
  350. package/renderer/lib/api-docs/auth/auth-storage.ts +0 -87
  351. package/renderer/lib/api-docs/auth/crypto.ts +0 -89
  352. package/renderer/lib/api-docs/auth/index.ts +0 -4
  353. package/renderer/lib/api-docs/code-editor/db.ts +0 -164
  354. package/renderer/lib/api-docs/code-editor/hooks.ts +0 -266
  355. package/renderer/lib/api-docs/code-editor/mode-context.tsx +0 -207
  356. package/renderer/lib/api-docs/code-editor/types.ts +0 -105
  357. package/renderer/lib/api-docs/codegen/definitions.ts +0 -297
  358. package/renderer/lib/api-docs/codegen/har.ts +0 -251
  359. package/renderer/lib/api-docs/codegen/index.ts +0 -159
  360. package/renderer/lib/api-docs/factories.ts +0 -170
  361. package/renderer/lib/api-docs/mobile-context.tsx +0 -112
  362. package/renderer/lib/api-docs/navigation-context.tsx +0 -88
  363. package/renderer/lib/api-docs/parsers/graphql/README.md +0 -129
  364. package/renderer/lib/api-docs/parsers/graphql/index.ts +0 -91
  365. package/renderer/lib/api-docs/parsers/graphql/parser.ts +0 -491
  366. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +0 -246
  367. package/renderer/lib/api-docs/parsers/graphql/types.ts +0 -283
  368. package/renderer/lib/api-docs/parsers/openapi/README.md +0 -32
  369. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +0 -60
  370. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +0 -574
  371. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +0 -403
  372. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +0 -232
  373. package/renderer/lib/api-docs/parsers/openapi/index.ts +0 -171
  374. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +0 -278
  375. package/renderer/lib/api-docs/parsers/openapi/validator.ts +0 -31
  376. package/renderer/lib/api-docs/playground/context.tsx +0 -107
  377. package/renderer/lib/api-docs/playground/navigation-context.tsx +0 -124
  378. package/renderer/lib/api-docs/playground/request-builder.ts +0 -223
  379. package/renderer/lib/api-docs/playground/request-runner.ts +0 -282
  380. package/renderer/lib/api-docs/playground/types.ts +0 -35
  381. package/renderer/lib/api-docs/types.ts +0 -269
  382. package/renderer/lib/api-docs/utils.ts +0 -311
  383. package/renderer/lib/cache.ts +0 -193
  384. package/renderer/lib/docs/config/domain-schema.ts +0 -260
  385. package/renderer/lib/docs/config/index.ts +0 -43
  386. package/renderer/lib/docs/config/loader.ts +0 -142
  387. package/renderer/lib/docs/config/schema.ts +0 -308
  388. package/renderer/lib/docs/index.ts +0 -12
  389. package/renderer/lib/docs/mdx/compiler.ts +0 -176
  390. package/renderer/lib/docs/mdx/frontmatter.ts +0 -91
  391. package/renderer/lib/docs/mdx/index.ts +0 -26
  392. package/renderer/lib/docs/navigation/generator.ts +0 -348
  393. package/renderer/lib/docs/navigation/index.ts +0 -12
  394. package/renderer/lib/docs/navigation/types.ts +0 -123
  395. package/renderer/lib/docs-navigation-context.tsx +0 -80
  396. package/renderer/lib/multi-tenant/context.ts +0 -105
  397. package/renderer/lib/storage/blob.ts +0 -1083
  398. package/renderer/lib/utils/icons.ts +0 -48
  399. package/renderer/lib/utils.ts +0 -6
  400. 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
+ }