@larkup/workspace-app 0.0.0-stage → 0.2.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,446 @@
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect, useMemo } from 'react';
4
+ import {
5
+ X,
6
+ Download,
7
+ ChevronLeft,
8
+ ChevronRight,
9
+ ZoomIn,
10
+ ZoomOut,
11
+ FileText,
12
+ Loader2,
13
+ Maximize2,
14
+ Minimize2,
15
+ } from 'lucide-react';
16
+ import { motion, AnimatePresence } from 'framer-motion';
17
+ import { useDocEditor } from './doc-editor-provider';
18
+ import { DocumentField } from './document-field';
19
+ import { cn } from '../../../lib/utils';
20
+ import { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip';
21
+
22
+ export function DocumentViewer() {
23
+ const {
24
+ parsedDocument,
25
+ activeFileName,
26
+ activeFileType,
27
+ fileBase64,
28
+ fileMimeType,
29
+ isLoading,
30
+ error,
31
+ fillingFields,
32
+ updatedFields,
33
+ updateVersion,
34
+ closeCanvas,
35
+ exportFile,
36
+ applyEdits,
37
+ } = useDocEditor();
38
+
39
+ const [currentPage, setCurrentPage] = useState(0);
40
+ const [zoom, setZoom] = useState(100);
41
+ const [isFullscreen, setIsFullscreen] = useState(false);
42
+ const contentRef = useRef<HTMLDivElement>(null);
43
+
44
+ const totalPages = parsedDocument?.totalPages ?? 0;
45
+ const currentPageData = parsedDocument?.pages?.[currentPage];
46
+
47
+ // Scroll to field being filled
48
+ useEffect(() => {
49
+ if (fillingFields.size > 0 && contentRef.current) {
50
+ const firstFieldId = Array.from(fillingFields)[0];
51
+ const fieldEl = contentRef.current.querySelector(`[data-field-id="${firstFieldId}"]`);
52
+ if (fieldEl) {
53
+ fieldEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
54
+ }
55
+ }
56
+ }, [fillingFields]);
57
+
58
+ /* ---- Render based on file type ---- */
59
+ const renderContent = () => {
60
+ if (isLoading) {
61
+ return (
62
+ <div className="flex flex-1 items-center justify-center">
63
+ <div className="flex flex-col items-center gap-3">
64
+ <Loader2 className="size-6 animate-spin text-muted-foreground" />
65
+ <span className="text-sm text-muted-foreground">Parsing document…</span>
66
+ </div>
67
+ </div>
68
+ );
69
+ }
70
+
71
+ if (error) {
72
+ return (
73
+ <div className="flex flex-1 items-center justify-center p-6">
74
+ <div className="flex flex-col items-center gap-2 text-center">
75
+ <FileText className="size-8 text-muted-foreground/40" />
76
+ <p className="text-sm text-destructive">{error}</p>
77
+ </div>
78
+ </div>
79
+ );
80
+ }
81
+
82
+ if (!parsedDocument) return null;
83
+
84
+ switch (activeFileType) {
85
+ case 'pdf':
86
+ return renderPDFView();
87
+ case 'docx':
88
+ return renderDOCXView();
89
+ case 'pptx':
90
+ return renderPPTXView();
91
+ case 'txt':
92
+ return renderTXTView();
93
+ default:
94
+ return renderGenericView();
95
+ }
96
+ };
97
+
98
+ /* ---- PDF View ---- */
99
+ const renderPDFView = () => {
100
+ if (!fileBase64 || !fileMimeType) return renderTextFallback();
101
+
102
+ return (
103
+ <div className="flex flex-1 flex-col overflow-hidden">
104
+ {/* PDF embed */}
105
+ <div className="flex-1 overflow-auto bg-muted/30 p-4">
106
+ <div
107
+ style={{ transform: `scale(${zoom / 100})`, transformOrigin: 'top center' }}
108
+ className="transition-transform duration-200"
109
+ >
110
+ <object
111
+ key={`pdf-view-${updateVersion}`}
112
+ data={`data:${fileMimeType};base64,${fileBase64}#page=${currentPage + 1}`}
113
+ type="application/pdf"
114
+ className="mx-auto w-full rounded-lg border border-border/40"
115
+ style={{ height: '80vh', minHeight: '500px' }}
116
+ >
117
+ {renderTextFallback()}
118
+ </object>
119
+ </div>
120
+ </div>
121
+
122
+ {/* Form fields overlay (below the PDF) */}
123
+ {parsedDocument?.fields && parsedDocument.fields.length > 0 && (
124
+ <div className="border-t border-border/40 bg-card">
125
+ <div className="px-4 py-2 text-xs font-medium text-muted-foreground flex items-center gap-2">
126
+ <FileText className="size-3" />
127
+ Form Fields ({parsedDocument.fields.length})
128
+ </div>
129
+ <div className="max-h-50 overflow-y-auto px-4 pb-3 space-y-2 [&::-webkit-scrollbar]:hidden">
130
+ {parsedDocument.fields.map((field) => (
131
+ <DocumentField
132
+ key={field.id}
133
+ field={field}
134
+ isFilling={fillingFields.has(field.id)}
135
+ isUpdated={updatedFields.has(field.id)}
136
+ onEdit={(value) => {
137
+ applyEdits([{ fieldId: field.id, value, type: 'fill' }]);
138
+ }}
139
+ />
140
+ ))}
141
+ </div>
142
+ </div>
143
+ )}
144
+ </div>
145
+ );
146
+ };
147
+
148
+ /* ---- DOCX View ---- */
149
+ const renderDOCXView = () => {
150
+ const html = currentPageData?.html;
151
+
152
+ return (
153
+ <div className="flex flex-1 flex-col overflow-hidden">
154
+ <div
155
+ ref={contentRef}
156
+ className="flex-1 overflow-auto p-6 bg-white dark:bg-card"
157
+ style={{ transform: `scale(${zoom / 100})`, transformOrigin: 'top left' }}
158
+ >
159
+ {html ? (
160
+ <div
161
+ className="docx-content prose prose-sm dark:prose-invert max-w-none"
162
+ dangerouslySetInnerHTML={{ __html: sanitizeHtml(html) }}
163
+ />
164
+ ) : (
165
+ renderTextFallback()
166
+ )}
167
+ </div>
168
+
169
+ {/* Fields */}
170
+ {parsedDocument?.fields && parsedDocument.fields.length > 0 && (
171
+ <div className="border-t border-border/40 bg-card">
172
+ <div className="px-4 py-2 text-xs font-medium text-muted-foreground flex items-center gap-2">
173
+ <FileText className="size-3" />
174
+ Detected Fields ({parsedDocument.fields.length})
175
+ </div>
176
+ <div className="max-h-50 overflow-y-auto px-4 pb-3 space-y-2 [&::-webkit-scrollbar]:hidden">
177
+ {parsedDocument.fields.map((field) => (
178
+ <DocumentField
179
+ key={field.id}
180
+ field={field}
181
+ isFilling={fillingFields.has(field.id)}
182
+ isUpdated={updatedFields.has(field.id)}
183
+ onEdit={(value) => {
184
+ applyEdits([{ fieldId: field.id, value, type: 'fill' }]);
185
+ }}
186
+ />
187
+ ))}
188
+ </div>
189
+ </div>
190
+ )}
191
+ </div>
192
+ );
193
+ };
194
+
195
+ /* ---- PPTX View ---- */
196
+ const renderPPTXView = () => {
197
+ if (!parsedDocument?.pages?.length) return renderTextFallback();
198
+
199
+ return (
200
+ <div className="flex flex-1 flex-col overflow-hidden">
201
+ {/* Slide content */}
202
+ <div className="flex-1 overflow-auto p-6 bg-muted/30">
203
+ <AnimatePresence mode="wait">
204
+ <motion.div
205
+ key={currentPage}
206
+ initial={{ opacity: 0, x: 20 }}
207
+ animate={{ opacity: 1, x: 0 }}
208
+ exit={{ opacity: 0, x: -20 }}
209
+ transition={{ duration: 0.2 }}
210
+ className="mx-auto max-w-2xl rounded-xl border border-border bg-white dark:bg-card p-8 35"
211
+ style={{
212
+ aspectRatio: '16/9',
213
+ transform: `scale(${zoom / 100})`,
214
+ transformOrigin: 'top center',
215
+ }}
216
+ >
217
+ <div className="text-sm text-muted-foreground mb-2">
218
+ Slide {currentPage + 1} of {totalPages}
219
+ </div>
220
+ <div className="whitespace-pre-wrap text-sm leading-relaxed text-foreground">
221
+ {currentPageData?.text || 'Empty slide'}
222
+ </div>
223
+ </motion.div>
224
+ </AnimatePresence>
225
+ </div>
226
+
227
+ {/* Slide thumbnails */}
228
+ {totalPages > 1 && (
229
+ <div className="border-t border-border/40 bg-card px-4 py-2">
230
+ <div className="flex gap-2 overflow-x-auto [&::-webkit-scrollbar]:hidden">
231
+ {parsedDocument.pages.map((page, i) => (
232
+ <button
233
+ key={i}
234
+ type="button"
235
+ onClick={() => setCurrentPage(i)}
236
+ className={cn(
237
+ 'shrink-0 rounded-lg border px-3 py-1.5 text-[10px] transition',
238
+ i === currentPage
239
+ ? 'border-primary bg-primary/5 text-primary font-medium'
240
+ : 'border-border text-muted-foreground hover:bg-muted',
241
+ )}
242
+ >
243
+ Slide {i + 1}
244
+ </button>
245
+ ))}
246
+ </div>
247
+ </div>
248
+ )}
249
+ </div>
250
+ );
251
+ };
252
+
253
+ /* ---- TXT View ---- */
254
+ const renderTXTView = () => {
255
+ const text = currentPageData?.text || parsedDocument?.rawText || '';
256
+
257
+ return (
258
+ <div className="flex flex-1 flex-col overflow-hidden">
259
+ <div className="flex-1 overflow-auto p-4 bg-card">
260
+ <pre
261
+ className="whitespace-pre-wrap text-sm leading-relaxed text-foreground font-mono"
262
+ style={{ transform: `scale(${zoom / 100})`, transformOrigin: 'top left' }}
263
+ >
264
+ {text}
265
+ </pre>
266
+ </div>
267
+
268
+ {parsedDocument?.fields && parsedDocument.fields.length > 0 && (
269
+ <div className="border-t border-border/40 bg-card">
270
+ <div className="px-4 py-2 text-xs font-medium text-muted-foreground flex items-center gap-2">
271
+ <FileText className="size-3" />
272
+ Detected Fields ({parsedDocument.fields.length})
273
+ </div>
274
+ <div className="max-h-50 overflow-y-auto px-4 pb-3 space-y-2 [&::-webkit-scrollbar]:hidden">
275
+ {parsedDocument.fields.map((field) => (
276
+ <DocumentField
277
+ key={field.id}
278
+ field={field}
279
+ isFilling={fillingFields.has(field.id)}
280
+ isUpdated={updatedFields.has(field.id)}
281
+ onEdit={(value) => {
282
+ applyEdits([{ fieldId: field.id, value, type: 'fill' }]);
283
+ }}
284
+ />
285
+ ))}
286
+ </div>
287
+ </div>
288
+ )}
289
+ </div>
290
+ );
291
+ };
292
+
293
+ const renderGenericView = () => renderTextFallback();
294
+
295
+ const renderTextFallback = () => {
296
+ const text = currentPageData?.text || parsedDocument?.rawText || 'No content to display';
297
+
298
+ return (
299
+ <div className="flex-1 overflow-auto p-6 bg-card">
300
+ <div className="whitespace-pre-wrap text-sm leading-relaxed text-foreground">{text}</div>
301
+ </div>
302
+ );
303
+ };
304
+
305
+ /* ---- Main Render ---- */
306
+ return (
307
+ <motion.div
308
+ initial={{ width: 0, opacity: 0 }}
309
+ animate={{ width: '100%', opacity: 1 }}
310
+ exit={{ width: 0, opacity: 0 }}
311
+ transition={{ type: 'spring', stiffness: 300, damping: 30 }}
312
+ className={cn(
313
+ 'flex h-full flex-col border-l border-border bg-card overflow-hidden',
314
+ isFullscreen && 'fixed inset-0 z-50 border-none',
315
+ )}
316
+ >
317
+ {/* Toolbar */}
318
+ <div className="flex items-center justify-between border-b border-border/40 px-3 py-2 bg-card">
319
+ <div className="flex items-center gap-2 min-w-0">
320
+ <FileText className="size-3.5 shrink-0 text-muted-foreground" />
321
+ <span className="truncate text-xs font-medium text-foreground">
322
+ {activeFileName || 'Document'}
323
+ </span>
324
+ {parsedDocument?.fields && parsedDocument.fields.length > 0 && (
325
+ <span className="shrink-0 rounded-full bg-primary/10 px-1.5 py-0.5 text-[9px] font-semibold text-primary">
326
+ {parsedDocument.fields.length} fields
327
+ </span>
328
+ )}
329
+ </div>
330
+
331
+ <div className="flex items-center gap-1">
332
+ {/* Page navigation */}
333
+ {totalPages > 1 && (
334
+ <>
335
+ <button
336
+ type="button"
337
+ onClick={() => setCurrentPage((p) => Math.max(0, p - 1))}
338
+ disabled={currentPage === 0}
339
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted disabled:opacity-30"
340
+ >
341
+ <ChevronLeft className="size-3.5" />
342
+ </button>
343
+ <span className="text-[10px] tabular-nums text-muted-foreground px-1">
344
+ {currentPage + 1}/{totalPages}
345
+ </span>
346
+ <button
347
+ type="button"
348
+ onClick={() => setCurrentPage((p) => Math.min(totalPages - 1, p + 1))}
349
+ disabled={currentPage >= totalPages - 1}
350
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted disabled:opacity-30"
351
+ >
352
+ <ChevronRight className="size-3.5" />
353
+ </button>
354
+ <div className="mx-1 h-4 w-px bg-border" />
355
+ </>
356
+ )}
357
+
358
+ {/* Zoom */}
359
+ <button
360
+ type="button"
361
+ onClick={() => setZoom((z) => Math.max(50, z - 10))}
362
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted"
363
+ >
364
+ <ZoomOut className="size-3.5" />
365
+ </button>
366
+ <span className="text-[10px] tabular-nums text-muted-foreground w-8 text-center">
367
+ {zoom}%
368
+ </span>
369
+ <button
370
+ type="button"
371
+ onClick={() => setZoom((z) => Math.min(200, z + 10))}
372
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted"
373
+ >
374
+ <ZoomIn className="size-3.5" />
375
+ </button>
376
+
377
+ <div className="mx-1 h-4 w-px bg-border" />
378
+
379
+ {/* Fullscreen */}
380
+ <Tooltip>
381
+ <TooltipTrigger
382
+ render={
383
+ <button
384
+ type="button"
385
+ onClick={() => setIsFullscreen((f) => !f)}
386
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted"
387
+ >
388
+ {isFullscreen ? (
389
+ <Minimize2 className="size-3.5" />
390
+ ) : (
391
+ <Maximize2 className="size-3.5" />
392
+ )}
393
+ </button>
394
+ }
395
+ />
396
+ <TooltipContent>{isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}</TooltipContent>
397
+ </Tooltip>
398
+
399
+ {/* Download */}
400
+ <Tooltip>
401
+ <TooltipTrigger
402
+ render={
403
+ <button
404
+ type="button"
405
+ onClick={exportFile}
406
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted"
407
+ >
408
+ <Download className="size-3.5" />
409
+ </button>
410
+ }
411
+ />
412
+ <TooltipContent>Download</TooltipContent>
413
+ </Tooltip>
414
+
415
+ {/* Close */}
416
+ <button
417
+ type="button"
418
+ onClick={closeCanvas}
419
+ className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted hover:text-foreground"
420
+ >
421
+ <X className="size-3.5" />
422
+ </button>
423
+ </div>
424
+ </div>
425
+
426
+ {/* Content */}
427
+ <div ref={contentRef} className="flex flex-1 flex-col min-h-0 overflow-hidden">
428
+ {renderContent()}
429
+ </div>
430
+ </motion.div>
431
+ );
432
+ }
433
+
434
+ /* Document viewer helpers. */
435
+ /* Helpers */
436
+ /* End document viewer helpers. */
437
+
438
+ /** Basic HTML sanitization for DOCX HTML output */
439
+ function sanitizeHtml(html: string): string {
440
+ // mammoth produces clean HTML, but let's be safe
441
+ return html
442
+ .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
443
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
444
+ .replace(/on\w+="[^"]*"/gi, '')
445
+ .replace(/on\w+='[^']*'/gi, '');
446
+ }
@@ -0,0 +1,88 @@
1
+ 'use client';
2
+
3
+ import { useRef, useCallback } from 'react';
4
+ import { Paperclip } from 'lucide-react';
5
+ import { useDocEditor } from './doc-editor-provider';
6
+ import { cn } from '../../../lib/utils';
7
+ import { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/tooltip';
8
+
9
+ const ACCEPTED_TYPES = [
10
+ 'application/pdf',
11
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
12
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
13
+ 'text/plain',
14
+ ];
15
+
16
+ const ACCEPTED_EXTENSIONS = '.pdf,.docx,.pptx,.txt';
17
+
18
+ interface FileAttachmentButtonProps {
19
+ /** Callback when a file is selected (for adding to chat message) */
20
+ onFileSelected?: (file: File) => void;
21
+ className?: string;
22
+ id?: string;
23
+ }
24
+
25
+ export function FileAttachmentButton({ onFileSelected, className, id }: FileAttachmentButtonProps) {
26
+ const inputRef = useRef<HTMLInputElement>(null);
27
+ const { openCanvas, isLoading } = useDocEditor();
28
+
29
+ const handleChange = useCallback(
30
+ async (e: React.ChangeEvent<HTMLInputElement>) => {
31
+ const file = e.target.files?.[0];
32
+ if (!file) return;
33
+
34
+ // Validate type
35
+ const ext = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();
36
+ const validExts = ['.pdf', '.docx', '.pptx', '.txt'];
37
+ if (!ACCEPTED_TYPES.includes(file.type) && !validExts.includes(ext)) {
38
+ return;
39
+ }
40
+
41
+ // Open the canvas with the file
42
+ await openCanvas(file);
43
+
44
+ // Notify parent (for chat input)
45
+ onFileSelected?.(file);
46
+
47
+ // Reset input
48
+ if (inputRef.current) {
49
+ inputRef.current.value = '';
50
+ }
51
+ },
52
+ [openCanvas, onFileSelected],
53
+ );
54
+
55
+ return (
56
+ <>
57
+ <input
58
+ id={id}
59
+ ref={inputRef}
60
+ type="file"
61
+ accept={ACCEPTED_EXTENSIONS}
62
+ onChange={handleChange}
63
+ className="hidden"
64
+ aria-label="Attach document"
65
+ />
66
+ <Tooltip>
67
+ <TooltipTrigger
68
+ render={
69
+ <button
70
+ type="button"
71
+ onClick={() => inputRef.current?.click()}
72
+ disabled={isLoading}
73
+ className={cn(
74
+ 'flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-muted-foreground transition',
75
+ 'hover:bg-secondary hover:text-foreground',
76
+ 'disabled:opacity-40 disabled:cursor-not-allowed',
77
+ className,
78
+ )}
79
+ >
80
+ <Paperclip className="size-4.5" />
81
+ </button>
82
+ }
83
+ />
84
+ <TooltipContent>Attach document (PDF, Word, PPT, TXT)</TooltipContent>
85
+ </Tooltip>
86
+ </>
87
+ );
88
+ }