@agent-native/core 0.37.3 → 0.39.0

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 (476) hide show
  1. package/README.md +19 -6
  2. package/dist/action.d.ts +60 -2
  3. package/dist/action.d.ts.map +1 -1
  4. package/dist/action.js +6 -2
  5. package/dist/action.js.map +1 -1
  6. package/dist/agent/production-agent.d.ts +12 -6
  7. package/dist/agent/production-agent.d.ts.map +1 -1
  8. package/dist/agent/production-agent.js +161 -11
  9. package/dist/agent/production-agent.js.map +1 -1
  10. package/dist/agent/types.d.ts +2 -0
  11. package/dist/agent/types.d.ts.map +1 -1
  12. package/dist/agent/types.js.map +1 -1
  13. package/dist/catalog.json +2 -2
  14. package/dist/cli/connect.d.ts.map +1 -1
  15. package/dist/cli/connect.js +15 -0
  16. package/dist/cli/connect.js.map +1 -1
  17. package/dist/cli/create.d.ts.map +1 -1
  18. package/dist/cli/create.js +8 -1
  19. package/dist/cli/create.js.map +1 -1
  20. package/dist/cli/index.js +10 -6
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/plan-publish-store.d.ts +52 -0
  23. package/dist/cli/plan-publish-store.d.ts.map +1 -0
  24. package/dist/cli/plan-publish-store.js +103 -0
  25. package/dist/cli/plan-publish-store.js.map +1 -0
  26. package/dist/cli/skills.d.ts +30 -4
  27. package/dist/cli/skills.d.ts.map +1 -1
  28. package/dist/cli/skills.js +1240 -339
  29. package/dist/cli/skills.js.map +1 -1
  30. package/dist/cli/templates-meta.js +12 -12
  31. package/dist/cli/templates-meta.js.map +1 -1
  32. package/dist/client/AssistantChat.d.ts +3 -1
  33. package/dist/client/AssistantChat.d.ts.map +1 -1
  34. package/dist/client/AssistantChat.js +65 -15
  35. package/dist/client/AssistantChat.js.map +1 -1
  36. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  37. package/dist/client/MultiTabAssistantChat.js +20 -2
  38. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  39. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  40. package/dist/client/agent-chat-adapter.js +12 -0
  41. package/dist/client/agent-chat-adapter.js.map +1 -1
  42. package/dist/client/agent-engine-key.d.ts +24 -0
  43. package/dist/client/agent-engine-key.d.ts.map +1 -0
  44. package/dist/client/agent-engine-key.js +49 -0
  45. package/dist/client/agent-engine-key.js.map +1 -0
  46. package/dist/client/analytics.d.ts.map +1 -1
  47. package/dist/client/analytics.js +34 -0
  48. package/dist/client/analytics.js.map +1 -1
  49. package/dist/client/blocks/BlockView.d.ts +35 -0
  50. package/dist/client/blocks/BlockView.d.ts.map +1 -0
  51. package/dist/client/blocks/BlockView.js +45 -0
  52. package/dist/client/blocks/BlockView.js.map +1 -0
  53. package/dist/client/blocks/SchemaBlockEditor.d.ts +25 -0
  54. package/dist/client/blocks/SchemaBlockEditor.d.ts.map +1 -0
  55. package/dist/client/blocks/SchemaBlockEditor.js +165 -0
  56. package/dist/client/blocks/SchemaBlockEditor.js.map +1 -0
  57. package/dist/client/blocks/agent.d.ts +30 -0
  58. package/dist/client/blocks/agent.d.ts.map +1 -0
  59. package/dist/client/blocks/agent.js +61 -0
  60. package/dist/client/blocks/agent.js.map +1 -0
  61. package/dist/client/blocks/index.d.ts +51 -0
  62. package/dist/client/blocks/index.d.ts.map +1 -0
  63. package/dist/client/blocks/index.js +67 -0
  64. package/dist/client/blocks/index.js.map +1 -0
  65. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts +6 -0
  66. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -0
  67. package/dist/client/blocks/library/AnnotatedCodeBlock.js +135 -0
  68. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -0
  69. package/dist/client/blocks/library/ApiEndpointBlock.d.ts +20 -0
  70. package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -0
  71. package/dist/client/blocks/library/ApiEndpointBlock.js +131 -0
  72. package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -0
  73. package/dist/client/blocks/library/DataModelBlock.d.ts +28 -0
  74. package/dist/client/blocks/library/DataModelBlock.d.ts.map +1 -0
  75. package/dist/client/blocks/library/DataModelBlock.js +222 -0
  76. package/dist/client/blocks/library/DataModelBlock.js.map +1 -0
  77. package/dist/client/blocks/library/DiffBlock.d.ts +6 -0
  78. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -0
  79. package/dist/client/blocks/library/DiffBlock.js +293 -0
  80. package/dist/client/blocks/library/DiffBlock.js.map +1 -0
  81. package/dist/client/blocks/library/FileTreeBlock.d.ts +23 -0
  82. package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -0
  83. package/dist/client/blocks/library/FileTreeBlock.js +225 -0
  84. package/dist/client/blocks/library/FileTreeBlock.js.map +1 -0
  85. package/dist/client/blocks/library/JsonExplorerBlock.d.ts +19 -0
  86. package/dist/client/blocks/library/JsonExplorerBlock.d.ts.map +1 -0
  87. package/dist/client/blocks/library/JsonExplorerBlock.js +171 -0
  88. package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -0
  89. package/dist/client/blocks/library/MermaidBlock.d.ts +17 -0
  90. package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -0
  91. package/dist/client/blocks/library/MermaidBlock.js +131 -0
  92. package/dist/client/blocks/library/MermaidBlock.js.map +1 -0
  93. package/dist/client/blocks/library/OpenApiSpecBlock.d.ts +19 -0
  94. package/dist/client/blocks/library/OpenApiSpecBlock.d.ts.map +1 -0
  95. package/dist/client/blocks/library/OpenApiSpecBlock.js +494 -0
  96. package/dist/client/blocks/library/OpenApiSpecBlock.js.map +1 -0
  97. package/dist/client/blocks/library/annotated-code.config.d.ts +58 -0
  98. package/dist/client/blocks/library/annotated-code.config.d.ts.map +1 -0
  99. package/dist/client/blocks/library/annotated-code.config.js +53 -0
  100. package/dist/client/blocks/library/annotated-code.config.js.map +1 -0
  101. package/dist/client/blocks/library/api-endpoint.config.d.ts +71 -0
  102. package/dist/client/blocks/library/api-endpoint.config.d.ts.map +1 -0
  103. package/dist/client/blocks/library/api-endpoint.config.js +91 -0
  104. package/dist/client/blocks/library/api-endpoint.config.js.map +1 -0
  105. package/dist/client/blocks/library/checklist.config.d.ts +36 -0
  106. package/dist/client/blocks/library/checklist.config.d.ts.map +1 -0
  107. package/dist/client/blocks/library/checklist.config.js +25 -0
  108. package/dist/client/blocks/library/checklist.config.js.map +1 -0
  109. package/dist/client/blocks/library/checklist.d.ts +26 -0
  110. package/dist/client/blocks/library/checklist.d.ts.map +1 -0
  111. package/dist/client/blocks/library/checklist.js +78 -0
  112. package/dist/client/blocks/library/checklist.js.map +1 -0
  113. package/dist/client/blocks/library/code-tabs.config.d.ts +36 -0
  114. package/dist/client/blocks/library/code-tabs.config.d.ts.map +1 -0
  115. package/dist/client/blocks/library/code-tabs.config.js +30 -0
  116. package/dist/client/blocks/library/code-tabs.config.js.map +1 -0
  117. package/dist/client/blocks/library/code-tabs.d.ts +3 -0
  118. package/dist/client/blocks/library/code-tabs.d.ts.map +1 -0
  119. package/dist/client/blocks/library/code-tabs.js +165 -0
  120. package/dist/client/blocks/library/code-tabs.js.map +1 -0
  121. package/dist/client/blocks/library/data-model.config.d.ts +72 -0
  122. package/dist/client/blocks/library/data-model.config.d.ts.map +1 -0
  123. package/dist/client/blocks/library/data-model.config.js +59 -0
  124. package/dist/client/blocks/library/data-model.config.js.map +1 -0
  125. package/dist/client/blocks/library/dev-doc-ui.d.ts +49 -0
  126. package/dist/client/blocks/library/dev-doc-ui.d.ts.map +1 -0
  127. package/dist/client/blocks/library/dev-doc-ui.js +50 -0
  128. package/dist/client/blocks/library/dev-doc-ui.js.map +1 -0
  129. package/dist/client/blocks/library/diff.config.d.ts +41 -0
  130. package/dist/client/blocks/library/diff.config.d.ts.map +1 -0
  131. package/dist/client/blocks/library/diff.config.js +34 -0
  132. package/dist/client/blocks/library/diff.config.js.map +1 -0
  133. package/dist/client/blocks/library/file-tree.config.d.ts +59 -0
  134. package/dist/client/blocks/library/file-tree.config.d.ts.map +1 -0
  135. package/dist/client/blocks/library/file-tree.config.js +45 -0
  136. package/dist/client/blocks/library/file-tree.config.js.map +1 -0
  137. package/dist/client/blocks/library/html.config.d.ts +37 -0
  138. package/dist/client/blocks/library/html.config.d.ts.map +1 -0
  139. package/dist/client/blocks/library/html.config.js +46 -0
  140. package/dist/client/blocks/library/html.config.js.map +1 -0
  141. package/dist/client/blocks/library/html.d.ts +21 -0
  142. package/dist/client/blocks/library/html.d.ts.map +1 -0
  143. package/dist/client/blocks/library/html.js +72 -0
  144. package/dist/client/blocks/library/html.js.map +1 -0
  145. package/dist/client/blocks/library/json-explorer.config.d.ts +46 -0
  146. package/dist/client/blocks/library/json-explorer.config.d.ts.map +1 -0
  147. package/dist/client/blocks/library/json-explorer.config.js +28 -0
  148. package/dist/client/blocks/library/json-explorer.config.js.map +1 -0
  149. package/dist/client/blocks/library/mermaid.config.d.ts +32 -0
  150. package/dist/client/blocks/library/mermaid.config.d.ts.map +1 -0
  151. package/dist/client/blocks/library/mermaid.config.js +24 -0
  152. package/dist/client/blocks/library/mermaid.config.js.map +1 -0
  153. package/dist/client/blocks/library/openapi-spec.config.d.ts +49 -0
  154. package/dist/client/blocks/library/openapi-spec.config.d.ts.map +1 -0
  155. package/dist/client/blocks/library/openapi-spec.config.js +24 -0
  156. package/dist/client/blocks/library/openapi-spec.config.js.map +1 -0
  157. package/dist/client/blocks/library/server-specs.d.ts +35 -0
  158. package/dist/client/blocks/library/server-specs.d.ts.map +1 -0
  159. package/dist/client/blocks/library/server-specs.js +171 -0
  160. package/dist/client/blocks/library/server-specs.js.map +1 -0
  161. package/dist/client/blocks/library/specs.d.ts +29 -0
  162. package/dist/client/blocks/library/specs.d.ts.map +1 -0
  163. package/dist/client/blocks/library/specs.js +229 -0
  164. package/dist/client/blocks/library/specs.js.map +1 -0
  165. package/dist/client/blocks/library/table.config.d.ts +30 -0
  166. package/dist/client/blocks/library/table.config.d.ts.map +1 -0
  167. package/dist/client/blocks/library/table.config.js +22 -0
  168. package/dist/client/blocks/library/table.config.js.map +1 -0
  169. package/dist/client/blocks/library/table.d.ts +8 -0
  170. package/dist/client/blocks/library/table.d.ts.map +1 -0
  171. package/dist/client/blocks/library/table.js +109 -0
  172. package/dist/client/blocks/library/table.js.map +1 -0
  173. package/dist/client/blocks/library/tabs.config.d.ts +56 -0
  174. package/dist/client/blocks/library/tabs.config.d.ts.map +1 -0
  175. package/dist/client/blocks/library/tabs.config.js +36 -0
  176. package/dist/client/blocks/library/tabs.config.js.map +1 -0
  177. package/dist/client/blocks/library/tabs.d.ts +20 -0
  178. package/dist/client/blocks/library/tabs.d.ts.map +1 -0
  179. package/dist/client/blocks/library/tabs.js +123 -0
  180. package/dist/client/blocks/library/tabs.js.map +1 -0
  181. package/dist/client/blocks/mdx.d.ts +74 -0
  182. package/dist/client/blocks/mdx.d.ts.map +1 -0
  183. package/dist/client/blocks/mdx.js +205 -0
  184. package/dist/client/blocks/mdx.js.map +1 -0
  185. package/dist/client/blocks/provider.d.ts +25 -0
  186. package/dist/client/blocks/provider.d.ts.map +1 -0
  187. package/dist/client/blocks/provider.js +19 -0
  188. package/dist/client/blocks/provider.js.map +1 -0
  189. package/dist/client/blocks/registry.d.ts +32 -0
  190. package/dist/client/blocks/registry.d.ts.map +1 -0
  191. package/dist/client/blocks/registry.js +65 -0
  192. package/dist/client/blocks/registry.js.map +1 -0
  193. package/dist/client/blocks/schema-form/introspect.d.ts +31 -0
  194. package/dist/client/blocks/schema-form/introspect.d.ts.map +1 -0
  195. package/dist/client/blocks/schema-form/introspect.js +164 -0
  196. package/dist/client/blocks/schema-form/introspect.js.map +1 -0
  197. package/dist/client/blocks/server.d.ts +31 -0
  198. package/dist/client/blocks/server.d.ts.map +1 -0
  199. package/dist/client/blocks/server.js +41 -0
  200. package/dist/client/blocks/server.js.map +1 -0
  201. package/dist/client/blocks/types.d.ts +252 -0
  202. package/dist/client/blocks/types.d.ts.map +1 -0
  203. package/dist/client/blocks/types.js +5 -0
  204. package/dist/client/blocks/types.js.map +1 -0
  205. package/dist/client/composer/ComposerPlusMenu.js +10 -1
  206. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  207. package/dist/client/guided-questions.d.ts +68 -0
  208. package/dist/client/guided-questions.d.ts.map +1 -1
  209. package/dist/client/guided-questions.js +158 -3
  210. package/dist/client/guided-questions.js.map +1 -1
  211. package/dist/client/index.d.ts +6 -1
  212. package/dist/client/index.d.ts.map +1 -1
  213. package/dist/client/index.js +24 -1
  214. package/dist/client/index.js.map +1 -1
  215. package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts +37 -0
  216. package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +1 -0
  217. package/dist/client/rich-markdown-editor/BubbleToolbar.js +161 -0
  218. package/dist/client/rich-markdown-editor/BubbleToolbar.js.map +1 -0
  219. package/dist/client/rich-markdown-editor/DragHandle.d.ts +52 -0
  220. package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -0
  221. package/dist/client/rich-markdown-editor/DragHandle.js +403 -0
  222. package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -0
  223. package/dist/client/rich-markdown-editor/ImageExtension.d.ts +63 -0
  224. package/dist/client/rich-markdown-editor/ImageExtension.d.ts.map +1 -0
  225. package/dist/client/rich-markdown-editor/ImageExtension.js +242 -0
  226. package/dist/client/rich-markdown-editor/ImageExtension.js.map +1 -0
  227. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts +97 -0
  228. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -0
  229. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +214 -0
  230. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -0
  231. package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts +51 -0
  232. package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts.map +1 -0
  233. package/dist/client/rich-markdown-editor/RichMarkdownEditor.js +37 -0
  234. package/dist/client/rich-markdown-editor/RichMarkdownEditor.js.map +1 -0
  235. package/dist/client/rich-markdown-editor/RunId.d.ts +28 -0
  236. package/dist/client/rich-markdown-editor/RunId.d.ts.map +1 -0
  237. package/dist/client/rich-markdown-editor/RunId.js +60 -0
  238. package/dist/client/rich-markdown-editor/RunId.js.map +1 -0
  239. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +85 -0
  240. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -0
  241. package/dist/client/rich-markdown-editor/SharedRichEditor.js +130 -0
  242. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -0
  243. package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +36 -0
  244. package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +1 -0
  245. package/dist/client/rich-markdown-editor/SlashCommandMenu.js +193 -0
  246. package/dist/client/rich-markdown-editor/SlashCommandMenu.js.map +1 -0
  247. package/dist/client/rich-markdown-editor/extensions.d.ts +166 -0
  248. package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -0
  249. package/dist/client/rich-markdown-editor/extensions.js +222 -0
  250. package/dist/client/rich-markdown-editor/extensions.js.map +1 -0
  251. package/dist/client/rich-markdown-editor/gfmDoc.d.ts +24 -0
  252. package/dist/client/rich-markdown-editor/gfmDoc.d.ts.map +1 -0
  253. package/dist/client/rich-markdown-editor/gfmDoc.js +83 -0
  254. package/dist/client/rich-markdown-editor/gfmDoc.js.map +1 -0
  255. package/dist/client/rich-markdown-editor/index.d.ts +14 -0
  256. package/dist/client/rich-markdown-editor/index.d.ts.map +1 -0
  257. package/dist/client/rich-markdown-editor/index.js +14 -0
  258. package/dist/client/rich-markdown-editor/index.js.map +1 -0
  259. package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts +46 -0
  260. package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts.map +1 -0
  261. package/dist/client/rich-markdown-editor/registrySlashCommands.js +13 -0
  262. package/dist/client/rich-markdown-editor/registrySlashCommands.js.map +1 -0
  263. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts +18 -0
  264. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts.map +1 -0
  265. package/dist/client/rich-markdown-editor/uploadEditorImage.js +57 -0
  266. package/dist/client/rich-markdown-editor/uploadEditorImage.js.map +1 -0
  267. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +91 -0
  268. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -0
  269. package/dist/client/rich-markdown-editor/useCollabReconcile.js +375 -0
  270. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -0
  271. package/dist/client/track.d.ts +25 -0
  272. package/dist/client/track.d.ts.map +1 -0
  273. package/dist/client/track.js +53 -0
  274. package/dist/client/track.js.map +1 -0
  275. package/dist/client/use-action.d.ts.map +1 -1
  276. package/dist/client/use-action.js +6 -0
  277. package/dist/client/use-action.js.map +1 -1
  278. package/dist/client/use-session.d.ts +3 -2
  279. package/dist/client/use-session.d.ts.map +1 -1
  280. package/dist/client/use-session.js +3 -2
  281. package/dist/client/use-session.js.map +1 -1
  282. package/dist/deploy/build.d.ts +5 -0
  283. package/dist/deploy/build.d.ts.map +1 -1
  284. package/dist/deploy/build.js +67 -1
  285. package/dist/deploy/build.js.map +1 -1
  286. package/dist/extensions/schema.d.ts +1 -1
  287. package/dist/mcp/build-server.d.ts.map +1 -1
  288. package/dist/mcp/build-server.js +9 -2
  289. package/dist/mcp/build-server.js.map +1 -1
  290. package/dist/mcp/server.d.ts +1 -1
  291. package/dist/mcp/server.d.ts.map +1 -1
  292. package/dist/mcp/server.js +35 -2
  293. package/dist/mcp/server.js.map +1 -1
  294. package/dist/provider-api/index.d.ts +1 -1
  295. package/dist/provider-api/index.d.ts.map +1 -1
  296. package/dist/scripts/docs/search.d.ts.map +1 -1
  297. package/dist/scripts/docs/search.js +5 -2
  298. package/dist/scripts/docs/search.js.map +1 -1
  299. package/dist/scripts/runner.d.ts.map +1 -1
  300. package/dist/scripts/runner.js +16 -3
  301. package/dist/scripts/runner.js.map +1 -1
  302. package/dist/server/action-discovery.d.ts.map +1 -1
  303. package/dist/server/action-discovery.js +2 -0
  304. package/dist/server/action-discovery.js.map +1 -1
  305. package/dist/server/action-routes.d.ts.map +1 -1
  306. package/dist/server/action-routes.js +30 -4
  307. package/dist/server/action-routes.js.map +1 -1
  308. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  309. package/dist/server/agent-chat-plugin.js +65 -19
  310. package/dist/server/agent-chat-plugin.js.map +1 -1
  311. package/dist/server/agent-teams.d.ts.map +1 -1
  312. package/dist/server/agent-teams.js +8 -1
  313. package/dist/server/agent-teams.js.map +1 -1
  314. package/dist/server/agents-bundle.d.ts +27 -1
  315. package/dist/server/agents-bundle.d.ts.map +1 -1
  316. package/dist/server/agents-bundle.js +41 -3
  317. package/dist/server/agents-bundle.js.map +1 -1
  318. package/dist/server/auth.d.ts.map +1 -1
  319. package/dist/server/auth.js +76 -3
  320. package/dist/server/auth.js.map +1 -1
  321. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  322. package/dist/server/core-routes-plugin.js +60 -0
  323. package/dist/server/core-routes-plugin.js.map +1 -1
  324. package/dist/server/onboarding-html.d.ts.map +1 -1
  325. package/dist/server/onboarding-html.js +160 -22
  326. package/dist/server/onboarding-html.js.map +1 -1
  327. package/dist/server/sentry.d.ts.map +1 -1
  328. package/dist/server/sentry.js +6 -0
  329. package/dist/server/sentry.js.map +1 -1
  330. package/dist/server/social-og-image.d.ts +2 -1
  331. package/dist/server/social-og-image.d.ts.map +1 -1
  332. package/dist/server/social-og-image.js +24 -4
  333. package/dist/server/social-og-image.js.map +1 -1
  334. package/dist/sharing/schema.d.ts +1 -1
  335. package/dist/styles/agent-native.css +1 -0
  336. package/dist/styles/rich-markdown-editor.css +439 -0
  337. package/dist/templates/default/.agents/skills/actions/SKILL.md +4 -1
  338. package/dist/templates/default/.agents/skills/security/SKILL.md +13 -4
  339. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +15 -3
  340. package/dist/templates/default/AGENTS.md +1 -0
  341. package/dist/templates/default/DEVELOPING.md +2 -0
  342. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +10 -3
  343. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +98 -10
  344. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +45 -3
  345. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +2 -0
  346. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +37 -4
  347. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +9 -4
  348. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +2 -0
  349. package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +106 -0
  350. package/dist/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +53 -0
  351. package/dist/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +2 -0
  352. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +62 -61
  353. package/dist/templates/workspace-core/.agents/skills/context-xray/SKILL.md +47 -0
  354. package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +28 -0
  355. package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +52 -1
  356. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +2 -0
  357. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +95 -433
  358. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +285 -0
  359. package/dist/templates/workspace-core/.agents/skills/extensions/references/examples.md +259 -0
  360. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +398 -0
  361. package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +157 -0
  362. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +17 -0
  363. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +13 -2
  364. package/dist/templates/workspace-core/.agents/skills/mvp-followup/SKILL.md +51 -0
  365. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +14 -4
  366. package/dist/templates/workspace-core/.agents/skills/onboarding/SKILL.md +13 -1
  367. package/dist/templates/workspace-core/.agents/skills/portability/SKILL.md +27 -5
  368. package/dist/templates/workspace-core/.agents/skills/qa/SKILL.md +24 -8
  369. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +53 -7
  370. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +43 -10
  371. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +2 -0
  372. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +43 -14
  373. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +50 -1
  374. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +4 -2
  375. package/dist/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +11 -1
  376. package/dist/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +15 -0
  377. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +5 -1
  378. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +48 -19
  379. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +7 -3
  380. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +13 -6
  381. package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +236 -0
  382. package/dist/templates/workspace-core/AGENTS.md +5 -1
  383. package/dist/templates/workspace-root/AGENTS.md +5 -2
  384. package/dist/tracking/route.d.ts +43 -0
  385. package/dist/tracking/route.d.ts.map +1 -0
  386. package/dist/tracking/route.js +85 -0
  387. package/dist/tracking/route.js.map +1 -0
  388. package/dist/vite/client.d.ts.map +1 -1
  389. package/dist/vite/client.js +15 -0
  390. package/dist/vite/client.js.map +1 -1
  391. package/docs/content/a2a-protocol.md +18 -4
  392. package/docs/content/actions.md +87 -0
  393. package/docs/content/agent-mentions.md +2 -1
  394. package/docs/content/authentication.md +2 -1
  395. package/docs/content/client.md +64 -13
  396. package/docs/content/cloneable-saas.md +1 -1
  397. package/docs/content/code-agents-ui.md +17 -11
  398. package/docs/content/context-awareness.md +23 -28
  399. package/docs/content/creating-templates.md +1 -1
  400. package/docs/content/drop-in-agent.md +2 -0
  401. package/docs/content/getting-started.md +2 -2
  402. package/docs/content/key-concepts.md +2 -2
  403. package/docs/content/messaging.md +57 -15
  404. package/docs/content/migration-workbench.md +1 -1
  405. package/docs/content/multi-app-workspace.md +1 -1
  406. package/docs/content/multi-tenancy.md +17 -15
  407. package/docs/content/real-time-collaboration.md +1 -1
  408. package/docs/content/recurring-jobs.md +1 -1
  409. package/docs/content/security.md +2 -2
  410. package/docs/content/server.md +4 -4
  411. package/docs/content/skills-guide.md +30 -0
  412. package/docs/content/template-analytics.md +2 -2
  413. package/docs/content/template-assets.md +17 -1
  414. package/docs/content/template-brain.md +2 -2
  415. package/docs/content/template-calendar.md +1 -1
  416. package/docs/content/template-clips.md +3 -3
  417. package/docs/content/template-content.md +2 -2
  418. package/docs/content/template-design.md +2 -2
  419. package/docs/content/template-dispatch.md +3 -3
  420. package/docs/content/template-forms.md +14 -2
  421. package/docs/content/template-mail.md +1 -3
  422. package/docs/content/template-plan.md +133 -0
  423. package/docs/content/template-slides.md +5 -4
  424. package/docs/content/template-starter.md +4 -4
  425. package/docs/content/template-videos.md +6 -11
  426. package/docs/content/tracking.md +21 -1
  427. package/docs/content/visual-plans.md +74 -0
  428. package/docs/content/workspace.md +9 -9
  429. package/package.json +26 -11
  430. package/src/templates/default/.agents/skills/actions/SKILL.md +4 -1
  431. package/src/templates/default/.agents/skills/security/SKILL.md +13 -4
  432. package/src/templates/default/.agents/skills/storing-data/SKILL.md +15 -3
  433. package/src/templates/default/AGENTS.md +1 -0
  434. package/src/templates/default/DEVELOPING.md +2 -0
  435. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +10 -3
  436. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +98 -10
  437. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +45 -3
  438. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +2 -0
  439. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +37 -4
  440. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +9 -4
  441. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +2 -0
  442. package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +106 -0
  443. package/src/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +53 -0
  444. package/src/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +2 -0
  445. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +62 -61
  446. package/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +47 -0
  447. package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +28 -0
  448. package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +52 -1
  449. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +2 -0
  450. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +95 -433
  451. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +285 -0
  452. package/src/templates/workspace-core/.agents/skills/extensions/references/examples.md +259 -0
  453. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +398 -0
  454. package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +157 -0
  455. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +17 -0
  456. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +13 -2
  457. package/src/templates/workspace-core/.agents/skills/mvp-followup/SKILL.md +51 -0
  458. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +14 -4
  459. package/src/templates/workspace-core/.agents/skills/onboarding/SKILL.md +13 -1
  460. package/src/templates/workspace-core/.agents/skills/portability/SKILL.md +27 -5
  461. package/src/templates/workspace-core/.agents/skills/qa/SKILL.md +24 -8
  462. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +53 -7
  463. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +43 -10
  464. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +2 -0
  465. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +43 -14
  466. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +50 -1
  467. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +4 -2
  468. package/src/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +11 -1
  469. package/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +15 -0
  470. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +5 -1
  471. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +48 -19
  472. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +7 -3
  473. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +13 -6
  474. package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +236 -0
  475. package/src/templates/workspace-core/AGENTS.md +5 -1
  476. package/src/templates/workspace-root/AGENTS.md +5 -2
@@ -0,0 +1,222 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useRef, useState } from "react";
3
+ import { IconArrowNarrowRight, IconChevronRight, IconDatabase, IconKey, IconLink, IconPlus, IconTrash, } from "@tabler/icons-react";
4
+ import { cn } from "../../utils.js";
5
+ import { DevInput } from "./dev-doc-ui.js";
6
+ /**
7
+ * Read + Edit renderers for a `data-model` block — a dbdiagram / Prisma-style
8
+ * entity-relationship diagram. Lives in core so any app can register the dev-doc
9
+ * block (no shadcn import).
10
+ */
11
+ /* ── Resolution helpers (shared by Read + relation inference) ──────────────── */
12
+ /** Split a `fk` string like `"User.id"` into `{ entity: "User", field: "id" }`. */
13
+ function parseFk(fk) {
14
+ const trimmed = fk.trim();
15
+ const dot = trimmed.indexOf(".");
16
+ if (dot === -1)
17
+ return { entity: trimmed };
18
+ return {
19
+ entity: trimmed.slice(0, dot).trim(),
20
+ field: trimmed.slice(dot + 1).trim() || undefined,
21
+ };
22
+ }
23
+ /**
24
+ * Resolve an entity reference (used by `fk` targets and `relation.from`/`to`)
25
+ * against the entity list by `id` first, then by case-insensitive `name`. Returns
26
+ * the matched entity or `undefined`.
27
+ */
28
+ function resolveEntity(entities, ref) {
29
+ const needle = ref.trim();
30
+ return (entities.find((entity) => entity.id === needle) ??
31
+ entities.find((entity) => entity.name.toLowerCase() === needle.toLowerCase()));
32
+ }
33
+ /** A short, readable label for an entity reference (its name, or the raw ref). */
34
+ function entityLabel(entities, ref) {
35
+ return resolveEntity(entities, ref)?.name ?? ref;
36
+ }
37
+ /** The cardinality glyph shown in the relations list (1:1 / 1:n / n:n). */
38
+ function relationGlyph(kind) {
39
+ if (kind === "1-1")
40
+ return "1:1";
41
+ if (kind === "n-n")
42
+ return "n:n";
43
+ return "1:n";
44
+ }
45
+ /**
46
+ * Relations to render: explicit `relations` when present, otherwise inferred —
47
+ * every `fk` field becomes a `1-n` relation from the referenced (parent) entity
48
+ * to the entity holding the foreign key, so the connectors list is never empty
49
+ * when the schema clearly implies them.
50
+ */
51
+ function effectiveRelations(data) {
52
+ if (data.relations && data.relations.length > 0)
53
+ return data.relations;
54
+ const inferred = [];
55
+ for (const entity of data.entities) {
56
+ for (const field of entity.fields) {
57
+ if (!field.fk)
58
+ continue;
59
+ const target = resolveEntity(data.entities, parseFk(field.fk).entity);
60
+ if (!target)
61
+ continue;
62
+ inferred.push({
63
+ from: target.id,
64
+ to: entity.id,
65
+ kind: "1-n",
66
+ label: field.name,
67
+ });
68
+ }
69
+ }
70
+ return inferred;
71
+ }
72
+ /* ── Read (interactive ERD) ────────────────────────────────────────────────── */
73
+ /**
74
+ * Read-only renderer for a `data-model` block — a dbdiagram / Prisma-style
75
+ * entity-relationship diagram. Each entity is a collapsible card: the header
76
+ * shows the entity name + field count, and expanding it reveals a compact field
77
+ * table (Field · Type · flags) with PK / FK / nullable indicators.
78
+ *
79
+ * INTERACTIVITY (the reason this is a custom block, not a plain table): hovering
80
+ * or clicking a foreign-key field highlights the referenced entity card — it
81
+ * scrolls into view, expands, and gets a temporary accent ring — so a reader can
82
+ * trace a relationship across the whole model. Explicit `relations` (or relations
83
+ * inferred from `fk` fields) render as a labeled connector list below the cards.
84
+ *
85
+ * Every color is theme-aware via Tailwind `dark:` variants or plan CSS vars, so
86
+ * the diagram reads correctly in both the `.dark` plan theme and light mode.
87
+ */
88
+ export function DataModelRead({ data, blockId, title, summary, }) {
89
+ const entities = data.entities ?? [];
90
+ const relations = useMemo(() => effectiveRelations(data), [data]);
91
+ // Per-entity collapse state. Default: the first entity expanded (or all of them
92
+ // when the model is small) so the block is useful at a glance without a click.
93
+ const [expanded, setExpanded] = useState(() => {
94
+ const initial = {};
95
+ const expandAll = entities.length <= 2;
96
+ entities.forEach((entity, index) => {
97
+ initial[entity.id] = expandAll || index === 0;
98
+ });
99
+ return initial;
100
+ });
101
+ // Which entity is being hovered/clicked-to via an FK — drives the accent ring.
102
+ const [highlighted, setHighlighted] = useState(null);
103
+ const cardRefs = useRef({});
104
+ const toggle = useCallback((id) => {
105
+ setExpanded((current) => ({ ...current, [id]: !current[id] }));
106
+ }, []);
107
+ // Highlight + reveal a referenced entity: expand it, ring it, and scroll it
108
+ // into view. Used on FK hover (transient) and click (scroll).
109
+ const focusEntity = useCallback((targetId, scroll) => {
110
+ if (!targetId) {
111
+ setHighlighted(null);
112
+ return;
113
+ }
114
+ setHighlighted(targetId);
115
+ if (scroll) {
116
+ setExpanded((current) => ({ ...current, [targetId]: true }));
117
+ cardRefs.current[targetId]?.scrollIntoView({
118
+ behavior: "smooth",
119
+ block: "nearest",
120
+ });
121
+ }
122
+ }, []);
123
+ return (_jsxs("section", { className: "plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), _jsx("div", { className: "flex flex-col gap-3", children: entities.map((entity) => {
124
+ const isOpen = expanded[entity.id] ?? false;
125
+ const isHighlighted = highlighted === entity.id;
126
+ return (_jsxs("div", { ref: (node) => {
127
+ cardRefs.current[entity.id] = node;
128
+ }, "data-entity-id": entity.id, className: cn("overflow-hidden rounded-xl border bg-plan-block transition-shadow", isHighlighted
129
+ ? "border-blue-400 ring-2 ring-blue-400/60 dark:border-blue-400 dark:ring-blue-400/50"
130
+ : "border-plan-line"), children: [_jsxs("button", { type: "button", "data-plan-interactive": true, "aria-expanded": isOpen, onClick: () => toggle(entity.id), className: "flex w-full items-center gap-2 px-4 py-2.5 text-left transition-colors hover:bg-accent/40", children: [_jsx(IconChevronRight, { className: cn("size-4 shrink-0 text-plan-muted transition-transform", isOpen && "rotate-90") }), _jsx(IconDatabase, { className: "size-4 shrink-0 text-blue-600 dark:text-blue-300" }), _jsx("span", { className: "min-w-0 truncate font-mono text-sm font-semibold text-plan-text", children: entity.name }), _jsxs("span", { className: "ml-auto shrink-0 rounded-full bg-accent/50 px-2 py-0.5 text-[11px] font-medium text-plan-muted", children: [entity.fields.length, " ", entity.fields.length === 1 ? "field" : "fields"] })] }), isOpen && (_jsxs("div", { className: "border-t border-plan-line", children: [entity.note && (_jsx("p", { className: "px-4 pt-2 text-xs italic text-plan-muted", children: entity.note })), _jsx("table", { className: "w-full border-collapse text-sm", children: _jsxs("tbody", { children: [entity.fields.map((field, index) => {
131
+ const fkTarget = field.fk
132
+ ? resolveEntity(entities, parseFk(field.fk).entity)
133
+ : undefined;
134
+ return (_jsxs("tr", { className: cn("border-t border-plan-line/70 align-top first:border-t-0", field.fk && "cursor-pointer hover:bg-blue-500/5"),
135
+ // FK interactivity: hovering rings the referenced
136
+ // entity card; clicking also scrolls it into view.
137
+ onMouseEnter: fkTarget
138
+ ? () => focusEntity(fkTarget.id, false)
139
+ : undefined, onMouseLeave: fkTarget
140
+ ? () => focusEntity(undefined, false)
141
+ : undefined, onClick: fkTarget
142
+ ? () => focusEntity(fkTarget.id, true)
143
+ : undefined, children: [_jsx("td", { className: "w-px whitespace-nowrap py-1.5 pl-4 pr-2", children: _jsxs("div", { className: "flex items-center gap-1.5", children: [field.pk && (_jsx(IconKey, { className: "size-3.5 shrink-0 text-amber-500 dark:text-amber-300", "aria-label": "Primary key" })), field.fk && (_jsx(IconLink, { className: "size-3.5 shrink-0 text-blue-500 dark:text-blue-300", "aria-label": "Foreign key" })), _jsx("span", { className: cn("font-mono text-xs", field.pk
144
+ ? "font-semibold text-plan-text"
145
+ : "text-plan-text"), children: field.name })] }) }), _jsx("td", { className: "py-1.5 pr-2", children: field.type && (_jsx("span", { className: "inline-block rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted", children: field.type })) }), _jsxs("td", { className: "py-1.5 pr-4 text-right", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-end gap-1", children: [field.pk && (_jsx("span", { className: "rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-amber-600 dark:text-amber-300 bg-amber-100 dark:bg-amber-500/15", children: "PK" })), field.fk && (_jsxs("span", { className: "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-semibold text-blue-700 dark:text-blue-300 bg-blue-100 dark:bg-blue-500/15", children: ["FK", _jsx("span", { className: "font-mono font-normal opacity-90", children: fkTarget
146
+ ? `${fkTarget.name}${parseFk(field.fk).field
147
+ ? `.${parseFk(field.fk).field}`
148
+ : ""}`
149
+ : field.fk })] })), field.nullable && (_jsx("span", { className: "rounded px-1.5 py-0.5 text-[10px] font-medium text-plan-muted bg-accent/50", children: "nullable" })), field.default != null &&
150
+ field.default !== "" && (_jsxs("span", { className: "rounded px-1.5 py-0.5 font-mono text-[10px] text-plan-muted bg-accent/40", children: ["= ", field.default] }))] }), field.note && (_jsx("div", { className: "mt-0.5 text-[11px] italic text-plan-muted", children: field.note }))] })] }, `${field.name}-${index}`));
151
+ }), entity.fields.length === 0 && (_jsx("tr", { children: _jsx("td", { className: "px-4 py-2 text-xs text-plan-muted", children: "No fields yet." }) }))] }) })] }))] }, entity.id));
152
+ }) }), relations.length > 0 && (_jsxs("div", { className: "mt-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-plan-muted", children: "Relations" }), _jsx("div", { className: "mt-2 flex flex-col gap-1.5", children: relations.map((relation, index) => {
153
+ const fromEntity = resolveEntity(entities, relation.from);
154
+ const toEntity = resolveEntity(entities, relation.to);
155
+ return (_jsxs("button", { type: "button", "data-plan-interactive": true, className: "group flex w-fit items-center gap-2 rounded-md px-2 py-1 text-sm transition-colors hover:bg-accent/40", onMouseEnter: () => focusEntity(toEntity?.id, false), onMouseLeave: () => focusEntity(undefined, false), onClick: () => focusEntity(toEntity?.id, true), children: [_jsx("span", { className: "font-mono text-xs font-semibold text-plan-text", children: entityLabel(entities, relation.from) }), _jsxs("span", { className: "flex items-center gap-1 rounded bg-blue-100 px-1.5 py-0.5 font-mono text-[10px] font-bold text-blue-700 dark:bg-blue-500/15 dark:text-blue-300", children: [relationGlyph(relation.kind), _jsx(IconArrowNarrowRight, { className: "size-3" })] }), _jsx("span", { className: "font-mono text-xs font-semibold text-plan-text", children: entityLabel(entities, relation.to) }), relation.label && (_jsxs("span", { className: "text-xs text-plan-muted", children: ["\u00B7 ", relation.label] })), !fromEntity || !toEntity ? (_jsx("span", { className: "text-[10px] text-amber-600 dark:text-amber-300", children: "(unresolved)" })) : null] }, `${relation.from}-${relation.to}-${index}`));
156
+ }) })] })), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
157
+ }
158
+ /* ── Edit (panel form) ─────────────────────────────────────────────────────── */
159
+ let entitySeq = 0;
160
+ /** Stable-enough new entity id for a freshly-added entity in the editor. */
161
+ function newEntityId() {
162
+ entitySeq += 1;
163
+ return `e_${Date.now().toString(36)}_${entitySeq}`;
164
+ }
165
+ /**
166
+ * Panel editor for a `data-model` block. A structured form: a list of entities
167
+ * (add/remove), each with a name Input, an optional note, and repeatable field
168
+ * rows (add/remove) carrying name / type / PK checkbox / FK input / nullable
169
+ * checkbox. Relations are derived from `fk` in v1, so the form focuses on the
170
+ * entities + fields. Renders BARE content (no `<section>`); the registry's panel
171
+ * surface supplies the popover chrome.
172
+ */
173
+ export function DataModelEdit({ data, onChange, editable, }) {
174
+ const entities = data.entities ?? [];
175
+ const patchEntities = (next) => onChange({ ...data, entities: next });
176
+ const updateEntity = (index, next) => patchEntities(entities.map((entity, i) => i === index ? { ...entity, ...next } : entity));
177
+ const removeEntity = (index) => patchEntities(entities.filter((_, i) => i !== index));
178
+ const addEntity = () => patchEntities([
179
+ ...entities,
180
+ {
181
+ id: newEntityId(),
182
+ name: "NewEntity",
183
+ fields: [{ name: "id", pk: true }],
184
+ },
185
+ ]);
186
+ const updateField = (entityIndex, fieldIndex, next) => {
187
+ const entity = entities[entityIndex];
188
+ if (!entity)
189
+ return;
190
+ updateEntity(entityIndex, {
191
+ fields: entity.fields.map((field, i) => i === fieldIndex ? { ...field, ...next } : field),
192
+ });
193
+ };
194
+ const removeField = (entityIndex, fieldIndex) => {
195
+ const entity = entities[entityIndex];
196
+ if (!entity)
197
+ return;
198
+ updateEntity(entityIndex, {
199
+ fields: entity.fields.filter((_, i) => i !== fieldIndex),
200
+ });
201
+ };
202
+ const addField = (entityIndex) => {
203
+ const entity = entities[entityIndex];
204
+ if (!entity)
205
+ return;
206
+ updateEntity(entityIndex, {
207
+ fields: [...entity.fields, { name: "field" }],
208
+ });
209
+ };
210
+ return (_jsxs("div", { className: "flex flex-col gap-4", "data-plan-interactive": true, children: [entities.map((entity, entityIndex) => (_jsxs("div", { className: "flex flex-col gap-2 rounded-lg border border-input p-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(IconDatabase, { className: "size-4 shrink-0 text-muted-foreground" }), _jsx(DevInput, { className: "h-8 font-mono text-sm font-semibold", value: entity.name, disabled: !editable, placeholder: "EntityName", onChange: (event) => updateEntity(entityIndex, { name: event.target.value }) }), editable && (_jsx("button", { type: "button", "data-plan-interactive": true, "aria-label": "Remove entity", className: "flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground", onClick: () => removeEntity(entityIndex), children: _jsx(IconTrash, { className: "size-4" }) }))] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [entity.fields.map((field, fieldIndex) => (_jsxs("div", { className: "flex flex-col gap-1.5 rounded-md border border-input/60 bg-accent/20 p-2", children: [_jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] gap-1.5", children: [_jsx(DevInput, { className: "h-7 font-mono text-xs", value: field.name, disabled: !editable, placeholder: "name", onChange: (event) => updateField(entityIndex, fieldIndex, {
211
+ name: event.target.value,
212
+ }) }), _jsx(DevInput, { className: "h-7 font-mono text-xs", value: field.type ?? "", disabled: !editable, placeholder: "type (e.g. uuid)", onChange: (event) => updateField(entityIndex, fieldIndex, {
213
+ type: event.target.value || undefined,
214
+ }) }), editable && (_jsx("button", { type: "button", "data-plan-interactive": true, "aria-label": "Remove field", className: "flex size-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground", onClick: () => removeField(entityIndex, fieldIndex), children: _jsx(IconTrash, { className: "size-3.5" }) }))] }), _jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs("label", { className: "flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground", children: [_jsx("input", { type: "checkbox", className: "size-3.5 cursor-pointer accent-primary", checked: Boolean(field.pk), disabled: !editable, onChange: (event) => updateField(entityIndex, fieldIndex, {
215
+ pk: event.target.checked || undefined,
216
+ }) }), "PK"] }), _jsxs("label", { className: "flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground", children: [_jsx("input", { type: "checkbox", className: "size-3.5 cursor-pointer accent-primary", checked: Boolean(field.nullable), disabled: !editable, onChange: (event) => updateField(entityIndex, fieldIndex, {
217
+ nullable: event.target.checked || undefined,
218
+ }) }), "Nullable"] }), _jsx(DevInput, { className: "h-7 flex-1 font-mono text-xs", value: field.fk ?? "", disabled: !editable, placeholder: "FK \u2192 Entity.field", onChange: (event) => updateField(entityIndex, fieldIndex, {
219
+ fk: event.target.value || undefined,
220
+ }) })] })] }, fieldIndex))), editable && (_jsxs("button", { type: "button", "data-plan-interactive": true, className: "flex w-fit items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent/60 hover:text-foreground", onClick: () => addField(entityIndex), children: [_jsx(IconPlus, { className: "size-3.5" }), "Add field"] }))] })] }, entity.id))), editable && (_jsxs("button", { type: "button", "data-plan-interactive": true, className: "flex items-center justify-center gap-1.5 rounded-md border border-dashed border-input py-2 text-sm text-muted-foreground hover:bg-accent/40 hover:text-foreground", onClick: addEntity, children: [_jsx(IconPlus, { className: "size-4" }), "Add entity"] }))] }));
221
+ }
222
+ //# sourceMappingURL=DataModelBlock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataModelBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/DataModelBlock.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AASpC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C;;;;GAIG;AAEH,kFAAkF;AAElF,mFAAmF;AACnF,SAAS,OAAO,CAAC,EAAU;IACzB,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC3C,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE;QACpC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS;KAClD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CACpB,QAA2B,EAC3B,GAAW;IAEX,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC1B,OAAO,CACL,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC;QAC/C,QAAQ,CAAC,IAAI,CACX,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,CAC/D,CACF,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,SAAS,WAAW,CAAC,QAA2B,EAAE,GAAW;IAC3D,OAAO,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,IAAI,IAAI,GAAG,CAAC;AACnD,CAAC;AAED,2EAA2E;AAC3E,SAAS,aAAa,CAAC,IAA4B;IACjD,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACjC,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,IAAmB;IAC7C,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC;IACvE,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,KAAK,CAAC,EAAE;gBAAE,SAAS;YACxB,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;YACtE,IAAI,CAAC,MAAM;gBAAE,SAAS;YACtB,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,MAAM,CAAC,EAAE;gBACf,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,KAAK,CAAC,IAAI;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,kFAAkF;AAElF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,GACuB;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAElE,gFAAgF;IAChF,+EAA+E;IAC/E,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAA0B,GAAG,EAAE;QACrE,MAAM,OAAO,GAA4B,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC;QACvC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACjC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,IAAI,KAAK,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,+EAA+E;IAC/E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM,CAAwC,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,EAAU,EAAE,EAAE;QACxC,WAAW,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,4EAA4E;IAC5E,8DAA8D;IAC9D,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,QAA4B,EAAE,MAAe,EAAE,EAAE;QAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,cAAc,CAAC,IAAI,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,MAAM,EAAE,CAAC;YACX,WAAW,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC7D,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;gBACzC,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAC;IAEF,OAAO,CACL,mBAAS,SAAS,EAAC,YAAY,mBAAgB,OAAO,aACnD,KAAK,IAAI,cAAK,SAAS,EAAC,kBAAkB,YAAE,KAAK,GAAO,EAEzD,cAAK,SAAS,EAAC,qBAAqB,YACjC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;oBACvB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;oBAC5C,MAAM,aAAa,GAAG,WAAW,KAAK,MAAM,CAAC,EAAE,CAAC;oBAChD,OAAO,CACL,eAEE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;4BACZ,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;wBACrC,CAAC,oBACe,MAAM,CAAC,EAAE,EACzB,SAAS,EAAE,EAAE,CACX,mEAAmE,EACnE,aAAa;4BACX,CAAC,CAAC,oFAAoF;4BACtF,CAAC,CAAC,kBAAkB,CACvB,aAGD,kBACE,IAAI,EAAC,QAAQ,kDAEE,MAAM,EACrB,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAChC,SAAS,EAAC,2FAA2F,aAErG,KAAC,gBAAgB,IACf,SAAS,EAAE,EAAE,CACX,sDAAsD,EACtD,MAAM,IAAI,WAAW,CACtB,GACD,EACF,KAAC,YAAY,IAAC,SAAS,EAAC,kDAAkD,GAAG,EAC7E,eAAM,SAAS,EAAC,iEAAiE,YAC9E,MAAM,CAAC,IAAI,GACP,EACP,gBAAM,SAAS,EAAC,gGAAgG,aAC7G,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,EACzB,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,IAC3C,IACA,EAGR,MAAM,IAAI,CACT,eAAK,SAAS,EAAC,2BAA2B,aACvC,MAAM,CAAC,IAAI,IAAI,CACd,YAAG,SAAS,EAAC,0CAA0C,YACpD,MAAM,CAAC,IAAI,GACV,CACL,EACD,gBAAO,SAAS,EAAC,gCAAgC,YAC/C,4BACG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;oDAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE;wDACvB,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;wDACnD,CAAC,CAAC,SAAS,CAAC;oDACd,OAAO,CACL,cAEE,SAAS,EAAE,EAAE,CACX,yDAAyD,EACzD,KAAK,CAAC,EAAE,IAAI,oCAAoC,CACjD;wDACD,kDAAkD;wDAClD,mDAAmD;wDACnD,YAAY,EACV,QAAQ;4DACN,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;4DACvC,CAAC,CAAC,SAAS,EAEf,YAAY,EACV,QAAQ;4DACN,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC;4DACrC,CAAC,CAAC,SAAS,EAEf,OAAO,EACL,QAAQ;4DACN,CAAC,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;4DACtC,CAAC,CAAC,SAAS,aAGf,aAAI,SAAS,EAAC,yCAAyC,YACrD,eAAK,SAAS,EAAC,2BAA2B,aACvC,KAAK,CAAC,EAAE,IAAI,CACX,KAAC,OAAO,IACN,SAAS,EAAC,sDAAsD,gBACrD,aAAa,GACxB,CACH,EACA,KAAK,CAAC,EAAE,IAAI,CACX,KAAC,QAAQ,IACP,SAAS,EAAC,oDAAoD,gBACnD,aAAa,GACxB,CACH,EACD,eACE,SAAS,EAAE,EAAE,CACX,mBAAmB,EACnB,KAAK,CAAC,EAAE;gFACN,CAAC,CAAC,8BAA8B;gFAChC,CAAC,CAAC,gBAAgB,CACrB,YAEA,KAAK,CAAC,IAAI,GACN,IACH,GACH,EACL,aAAI,SAAS,EAAC,aAAa,YACxB,KAAK,CAAC,IAAI,IAAI,CACb,eAAM,SAAS,EAAC,uFAAuF,YACpG,KAAK,CAAC,IAAI,GACN,CACR,GACE,EACL,cAAI,SAAS,EAAC,wBAAwB,aACpC,eAAK,SAAS,EAAC,+CAA+C,aAC3D,KAAK,CAAC,EAAE,IAAI,CACX,eAAM,SAAS,EAAC,0IAA0I,mBAEnJ,CACR,EACA,KAAK,CAAC,EAAE,IAAI,CACX,gBAAM,SAAS,EAAC,iJAAiJ,mBAE/J,eAAM,SAAS,EAAC,kCAAkC,YAC/C,QAAQ;4FACP,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,GACd,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK;gGACrB,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE;gGAC/B,CAAC,CAAC,EACN,EAAE;4FACJ,CAAC,CAAC,KAAK,CAAC,EAAE,GACP,IACF,CACR,EACA,KAAK,CAAC,QAAQ,IAAI,CACjB,eAAM,SAAS,EAAC,4EAA4E,yBAErF,CACR,EACA,KAAK,CAAC,OAAO,IAAI,IAAI;gFACpB,KAAK,CAAC,OAAO,KAAK,EAAE,IAAI,CACtB,gBAAM,SAAS,EAAC,0EAA0E,mBACrF,KAAK,CAAC,OAAO,IACX,CACR,IACC,EACL,KAAK,CAAC,IAAI,IAAI,CACb,cAAK,SAAS,EAAC,2CAA2C,YACvD,KAAK,CAAC,IAAI,GACP,CACP,IACE,KA9FA,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,EAAE,CA+F1B,CACN,CAAC;gDACJ,CAAC,CAAC,EACD,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAC7B,uBACE,aAAI,SAAS,EAAC,mCAAmC,+BAE5C,GACF,CACN,IACK,GACF,IACJ,CACP,KAhKI,MAAM,CAAC,EAAE,CAiKV,CACP,CAAC;gBACJ,CAAC,CAAC,GACE,EAGL,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CACvB,eAAK,SAAS,EAAC,MAAM,aACnB,cAAK,SAAS,EAAC,+DAA+D,0BAExE,EACN,cAAK,SAAS,EAAC,4BAA4B,YACxC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE;4BACjC,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;4BAC1D,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;4BACtD,OAAO,CACL,kBAEE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,uGAAuG,EACjH,YAAY,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,EACpD,YAAY,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,EACjD,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,aAE9C,eAAM,SAAS,EAAC,gDAAgD,YAC7D,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,GAChC,EACP,gBAAM,SAAS,EAAC,gJAAgJ,aAC7J,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAC7B,KAAC,oBAAoB,IAAC,SAAS,EAAC,QAAQ,GAAG,IACtC,EACP,eAAM,SAAS,EAAC,gDAAgD,YAC7D,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,GAC9B,EACN,QAAQ,CAAC,KAAK,IAAI,CACjB,gBAAM,SAAS,EAAC,yBAAyB,wBACpC,QAAQ,CAAC,KAAK,IACZ,CACR,EACA,CAAC,UAAU,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC1B,eAAM,SAAS,EAAC,gDAAgD,6BAEzD,CACR,CAAC,CAAC,CAAC,IAAI,KA3BH,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,EAAE,IAAI,KAAK,EAAE,CA4BxC,CACV,CAAC;wBACJ,CAAC,CAAC,GACE,IACF,CACP,EAEA,OAAO,IAAI,YAAG,SAAS,EAAC,sBAAsB,YAAE,OAAO,GAAK,IACrD,CACX,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF,IAAI,SAAS,GAAG,CAAC,CAAC;AAClB,4EAA4E;AAC5E,SAAS,WAAW;IAClB,SAAS,IAAI,CAAC,CAAC;IACf,OAAO,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,QAAQ,EACR,QAAQ,GACsB;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAErC,MAAM,aAAa,GAAG,CAAC,IAAuB,EAAE,EAAE,CAChD,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAExC,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,IAA8B,EAAE,EAAE,CACrE,aAAa,CACX,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CACzB,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAC9C,CACF,CAAC;IAEJ,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE,CACrC,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,GAAG,EAAE,CACrB,aAAa,CAAC;QACZ,GAAG,QAAQ;QACX;YACE,EAAE,EAAE,WAAW,EAAE;YACjB,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;SACnC;KACF,CAAC,CAAC;IAEL,MAAM,WAAW,GAAG,CAClB,WAAmB,EACnB,UAAkB,EAClB,IAA6B,EAC7B,EAAE;QACF,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,YAAY,CAAC,WAAW,EAAE;YACxB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CACrC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CACjD;SACF,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,WAAmB,EAAE,UAAkB,EAAE,EAAE;QAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,YAAY,CAAC,WAAW,EAAE;YACxB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,UAAU,CAAC;SACzD,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,WAAmB,EAAE,EAAE;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,YAAY,CAAC,WAAW,EAAE;YACxB,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;SAC9C,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,qBAAqB,4CACjC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CACrC,eAEE,SAAS,EAAC,wDAAwD,aAElE,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,YAAY,IAAC,SAAS,EAAC,uCAAuC,GAAG,EAClE,KAAC,QAAQ,IACP,SAAS,EAAC,qCAAqC,EAC/C,KAAK,EAAE,MAAM,CAAC,IAAI,EAClB,QAAQ,EAAE,CAAC,QAAQ,EACnB,WAAW,EAAC,YAAY,EACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,YAAY,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,GAEzD,EACD,QAAQ,IAAI,CACX,iBACE,IAAI,EAAC,QAAQ,+CAEF,eAAe,EAC1B,SAAS,EAAC,4HAA4H,EACtI,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,YAExC,KAAC,SAAS,IAAC,SAAS,EAAC,QAAQ,GAAG,GACzB,CACV,IACG,EAGN,eAAK,SAAS,EAAC,uBAAuB,aACnC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CACxC,eAEE,SAAS,EAAC,0EAA0E,aAEpF,eAAK,SAAS,EAAC,2DAA2D,aACxE,KAAC,QAAQ,IACP,SAAS,EAAC,uBAAuB,EACjC,KAAK,EAAE,KAAK,CAAC,IAAI,EACjB,QAAQ,EAAE,CAAC,QAAQ,EACnB,WAAW,EAAC,MAAM,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE;oDACnC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK;iDACzB,CAAC,GAEJ,EACF,KAAC,QAAQ,IACP,SAAS,EAAC,uBAAuB,EACjC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EACvB,QAAQ,EAAE,CAAC,QAAQ,EACnB,WAAW,EAAC,kBAAkB,EAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE;oDACnC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;iDACtC,CAAC,GAEJ,EACD,QAAQ,IAAI,CACX,iBACE,IAAI,EAAC,QAAQ,+CAEF,cAAc,EACzB,SAAS,EAAC,mHAAmH,EAC7H,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,YAEnD,KAAC,SAAS,IAAC,SAAS,EAAC,UAAU,GAAG,GAC3B,CACV,IACG,EACN,eAAK,SAAS,EAAC,mCAAmC,aAChD,iBAAO,SAAS,EAAC,2EAA2E,aAC1F,gBACE,IAAI,EAAC,UAAU,EACf,SAAS,EAAC,wCAAwC,EAClD,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAC1B,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE;4DACnC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,IAAI,SAAS;yDACtC,CAAC,GAEJ,UAEI,EACR,iBAAO,SAAS,EAAC,2EAA2E,aAC1F,gBACE,IAAI,EAAC,UAAU,EACf,SAAS,EAAC,wCAAwC,EAClD,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAChC,QAAQ,EAAE,CAAC,QAAQ,EACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE;4DACnC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,IAAI,SAAS;yDAC5C,CAAC,GAEJ,gBAEI,EACR,KAAC,QAAQ,IACP,SAAS,EAAC,8BAA8B,EACxC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,EACrB,QAAQ,EAAE,CAAC,QAAQ,EACnB,WAAW,EAAC,wBAAmB,EAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,WAAW,CAAC,WAAW,EAAE,UAAU,EAAE;oDACnC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS;iDACpC,CAAC,GAEJ,IACE,KA9ED,UAAU,CA+EX,CACP,CAAC,EACD,QAAQ,IAAI,CACX,kBACE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,2HAA2H,EACrI,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,aAEpC,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,iBAE1B,CACV,IACG,KA3HD,MAAM,CAAC,EAAE,CA4HV,CACP,CAAC,EAED,QAAQ,IAAI,CACX,kBACE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,mKAAmK,EAC7K,OAAO,EAAE,SAAS,aAElB,KAAC,QAAQ,IAAC,SAAS,EAAC,QAAQ,GAAG,kBAExB,CACV,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback, useMemo, useRef, useState } from \"react\";\nimport {\n IconArrowNarrowRight,\n IconChevronRight,\n IconDatabase,\n IconKey,\n IconLink,\n IconPlus,\n IconTrash,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n DataModelData,\n DataModelEntity,\n DataModelField,\n DataModelRelation,\n DataModelRelationKind,\n} from \"./data-model.config.js\";\nimport { DevInput } from \"./dev-doc-ui.js\";\n\n/**\n * Read + Edit renderers for a `data-model` block — a dbdiagram / Prisma-style\n * entity-relationship diagram. Lives in core so any app can register the dev-doc\n * block (no shadcn import).\n */\n\n/* ── Resolution helpers (shared by Read + relation inference) ──────────────── */\n\n/** Split a `fk` string like `\"User.id\"` into `{ entity: \"User\", field: \"id\" }`. */\nfunction parseFk(fk: string): { entity: string; field?: string } {\n const trimmed = fk.trim();\n const dot = trimmed.indexOf(\".\");\n if (dot === -1) return { entity: trimmed };\n return {\n entity: trimmed.slice(0, dot).trim(),\n field: trimmed.slice(dot + 1).trim() || undefined,\n };\n}\n\n/**\n * Resolve an entity reference (used by `fk` targets and `relation.from`/`to`)\n * against the entity list by `id` first, then by case-insensitive `name`. Returns\n * the matched entity or `undefined`.\n */\nfunction resolveEntity(\n entities: DataModelEntity[],\n ref: string,\n): DataModelEntity | undefined {\n const needle = ref.trim();\n return (\n entities.find((entity) => entity.id === needle) ??\n entities.find(\n (entity) => entity.name.toLowerCase() === needle.toLowerCase(),\n )\n );\n}\n\n/** A short, readable label for an entity reference (its name, or the raw ref). */\nfunction entityLabel(entities: DataModelEntity[], ref: string): string {\n return resolveEntity(entities, ref)?.name ?? ref;\n}\n\n/** The cardinality glyph shown in the relations list (1:1 / 1:n / n:n). */\nfunction relationGlyph(kind?: DataModelRelationKind): string {\n if (kind === \"1-1\") return \"1:1\";\n if (kind === \"n-n\") return \"n:n\";\n return \"1:n\";\n}\n\n/**\n * Relations to render: explicit `relations` when present, otherwise inferred —\n * every `fk` field becomes a `1-n` relation from the referenced (parent) entity\n * to the entity holding the foreign key, so the connectors list is never empty\n * when the schema clearly implies them.\n */\nfunction effectiveRelations(data: DataModelData): DataModelRelation[] {\n if (data.relations && data.relations.length > 0) return data.relations;\n const inferred: DataModelRelation[] = [];\n for (const entity of data.entities) {\n for (const field of entity.fields) {\n if (!field.fk) continue;\n const target = resolveEntity(data.entities, parseFk(field.fk).entity);\n if (!target) continue;\n inferred.push({\n from: target.id,\n to: entity.id,\n kind: \"1-n\",\n label: field.name,\n });\n }\n }\n return inferred;\n}\n\n/* ── Read (interactive ERD) ────────────────────────────────────────────────── */\n\n/**\n * Read-only renderer for a `data-model` block — a dbdiagram / Prisma-style\n * entity-relationship diagram. Each entity is a collapsible card: the header\n * shows the entity name + field count, and expanding it reveals a compact field\n * table (Field · Type · flags) with PK / FK / nullable indicators.\n *\n * INTERACTIVITY (the reason this is a custom block, not a plain table): hovering\n * or clicking a foreign-key field highlights the referenced entity card — it\n * scrolls into view, expands, and gets a temporary accent ring — so a reader can\n * trace a relationship across the whole model. Explicit `relations` (or relations\n * inferred from `fk` fields) render as a labeled connector list below the cards.\n *\n * Every color is theme-aware via Tailwind `dark:` variants or plan CSS vars, so\n * the diagram reads correctly in both the `.dark` plan theme and light mode.\n */\nexport function DataModelRead({\n data,\n blockId,\n title,\n summary,\n}: BlockReadProps<DataModelData>) {\n const entities = data.entities ?? [];\n const relations = useMemo(() => effectiveRelations(data), [data]);\n\n // Per-entity collapse state. Default: the first entity expanded (or all of them\n // when the model is small) so the block is useful at a glance without a click.\n const [expanded, setExpanded] = useState<Record<string, boolean>>(() => {\n const initial: Record<string, boolean> = {};\n const expandAll = entities.length <= 2;\n entities.forEach((entity, index) => {\n initial[entity.id] = expandAll || index === 0;\n });\n return initial;\n });\n\n // Which entity is being hovered/clicked-to via an FK — drives the accent ring.\n const [highlighted, setHighlighted] = useState<string | null>(null);\n const cardRefs = useRef<Record<string, HTMLDivElement | null>>({});\n\n const toggle = useCallback((id: string) => {\n setExpanded((current) => ({ ...current, [id]: !current[id] }));\n }, []);\n\n // Highlight + reveal a referenced entity: expand it, ring it, and scroll it\n // into view. Used on FK hover (transient) and click (scroll).\n const focusEntity = useCallback(\n (targetId: string | undefined, scroll: boolean) => {\n if (!targetId) {\n setHighlighted(null);\n return;\n }\n setHighlighted(targetId);\n if (scroll) {\n setExpanded((current) => ({ ...current, [targetId]: true }));\n cardRefs.current[targetId]?.scrollIntoView({\n behavior: \"smooth\",\n block: \"nearest\",\n });\n }\n },\n [],\n );\n\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n\n <div className=\"flex flex-col gap-3\">\n {entities.map((entity) => {\n const isOpen = expanded[entity.id] ?? false;\n const isHighlighted = highlighted === entity.id;\n return (\n <div\n key={entity.id}\n ref={(node) => {\n cardRefs.current[entity.id] = node;\n }}\n data-entity-id={entity.id}\n className={cn(\n \"overflow-hidden rounded-xl border bg-plan-block transition-shadow\",\n isHighlighted\n ? \"border-blue-400 ring-2 ring-blue-400/60 dark:border-blue-400 dark:ring-blue-400/50\"\n : \"border-plan-line\",\n )}\n >\n {/* Entity header — always visible, toggles the field table. */}\n <button\n type=\"button\"\n data-plan-interactive\n aria-expanded={isOpen}\n onClick={() => toggle(entity.id)}\n className=\"flex w-full items-center gap-2 px-4 py-2.5 text-left transition-colors hover:bg-accent/40\"\n >\n <IconChevronRight\n className={cn(\n \"size-4 shrink-0 text-plan-muted transition-transform\",\n isOpen && \"rotate-90\",\n )}\n />\n <IconDatabase className=\"size-4 shrink-0 text-blue-600 dark:text-blue-300\" />\n <span className=\"min-w-0 truncate font-mono text-sm font-semibold text-plan-text\">\n {entity.name}\n </span>\n <span className=\"ml-auto shrink-0 rounded-full bg-accent/50 px-2 py-0.5 text-[11px] font-medium text-plan-muted\">\n {entity.fields.length}{\" \"}\n {entity.fields.length === 1 ? \"field\" : \"fields\"}\n </span>\n </button>\n\n {/* Expanded field table. */}\n {isOpen && (\n <div className=\"border-t border-plan-line\">\n {entity.note && (\n <p className=\"px-4 pt-2 text-xs italic text-plan-muted\">\n {entity.note}\n </p>\n )}\n <table className=\"w-full border-collapse text-sm\">\n <tbody>\n {entity.fields.map((field, index) => {\n const fkTarget = field.fk\n ? resolveEntity(entities, parseFk(field.fk).entity)\n : undefined;\n return (\n <tr\n key={`${field.name}-${index}`}\n className={cn(\n \"border-t border-plan-line/70 align-top first:border-t-0\",\n field.fk && \"cursor-pointer hover:bg-blue-500/5\",\n )}\n // FK interactivity: hovering rings the referenced\n // entity card; clicking also scrolls it into view.\n onMouseEnter={\n fkTarget\n ? () => focusEntity(fkTarget.id, false)\n : undefined\n }\n onMouseLeave={\n fkTarget\n ? () => focusEntity(undefined, false)\n : undefined\n }\n onClick={\n fkTarget\n ? () => focusEntity(fkTarget.id, true)\n : undefined\n }\n >\n <td className=\"w-px whitespace-nowrap py-1.5 pl-4 pr-2\">\n <div className=\"flex items-center gap-1.5\">\n {field.pk && (\n <IconKey\n className=\"size-3.5 shrink-0 text-amber-500 dark:text-amber-300\"\n aria-label=\"Primary key\"\n />\n )}\n {field.fk && (\n <IconLink\n className=\"size-3.5 shrink-0 text-blue-500 dark:text-blue-300\"\n aria-label=\"Foreign key\"\n />\n )}\n <span\n className={cn(\n \"font-mono text-xs\",\n field.pk\n ? \"font-semibold text-plan-text\"\n : \"text-plan-text\",\n )}\n >\n {field.name}\n </span>\n </div>\n </td>\n <td className=\"py-1.5 pr-2\">\n {field.type && (\n <span className=\"inline-block rounded bg-accent/40 px-1.5 py-0.5 font-mono text-[11px] text-plan-muted\">\n {field.type}\n </span>\n )}\n </td>\n <td className=\"py-1.5 pr-4 text-right\">\n <div className=\"flex flex-wrap items-center justify-end gap-1\">\n {field.pk && (\n <span className=\"rounded px-1.5 py-0.5 text-[10px] font-bold uppercase tracking-wide text-amber-600 dark:text-amber-300 bg-amber-100 dark:bg-amber-500/15\">\n PK\n </span>\n )}\n {field.fk && (\n <span className=\"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px] font-semibold text-blue-700 dark:text-blue-300 bg-blue-100 dark:bg-blue-500/15\">\n FK\n <span className=\"font-mono font-normal opacity-90\">\n {fkTarget\n ? `${fkTarget.name}${\n parseFk(field.fk).field\n ? `.${parseFk(field.fk).field}`\n : \"\"\n }`\n : field.fk}\n </span>\n </span>\n )}\n {field.nullable && (\n <span className=\"rounded px-1.5 py-0.5 text-[10px] font-medium text-plan-muted bg-accent/50\">\n nullable\n </span>\n )}\n {field.default != null &&\n field.default !== \"\" && (\n <span className=\"rounded px-1.5 py-0.5 font-mono text-[10px] text-plan-muted bg-accent/40\">\n = {field.default}\n </span>\n )}\n </div>\n {field.note && (\n <div className=\"mt-0.5 text-[11px] italic text-plan-muted\">\n {field.note}\n </div>\n )}\n </td>\n </tr>\n );\n })}\n {entity.fields.length === 0 && (\n <tr>\n <td className=\"px-4 py-2 text-xs text-plan-muted\">\n No fields yet.\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {/* Relations / connectors list. */}\n {relations.length > 0 && (\n <div className=\"mt-4\">\n <div className=\"text-xs font-semibold uppercase tracking-wide text-plan-muted\">\n Relations\n </div>\n <div className=\"mt-2 flex flex-col gap-1.5\">\n {relations.map((relation, index) => {\n const fromEntity = resolveEntity(entities, relation.from);\n const toEntity = resolveEntity(entities, relation.to);\n return (\n <button\n key={`${relation.from}-${relation.to}-${index}`}\n type=\"button\"\n data-plan-interactive\n className=\"group flex w-fit items-center gap-2 rounded-md px-2 py-1 text-sm transition-colors hover:bg-accent/40\"\n onMouseEnter={() => focusEntity(toEntity?.id, false)}\n onMouseLeave={() => focusEntity(undefined, false)}\n onClick={() => focusEntity(toEntity?.id, true)}\n >\n <span className=\"font-mono text-xs font-semibold text-plan-text\">\n {entityLabel(entities, relation.from)}\n </span>\n <span className=\"flex items-center gap-1 rounded bg-blue-100 px-1.5 py-0.5 font-mono text-[10px] font-bold text-blue-700 dark:bg-blue-500/15 dark:text-blue-300\">\n {relationGlyph(relation.kind)}\n <IconArrowNarrowRight className=\"size-3\" />\n </span>\n <span className=\"font-mono text-xs font-semibold text-plan-text\">\n {entityLabel(entities, relation.to)}\n </span>\n {relation.label && (\n <span className=\"text-xs text-plan-muted\">\n · {relation.label}\n </span>\n )}\n {!fromEntity || !toEntity ? (\n <span className=\"text-[10px] text-amber-600 dark:text-amber-300\">\n (unresolved)\n </span>\n ) : null}\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel form) ─────────────────────────────────────────────────────── */\n\nlet entitySeq = 0;\n/** Stable-enough new entity id for a freshly-added entity in the editor. */\nfunction newEntityId(): string {\n entitySeq += 1;\n return `e_${Date.now().toString(36)}_${entitySeq}`;\n}\n\n/**\n * Panel editor for a `data-model` block. A structured form: a list of entities\n * (add/remove), each with a name Input, an optional note, and repeatable field\n * rows (add/remove) carrying name / type / PK checkbox / FK input / nullable\n * checkbox. Relations are derived from `fk` in v1, so the form focuses on the\n * entities + fields. Renders BARE content (no `<section>`); the registry's panel\n * surface supplies the popover chrome.\n */\nexport function DataModelEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<DataModelData>) {\n const entities = data.entities ?? [];\n\n const patchEntities = (next: DataModelEntity[]) =>\n onChange({ ...data, entities: next });\n\n const updateEntity = (index: number, next: Partial<DataModelEntity>) =>\n patchEntities(\n entities.map((entity, i) =>\n i === index ? { ...entity, ...next } : entity,\n ),\n );\n\n const removeEntity = (index: number) =>\n patchEntities(entities.filter((_, i) => i !== index));\n\n const addEntity = () =>\n patchEntities([\n ...entities,\n {\n id: newEntityId(),\n name: \"NewEntity\",\n fields: [{ name: \"id\", pk: true }],\n },\n ]);\n\n const updateField = (\n entityIndex: number,\n fieldIndex: number,\n next: Partial<DataModelField>,\n ) => {\n const entity = entities[entityIndex];\n if (!entity) return;\n updateEntity(entityIndex, {\n fields: entity.fields.map((field, i) =>\n i === fieldIndex ? { ...field, ...next } : field,\n ),\n });\n };\n\n const removeField = (entityIndex: number, fieldIndex: number) => {\n const entity = entities[entityIndex];\n if (!entity) return;\n updateEntity(entityIndex, {\n fields: entity.fields.filter((_, i) => i !== fieldIndex),\n });\n };\n\n const addField = (entityIndex: number) => {\n const entity = entities[entityIndex];\n if (!entity) return;\n updateEntity(entityIndex, {\n fields: [...entity.fields, { name: \"field\" }],\n });\n };\n\n return (\n <div className=\"flex flex-col gap-4\" data-plan-interactive>\n {entities.map((entity, entityIndex) => (\n <div\n key={entity.id}\n className=\"flex flex-col gap-2 rounded-lg border border-input p-3\"\n >\n <div className=\"flex items-center gap-2\">\n <IconDatabase className=\"size-4 shrink-0 text-muted-foreground\" />\n <DevInput\n className=\"h-8 font-mono text-sm font-semibold\"\n value={entity.name}\n disabled={!editable}\n placeholder=\"EntityName\"\n onChange={(event) =>\n updateEntity(entityIndex, { name: event.target.value })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove entity\"\n className=\"flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeEntity(entityIndex)}\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n\n {/* Field rows. */}\n <div className=\"flex flex-col gap-1.5\">\n {entity.fields.map((field, fieldIndex) => (\n <div\n key={fieldIndex}\n className=\"flex flex-col gap-1.5 rounded-md border border-input/60 bg-accent/20 p-2\"\n >\n <div className=\"grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto] gap-1.5\">\n <DevInput\n className=\"h-7 font-mono text-xs\"\n value={field.name}\n disabled={!editable}\n placeholder=\"name\"\n onChange={(event) =>\n updateField(entityIndex, fieldIndex, {\n name: event.target.value,\n })\n }\n />\n <DevInput\n className=\"h-7 font-mono text-xs\"\n value={field.type ?? \"\"}\n disabled={!editable}\n placeholder=\"type (e.g. uuid)\"\n onChange={(event) =>\n updateField(entityIndex, fieldIndex, {\n type: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Remove field\"\n className=\"flex size-7 items-center justify-center rounded-md text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => removeField(entityIndex, fieldIndex)}\n >\n <IconTrash className=\"size-3.5\" />\n </button>\n )}\n </div>\n <div className=\"flex flex-wrap items-center gap-3\">\n <label className=\"flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"size-3.5 cursor-pointer accent-primary\"\n checked={Boolean(field.pk)}\n disabled={!editable}\n onChange={(event) =>\n updateField(entityIndex, fieldIndex, {\n pk: event.target.checked || undefined,\n })\n }\n />\n PK\n </label>\n <label className=\"flex items-center gap-1.5 whitespace-nowrap text-xs text-muted-foreground\">\n <input\n type=\"checkbox\"\n className=\"size-3.5 cursor-pointer accent-primary\"\n checked={Boolean(field.nullable)}\n disabled={!editable}\n onChange={(event) =>\n updateField(entityIndex, fieldIndex, {\n nullable: event.target.checked || undefined,\n })\n }\n />\n Nullable\n </label>\n <DevInput\n className=\"h-7 flex-1 font-mono text-xs\"\n value={field.fk ?? \"\"}\n disabled={!editable}\n placeholder=\"FK → Entity.field\"\n onChange={(event) =>\n updateField(entityIndex, fieldIndex, {\n fk: event.target.value || undefined,\n })\n }\n />\n </div>\n </div>\n ))}\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex w-fit items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent/60 hover:text-foreground\"\n onClick={() => addField(entityIndex)}\n >\n <IconPlus className=\"size-3.5\" />\n Add field\n </button>\n )}\n </div>\n </div>\n ))}\n\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"flex items-center justify-center gap-1.5 rounded-md border border-dashed border-input py-2 text-sm text-muted-foreground hover:bg-accent/40 hover:text-foreground\"\n onClick={addEntity}\n >\n <IconPlus className=\"size-4\" />\n Add entity\n </button>\n )}\n </div>\n );\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { BlockEditProps, BlockReadProps } from "../types.js";
2
+ import type { DiffData } from "./diff.config.js";
3
+ declare function DiffRead({ data, blockId, title, summary }: BlockReadProps<DiffData>): import("react/jsx-runtime").JSX.Element;
4
+ declare function DiffEdit({ data, onChange, editable }: BlockEditProps<DiffData>): import("react/jsx-runtime").JSX.Element;
5
+ export { DiffRead, DiffEdit };
6
+ //# sourceMappingURL=DiffBlock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/DiffBlock.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,kBAAkB,CAAC;AAsP3D,iBAAS,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,2CA4E5E;AA6ND,iBAAS,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,2CA+EvE;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,293 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo, useState } from "react";
3
+ import { IconColumns, IconDotsVertical, IconFileDiff, IconList, } from "@tabler/icons-react";
4
+ import { cn } from "../../utils.js";
5
+ import { DevInput, DevLabel, DevTextarea, DevSelect } from "./dev-doc-ui.js";
6
+ /**
7
+ * Split text into lines, each KEEPING its trailing newline (so the change
8
+ * `value`s concatenate back to the original and `splitLines` below behaves the
9
+ * same as it did against jsdiff output).
10
+ */
11
+ function toLineTokens(text) {
12
+ if (text === "")
13
+ return [];
14
+ const out = [];
15
+ let start = 0;
16
+ for (let i = 0; i < text.length; i += 1) {
17
+ if (text[i] === "\n") {
18
+ out.push(text.slice(start, i + 1));
19
+ start = i + 1;
20
+ }
21
+ }
22
+ if (start < text.length)
23
+ out.push(text.slice(start));
24
+ return out;
25
+ }
26
+ /**
27
+ * A minimal line-level diff producing jsdiff-compatible `Change[]` records
28
+ * (`{ value }` for context, `{ value, added: true }`, `{ value, removed: true }`).
29
+ * Uses a classic LCS table over line tokens; the inputs here are short code
30
+ * snippets so the O(n·m) table is fine. Removed lines are emitted before added
31
+ * lines within a change region, matching jsdiff's ordering.
32
+ */
33
+ function diffLines(before, after) {
34
+ const a = toLineTokens(before);
35
+ const b = toLineTokens(after);
36
+ const n = a.length;
37
+ const m = b.length;
38
+ // LCS length table.
39
+ const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
40
+ for (let i = n - 1; i >= 0; i -= 1) {
41
+ for (let j = m - 1; j >= 0; j -= 1) {
42
+ lcs[i][j] =
43
+ a[i] === b[j]
44
+ ? lcs[i + 1][j + 1] + 1
45
+ : Math.max(lcs[i + 1][j], lcs[i][j + 1]);
46
+ }
47
+ }
48
+ const changes = [];
49
+ // Push a token onto the last change if same kind, else open a new change.
50
+ const push = (value, kind) => {
51
+ const last = changes[changes.length - 1];
52
+ const sameKind = last &&
53
+ Boolean(last.added) === (kind === "added") &&
54
+ Boolean(last.removed) === (kind === "removed");
55
+ if (sameKind) {
56
+ last.value += value;
57
+ }
58
+ else {
59
+ changes.push({
60
+ value,
61
+ added: kind === "added" ? true : undefined,
62
+ removed: kind === "removed" ? true : undefined,
63
+ });
64
+ }
65
+ };
66
+ let i = 0;
67
+ let j = 0;
68
+ while (i < n && j < m) {
69
+ if (a[i] === b[j]) {
70
+ push(a[i], "context");
71
+ i += 1;
72
+ j += 1;
73
+ }
74
+ else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
75
+ push(a[i], "removed");
76
+ i += 1;
77
+ }
78
+ else {
79
+ push(b[j], "added");
80
+ j += 1;
81
+ }
82
+ }
83
+ while (i < n) {
84
+ push(a[i], "removed");
85
+ i += 1;
86
+ }
87
+ while (j < m) {
88
+ push(b[j], "added");
89
+ j += 1;
90
+ }
91
+ return changes;
92
+ }
93
+ /** Number of context lines above which an unchanged run is collapsed. */
94
+ const COLLAPSE_THRESHOLD = 6;
95
+ /** Context lines kept visible at each edge of a collapsed run. */
96
+ const CONTEXT_EDGE = 3;
97
+ /**
98
+ * Split a change `value` into individual lines. Most hunks carry a trailing
99
+ * newline; drop the empty final element it produces so a 2-line change does not
100
+ * render a phantom 3rd blank line.
101
+ */
102
+ function splitLines(value) {
103
+ const lines = value.split("\n");
104
+ if (lines.length > 0 && lines[lines.length - 1] === "")
105
+ lines.pop();
106
+ return lines;
107
+ }
108
+ /** Flatten change objects into numbered diff rows. */
109
+ function buildRows(changes) {
110
+ const rows = [];
111
+ let oldNo = 0;
112
+ let newNo = 0;
113
+ for (const change of changes) {
114
+ const lines = splitLines(change.value);
115
+ for (const text of lines) {
116
+ if (change.added) {
117
+ newNo += 1;
118
+ rows.push({ kind: "added", newNo, text });
119
+ }
120
+ else if (change.removed) {
121
+ oldNo += 1;
122
+ rows.push({ kind: "removed", oldNo, text });
123
+ }
124
+ else {
125
+ oldNo += 1;
126
+ newNo += 1;
127
+ rows.push({ kind: "context", oldNo, newNo, text });
128
+ }
129
+ }
130
+ }
131
+ return rows;
132
+ }
133
+ /**
134
+ * Group rows into segments, collapsing interior runs of >COLLAPSE_THRESHOLD
135
+ * context rows (keeping CONTEXT_EDGE visible at each side). Leading/trailing runs
136
+ * collapse too, but keep only the inner edge visible.
137
+ */
138
+ function segmentRows(rows) {
139
+ const segments = [];
140
+ let i = 0;
141
+ while (i < rows.length) {
142
+ if (rows[i].kind !== "context") {
143
+ segments.push(rows[i]);
144
+ i += 1;
145
+ continue;
146
+ }
147
+ // Gather the full contiguous context run.
148
+ let j = i;
149
+ while (j < rows.length && rows[j].kind === "context")
150
+ j += 1;
151
+ const run = rows.slice(i, j);
152
+ if (run.length <= COLLAPSE_THRESHOLD) {
153
+ for (const row of run)
154
+ segments.push(row);
155
+ }
156
+ else {
157
+ const atStart = i === 0;
158
+ const atEnd = j === rows.length;
159
+ const head = atStart ? [] : run.slice(0, CONTEXT_EDGE);
160
+ const tail = atEnd ? [] : run.slice(run.length - CONTEXT_EDGE);
161
+ const hidden = run.slice(head.length, run.length - tail.length);
162
+ for (const row of head)
163
+ segments.push(row);
164
+ if (hidden.length > 0)
165
+ segments.push({ collapsed: true, rows: hidden });
166
+ for (const row of tail)
167
+ segments.push(row);
168
+ }
169
+ i = j;
170
+ }
171
+ return segments;
172
+ }
173
+ /* ── Theme-aware row styling (light + dark) ────────────────────────────────── */
174
+ const ROW_BG = {
175
+ added: "bg-emerald-500/10 dark:bg-emerald-400/15",
176
+ removed: "bg-rose-500/10 dark:bg-rose-400/15",
177
+ context: "",
178
+ };
179
+ const GUTTER_BG = {
180
+ added: "bg-emerald-500/15 dark:bg-emerald-400/20",
181
+ removed: "bg-rose-500/15 dark:bg-rose-400/20",
182
+ context: "bg-transparent",
183
+ };
184
+ const SIGN_COLOR = {
185
+ added: "text-emerald-700 dark:text-emerald-300",
186
+ removed: "text-rose-700 dark:text-rose-300",
187
+ context: "text-plan-muted",
188
+ };
189
+ const SIGN = {
190
+ added: "+",
191
+ removed: "−",
192
+ context: " ",
193
+ };
194
+ const LINE_NO_CLASS = "select-none px-2 text-right font-mono text-[11px] leading-5 text-plan-muted/70 tabular-nums";
195
+ /* ── Read ──────────────────────────────────────────────────────────────────── */
196
+ function DiffRead({ data, blockId, title, summary }) {
197
+ const [mode, setMode] = useState(data.mode ?? "unified");
198
+ const [expanded, setExpanded] = useState(() => new Set());
199
+ const rows = useMemo(() => buildRows(diffLines(data.before, data.after)), [data.before, data.after]);
200
+ const added = rows.filter((r) => r.kind === "added").length;
201
+ const removed = rows.filter((r) => r.kind === "removed").length;
202
+ const unchanged = data.before === data.after;
203
+ const toggleRun = (index) => setExpanded((prev) => {
204
+ const next = new Set(prev);
205
+ if (next.has(index))
206
+ next.delete(index);
207
+ else
208
+ next.add(index);
209
+ return next;
210
+ });
211
+ return (_jsxs("section", { className: "plan-block", "data-block-id": blockId, children: [title && _jsx("div", { className: "plan-block-label", children: title }), _jsxs("div", { className: "overflow-hidden rounded-lg border border-plan-line bg-plan-code", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-plan-line bg-plan-block px-3 py-2", children: [_jsx(IconFileDiff, { className: "size-4 shrink-0 text-plan-muted" }), _jsx("span", { className: "min-w-0 truncate font-mono text-sm font-medium text-plan-text", children: data.filename || "diff" }), data.language && (_jsx("span", { className: "shrink-0 rounded border border-plan-line px-1.5 py-0.5 font-mono text-[11px] uppercase tracking-wide text-plan-muted", children: data.language })), _jsxs("span", { className: "ml-1 flex shrink-0 items-center gap-2 font-mono text-xs", children: [_jsxs("span", { className: "text-emerald-700 dark:text-emerald-300", children: ["+", added] }), _jsxs("span", { className: "text-rose-700 dark:text-rose-300", children: ["\u2212", removed] })] }), _jsxs("div", { className: "ml-auto flex shrink-0 items-center overflow-hidden rounded-md border border-plan-line", children: [_jsx(ModeButton, { active: mode === "unified", onClick: () => setMode("unified"), icon: _jsx(IconList, { className: "size-3.5" }), label: "Unified" }), _jsx(ModeButton, { active: mode === "split", onClick: () => setMode("split"), icon: _jsx(IconColumns, { className: "size-3.5" }), label: "Split" })] })] }), unchanged ? (_jsx("div", { className: "px-4 py-6 text-center font-mono text-sm text-plan-muted", children: "No changes" })) : mode === "split" ? (_jsx(SplitView, { rows: rows })) : (_jsx(UnifiedView, { rows: rows, expanded: expanded, onToggleRun: toggleRun }))] }), summary && _jsx("p", { className: "mt-5 text-plan-muted", children: summary })] }));
212
+ }
213
+ function ModeButton({ active, onClick, icon, label, }) {
214
+ return (_jsxs("button", { type: "button", "data-plan-interactive": true, onClick: onClick, "aria-pressed": active, className: cn("flex cursor-pointer items-center gap-1 px-2 py-1 text-xs font-medium transition-colors", active
215
+ ? "bg-plan-code text-plan-text"
216
+ : "text-plan-muted hover:bg-plan-code/60 hover:text-plan-text"), children: [icon, label] }));
217
+ }
218
+ /* ── Unified view ──────────────────────────────────────────────────────────── */
219
+ function UnifiedView({ rows, expanded, onToggleRun, }) {
220
+ const segments = useMemo(() => segmentRows(rows), [rows]);
221
+ let runIndex = 0;
222
+ return (_jsx("div", { className: "overflow-x-auto", children: _jsx("div", { className: "min-w-full font-mono text-[13px] leading-5", children: segments.map((segment, idx) => {
223
+ if ("collapsed" in segment) {
224
+ const key = runIndex++;
225
+ const open = expanded.has(key);
226
+ return (_jsxs("div", { children: [_jsx(CollapsedRow, { count: segment.rows.length, open: open, onClick: () => onToggleRun(key) }), open &&
227
+ segment.rows.map((row, ri) => (_jsx(UnifiedRow, { row: row }, `run-${key}-${ri}`)))] }, `run-${key}`));
228
+ }
229
+ return _jsx(UnifiedRow, { row: segment }, idx);
230
+ }) }) }));
231
+ }
232
+ function UnifiedRow({ row }) {
233
+ return (_jsxs("div", { className: cn("flex w-full", ROW_BG[row.kind]), children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-10"), children: row.oldNo ?? "" }), _jsx("span", { className: cn(LINE_NO_CLASS, "w-10"), children: row.newNo ?? "" }), _jsx("span", { className: cn("w-6 shrink-0 select-none text-center font-semibold", GUTTER_BG[row.kind], SIGN_COLOR[row.kind]), children: SIGN[row.kind] }), _jsx("pre", { className: "m-0 flex-1 overflow-visible whitespace-pre px-2 text-plan-text", children: row.text || " " })] }));
234
+ }
235
+ function CollapsedRow({ count, open, onClick, }) {
236
+ return (_jsxs("button", { type: "button", "data-plan-interactive": true, onClick: onClick, className: "flex w-full cursor-pointer items-center gap-2 border-y border-plan-line/60 bg-plan-block/50 px-3 py-1 text-left text-xs text-plan-muted transition-colors hover:bg-plan-block", children: [_jsx(IconDotsVertical, { className: "size-3.5 shrink-0" }), _jsxs("span", { children: [open ? "Hide" : "Show", " ", count, " unchanged line", count === 1 ? "" : "s"] })] }));
237
+ }
238
+ /**
239
+ * Pair removed lines (left) with added lines (right) so a modification shows the
240
+ * old and new side by side; context lines mirror on both columns. Leftover adds
241
+ * or removes fall through as half-empty rows (GitHub split behavior).
242
+ */
243
+ function pairSplitRows(rows) {
244
+ const out = [];
245
+ let i = 0;
246
+ while (i < rows.length) {
247
+ const row = rows[i];
248
+ if (row.kind === "context") {
249
+ out.push({ left: row, right: row });
250
+ i += 1;
251
+ continue;
252
+ }
253
+ // Collect a contiguous block of removed-then-added rows.
254
+ const removed = [];
255
+ const added = [];
256
+ while (i < rows.length && rows[i].kind === "removed")
257
+ removed.push(rows[i++]);
258
+ while (i < rows.length && rows[i].kind === "added")
259
+ added.push(rows[i++]);
260
+ const max = Math.max(removed.length, added.length);
261
+ for (let k = 0; k < max; k += 1) {
262
+ out.push({ left: removed[k], right: added[k] });
263
+ }
264
+ }
265
+ return out;
266
+ }
267
+ function SplitView({ rows }) {
268
+ const pairs = useMemo(() => pairSplitRows(rows), [rows]);
269
+ return (_jsx("div", { className: "overflow-x-auto", children: _jsx("div", { className: "grid min-w-full grid-cols-2 font-mono text-[13px] leading-5", children: pairs.map((pair, idx) => (_jsx(SplitRowView, { pair: pair }, idx))) }) }));
270
+ }
271
+ function SplitRowView({ pair }) {
272
+ return (_jsxs(_Fragment, { children: [_jsx(SplitCell, { row: pair.left, side: "old" }), _jsx(SplitCell, { row: pair.right, side: "new" })] }));
273
+ }
274
+ function SplitCell({ row, side }) {
275
+ if (!row) {
276
+ return (_jsx("div", { className: cn("min-h-5 bg-plan-block/40", side === "old" && "border-r border-plan-line") }));
277
+ }
278
+ const sign = side === "old" ? "−" : "+";
279
+ const showSign = row.kind !== "context";
280
+ return (_jsxs("div", { className: cn("flex", ROW_BG[row.kind], side === "old" && "border-r border-plan-line"), children: [_jsx("span", { className: cn(LINE_NO_CLASS, "w-10"), children: side === "old" ? (row.oldNo ?? "") : (row.newNo ?? "") }), _jsx("span", { className: cn("w-5 shrink-0 select-none text-center font-semibold", GUTTER_BG[row.kind], SIGN_COLOR[row.kind]), children: showSign ? sign : " " }), _jsx("pre", { className: "m-0 flex-1 overflow-visible whitespace-pre px-2 text-plan-text", children: row.text || " " })] }));
281
+ }
282
+ /* ── Edit (panel) ──────────────────────────────────────────────────────────── */
283
+ const codeAreaClass = "min-h-[140px] font-mono text-xs leading-5";
284
+ function DiffEdit({ data, onChange, editable }) {
285
+ const patch = (next) => onChange({ ...data, ...next });
286
+ const mode = data.mode ?? "unified";
287
+ return (_jsxs("div", { className: "flex flex-col gap-3", "data-plan-interactive": true, children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(DevLabel, { htmlFor: "diff-filename", className: "text-xs", children: "Filename" }), _jsx(DevInput, { id: "diff-filename", value: data.filename ?? "", placeholder: "src/add.ts", disabled: !editable, onChange: (event) => patch({ filename: event.target.value || undefined }) })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(DevLabel, { htmlFor: "diff-language", className: "text-xs", children: "Language" }), _jsx(DevInput, { id: "diff-language", value: data.language ?? "", placeholder: "ts", disabled: !editable, onChange: (event) => patch({ language: event.target.value || undefined }) })] })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(DevLabel, { className: "text-xs", children: "Layout" }), _jsx(DevSelect, { value: mode, disabled: !editable, onValueChange: (value) => patch({ mode: value }), options: [
288
+ { value: "unified", label: "Unified" },
289
+ { value: "split", label: "Split (side-by-side)" },
290
+ ] })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(DevLabel, { htmlFor: "diff-before", className: "text-xs", children: "Before" }), _jsx(DevTextarea, { id: "diff-before", spellCheck: false, className: codeAreaClass, value: data.before, disabled: !editable, onChange: (event) => patch({ before: event.target.value }) })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(DevLabel, { htmlFor: "diff-after", className: "text-xs", children: "After" }), _jsx(DevTextarea, { id: "diff-after", spellCheck: false, className: codeAreaClass, value: data.after, disabled: !editable, onChange: (event) => patch({ after: event.target.value }) })] })] }));
291
+ }
292
+ export { DiffRead, DiffEdit };
293
+ //# sourceMappingURL=DiffBlock.js.map