@larkup/workspace-app 0.0.0-stage → 0.1.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 (440) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +4 -2
  3. package/assets/github.svg +3 -0
  4. package/assets/icons/Confluence.png +0 -0
  5. package/assets/icons/Instagram.png +0 -0
  6. package/assets/icons/Northflank.png +0 -0
  7. package/assets/icons/Salesforce.png +0 -0
  8. package/assets/icons/agentskills.png +0 -0
  9. package/assets/icons/airtable.png +0 -0
  10. package/assets/icons/asana.png +0 -0
  11. package/assets/icons/ashby.png +0 -0
  12. package/assets/icons/audio.png +0 -0
  13. package/assets/icons/aws-kendra.png +0 -0
  14. package/assets/icons/aws.svg +38 -0
  15. package/assets/icons/azure-ai-search.png +0 -0
  16. package/assets/icons/azure.svg +1 -0
  17. package/assets/icons/bigquery.png +0 -0
  18. package/assets/icons/bing.png +0 -0
  19. package/assets/icons/bitbucket.png +0 -0
  20. package/assets/icons/brave.png +0 -0
  21. package/assets/icons/browserbase.png +0 -0
  22. package/assets/icons/calendly.png +0 -0
  23. package/assets/icons/chroma.png +0 -0
  24. package/assets/icons/cloudflare.png +0 -0
  25. package/assets/icons/cohere.svg +30 -0
  26. package/assets/icons/databricks.png +0 -0
  27. package/assets/icons/daytonaio.png +0 -0
  28. package/assets/icons/daytonaio2.png +0 -0
  29. package/assets/icons/deepgram.png +0 -0
  30. package/assets/icons/deepl.png +0 -0
  31. package/assets/icons/digital-ocean.webp +0 -0
  32. package/assets/icons/discord.png +0 -0
  33. package/assets/icons/e2b-2.png +0 -0
  34. package/assets/icons/e2b.png +0 -0
  35. package/assets/icons/elevenlabs.png +0 -0
  36. package/assets/icons/email.png +0 -0
  37. package/assets/icons/exa.png +0 -0
  38. package/assets/icons/excel.png +0 -0
  39. package/assets/icons/fal.png +0 -0
  40. package/assets/icons/firecrawl.png +0 -0
  41. package/assets/icons/firecrawl2.png +0 -0
  42. package/assets/icons/flyio.jpeg +0 -0
  43. package/assets/icons/gcp.svg +1 -0
  44. package/assets/icons/gemini.svg +1 -0
  45. package/assets/icons/gmail.png +0 -0
  46. package/assets/icons/google-analytics.png +0 -0
  47. package/assets/icons/google-calender.png +0 -0
  48. package/assets/icons/google-docs.png +0 -0
  49. package/assets/icons/google-drive.png +0 -0
  50. package/assets/icons/google-maps.png +0 -0
  51. package/assets/icons/google-meet.png +0 -0
  52. package/assets/icons/google-sheets.png +0 -0
  53. package/assets/icons/google-slides.png +0 -0
  54. package/assets/icons/google-tasks.png +0 -0
  55. package/assets/icons/google.png +0 -0
  56. package/assets/icons/grok.png +0 -0
  57. package/assets/icons/hubspot.png +0 -0
  58. package/assets/icons/image.png +0 -0
  59. package/assets/icons/jina.svg +1 -0
  60. package/assets/icons/jira.png +0 -0
  61. package/assets/icons/lancedb2.png +0 -0
  62. package/assets/icons/linear.png +0 -0
  63. package/assets/icons/linux.png +0 -0
  64. package/assets/icons/looker.png +0 -0
  65. package/assets/icons/luma.png +0 -0
  66. package/assets/icons/mac.png +0 -0
  67. package/assets/icons/markdown.png +0 -0
  68. package/assets/icons/mcp.png +0 -0
  69. package/assets/icons/mcp.svg +1 -0
  70. package/assets/icons/messenger.svg +1 -0
  71. package/assets/icons/microsoft-intra.png +0 -0
  72. package/assets/icons/microsoft-onenote.png +0 -0
  73. package/assets/icons/microsoft-planner.png +0 -0
  74. package/assets/icons/microsoft-teams.png +0 -0
  75. package/assets/icons/miro.png +0 -0
  76. package/assets/icons/mistral.svg +469 -0
  77. package/assets/icons/modal.png +0 -0
  78. package/assets/icons/ngrok.png +0 -0
  79. package/assets/icons/nomic.png +0 -0
  80. package/assets/icons/onedrive.png +0 -0
  81. package/assets/icons/openai.svg +1 -0
  82. package/assets/icons/outlook-calendar.png +0 -0
  83. package/assets/icons/outlook-email.png +0 -0
  84. package/assets/icons/outlook.png +0 -0
  85. package/assets/icons/pdf.png +0 -0
  86. package/assets/icons/personio.png +0 -0
  87. package/assets/icons/pgvector2.png +0 -0
  88. package/assets/icons/phone.png +0 -0
  89. package/assets/icons/pinecone.png +0 -0
  90. package/assets/icons/pipedrive.png +0 -0
  91. package/assets/icons/power-pi.png +0 -0
  92. package/assets/icons/pylon.png +0 -0
  93. package/assets/icons/python.png +0 -0
  94. package/assets/icons/qdrant.svg +35 -0
  95. package/assets/icons/revai.png +0 -0
  96. package/assets/icons/revai.svg +1 -0
  97. package/assets/icons/sap.png +0 -0
  98. package/assets/icons/serpapi.svg +34 -0
  99. package/assets/icons/serper.png +0 -0
  100. package/assets/icons/servicenow.png +0 -0
  101. package/assets/icons/sharepoint.png +0 -0
  102. package/assets/icons/slack.png +0 -0
  103. package/assets/icons/snowflake.png +0 -0
  104. package/assets/icons/statistia.png +0 -0
  105. package/assets/icons/stripe.png +0 -0
  106. package/assets/icons/supabase.png +0 -0
  107. package/assets/icons/tableau.png +0 -0
  108. package/assets/icons/tavily.png +0 -0
  109. package/assets/icons/telegram.png +0 -0
  110. package/assets/icons/typescript.png +0 -0
  111. package/assets/icons/vercel copy.svg +1 -0
  112. package/assets/icons/vercel.svg +1 -0
  113. package/assets/icons/vertex-ai.png +0 -0
  114. package/assets/icons/video.png +0 -0
  115. package/assets/icons/voyage-light.png +0 -0
  116. package/assets/icons/weaviate.webp +0 -0
  117. package/assets/icons/webcontainers.svg +11 -0
  118. package/assets/icons/webhook.png +0 -0
  119. package/assets/icons/whatsapp copy.png +0 -0
  120. package/assets/icons/whatsapp.png +0 -0
  121. package/assets/icons/windows.png +0 -0
  122. package/assets/icons/word.png +0 -0
  123. package/assets/icons/zendesk.png +0 -0
  124. package/assets/icons/zoom.png +0 -0
  125. package/assets/notion-white.png +0 -0
  126. package/assets/notion.png +0 -0
  127. package/dist-types/asset-server.d.ts +3 -0
  128. package/dist-types/asset-server.d.ts.map +1 -0
  129. package/dist-types/components/alerts/generic-alert.d.ts +15 -0
  130. package/dist-types/components/alerts/generic-alert.d.ts.map +1 -0
  131. package/dist-types/components/chat/canvas/doc-editor-provider.d.ts +62 -0
  132. package/dist-types/components/chat/canvas/doc-editor-provider.d.ts.map +1 -0
  133. package/dist-types/components/chat/canvas/document-canvas.d.ts +7 -0
  134. package/dist-types/components/chat/canvas/document-canvas.d.ts.map +1 -0
  135. package/dist-types/components/chat/canvas/document-field.d.ts +13 -0
  136. package/dist-types/components/chat/canvas/document-field.d.ts.map +1 -0
  137. package/dist-types/components/chat/canvas/document-viewer.d.ts +2 -0
  138. package/dist-types/components/chat/canvas/document-viewer.d.ts.map +1 -0
  139. package/dist-types/components/chat/canvas/file-attachment-button.d.ts +9 -0
  140. package/dist-types/components/chat/canvas/file-attachment-button.d.ts.map +1 -0
  141. package/dist-types/components/chat/chat-workspace.d.ts +4 -0
  142. package/dist-types/components/chat/chat-workspace.d.ts.map +1 -0
  143. package/dist-types/components/chat/message-actions.d.ts +11 -0
  144. package/dist-types/components/chat/message-actions.d.ts.map +1 -0
  145. package/dist-types/components/chat/message-item.d.ts +20 -0
  146. package/dist-types/components/chat/message-item.d.ts.map +1 -0
  147. package/dist-types/components/chat/message-queue.d.ts +15 -0
  148. package/dist-types/components/chat/message-queue.d.ts.map +1 -0
  149. package/dist-types/components/chat/tools/chat-chart.d.ts +6 -0
  150. package/dist-types/components/chat/tools/chat-chart.d.ts.map +1 -0
  151. package/dist-types/components/chat/tools/chat-citations.d.ts +32 -0
  152. package/dist-types/components/chat/tools/chat-citations.d.ts.map +1 -0
  153. package/dist-types/components/chat/tools/chat-data-table.d.ts +14 -0
  154. package/dist-types/components/chat/tools/chat-data-table.d.ts.map +1 -0
  155. package/dist-types/components/chat/tools/chat-file-export.d.ts +5 -0
  156. package/dist-types/components/chat/tools/chat-file-export.d.ts.map +1 -0
  157. package/dist-types/components/chat/tools/chat-media-preview.d.ts +35 -0
  158. package/dist-types/components/chat/tools/chat-media-preview.d.ts.map +1 -0
  159. package/dist-types/components/chat/tools/chat-sandbox-result.d.ts +17 -0
  160. package/dist-types/components/chat/tools/chat-sandbox-result.d.ts.map +1 -0
  161. package/dist-types/components/chat/tools/chat-signature-request.d.ts +13 -0
  162. package/dist-types/components/chat/tools/chat-signature-request.d.ts.map +1 -0
  163. package/dist-types/components/chat/tools/chat-tabs.d.ts +17 -0
  164. package/dist-types/components/chat/tools/chat-tabs.d.ts.map +1 -0
  165. package/dist-types/components/chat/tools/corpus-data-result.d.ts +36 -0
  166. package/dist-types/components/chat/tools/corpus-data-result.d.ts.map +1 -0
  167. package/dist-types/components/chat/tools/knowledge-base-result.d.ts +14 -0
  168. package/dist-types/components/chat/tools/knowledge-base-result.d.ts.map +1 -0
  169. package/dist-types/components/chat/tools/visual-placement-modal.d.ts +23 -0
  170. package/dist-types/components/chat/tools/visual-placement-modal.d.ts.map +1 -0
  171. package/dist-types/components/configure/custom-model-modal.d.ts +13 -0
  172. package/dist-types/components/configure/custom-model-modal.d.ts.map +1 -0
  173. package/dist-types/components/configure/store-fields.d.ts +11 -0
  174. package/dist-types/components/configure/store-fields.d.ts.map +1 -0
  175. package/dist-types/components/data/corpus-panel.d.ts +12 -0
  176. package/dist-types/components/data/corpus-panel.d.ts.map +1 -0
  177. package/dist-types/components/data/data-entry-mode-switch.d.ts +13 -0
  178. package/dist-types/components/data/data-entry-mode-switch.d.ts.map +1 -0
  179. package/dist-types/components/data/data-primary-action.d.ts +7 -0
  180. package/dist-types/components/data/data-primary-action.d.ts.map +1 -0
  181. package/dist-types/components/data/data-workspace.d.ts +6 -0
  182. package/dist-types/components/data/data-workspace.d.ts.map +1 -0
  183. package/dist-types/components/data/groups-panel.d.ts +5 -0
  184. package/dist-types/components/data/groups-panel.d.ts.map +1 -0
  185. package/dist-types/components/data/integration-resources-panel.d.ts +9 -0
  186. package/dist-types/components/data/integration-resources-panel.d.ts.map +1 -0
  187. package/dist-types/components/data/integrations-panel.d.ts +5 -0
  188. package/dist-types/components/data/integrations-panel.d.ts.map +1 -0
  189. package/dist-types/components/data/jobs-panel.d.ts +6 -0
  190. package/dist-types/components/data/jobs-panel.d.ts.map +1 -0
  191. package/dist-types/components/data/jobs-tracking-button.d.ts +2 -0
  192. package/dist-types/components/data/jobs-tracking-button.d.ts.map +1 -0
  193. package/dist-types/components/data/live-media-progress.d.ts +9 -0
  194. package/dist-types/components/data/live-media-progress.d.ts.map +1 -0
  195. package/dist-types/components/data/media-indexing-jobs-panel.d.ts +34 -0
  196. package/dist-types/components/data/media-indexing-jobs-panel.d.ts.map +1 -0
  197. package/dist-types/components/data/media-panel.d.ts +58 -0
  198. package/dist-types/components/data/media-panel.d.ts.map +1 -0
  199. package/dist-types/components/data/notion-panel.d.ts +6 -0
  200. package/dist-types/components/data/notion-panel.d.ts.map +1 -0
  201. package/dist-types/components/data/paste-panel.d.ts +7 -0
  202. package/dist-types/components/data/paste-panel.d.ts.map +1 -0
  203. package/dist-types/components/data/project-data-page.d.ts +3 -0
  204. package/dist-types/components/data/project-data-page.d.ts.map +1 -0
  205. package/dist-types/components/data/scrape-panel.d.ts +9 -0
  206. package/dist-types/components/data/scrape-panel.d.ts.map +1 -0
  207. package/dist-types/components/data/tabular-preview.d.ts +10 -0
  208. package/dist-types/components/data/tabular-preview.d.ts.map +1 -0
  209. package/dist-types/components/data/tool-indexing-dialog.d.ts +54 -0
  210. package/dist-types/components/data/tool-indexing-dialog.d.ts.map +1 -0
  211. package/dist-types/components/data/upload-panel.d.ts +7 -0
  212. package/dist-types/components/data/upload-panel.d.ts.map +1 -0
  213. package/dist-types/components/data/web-crawler-status.d.ts +3 -0
  214. package/dist-types/components/data/web-crawler-status.d.ts.map +1 -0
  215. package/dist-types/components/projects/project-form-dialog.d.ts +10 -0
  216. package/dist-types/components/projects/project-form-dialog.d.ts.map +1 -0
  217. package/dist-types/components/projects/project-provider.d.ts +34 -0
  218. package/dist-types/components/projects/project-provider.d.ts.map +1 -0
  219. package/dist-types/components/settings/general/agent-customization-section.d.ts +2 -0
  220. package/dist-types/components/settings/general/agent-customization-section.d.ts.map +1 -0
  221. package/dist-types/components/settings/general/mcp-connections-section.d.ts +2 -0
  222. package/dist-types/components/settings/general/mcp-connections-section.d.ts.map +1 -0
  223. package/dist-types/components/settings/general/model-combobox.d.ts +24 -0
  224. package/dist-types/components/settings/general/model-combobox.d.ts.map +1 -0
  225. package/dist-types/components/settings/general/models-section.d.ts +2 -0
  226. package/dist-types/components/settings/general/models-section.d.ts.map +1 -0
  227. package/dist-types/components/settings/general/sandbox-section.d.ts +7 -0
  228. package/dist-types/components/settings/general/sandbox-section.d.ts.map +1 -0
  229. package/dist-types/components/settings/general/search-scraping-section.d.ts +2 -0
  230. package/dist-types/components/settings/general/search-scraping-section.d.ts.map +1 -0
  231. package/dist-types/components/settings/general/storage-indexing-section.d.ts +2 -0
  232. package/dist-types/components/settings/general/storage-indexing-section.d.ts.map +1 -0
  233. package/dist-types/components/ui/alert-dialog.d.ts +19 -0
  234. package/dist-types/components/ui/alert-dialog.d.ts.map +1 -0
  235. package/dist-types/components/ui/alert.d.ts +11 -0
  236. package/dist-types/components/ui/alert.d.ts.map +1 -0
  237. package/dist-types/components/ui/badge.d.ts +8 -0
  238. package/dist-types/components/ui/badge.d.ts.map +1 -0
  239. package/dist-types/components/ui/card.d.ts +2 -0
  240. package/dist-types/components/ui/card.d.ts.map +1 -0
  241. package/dist-types/components/ui/checkbox.d.ts +4 -0
  242. package/dist-types/components/ui/checkbox.d.ts.map +1 -0
  243. package/dist-types/components/ui/collapsible.d.ts +6 -0
  244. package/dist-types/components/ui/collapsible.d.ts.map +1 -0
  245. package/dist-types/components/ui/command.d.ts +20 -0
  246. package/dist-types/components/ui/command.d.ts.map +1 -0
  247. package/dist-types/components/ui/dialog.d.ts +18 -0
  248. package/dist-types/components/ui/dialog.d.ts.map +1 -0
  249. package/dist-types/components/ui/dropdown-menu.d.ts +30 -0
  250. package/dist-types/components/ui/dropdown-menu.d.ts.map +1 -0
  251. package/dist-types/components/ui/input-group.d.ts +19 -0
  252. package/dist-types/components/ui/input-group.d.ts.map +1 -0
  253. package/dist-types/components/ui/input.d.ts +4 -0
  254. package/dist-types/components/ui/input.d.ts.map +1 -0
  255. package/dist-types/components/ui/line-tabs.d.ts +15 -0
  256. package/dist-types/components/ui/line-tabs.d.ts.map +1 -0
  257. package/dist-types/components/ui/popover.d.ts +10 -0
  258. package/dist-types/components/ui/popover.d.ts.map +1 -0
  259. package/dist-types/components/ui/progress.d.ts +8 -0
  260. package/dist-types/components/ui/progress.d.ts.map +1 -0
  261. package/dist-types/components/ui/scroll-area.d.ts +6 -0
  262. package/dist-types/components/ui/scroll-area.d.ts.map +1 -0
  263. package/dist-types/components/ui/sheet.d.ts +15 -0
  264. package/dist-types/components/ui/sheet.d.ts.map +1 -0
  265. package/dist-types/components/ui/slider.d.ts +4 -0
  266. package/dist-types/components/ui/slider.d.ts.map +1 -0
  267. package/dist-types/components/ui/switch.d.ts +6 -0
  268. package/dist-types/components/ui/switch.d.ts.map +1 -0
  269. package/dist-types/components/ui/table.d.ts +2 -0
  270. package/dist-types/components/ui/table.d.ts.map +1 -0
  271. package/dist-types/components/ui/tabs.d.ts +11 -0
  272. package/dist-types/components/ui/tabs.d.ts.map +1 -0
  273. package/dist-types/components/ui/textarea.d.ts +2 -0
  274. package/dist-types/components/ui/textarea.d.ts.map +1 -0
  275. package/dist-types/components/ui/tooltip.d.ts +7 -0
  276. package/dist-types/components/ui/tooltip.d.ts.map +1 -0
  277. package/dist-types/hooks/use-copy-to-clipboard.d.ts +5 -0
  278. package/dist-types/hooks/use-copy-to-clipboard.d.ts.map +1 -0
  279. package/dist-types/hooks/use-integration-auth.d.ts +10 -0
  280. package/dist-types/hooks/use-integration-auth.d.ts.map +1 -0
  281. package/dist-types/hooks/use-live-media-progress.d.ts +14 -0
  282. package/dist-types/hooks/use-live-media-progress.d.ts.map +1 -0
  283. package/dist-types/hooks/use-notion-auth.d.ts +9 -0
  284. package/dist-types/hooks/use-notion-auth.d.ts.map +1 -0
  285. package/dist-types/host.d.ts +20 -0
  286. package/dist-types/host.d.ts.map +1 -0
  287. package/dist-types/lib/browser-cache.d.ts +7 -0
  288. package/dist-types/lib/browser-cache.d.ts.map +1 -0
  289. package/dist-types/lib/chat/chart-config.d.ts +2 -0
  290. package/dist-types/lib/chat/chart-config.d.ts.map +1 -0
  291. package/dist-types/lib/chat/data-export.d.ts +2 -0
  292. package/dist-types/lib/chat/data-export.d.ts.map +1 -0
  293. package/dist-types/lib/chat/live-tool-progress.d.ts +44 -0
  294. package/dist-types/lib/chat/live-tool-progress.d.ts.map +1 -0
  295. package/dist-types/lib/chat/message-feedback.d.ts +2 -0
  296. package/dist-types/lib/chat/message-feedback.d.ts.map +1 -0
  297. package/dist-types/lib/chat/table-presentation.d.ts +2 -0
  298. package/dist-types/lib/chat/table-presentation.d.ts.map +1 -0
  299. package/dist-types/lib/chat/tool-output.d.ts +3 -0
  300. package/dist-types/lib/chat/tool-output.d.ts.map +1 -0
  301. package/dist-types/lib/chat-supporting-clip.d.ts +11 -0
  302. package/dist-types/lib/chat-supporting-clip.d.ts.map +1 -0
  303. package/dist-types/lib/constants/stores.d.ts +6 -0
  304. package/dist-types/lib/constants/stores.d.ts.map +1 -0
  305. package/dist-types/lib/constants/tools.d.ts +27 -0
  306. package/dist-types/lib/constants/tools.d.ts.map +1 -0
  307. package/dist-types/lib/error-formatter.d.ts +2 -0
  308. package/dist-types/lib/error-formatter.d.ts.map +1 -0
  309. package/dist-types/lib/jobs-client.d.ts +7 -0
  310. package/dist-types/lib/jobs-client.d.ts.map +1 -0
  311. package/dist-types/lib/media/pdf.d.ts +6 -0
  312. package/dist-types/lib/media/pdf.d.ts.map +1 -0
  313. package/dist-types/lib/media/progress.d.ts +61 -0
  314. package/dist-types/lib/media/progress.d.ts.map +1 -0
  315. package/dist-types/lib/media/source-selection.d.ts +10 -0
  316. package/dist-types/lib/media/source-selection.d.ts.map +1 -0
  317. package/dist-types/lib/media/tool-indexing-estimate.d.ts +13 -0
  318. package/dist-types/lib/media/tool-indexing-estimate.d.ts.map +1 -0
  319. package/dist-types/lib/media/video-intelligence-capacity.d.ts +2 -0
  320. package/dist-types/lib/media/video-intelligence-capacity.d.ts.map +1 -0
  321. package/dist-types/lib/media/video-runtime-scope.d.ts +2 -0
  322. package/dist-types/lib/media/video-runtime-scope.d.ts.map +1 -0
  323. package/dist-types/lib/shared/error-formatter.d.ts +2 -0
  324. package/dist-types/lib/shared/error-formatter.d.ts.map +1 -0
  325. package/dist-types/lib/utils.d.ts +3 -0
  326. package/dist-types/lib/utils.d.ts.map +1 -0
  327. package/dist-types/storage.d.ts +5 -0
  328. package/dist-types/storage.d.ts.map +1 -0
  329. package/dist-types/store/chat-store.d.ts +19 -0
  330. package/dist-types/store/chat-store.d.ts.map +1 -0
  331. package/dist-types/store/scrape-store.d.ts +42 -0
  332. package/dist-types/store/scrape-store.d.ts.map +1 -0
  333. package/package.json +579 -3
  334. package/scripts/build-assets.mjs +12 -0
  335. package/src/asset-data.json +1 -0
  336. package/src/asset-server.ts +19 -0
  337. package/src/components/alerts/generic-alert.tsx +76 -0
  338. package/src/components/chat/canvas/doc-editor-provider.tsx +338 -0
  339. package/src/components/chat/canvas/document-canvas.tsx +98 -0
  340. package/src/components/chat/canvas/document-field.tsx +167 -0
  341. package/src/components/chat/canvas/document-viewer.tsx +446 -0
  342. package/src/components/chat/canvas/file-attachment-button.tsx +88 -0
  343. package/src/components/chat/chat-workspace.tsx +1552 -0
  344. package/src/components/chat/message-actions.tsx +96 -0
  345. package/src/components/chat/message-item.tsx +1398 -0
  346. package/src/components/chat/message-queue.tsx +86 -0
  347. package/src/components/chat/tools/chat-chart.tsx +558 -0
  348. package/src/components/chat/tools/chat-citations.tsx +152 -0
  349. package/src/components/chat/tools/chat-data-table.tsx +373 -0
  350. package/src/components/chat/tools/chat-file-export.tsx +49 -0
  351. package/src/components/chat/tools/chat-media-preview.tsx +466 -0
  352. package/src/components/chat/tools/chat-sandbox-result.tsx +130 -0
  353. package/src/components/chat/tools/chat-signature-request.tsx +810 -0
  354. package/src/components/chat/tools/chat-tabs.tsx +59 -0
  355. package/src/components/chat/tools/corpus-data-result.tsx +194 -0
  356. package/src/components/chat/tools/knowledge-base-result.tsx +345 -0
  357. package/src/components/chat/tools/visual-placement-modal.tsx +308 -0
  358. package/src/components/configure/custom-model-modal.tsx +209 -0
  359. package/src/components/configure/store-fields.tsx +129 -0
  360. package/src/components/data/corpus-panel.tsx +1223 -0
  361. package/src/components/data/data-entry-mode-switch.tsx +53 -0
  362. package/src/components/data/data-primary-action.ts +6 -0
  363. package/src/components/data/data-workspace.tsx +623 -0
  364. package/src/components/data/groups-panel.tsx +530 -0
  365. package/src/components/data/integration-resources-panel.tsx +282 -0
  366. package/src/components/data/integrations-panel.tsx +392 -0
  367. package/src/components/data/jobs-panel.tsx +490 -0
  368. package/src/components/data/jobs-tracking-button.tsx +224 -0
  369. package/src/components/data/live-media-progress.tsx +79 -0
  370. package/src/components/data/media-indexing-jobs-panel.tsx +190 -0
  371. package/src/components/data/media-panel.tsx +2905 -0
  372. package/src/components/data/notion-panel.tsx +408 -0
  373. package/src/components/data/paste-panel.tsx +82 -0
  374. package/src/components/data/project-data-page.tsx +55 -0
  375. package/src/components/data/scrape-panel.tsx +1290 -0
  376. package/src/components/data/tabular-preview.tsx +205 -0
  377. package/src/components/data/tool-indexing-dialog.tsx +210 -0
  378. package/src/components/data/upload-panel.tsx +1313 -0
  379. package/src/components/data/web-crawler-status.tsx +132 -0
  380. package/src/components/projects/project-form-dialog.tsx +97 -0
  381. package/src/components/projects/project-provider.tsx +143 -0
  382. package/src/components/settings/general/agent-customization-section.tsx +620 -0
  383. package/src/components/settings/general/mcp-connections-section.tsx +907 -0
  384. package/src/components/settings/general/model-combobox.tsx +235 -0
  385. package/src/components/settings/general/models-section.tsx +909 -0
  386. package/src/components/settings/general/sandbox-section.tsx +394 -0
  387. package/src/components/settings/general/search-scraping-section.tsx +757 -0
  388. package/src/components/settings/general/storage-indexing-section.tsx +394 -0
  389. package/src/components/ui/alert-dialog.tsx +162 -0
  390. package/src/components/ui/alert.tsx +69 -0
  391. package/src/components/ui/badge.tsx +49 -0
  392. package/src/components/ui/card.tsx +9 -0
  393. package/src/components/ui/checkbox.tsx +28 -0
  394. package/src/components/ui/collapsible.tsx +17 -0
  395. package/src/components/ui/command.tsx +175 -0
  396. package/src/components/ui/dialog.tsx +138 -0
  397. package/src/components/ui/dropdown-menu.tsx +267 -0
  398. package/src/components/ui/input-group.tsx +146 -0
  399. package/src/components/ui/input.tsx +19 -0
  400. package/src/components/ui/line-tabs.tsx +49 -0
  401. package/src/components/ui/popover.tsx +77 -0
  402. package/src/components/ui/progress.tsx +66 -0
  403. package/src/components/ui/scroll-area.tsx +51 -0
  404. package/src/components/ui/sheet.tsx +125 -0
  405. package/src/components/ui/slider.tsx +52 -0
  406. package/src/components/ui/switch.tsx +32 -0
  407. package/src/components/ui/table.tsx +10 -0
  408. package/src/components/ui/tabs.tsx +77 -0
  409. package/src/components/ui/textarea.tsx +1 -0
  410. package/src/components/ui/tooltip.tsx +54 -0
  411. package/src/hooks/use-copy-to-clipboard.ts +25 -0
  412. package/src/hooks/use-integration-auth.ts +39 -0
  413. package/src/hooks/use-live-media-progress.ts +71 -0
  414. package/src/hooks/use-notion-auth.ts +66 -0
  415. package/src/host.ts +55 -0
  416. package/src/lib/browser-cache.ts +17 -0
  417. package/src/lib/chat/chart-config.ts +1 -0
  418. package/src/lib/chat/data-export.ts +1 -0
  419. package/src/lib/chat/live-tool-progress.ts +69 -0
  420. package/src/lib/chat/message-feedback.ts +1 -0
  421. package/src/lib/chat/table-presentation.ts +1 -0
  422. package/src/lib/chat/tool-output.ts +14 -0
  423. package/src/lib/chat-supporting-clip.ts +16 -0
  424. package/src/lib/constants/stores.ts +12 -0
  425. package/src/lib/constants/tools.ts +178 -0
  426. package/src/lib/error-formatter.ts +30 -0
  427. package/src/lib/jobs-client.ts +27 -0
  428. package/src/lib/media/pdf.ts +57 -0
  429. package/src/lib/media/progress.ts +209 -0
  430. package/src/lib/media/source-selection.ts +47 -0
  431. package/src/lib/media/tool-indexing-estimate.ts +39 -0
  432. package/src/lib/media/video-intelligence-capacity.ts +1 -0
  433. package/src/lib/media/video-runtime-scope.ts +1 -0
  434. package/src/lib/shared/error-formatter.ts +1 -0
  435. package/src/lib/utils.ts +6 -0
  436. package/src/source.css +1 -0
  437. package/src/storage.ts +16 -0
  438. package/src/store/chat-store.ts +19 -0
  439. package/src/store/scrape-store.ts +76 -0
  440. package/src/styles.d.ts +1 -0
@@ -0,0 +1,19 @@
1
+ import assetData from './asset-data.json';
2
+ /** Generated from the canonical assets at package build time; no host filesystem paths. */
3
+ export function workspaceAssetResponse(path: string): Response {
4
+ const bytes = Object.prototype.hasOwnProperty.call(assetData, path)
5
+ ? (assetData as Record<string, string>)[path]
6
+ : undefined;
7
+ if (!bytes) return new Response('Not found', { status: 404 });
8
+ const extension = path.split('.').at(-1)!;
9
+ return new Response(Buffer.from(bytes, 'base64'), {
10
+ headers: {
11
+ 'content-type':
12
+ extension === 'svg'
13
+ ? 'image/svg+xml'
14
+ : 'image/' + (extension === 'jpg' ? 'jpeg' : extension),
15
+ 'cache-control': 'public, max-age=3600',
16
+ 'x-content-type-options': 'nosniff',
17
+ },
18
+ });
19
+ }
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import {
5
+ AlertDialog,
6
+ AlertDialogAction,
7
+ AlertDialogCancel,
8
+ AlertDialogContent,
9
+ AlertDialogDescription,
10
+ AlertDialogFooter,
11
+ AlertDialogHeader,
12
+ AlertDialogTitle,
13
+ } from '../ui/alert-dialog';
14
+ import { cn } from '../../lib/utils';
15
+
16
+ export interface GenericAlertProps {
17
+ open: boolean;
18
+ onOpenChange: (open: boolean) => void;
19
+ title: React.ReactNode;
20
+ description?: React.ReactNode;
21
+ cancelText?: React.ReactNode;
22
+ actionText?: React.ReactNode;
23
+ onAction?: () => void;
24
+ variant?: 'default' | 'destructive';
25
+ icon?: React.ReactNode;
26
+ contentClassName?: string;
27
+ }
28
+
29
+ export function GenericAlert({
30
+ open,
31
+ onOpenChange,
32
+ title,
33
+ description,
34
+ cancelText = 'Cancel',
35
+ actionText = 'Continue',
36
+ onAction,
37
+ variant = 'default',
38
+ icon,
39
+ contentClassName,
40
+ }: GenericAlertProps) {
41
+ return (
42
+ <AlertDialog open={open} onOpenChange={onOpenChange}>
43
+ <AlertDialogContent className={contentClassName}>
44
+ <AlertDialogHeader>
45
+ <AlertDialogTitle className="flex items-center gap-2">
46
+ {icon}
47
+ {title}
48
+ </AlertDialogTitle>
49
+ {typeof description === 'string' ? (
50
+ <AlertDialogDescription className="whitespace-pre-wrap">
51
+ {description}
52
+ </AlertDialogDescription>
53
+ ) : description ? (
54
+ <div className="space-y-2 text-sm text-muted-foreground">{description}</div>
55
+ ) : null}
56
+ </AlertDialogHeader>
57
+ <AlertDialogFooter>
58
+ <AlertDialogCancel>{cancelText}</AlertDialogCancel>
59
+ <AlertDialogAction
60
+ onClick={(e) => {
61
+ e.preventDefault();
62
+ if (onAction) onAction();
63
+ onOpenChange(false);
64
+ }}
65
+ className={cn(
66
+ variant === 'destructive' &&
67
+ 'bg-destructive text-white hover:bg-destructive/90 gap-2',
68
+ )}
69
+ >
70
+ {actionText}
71
+ </AlertDialogAction>
72
+ </AlertDialogFooter>
73
+ </AlertDialogContent>
74
+ </AlertDialog>
75
+ );
76
+ }
@@ -0,0 +1,338 @@
1
+ 'use client';
2
+
3
+ import { workspaceCapabilities, workspaceUrl, workspaceFetch as fetch } from '../../../host';
4
+ import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
5
+ import type { ParsedDocument, DocumentField, FieldEdit } from '@larkup/tool-doc-editor/types';
6
+
7
+ interface DocEditorState {
8
+ /** Whether the canvas split-view is open */
9
+ isCanvasOpen: boolean;
10
+ /** Active editor session ID */
11
+ sessionId: string | null;
12
+ /** Parsed document data */
13
+ parsedDocument: ParsedDocument | null;
14
+ /** File being processed */
15
+ activeFileName: string | null;
16
+ /** File type */
17
+ activeFileType: string | null;
18
+ /** Base64 file data for live preview */
19
+ fileBase64: string | null;
20
+ /** MIME type */
21
+ fileMimeType: string | null;
22
+ /** Loading state */
23
+ isLoading: boolean;
24
+ /** Error state */
25
+ error: string | null;
26
+ /** Fields currently being filled by AI (for animation) */
27
+ fillingFields: Set<string>;
28
+ /** Recently updated fields (for highlight animation) */
29
+ updatedFields: Set<string>;
30
+ /** Monotonically increasing version counter to force `<object>` remounting */
31
+ updateVersion: number;
32
+ }
33
+
34
+ interface DocEditorActions {
35
+ /** Open the canvas with a file */
36
+ openCanvas: (file: File, options?: { background?: boolean }) => Promise<void>;
37
+ /** Close the canvas */
38
+ closeCanvas: () => void;
39
+ /** Toggle the canvas */
40
+ toggleCanvas: () => void;
41
+ /** Apply field edits */
42
+ applyEdits: (edits: FieldEdit[]) => Promise<void>;
43
+ /** Mark fields as being filled (for animation) */
44
+ setFillingFields: (fieldIds: string[]) => void;
45
+ /** Clear filling state */
46
+ clearFillingFields: () => void;
47
+ /** Export the current document */
48
+ exportFile: () => void;
49
+ /** Update parsed document from external source (e.g., chat tool result) */
50
+ updateFromToolResult: (result: {
51
+ sessionId: string;
52
+ fields: DocumentField[];
53
+ updatedFields: string[];
54
+ fileBase64?: string;
55
+ pages?: any[];
56
+ totalPages?: number;
57
+ }) => void;
58
+ }
59
+
60
+ type DocEditorContext = DocEditorState & DocEditorActions;
61
+
62
+ const DocEditorCtx = createContext<DocEditorContext | null>(null);
63
+
64
+ export function useDocEditor(): DocEditorContext {
65
+ const ctx = useContext(DocEditorCtx);
66
+ if (!ctx) {
67
+ throw new Error('useDocEditor must be used within a DocEditorProvider');
68
+ }
69
+ return ctx;
70
+ }
71
+
72
+ export function DocEditorProvider({ children }: { children: ReactNode }) {
73
+ const [state, setState] = useState<DocEditorState>({
74
+ isCanvasOpen: false,
75
+ sessionId: null,
76
+ parsedDocument: null,
77
+ activeFileName: null,
78
+ activeFileType: null,
79
+ fileBase64: null,
80
+ fileMimeType: null,
81
+ isLoading: false,
82
+ error: null,
83
+ fillingFields: new Set(),
84
+ updatedFields: new Set(),
85
+ updateVersion: 0,
86
+ });
87
+
88
+ /* ---- Open Canvas ---- */
89
+ const openCanvas = useCallback(async (file: File, options?: { background?: boolean }) => {
90
+ setState((s) => ({
91
+ ...s,
92
+ isLoading: true,
93
+ error: null,
94
+ activeFileName: file.name,
95
+ isCanvasOpen: options?.background ? s.isCanvasOpen : true,
96
+ }));
97
+
98
+ try {
99
+ const formData = new FormData();
100
+ formData.append('file', file);
101
+
102
+ const res = await fetch(workspaceUrl('/api/doc-editor/parse'), {
103
+ method: 'POST',
104
+ body: formData,
105
+ });
106
+
107
+ if (!res.ok) {
108
+ const data = await res.json();
109
+ throw new Error(data.error || 'Failed to parse file');
110
+ }
111
+
112
+ const data = await res.json();
113
+
114
+ // Read the file as base64 for preview
115
+ const fileBase64 = await new Promise<string>((resolve) => {
116
+ const reader = new FileReader();
117
+ reader.onload = () => {
118
+ const result = reader.result as string;
119
+ // Remove data URL prefix
120
+ resolve(result.split(',')[1] || result);
121
+ };
122
+ reader.readAsDataURL(file);
123
+ });
124
+
125
+ setState((s) => ({
126
+ ...s,
127
+ isLoading: false,
128
+ sessionId: data.sessionId,
129
+ parsedDocument: {
130
+ sessionId: data.sessionId,
131
+ fileName: data.fileName,
132
+ type: data.type,
133
+ mimeType: data.mimeType,
134
+ fileSize: data.fileSize,
135
+ pages: data.pages,
136
+ fields: data.fields,
137
+ rawText: data.rawText,
138
+ metadata: data.metadata,
139
+ totalPages: data.totalPages,
140
+ },
141
+ activeFileType: data.type,
142
+ fileMimeType: data.mimeType,
143
+ fileBase64,
144
+ updateVersion: s.updateVersion + 1,
145
+ }));
146
+ } catch (err: any) {
147
+ setState((s) => ({
148
+ ...s,
149
+ isLoading: false,
150
+ error: err.message || 'Failed to parse file',
151
+ }));
152
+ }
153
+ }, []);
154
+
155
+ /* ---- Close Canvas ---- */
156
+ const closeCanvas = useCallback(() => {
157
+ setState((s) => ({
158
+ ...s,
159
+ isCanvasOpen: false,
160
+ }));
161
+ }, []);
162
+
163
+ /* ---- Toggle Canvas ---- */
164
+ const toggleCanvas = useCallback(() => {
165
+ setState((s) => ({
166
+ ...s,
167
+ isCanvasOpen: !s.isCanvasOpen,
168
+ }));
169
+ }, []);
170
+
171
+ /* ---- Apply Edits ---- */
172
+ const applyEdits = useCallback(
173
+ async (edits: FieldEdit[]) => {
174
+ if (!state.sessionId) return;
175
+
176
+ // Mark fields as filling (for animation)
177
+ setState((s) => ({
178
+ ...s,
179
+ fillingFields: new Set(edits.map((e) => e.fieldId)),
180
+ }));
181
+
182
+ try {
183
+ const res = await fetch(workspaceUrl('/api/doc-editor/edit'), {
184
+ method: 'POST',
185
+ headers: { 'Content-Type': 'application/json' },
186
+ body: JSON.stringify({
187
+ sessionId: state.sessionId,
188
+ fieldEdits: edits,
189
+ }),
190
+ });
191
+
192
+ if (!res.ok) {
193
+ const data = await res.json();
194
+ throw new Error(data.error || 'Edit failed');
195
+ }
196
+
197
+ const data = await res.json();
198
+
199
+ setState((s) => ({
200
+ ...s,
201
+ fillingFields: new Set(),
202
+ updatedFields: new Set(data.updatedFields || []),
203
+ parsedDocument: s.parsedDocument
204
+ ? {
205
+ ...s.parsedDocument,
206
+ fields: data.fields || s.parsedDocument.fields,
207
+ pages: data.pages || s.parsedDocument.pages,
208
+ totalPages: data.totalPages || s.parsedDocument.totalPages,
209
+ }
210
+ : null,
211
+ fileBase64: data.fileBase64 || s.fileBase64,
212
+ updateVersion: s.updateVersion + 1,
213
+ }));
214
+
215
+ // Clear the updated highlight after 2 seconds
216
+ setTimeout(() => {
217
+ setState((s) => ({ ...s, updatedFields: new Set() }));
218
+ }, 2000);
219
+ } catch (err: any) {
220
+ setState((s) => ({
221
+ ...s,
222
+ fillingFields: new Set(),
223
+ error: err.message || 'Edit failed',
224
+ }));
225
+ }
226
+ },
227
+ [state.sessionId],
228
+ );
229
+
230
+ /* ---- Set Filling Fields ---- */
231
+ const setFillingFields = useCallback((fieldIds: string[]) => {
232
+ setState((s) => ({ ...s, fillingFields: new Set(fieldIds) }));
233
+ }, []);
234
+
235
+ /* ---- Clear Filling Fields ---- */
236
+ const clearFillingFields = useCallback(() => {
237
+ setState((s) => ({ ...s, fillingFields: new Set() }));
238
+ }, []);
239
+
240
+ /* ---- Export File ---- */
241
+ const exportFile = useCallback(() => {
242
+ if (!state.sessionId) return;
243
+
244
+ const url = workspaceUrl(
245
+ `/api/doc-editor/export?sessionId=${encodeURIComponent(state.sessionId)}`,
246
+ );
247
+ const link = document.createElement('a');
248
+ link.href = url;
249
+ link.download = state.activeFileName || 'document';
250
+ link.click();
251
+ }, [state.sessionId, state.activeFileName]);
252
+
253
+ /* ---- Update from Tool Result ---- */
254
+ const updateFromToolResult = useCallback(
255
+ (result: {
256
+ sessionId: string;
257
+ fields: DocumentField[];
258
+ updatedFields: string[];
259
+ fileBase64?: string;
260
+ pages?: any[];
261
+ totalPages?: number;
262
+ }) => {
263
+ setState((s) => {
264
+ // If the canvas is not open for this session, open it
265
+ const shouldOpen = !s.isCanvasOpen || s.sessionId !== result.sessionId;
266
+
267
+ return {
268
+ ...s,
269
+ sessionId: result.sessionId,
270
+ isCanvasOpen: true,
271
+ parsedDocument: s.parsedDocument
272
+ ? {
273
+ ...s.parsedDocument,
274
+ fields: result.fields,
275
+ pages: result.pages || s.parsedDocument.pages,
276
+ totalPages: result.totalPages || s.parsedDocument.totalPages,
277
+ }
278
+ : {
279
+ sessionId: result.sessionId,
280
+ fileName: s.activeFileName || 'Document',
281
+ type: 'pdf',
282
+ mimeType: 'application/pdf',
283
+ fileSize: 0,
284
+ pages: result.pages || [],
285
+ fields: result.fields || [],
286
+ rawText: '',
287
+ metadata: {},
288
+ totalPages: result.totalPages || 1,
289
+ },
290
+ fileBase64: result.fileBase64 || s.fileBase64,
291
+ updatedFields: new Set(result.updatedFields),
292
+ fillingFields: new Set(),
293
+ updateVersion: s.updateVersion + 1,
294
+ };
295
+ });
296
+
297
+ // Restore on the backend just in case the server restarted and memory was cleared
298
+ if (
299
+ result.fileBase64 &&
300
+ result.sessionId &&
301
+ !workspaceCapabilities().durableDocumentSessions
302
+ ) {
303
+ fetch(workspaceUrl('/api/doc-editor/restore'), {
304
+ method: 'POST',
305
+ headers: { 'Content-Type': 'application/json' },
306
+ body: JSON.stringify({
307
+ sessionId: result.sessionId,
308
+ fileBase64: result.fileBase64,
309
+ // Pass minimal required fields for the backend session
310
+ fileName: 'Document',
311
+ mimeType: 'application/pdf',
312
+ activeFileType: 'pdf',
313
+ }),
314
+ }).catch(console.error);
315
+ }
316
+
317
+ // Clear highlight after animation
318
+ setTimeout(() => {
319
+ setState((s) => ({ ...s, updatedFields: new Set() }));
320
+ }, 2000);
321
+ },
322
+ [],
323
+ );
324
+
325
+ const value: DocEditorContext = {
326
+ ...state,
327
+ openCanvas,
328
+ closeCanvas,
329
+ toggleCanvas,
330
+ applyEdits,
331
+ setFillingFields,
332
+ clearFillingFields,
333
+ exportFile,
334
+ updateFromToolResult,
335
+ };
336
+
337
+ return <DocEditorCtx.Provider value={value}>{children}</DocEditorCtx.Provider>;
338
+ }
@@ -0,0 +1,98 @@
1
+ 'use client';
2
+
3
+ import { useRef, useCallback, useState } from 'react';
4
+ import { AnimatePresence, motion } from 'framer-motion';
5
+ import { useDocEditor } from './doc-editor-provider';
6
+ import { DocumentViewer } from './document-viewer';
7
+ import { cn } from '../../../lib/utils';
8
+
9
+ interface DocumentCanvasProps {
10
+ /** The chat content to render on the left side */
11
+ children: React.ReactNode;
12
+ }
13
+
14
+ export function DocumentCanvas({ children }: DocumentCanvasProps) {
15
+ const { isCanvasOpen, parsedDocument } = useDocEditor();
16
+ const [splitRatio, setSplitRatio] = useState(50); // percentage for left panel
17
+ const containerRef = useRef<HTMLDivElement>(null);
18
+ const isDragging = useRef(false);
19
+
20
+ /* ---- Resize handle drag ---- */
21
+ const handleMouseDown = useCallback((e: React.MouseEvent) => {
22
+ e.preventDefault();
23
+ isDragging.current = true;
24
+ document.body.style.cursor = 'col-resize';
25
+ document.body.style.userSelect = 'none';
26
+
27
+ const handleMouseMove = (ev: MouseEvent) => {
28
+ if (!isDragging.current || !containerRef.current) return;
29
+ const rect = containerRef.current.getBoundingClientRect();
30
+ const x = ev.clientX - rect.left;
31
+ const pct = Math.max(25, Math.min(75, (x / rect.width) * 100));
32
+ setSplitRatio(pct);
33
+ };
34
+
35
+ const handleMouseUp = () => {
36
+ isDragging.current = false;
37
+ document.body.style.cursor = '';
38
+ document.body.style.userSelect = '';
39
+ window.removeEventListener('mousemove', handleMouseMove);
40
+ window.removeEventListener('mouseup', handleMouseUp);
41
+ };
42
+
43
+ window.addEventListener('mousemove', handleMouseMove);
44
+ window.addEventListener('mouseup', handleMouseUp);
45
+ }, []);
46
+
47
+ /* ---- Split-view layout ---- */
48
+ return (
49
+ <div ref={containerRef} className="flex h-full w-full overflow-hidden">
50
+ {/* Left panel — Chat */}
51
+ <motion.div
52
+ initial={{ width: '100%' }}
53
+ animate={{ width: isCanvasOpen ? `${splitRatio}%` : '100%' }}
54
+ transition={{ type: 'spring', stiffness: 300, damping: 30 }}
55
+ className="flex h-full min-w-0 flex-col overflow-hidden"
56
+ >
57
+ {children}
58
+ </motion.div>
59
+
60
+ {/* Resize handle */}
61
+ {isCanvasOpen && (
62
+ <div
63
+ role="separator"
64
+ aria-orientation="vertical"
65
+ onMouseDown={handleMouseDown}
66
+ className={cn(
67
+ 'relative z-10 flex w-0.75 shrink-0 cursor-col-resize items-center justify-center',
68
+ 'bg-border/40 transition-colors hover:bg-primary/30 active:bg-primary/50',
69
+ 'group',
70
+ )}
71
+ >
72
+ {/* Visual handle indicator */}
73
+ <div className="absolute h-8 w-1 rounded-full bg-border group-hover:bg-primary/40 transition-colors" />
74
+ </div>
75
+ )}
76
+
77
+ {/* Right panel — Document Viewer */}
78
+ <AnimatePresence mode="wait">
79
+ {isCanvasOpen && (
80
+ <motion.div
81
+ key="canvas-panel"
82
+ initial={{ width: 0, opacity: 0, scale: 0.95 }}
83
+ animate={{
84
+ width: `${100 - splitRatio}%`,
85
+ opacity: 1,
86
+ scale: 1,
87
+ }}
88
+ exit={{ width: 0, opacity: 0, scale: 0.95 }}
89
+ transition={{ type: 'spring', stiffness: 300, damping: 30 }}
90
+ className="flex h-full min-w-0 flex-col overflow-hidden origin-top-left"
91
+ >
92
+ <DocumentViewer />
93
+ </motion.div>
94
+ )}
95
+ </AnimatePresence>
96
+ </div>
97
+ );
98
+ }
@@ -0,0 +1,167 @@
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { motion } from 'framer-motion';
5
+ import { Check, Loader2 } from 'lucide-react';
6
+ import { cn } from '../../../lib/utils';
7
+ import type { DocumentField as DocumentFieldType } from '@larkup/tool-doc-editor/types';
8
+
9
+ interface DocumentFieldProps {
10
+ field: DocumentFieldType;
11
+ /** Whether this field is currently being filled by AI */
12
+ isFilling: boolean;
13
+ /** Whether this field was recently updated */
14
+ isUpdated: boolean;
15
+ /** Callback when user manually edits the field */
16
+ onEdit: (value: string) => void;
17
+ }
18
+
19
+ export function DocumentField({ field, isFilling, isUpdated, onEdit }: DocumentFieldProps) {
20
+ const [localValue, setLocalValue] = useState(field.value);
21
+ const [isEditing, setIsEditing] = useState(false);
22
+ const inputRef = useRef<HTMLInputElement>(null);
23
+
24
+ // Sync external value changes (from AI fills)
25
+ useEffect(() => {
26
+ setLocalValue(field.value);
27
+ }, [field.value]);
28
+
29
+ const handleBlur = () => {
30
+ setIsEditing(false);
31
+ if (localValue !== field.value) {
32
+ onEdit(localValue);
33
+ }
34
+ };
35
+
36
+ const handleKeyDown = (e: React.KeyboardEvent) => {
37
+ if (e.key === 'Enter') {
38
+ (e.target as HTMLElement).blur();
39
+ }
40
+ };
41
+
42
+ return (
43
+ <motion.div
44
+ data-field-id={field.id}
45
+ layout
46
+ initial={{ opacity: 0, y: 4 }}
47
+ animate={{ opacity: 1, y: 0 }}
48
+ className={cn(
49
+ 'group relative rounded-lg border px-3 py-2 transition-all duration-300',
50
+ isFilling && 'border-primary/40 bg-primary/5',
51
+ isUpdated && !isFilling && 'border-emerald-400/60 bg-emerald-50/50 dark:bg-emerald-900/10',
52
+ !isFilling && !isUpdated && 'border-border/60 bg-card hover:border-border',
53
+ )}
54
+ >
55
+ {/* Label */}
56
+ <div className="flex items-center justify-between mb-1">
57
+ <label className="text-[11px] font-medium text-muted-foreground">
58
+ {field.name}
59
+ {field.required && <span className="text-destructive ml-0.5">*</span>}
60
+ </label>
61
+ <div className="flex items-center gap-1">
62
+ {isFilling && (
63
+ <motion.div
64
+ initial={{ scale: 0 }}
65
+ animate={{ scale: 1 }}
66
+ className="flex items-center gap-1"
67
+ >
68
+ <Loader2 className="size-3 animate-spin text-primary" />
69
+ <span className="text-[9px] text-primary font-medium">Filling…</span>
70
+ </motion.div>
71
+ )}
72
+ {isUpdated && !isFilling && (
73
+ <motion.div
74
+ initial={{ scale: 0 }}
75
+ animate={{ scale: 1 }}
76
+ transition={{ type: 'spring', stiffness: 500, damping: 25 }}
77
+ className="flex items-center gap-1"
78
+ >
79
+ <div className="flex h-4 w-4 items-center justify-center rounded-full bg-emerald-500">
80
+ <Check className="size-2.5 text-white" />
81
+ </div>
82
+ <span className="text-[9px] text-emerald-600 dark:text-emerald-400 font-medium">
83
+ Updated
84
+ </span>
85
+ </motion.div>
86
+ )}
87
+ </div>
88
+ </div>
89
+
90
+ {/* Field input */}
91
+ {field.type === 'checkbox' ? (
92
+ <label className="flex items-center gap-2 cursor-pointer">
93
+ <input
94
+ type="checkbox"
95
+ checked={localValue === 'true'}
96
+ onChange={(e) => {
97
+ const val = e.target.checked ? 'true' : 'false';
98
+ setLocalValue(val);
99
+ onEdit(val);
100
+ }}
101
+ className="h-4 w-4 rounded border-border text-primary focus:ring-primary"
102
+ />
103
+ <span className="text-xs text-foreground">{field.name}</span>
104
+ </label>
105
+ ) : field.type === 'select' && field.options ? (
106
+ <select
107
+ value={localValue}
108
+ onChange={(e) => {
109
+ setLocalValue(e.target.value);
110
+ onEdit(e.target.value);
111
+ }}
112
+ className="w-full rounded-md border border-border/60 bg-transparent px-2 py-1 text-xs text-foreground outline-none focus:border-primary"
113
+ >
114
+ <option value="">Select…</option>
115
+ {field.options.map((opt) => (
116
+ <option key={opt} value={opt}>
117
+ {opt}
118
+ </option>
119
+ ))}
120
+ </select>
121
+ ) : field.type === 'textarea' ? (
122
+ <textarea
123
+ ref={inputRef as any}
124
+ value={localValue}
125
+ onChange={(e) => setLocalValue(e.target.value)}
126
+ onFocus={() => setIsEditing(true)}
127
+ onBlur={handleBlur}
128
+ placeholder={field.placeholder || `Enter ${field.name.toLowerCase()}`}
129
+ rows={2}
130
+ className={cn(
131
+ 'w-full rounded-md border bg-transparent px-2 py-1 text-xs text-foreground outline-none resize-none transition',
132
+ 'border-border/60 focus:border-primary placeholder:text-muted-foreground/50',
133
+ isFilling && 'animate-pulse',
134
+ )}
135
+ />
136
+ ) : (
137
+ <input
138
+ ref={inputRef}
139
+ type={field.type === 'date' ? 'date' : field.type === 'number' ? 'number' : 'text'}
140
+ value={localValue}
141
+ onChange={(e) => setLocalValue(e.target.value)}
142
+ onFocus={() => setIsEditing(true)}
143
+ onBlur={handleBlur}
144
+ onKeyDown={handleKeyDown}
145
+ placeholder={field.placeholder || `Enter ${field.name.toLowerCase()}`}
146
+ className={cn(
147
+ 'w-full rounded-md border bg-transparent px-2 py-1 text-xs text-foreground outline-none transition',
148
+ 'border-border/60 focus:border-primary placeholder:text-muted-foreground/50',
149
+ isFilling && 'animate-pulse',
150
+ )}
151
+ />
152
+ )}
153
+
154
+ {/* Filling shimmer overlay */}
155
+ {isFilling && (
156
+ <motion.div
157
+ initial={{ opacity: 0 }}
158
+ animate={{ opacity: 1 }}
159
+ exit={{ opacity: 0 }}
160
+ className="absolute inset-0 rounded-lg overflow-hidden pointer-events-none"
161
+ >
162
+ <div className="absolute inset-0 bg-linear-to-r from-transparent via-primary/5 to-transparent animate-shimmer" />
163
+ </motion.div>
164
+ )}
165
+ </motion.div>
166
+ );
167
+ }