@agent-native/core 0.80.2 → 0.80.5

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 (322) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +66 -2
  3. package/corpus/core/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
  4. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -1
  5. package/corpus/core/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
  6. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -1
  7. package/corpus/core/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
  8. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -1
  9. package/corpus/core/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
  10. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -1
  11. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -1
  12. package/corpus/core/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
  13. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -1
  14. package/corpus/core/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
  15. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -1
  16. package/corpus/core/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
  17. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -1
  18. package/corpus/core/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
  19. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -1
  20. package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
  21. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -1
  22. package/corpus/core/docs/content/real-time-collaboration.mdx +2 -2
  23. package/corpus/core/docs/content/template-design.mdx +1 -1
  24. package/corpus/core/package.json +3 -7
  25. package/corpus/core/src/action.ts +32 -0
  26. package/corpus/core/src/agent/durable-background.ts +32 -11
  27. package/corpus/core/src/agent/production-agent.ts +14 -1
  28. package/corpus/core/src/agent/run-loop-with-resume.ts +3 -1
  29. package/corpus/core/src/brand-kit/fig/index.ts +17 -37
  30. package/corpus/core/src/cli/index.ts +1 -1
  31. package/corpus/core/src/cli/mcp-config-writers.ts +187 -51
  32. package/corpus/core/src/cli/plan-local.ts +445 -108
  33. package/corpus/core/src/cli/skills.ts +32 -8
  34. package/corpus/core/src/client/AssistantChat.tsx +11 -1
  35. package/corpus/core/src/client/agent-chat.ts +12 -1
  36. package/corpus/core/src/client/composer/PromptComposer.tsx +100 -41
  37. package/corpus/core/src/client/org/OrgSwitcher.tsx +1 -1
  38. package/corpus/core/src/client/sharing/ShareButton.tsx +3 -27
  39. package/corpus/core/src/collab/presence.ts +1 -1
  40. package/corpus/core/src/mcp/connect-route.ts +34 -5
  41. package/corpus/core/src/server/action-discovery.ts +4 -0
  42. package/corpus/core/src/server/action-routes.ts +14 -0
  43. package/corpus/core/src/server/agent-chat-plugin.ts +20 -0
  44. package/corpus/core/src/vite/client.ts +15 -1
  45. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -0
  46. package/corpus/templates/analytics/actions/update-dashboard.ts +8 -0
  47. package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
  48. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +117 -33
  49. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -0
  50. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +7 -0
  51. package/corpus/templates/analytics/changelog/2026-06-27-dashboards-can-now-nest-under-a-parent-in-the-sidebar-via-a-.md +6 -0
  52. package/corpus/templates/analytics/changelog/2026-06-29-analytics-pages-now-sit-closer-under-the-header-with-tighter.md +6 -0
  53. package/corpus/templates/assets/actions/generate-image-batch.ts +3 -0
  54. package/corpus/templates/assets/actions/generate-image.ts +3 -0
  55. package/corpus/templates/assets/changelog/2026-06-29-longer-agent-generation-window.md +6 -0
  56. package/corpus/templates/assets/netlify.toml +3 -3
  57. package/corpus/templates/assets/server/plugins/agent-chat.ts +4 -1
  58. package/corpus/templates/clips/app/components/capture-install-options.tsx +7 -8
  59. package/corpus/templates/clips/app/components/player/timestamped-comment-button.tsx +162 -0
  60. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -1
  61. package/corpus/templates/clips/app/i18n/ar-SA.ts +4 -0
  62. package/corpus/templates/clips/app/i18n/de-DE.ts +4 -0
  63. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  64. package/corpus/templates/clips/app/i18n/es-ES.ts +4 -0
  65. package/corpus/templates/clips/app/i18n/fr-FR.ts +4 -0
  66. package/corpus/templates/clips/app/i18n/hi-IN.ts +4 -0
  67. package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -0
  68. package/corpus/templates/clips/app/i18n/ko-KR.ts +4 -0
  69. package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -0
  70. package/corpus/templates/clips/app/i18n/zh-CN.ts +4 -0
  71. package/corpus/templates/clips/app/i18n/zh-TW.ts +4 -0
  72. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +42 -18
  73. package/corpus/templates/content/AGENTS.md +12 -0
  74. package/corpus/templates/content/app/blocks/BuilderDocsBlocks.tsx +10 -0
  75. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -0
  76. package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +185 -0
  77. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -0
  78. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +19 -0
  79. package/corpus/templates/content/app/components/editor/extensions/ContentReferenceNode.tsx +82 -0
  80. package/corpus/templates/content/app/global.css +9 -0
  81. package/corpus/templates/content/app/i18n/zh-TW.ts +12 -0
  82. package/corpus/templates/content/app/i18n-data.ts +140 -0
  83. package/corpus/templates/content/changelog/2026-06-29-reusable-mdx-references-now-preview-linked-local-documents-i.md +6 -0
  84. package/corpus/templates/content/shared/builder-docs-blocks.ts +8 -0
  85. package/corpus/templates/content/shared/builder-mdx.ts +141 -4
  86. package/corpus/templates/content/shared/nfm.ts +62 -0
  87. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +10 -11
  88. package/corpus/templates/design/AGENTS.md +5 -0
  89. package/corpus/templates/design/_gitignore +7 -0
  90. package/corpus/templates/design/actions/apply-visual-edit.ts +22 -12
  91. package/corpus/templates/design/actions/create-design-system.ts +15 -4
  92. package/corpus/templates/design/actions/create-file.ts +20 -1
  93. package/corpus/templates/design/actions/delete-design-system.ts +2 -2
  94. package/corpus/templates/design/actions/duplicate-design.ts +35 -9
  95. package/corpus/templates/design/actions/generate-design.ts +146 -69
  96. package/corpus/templates/design/actions/generate-screens.ts +51 -19
  97. package/corpus/templates/design/actions/get-design-snapshot.ts +5 -1
  98. package/corpus/templates/design/actions/get-design.ts +2 -0
  99. package/corpus/templates/design/actions/import-design-project.ts +28 -9
  100. package/corpus/templates/design/actions/import-document.ts +22 -8
  101. package/corpus/templates/design/actions/index-design-system-with-builder.ts +6 -153
  102. package/corpus/templates/design/actions/navigate.ts +105 -54
  103. package/corpus/templates/design/actions/set-default-design-system.ts +17 -3
  104. package/corpus/templates/design/actions/show-design-questions.ts +2 -0
  105. package/corpus/templates/design/actions/update-design.ts +2 -1
  106. package/corpus/templates/design/actions/view-screen.ts +12 -6
  107. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +4 -4
  108. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +159 -41
  109. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +8 -4
  110. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +37 -42
  111. package/corpus/templates/design/app/components/design/EditPanel.tsx +336 -183
  112. package/corpus/templates/design/app/components/design/LayersPanel.tsx +153 -34
  113. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +135 -33
  114. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +6 -0
  115. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
  116. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +4 -10
  117. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +84 -43
  118. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +4 -4
  119. package/corpus/templates/design/app/components/design/inspector/{FigmaColorPicker.tsx → DesignColorPicker.tsx} +89 -62
  120. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +14 -26
  121. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +40 -12
  122. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -4
  123. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +13 -13
  124. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -9
  125. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +13 -4
  126. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
  127. package/corpus/templates/design/app/components/design/inspector/{figma-icons.tsx → design-icons.tsx} +2 -2
  128. package/corpus/templates/design/app/components/design/inspector/index.ts +12 -12
  129. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +5 -2
  130. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -3
  131. package/corpus/templates/design/app/components/layout/Layout.tsx +5 -2
  132. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  133. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +167 -91
  134. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +16 -3
  135. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +15 -0
  136. package/corpus/templates/design/app/global.css +4 -0
  137. package/corpus/templates/design/app/hooks/use-design-system.ts +4 -1
  138. package/corpus/templates/design/app/hooks/use-navigation-state.ts +38 -3
  139. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +9 -2
  140. package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
  141. package/corpus/templates/design/app/i18n-data.ts +527 -0
  142. package/corpus/templates/design/app/lib/design-systems.ts +6 -4
  143. package/corpus/templates/design/app/lib/design-templates.ts +15 -3
  144. package/corpus/templates/design/app/pages/DesignEditor.tsx +641 -158
  145. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +42 -34
  146. package/corpus/templates/design/app/pages/VisualEdit.tsx +100 -0
  147. package/corpus/templates/design/app/root.tsx +42 -9
  148. package/corpus/templates/design/app/routes/visual-edit.tsx +7 -0
  149. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +1 -1
  150. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +1 -1
  151. package/corpus/templates/design/changelog/2026-06-28-visual-code-design-mode.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-29-design-generation-prompts-now-show-connect-ai-before-sending.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +1 -1
  154. package/corpus/templates/design/changelog/2026-06-29-fixed-design-editor-exports-and-gradient-edits-so-multi-scre.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-29-png-export-handles-modern-css-color-functions-more-reliably.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-29-png-export-now-ignores-duplicate-clicks-while-a-download-is-.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-29-public-visual-edit-and-shared-design-links-now-invite-visito.md +6 -0
  159. package/corpus/templates/design/changelog/2026-06-29-visual-edit-actions-now-reject-missing-design-targets-before.md +6 -0
  160. package/corpus/templates/design/e2e/README.md +71 -0
  161. package/corpus/templates/design/e2e/global-setup.ts +157 -0
  162. package/corpus/templates/design/e2e/helpers.ts +148 -0
  163. package/corpus/templates/design/netlify.toml +3 -4
  164. package/corpus/templates/design/package.json +5 -1
  165. package/corpus/templates/design/playwright.config.ts +51 -0
  166. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +121 -0
  167. package/corpus/templates/design/server/handlers/uploads.ts +89 -38
  168. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +181 -0
  169. package/corpus/templates/design/server/lib/coding-handoff.ts +33 -4
  170. package/corpus/templates/design/server/lib/design-export.ts +35 -8
  171. package/corpus/templates/design/server/plugins/agent-chat.ts +4 -0
  172. package/corpus/templates/design/server/plugins/auth.ts +10 -1
  173. package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +1 -0
  174. package/corpus/templates/design/shared/api.ts +2 -0
  175. package/corpus/templates/design/shared/apply-edits.ts +12 -8
  176. package/corpus/templates/design/shared/canvas-math.ts +19 -1
  177. package/corpus/templates/design/shared/code-layer.ts +87 -28
  178. package/corpus/templates/design/shared/generation-session.ts +1 -0
  179. package/corpus/templates/design/shared/resolve-tweaks.ts +4 -3
  180. package/corpus/templates/design/shared/shader-presets.ts +10 -0
  181. package/corpus/templates/design/shared/source-mode.ts +9 -0
  182. package/corpus/templates/design/vitest.config.ts +2 -1
  183. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +1 -1
  184. package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +1 -1
  185. package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +14 -5
  186. package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +14 -5
  187. package/corpus/templates/plan/AGENTS.md +1 -1
  188. package/corpus/templates/plan/actions/create-plan-design.ts +1 -1
  189. package/corpus/templates/plan/actions/validate-local-plan-source.ts +110 -0
  190. package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -0
  191. package/corpus/templates/plan/docs/commenting-ux-plan.md +2 -2
  192. package/corpus/templates/plan/server/lib/plan-connector-catalog.ts +1 -0
  193. package/corpus/templates/plan/server/lib/public-action-paths.ts +1 -0
  194. package/corpus/templates/plan/server/plan-content.ts +1 -1
  195. package/corpus/templates/plan/server/ui-plan-html.ts +2 -2
  196. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +6 -153
  197. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +53 -38
  198. package/corpus/templates/slides/app/components/design-system/{fig-import-response.ts → builder-index-response.ts} +9 -6
  199. package/corpus/templates/slides/app/components/visual-editor/MultiSelectChip.tsx +1 -1
  200. package/corpus/templates/slides/changelog/2026-06-29-design-system-setup-now-indexes-uploaded-design-files-throug.md +6 -0
  201. package/corpus/templates/slides/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
  202. package/corpus/templates/slides/netlify.toml +3 -6
  203. package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +116 -0
  204. package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +179 -0
  205. package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -1
  206. package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +1 -0
  207. package/dist/action.d.ts +23 -0
  208. package/dist/action.d.ts.map +1 -1
  209. package/dist/action.js +9 -0
  210. package/dist/action.js.map +1 -1
  211. package/dist/agent/durable-background.d.ts +9 -7
  212. package/dist/agent/durable-background.d.ts.map +1 -1
  213. package/dist/agent/durable-background.js +27 -11
  214. package/dist/agent/durable-background.js.map +1 -1
  215. package/dist/agent/production-agent.d.ts +10 -0
  216. package/dist/agent/production-agent.d.ts.map +1 -1
  217. package/dist/agent/production-agent.js +4 -1
  218. package/dist/agent/production-agent.js.map +1 -1
  219. package/dist/agent/run-loop-with-resume.d.ts +2 -1
  220. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  221. package/dist/agent/run-loop-with-resume.js +2 -2
  222. package/dist/agent/run-loop-with-resume.js.map +1 -1
  223. package/dist/brand-kit/fig/index.d.ts +4 -4
  224. package/dist/brand-kit/fig/index.d.ts.map +1 -1
  225. package/dist/brand-kit/fig/index.js +14 -27
  226. package/dist/brand-kit/fig/index.js.map +1 -1
  227. package/dist/cli/index.js +1 -1
  228. package/dist/cli/index.js.map +1 -1
  229. package/dist/cli/mcp-config-writers.d.ts +15 -7
  230. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  231. package/dist/cli/mcp-config-writers.js +198 -45
  232. package/dist/cli/mcp-config-writers.js.map +1 -1
  233. package/dist/cli/plan-local.d.ts +30 -0
  234. package/dist/cli/plan-local.d.ts.map +1 -1
  235. package/dist/cli/plan-local.js +281 -56
  236. package/dist/cli/plan-local.js.map +1 -1
  237. package/dist/cli/skills.d.ts +2 -2
  238. package/dist/cli/skills.d.ts.map +1 -1
  239. package/dist/cli/skills.js +32 -8
  240. package/dist/cli/skills.js.map +1 -1
  241. package/dist/client/AssistantChat.d.ts.map +1 -1
  242. package/dist/client/AssistantChat.js +11 -1
  243. package/dist/client/AssistantChat.js.map +1 -1
  244. package/dist/client/agent-chat.d.ts.map +1 -1
  245. package/dist/client/agent-chat.js +15 -2
  246. package/dist/client/agent-chat.js.map +1 -1
  247. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  248. package/dist/client/composer/PromptComposer.js +35 -1
  249. package/dist/client/composer/PromptComposer.js.map +1 -1
  250. package/dist/client/org/OrgSwitcher.js +1 -1
  251. package/dist/client/org/OrgSwitcher.js.map +1 -1
  252. package/dist/client/sharing/ShareButton.d.ts +1 -1
  253. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  254. package/dist/client/sharing/ShareButton.js +2 -15
  255. package/dist/client/sharing/ShareButton.js.map +1 -1
  256. package/dist/collab/presence.d.ts +1 -1
  257. package/dist/collab/presence.js +1 -1
  258. package/dist/collab/presence.js.map +1 -1
  259. package/dist/collab/routes.d.ts +1 -1
  260. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  261. package/dist/mcp/connect-route.d.ts.map +1 -1
  262. package/dist/mcp/connect-route.js +34 -5
  263. package/dist/mcp/connect-route.js.map +1 -1
  264. package/dist/observability/routes.d.ts +2 -2
  265. package/dist/progress/routes.d.ts +1 -1
  266. package/dist/resources/handlers.d.ts +1 -1
  267. package/dist/server/action-discovery.d.ts.map +1 -1
  268. package/dist/server/action-discovery.js +5 -0
  269. package/dist/server/action-discovery.js.map +1 -1
  270. package/dist/server/action-routes.d.ts.map +1 -1
  271. package/dist/server/action-routes.js +14 -0
  272. package/dist/server/action-routes.js.map +1 -1
  273. package/dist/server/agent-chat-plugin.d.ts +6 -0
  274. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  275. package/dist/server/agent-chat-plugin.js +12 -3
  276. package/dist/server/agent-chat-plugin.js.map +1 -1
  277. package/dist/vite/client.d.ts.map +1 -1
  278. package/dist/vite/client.js +12 -1
  279. package/dist/vite/client.js.map +1 -1
  280. package/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
  281. package/docs/content/locales/ar-SA/template-design.mdx +1 -1
  282. package/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
  283. package/docs/content/locales/de-DE/template-design.mdx +1 -1
  284. package/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
  285. package/docs/content/locales/es-ES/template-design.mdx +1 -1
  286. package/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
  287. package/docs/content/locales/fr-FR/template-design.mdx +1 -1
  288. package/docs/content/locales/hi-IN/template-design.mdx +1 -1
  289. package/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
  290. package/docs/content/locales/ja-JP/template-design.mdx +1 -1
  291. package/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
  292. package/docs/content/locales/ko-KR/template-design.mdx +1 -1
  293. package/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
  294. package/docs/content/locales/pt-BR/template-design.mdx +1 -1
  295. package/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
  296. package/docs/content/locales/zh-CN/template-design.mdx +1 -1
  297. package/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
  298. package/docs/content/locales/zh-TW/template-design.mdx +1 -1
  299. package/docs/content/real-time-collaboration.mdx +2 -2
  300. package/docs/content/template-design.mdx +1 -1
  301. package/package.json +3 -7
  302. package/corpus/core/src/brand-kit/fig/decode.ts +0 -410
  303. package/corpus/core/src/brand-kit/fig/extract-design-system.ts +0 -947
  304. package/corpus/core/src/brand-kit/fig/fig-to-html.ts +0 -1906
  305. package/corpus/templates/design/actions/import-figma.ts +0 -55
  306. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +0 -6
  307. package/corpus/templates/design/server/handlers/import-figma-system.ts +0 -86
  308. package/corpus/templates/design/server/routes/api/import-figma-system.post.ts +0 -1
  309. package/corpus/templates/slides/server/handlers/import-figma-system.ts +0 -101
  310. package/corpus/templates/slides/server/routes/api/import-figma-system.post.ts +0 -1
  311. package/dist/brand-kit/fig/decode.d.ts +0 -33
  312. package/dist/brand-kit/fig/decode.d.ts.map +0 -1
  313. package/dist/brand-kit/fig/decode.js +0 -358
  314. package/dist/brand-kit/fig/decode.js.map +0 -1
  315. package/dist/brand-kit/fig/extract-design-system.d.ts +0 -44
  316. package/dist/brand-kit/fig/extract-design-system.d.ts.map +0 -1
  317. package/dist/brand-kit/fig/extract-design-system.js +0 -752
  318. package/dist/brand-kit/fig/extract-design-system.js.map +0 -1
  319. package/dist/brand-kit/fig/fig-to-html.d.ts +0 -246
  320. package/dist/brand-kit/fig/fig-to-html.d.ts.map +0 -1
  321. package/dist/brand-kit/fig/fig-to-html.js +0 -1506
  322. package/dist/brand-kit/fig/fig-to-html.js.map +0 -1
@@ -30,7 +30,14 @@ import {
30
30
  type QueryKey,
31
31
  } from "@tanstack/react-query";
32
32
  import { useTheme } from "next-themes";
33
- import { useState, useEffect, useCallback, useRef, useMemo } from "react";
33
+ import {
34
+ useState,
35
+ useEffect,
36
+ useCallback,
37
+ useRef,
38
+ useMemo,
39
+ Fragment,
40
+ } from "react";
34
41
  import { Link, useLocation, useNavigate } from "react-router";
35
42
  import { toast } from "sonner";
36
43
 
@@ -51,6 +58,8 @@ type SidebarDashboard = {
51
58
  subviews?: DashboardSubview[];
52
59
  source: "static" | "sql";
53
60
  visibility?: Visibility;
61
+ /** Id of the dashboard this one nests under in the sidebar, if any. */
62
+ parentId?: string;
54
63
  };
55
64
  import {
56
65
  DevDatabaseLink,
@@ -1026,6 +1035,7 @@ type SqlDashboardListItem = {
1026
1035
  id: string;
1027
1036
  name: string;
1028
1037
  visibility?: Visibility;
1038
+ parentId?: string;
1029
1039
  };
1030
1040
 
1031
1041
  async function fetchSqlDashboards(
@@ -1045,6 +1055,10 @@ async function fetchSqlDashboards(
1045
1055
  d.visibility === "org" || d.visibility === "public"
1046
1056
  ? (d.visibility as Visibility)
1047
1057
  : ("private" as Visibility),
1058
+ parentId:
1059
+ typeof d.parentId === "string" && d.parentId.trim().length > 0
1060
+ ? d.parentId
1061
+ : undefined,
1048
1062
  }));
1049
1063
  } catch {
1050
1064
  return [];
@@ -1445,6 +1459,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1445
1459
  name: d.name,
1446
1460
  source: "sql",
1447
1461
  visibility: d.visibility,
1462
+ parentId: d.parentId,
1448
1463
  }));
1449
1464
  const all = [...staticItems, ...sqlItems];
1450
1465
  if (dashboardSortMode === "alphabetical") {
@@ -1482,12 +1497,54 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1482
1497
  [visibleDashboards, dashFilter],
1483
1498
  );
1484
1499
 
1500
+ // Group dashboards that declare a parentId beneath their parent. Nesting is
1501
+ // intentionally one level deep: a dashboard only nests when its parent is
1502
+ // itself top-level. Orphans (parent missing/filtered out), self-references,
1503
+ // cycles, and deeper descendants all fall back to top level so nothing is
1504
+ // ever hidden.
1505
+ const dashboardChildren = useMemo<Map<string, SidebarDashboard[]>>(() => {
1506
+ const byId = new Map(filteredDashboards.map((d) => [d.id, d]));
1507
+ const hasValidParent = (d: SidebarDashboard) =>
1508
+ !!d.parentId && d.parentId !== d.id && byId.has(d.parentId);
1509
+ const byParent = new Map<string, SidebarDashboard[]>();
1510
+ for (const d of filteredDashboards) {
1511
+ if (!hasValidParent(d)) continue;
1512
+ const parent = byId.get(d.parentId as string);
1513
+ if (!parent || hasValidParent(parent)) continue;
1514
+ const arr = byParent.get(d.parentId as string) ?? [];
1515
+ arr.push(d);
1516
+ byParent.set(d.parentId as string, arr);
1517
+ }
1518
+ return byParent;
1519
+ }, [filteredDashboards]);
1520
+
1521
+ const topLevelDashboards = useMemo(() => {
1522
+ const childIds = new Set<string>();
1523
+ for (const arr of dashboardChildren.values())
1524
+ for (const c of arr) childIds.add(c.id);
1525
+ return filteredDashboards.filter((d) => !childIds.has(d.id));
1526
+ }, [filteredDashboards, dashboardChildren]);
1527
+
1485
1528
  const displayedDashboards = useMemo(
1486
1529
  () =>
1487
1530
  dashShowAll
1488
- ? filteredDashboards
1489
- : filteredDashboards.slice(0, SIDEBAR_PREVIEW_COUNT),
1490
- [filteredDashboards, dashShowAll],
1531
+ ? topLevelDashboards
1532
+ : topLevelDashboards.slice(0, SIDEBAR_PREVIEW_COUNT),
1533
+ [topLevelDashboards, dashShowAll],
1534
+ );
1535
+
1536
+ // The flattened id order exactly as rendered (each parent immediately
1537
+ // followed by its nested children). Drag reordering must use this so the
1538
+ // arrayMove indices match what the user sees; the raw `visibleDashboards`
1539
+ // order interleaves children at their sorted positions and would move the
1540
+ // wrong rows once a dashboard is nested.
1541
+ const dashboardRenderOrderIds = useMemo(
1542
+ () =>
1543
+ topLevelDashboards.flatMap((d) => [
1544
+ d.id,
1545
+ ...(dashboardChildren.get(d.id) ?? []).map((c) => c.id),
1546
+ ]),
1547
+ [topLevelDashboards, dashboardChildren],
1491
1548
  );
1492
1549
 
1493
1550
  const handleDashboardDelete = useCallback(
@@ -1801,18 +1858,16 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
1801
1858
  (event: DragEndEvent) => {
1802
1859
  const { active, over } = event;
1803
1860
  if (!over || active.id === over.id) return;
1861
+ const ids = dashboardRenderOrderIds;
1862
+ const oldIndex = ids.indexOf(active.id as string);
1863
+ const newIndex = ids.indexOf(over.id as string);
1864
+ if (oldIndex === -1 || newIndex === -1) return;
1804
1865
  setDashboardSortMode("manual");
1805
- setDashboardOrderState((prev) => {
1806
- const ids = prev.length > 0 ? prev : visibleDashboards.map((d) => d.id);
1807
- const oldIndex = ids.indexOf(active.id as string);
1808
- const newIndex = ids.indexOf(over.id as string);
1809
- if (oldIndex === -1 || newIndex === -1) return prev;
1810
- const newOrder = arrayMove(ids, oldIndex, newIndex);
1811
- setDashboardOrder(newOrder);
1812
- return newOrder;
1813
- });
1866
+ const newOrder = arrayMove(ids, oldIndex, newIndex);
1867
+ setDashboardOrder(newOrder);
1868
+ setDashboardOrderState(newOrder);
1814
1869
  },
1815
- [setDashboardSortMode, visibleDashboards],
1870
+ [setDashboardSortMode, dashboardRenderOrderIds],
1816
1871
  );
1817
1872
 
1818
1873
  const handleAnalysisDragEnd = useCallback(
@@ -2169,27 +2224,56 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2169
2224
  onDragEnd={handleDashboardDragEnd}
2170
2225
  >
2171
2226
  <SortableContext
2172
- items={displayedDashboards.map((d) => d.id)}
2227
+ items={displayedDashboards.flatMap((d) => [
2228
+ d.id,
2229
+ ...(dashboardChildren.get(d.id) ?? []).map((c) => c.id),
2230
+ ])}
2173
2231
  strategy={verticalListSortingStrategy}
2174
2232
  >
2175
2233
  <div className="ms-4 min-w-0 space-y-0.5">
2176
- {displayedDashboards.map((d) => (
2177
- <SortableDashboardItem
2178
- key={d.id}
2179
- d={d}
2180
- isActive={activeDashboardId === d.id}
2181
- location={location}
2182
- favoriteIds={favoriteIds}
2183
- onToggleFavorite={toggleFavorite}
2184
- onDelete={handleDashboardDelete}
2185
- onRename={handleDashboardRename}
2186
- onArchive={handleDashboardArchive}
2187
- onSetVisibility={handleDashboardSetVisibility}
2188
- onPrefetch={prefetchDashboard}
2189
- views={allViewsMap[d.id]}
2190
- />
2191
- ))}
2192
- {filteredDashboards.length > SIDEBAR_PREVIEW_COUNT && (
2234
+ {displayedDashboards.map((d) => {
2235
+ const children = dashboardChildren.get(d.id) ?? [];
2236
+ return (
2237
+ <Fragment key={d.id}>
2238
+ <SortableDashboardItem
2239
+ d={d}
2240
+ isActive={activeDashboardId === d.id}
2241
+ location={location}
2242
+ favoriteIds={favoriteIds}
2243
+ onToggleFavorite={toggleFavorite}
2244
+ onDelete={handleDashboardDelete}
2245
+ onRename={handleDashboardRename}
2246
+ onArchive={handleDashboardArchive}
2247
+ onSetVisibility={handleDashboardSetVisibility}
2248
+ onPrefetch={prefetchDashboard}
2249
+ views={allViewsMap[d.id]}
2250
+ />
2251
+ {children.length > 0 && (
2252
+ <div className="ms-3 space-y-0.5 border-s border-sidebar-border/60 ps-1">
2253
+ {children.map((child) => (
2254
+ <SortableDashboardItem
2255
+ key={child.id}
2256
+ d={child}
2257
+ isActive={activeDashboardId === child.id}
2258
+ location={location}
2259
+ favoriteIds={favoriteIds}
2260
+ onToggleFavorite={toggleFavorite}
2261
+ onDelete={handleDashboardDelete}
2262
+ onRename={handleDashboardRename}
2263
+ onArchive={handleDashboardArchive}
2264
+ onSetVisibility={
2265
+ handleDashboardSetVisibility
2266
+ }
2267
+ onPrefetch={prefetchDashboard}
2268
+ views={allViewsMap[child.id]}
2269
+ />
2270
+ ))}
2271
+ </div>
2272
+ )}
2273
+ </Fragment>
2274
+ );
2275
+ })}
2276
+ {topLevelDashboards.length > SIDEBAR_PREVIEW_COUNT && (
2193
2277
  <button
2194
2278
  onClick={() => setDashShowAll(!dashShowAll)}
2195
2279
  className="flex items-center gap-1 px-3 py-1 text-[11px] text-muted-foreground/70 hover:text-primary"
@@ -2198,7 +2282,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2198
2282
  ? t("sidebar.showLess")
2199
2283
  : t("sidebar.showMore", {
2200
2284
  count:
2201
- filteredDashboards.length -
2285
+ topLevelDashboards.length -
2202
2286
  SIDEBAR_PREVIEW_COUNT,
2203
2287
  })}
2204
2288
  </button>
@@ -379,6 +379,10 @@ async function fetchDashboard(id: string): Promise<FetchedDashboard | null> {
379
379
  config: {
380
380
  name: data.name ?? "Untitled Dashboard",
381
381
  description: data.description,
382
+ parentId:
383
+ typeof data.parentId === "string" && data.parentId.trim().length > 0
384
+ ? data.parentId
385
+ : undefined,
382
386
  catalog: parseDashboardCatalogMetadata(data.catalog),
383
387
  demo: parseDashboardDemoMetadata(data.demo),
384
388
  filters: data.filters,
@@ -114,6 +114,13 @@ export interface SqlPanel {
114
114
  export interface SqlDashboardConfig {
115
115
  name: string;
116
116
  description?: string;
117
+ /**
118
+ * Optional id of another dashboard this one nests under. When set, the
119
+ * sidebar renders this dashboard indented beneath its parent instead of at
120
+ * the top level. Orphans (parent missing/inaccessible) fall back to the top
121
+ * level. Self-references and cycles are ignored by the renderer.
122
+ */
123
+ parentId?: string;
117
124
  catalog?: {
118
125
  templateId?: string;
119
126
  templateVersion?: string;
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-06-27
4
+ ---
5
+
6
+ Dashboards can now nest under a parent in the sidebar via a parentId field
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-29
4
+ ---
5
+
6
+ Analytics pages now sit closer under the header with tighter content padding.
@@ -22,6 +22,8 @@ import { readImageModelDefault } from "./_image-model-default.js";
22
22
  import generateImage from "./generate-image.js";
23
23
  import { upsertVariantSlot } from "./variant-slots.js";
24
24
 
25
+ const IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12 * 60_000;
26
+
25
27
  export default defineAction({
26
28
  description:
27
29
  "Generate several brand-consistent images in parallel from one brand kit/library. Use @brand-kit mentions as libraryId and @preset mentions as presetId when present. This is synchronous for images: one call waits for every slot and returns final image artifacts. Use this for slide decks, landing pages, and multi-slot design work. Do not call get-generation-run or refresh-generation-run after a normal image batch result.",
@@ -74,6 +76,7 @@ export default defineAction({
74
76
  ),
75
77
  }),
76
78
  parallelSafe: true,
79
+ timeoutMs: IMAGE_GENERATION_TOOL_TIMEOUT_MS,
77
80
  run: async ({ slots, ...inputBase }, context?: ActionRunContext) => {
78
81
  const imageModelDefault = await readImageModelDefault();
79
82
  const libraryId = inputBase.libraryId;
@@ -46,6 +46,8 @@ import {
46
46
  import { readImageModelDefault } from "./_image-model-default.js";
47
47
  import { upsertVariantSlot, wasVariantSlotDismissed } from "./variant-slots.js";
48
48
 
49
+ const IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12 * 60_000;
50
+
49
51
  function resolveModelForTier(
50
52
  tier: ImageQualityTier | undefined,
51
53
  category: ImageCategory | undefined,
@@ -125,6 +127,7 @@ export default defineAction({
125
127
  ),
126
128
  }),
127
129
  parallelSafe: true,
130
+ timeoutMs: IMAGE_GENERATION_TOOL_TIMEOUT_MS,
128
131
  run: async (input, context?: ActionRunContext) => {
129
132
  const imageModelDefault = await readImageModelDefault();
130
133
  const libraryId = input.libraryId;
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-29
4
+ ---
5
+
6
+ Image generation requests have a longer hosted agent window, reducing timeouts for slow models and multi-image batches.
@@ -8,9 +8,9 @@ functions = "templates/assets/.netlify/functions-internal"
8
8
  GA_MEASUREMENT_ID = "G-ESF7FYXGN9"
9
9
  NITRO_PRESET = "netlify"
10
10
  NPM_CONFIG_PRODUCTION = "false"
11
+ AGENT_CHAT_DURABLE_BACKGROUND = "true"
11
12
 
12
- # Image generation calls run a full Gemini round-trip plus Sharp post-processing.
13
- # Each `generate-image` call is ~6-12s; A2A delegation may chain several. Match
14
- # slides' generous timeout so multi-image runs don't get killed mid-flight.
13
+ # Emit the Netlify background function used by Assets' durable agent-chat opt-in.
14
+ # The normal server timeout still protects non-agent image/video HTTP handlers.
15
15
  [functions."*"]
16
16
  timeout = 300
@@ -10,6 +10,8 @@ import actionsRegistry from "../../.generated/actions-registry.js";
10
10
  import { getDb, schema } from "../db/index.js";
11
11
  import "../register-secrets.js";
12
12
 
13
+ const ASSETS_BACKGROUND_RUN_SOFT_TIMEOUT_MS = 13 * 60_000;
14
+
13
15
  const INITIAL_TOOL_NAMES = [
14
16
  "view-screen",
15
17
  "list-libraries",
@@ -240,5 +242,6 @@ export default createAgentChatPlugin({
240
242
  },
241
243
  },
242
244
  },
243
- runSoftTimeoutMs: 240_000,
245
+ durableBackgroundRuns: true,
246
+ runSoftTimeoutMs: ASSETS_BACKGROUND_RUN_SOFT_TIMEOUT_MS,
244
247
  });
@@ -1,4 +1,4 @@
1
- import { useT } from "@agent-native/core/client";
1
+ import { appPath, useT } from "@agent-native/core/client";
2
2
  import {
3
3
  IconBrandApple,
4
4
  IconBrandChrome,
@@ -8,7 +8,6 @@ import {
8
8
  IconExternalLink,
9
9
  } from "@tabler/icons-react";
10
10
  import { type ReactNode } from "react";
11
- import { Link } from "react-router";
12
11
 
13
12
  import { Button, type ButtonProps } from "@/components/ui/button";
14
13
  import {
@@ -91,8 +90,8 @@ function InstallOptionsContent({ desktopHref = "/download" }) {
91
90
  </div>
92
91
  )}
93
92
 
94
- <Link
95
- to={desktopHref}
93
+ <a
94
+ href={appPath(desktopHref)}
96
95
  className="flex items-start gap-3 rounded-md border border-border p-3 text-start transition hover:bg-accent"
97
96
  >
98
97
  <DesktopIcon className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
@@ -104,7 +103,7 @@ function InstallOptionsContent({ desktopHref = "/download" }) {
104
103
  {t("captureInstall.desktopDescription")}
105
104
  </span>
106
105
  </span>
107
- </Link>
106
+ </a>
108
107
  </div>
109
108
  );
110
109
  }
@@ -120,7 +119,7 @@ export function CaptureInstallButton({
120
119
  if (!clipsChromeExtensionEnabled) {
121
120
  return (
122
121
  <Button asChild className={className} {...buttonProps}>
123
- <Link to={desktopHref}>{children}</Link>
122
+ <a href={appPath(desktopHref)}>{children}</a>
124
123
  </Button>
125
124
  );
126
125
  }
@@ -149,9 +148,9 @@ export function CaptureInstallInlineLink({
149
148
  }: CaptureInstallInlineLinkProps) {
150
149
  if (!clipsChromeExtensionEnabled) {
151
150
  return (
152
- <Link to={desktopHref} className={className}>
151
+ <a href={appPath(desktopHref)} className={className}>
153
152
  {children}
154
- </Link>
153
+ </a>
155
154
  );
156
155
  }
157
156
 
@@ -0,0 +1,162 @@
1
+ import { useActionMutation, useT } from "@agent-native/core/client";
2
+ import { IconMessagePlus, IconAt, IconMoodSmile } from "@tabler/icons-react";
3
+ import { useEffect, useRef, useState } from "react";
4
+
5
+ import { Button } from "@/components/ui/button";
6
+ import { Textarea } from "@/components/ui/textarea";
7
+ import { cn } from "@/lib/utils";
8
+
9
+ import { msToClock } from "./scrubber";
10
+
11
+ interface TimestampedCommentButtonProps {
12
+ enableComments: boolean;
13
+ onOpen: () => void;
14
+ className?: string;
15
+ }
16
+
17
+ /** Trigger that opens the docked comment composer, pinned to the current time. */
18
+ export function TimestampedCommentButton({
19
+ enableComments,
20
+ onOpen,
21
+ className,
22
+ }: TimestampedCommentButtonProps) {
23
+ const t = useT();
24
+ if (!enableComments) return null;
25
+ return (
26
+ <Button
27
+ type="button"
28
+ variant="outline"
29
+ size="sm"
30
+ className={cn("gap-1.5", className)}
31
+ onClick={onOpen}
32
+ >
33
+ <IconMessagePlus className="h-4 w-4" />
34
+ {t("commentsPanel.commentButton")}
35
+ </Button>
36
+ );
37
+ }
38
+
39
+ interface TimestampedCommentBarProps {
40
+ recordingId: string;
41
+ atMs: number;
42
+ onClose: () => void;
43
+ onAdded?: () => void;
44
+ className?: string;
45
+ }
46
+
47
+ /**
48
+ * Bottom-docked comment composer. Render inside a `relative` container (the
49
+ * video wrapper) so it overlays the bottom of the video at the captured moment.
50
+ */
51
+ export function TimestampedCommentBar({
52
+ recordingId,
53
+ atMs,
54
+ onClose,
55
+ onAdded,
56
+ className,
57
+ }: TimestampedCommentBarProps) {
58
+ const t = useT();
59
+ const [draft, setDraft] = useState("");
60
+ const textareaRef = useRef<HTMLTextAreaElement | null>(null);
61
+
62
+ const addComment = useActionMutation("add-comment");
63
+
64
+ useEffect(() => {
65
+ requestAnimationFrame(() => textareaRef.current?.focus());
66
+ }, []);
67
+
68
+ const insertAtCursor = (text: string) => {
69
+ const el = textareaRef.current;
70
+ if (!el) {
71
+ setDraft((d) => d + text);
72
+ return;
73
+ }
74
+ const start = el.selectionStart ?? draft.length;
75
+ const end = el.selectionEnd ?? draft.length;
76
+ const next = draft.slice(0, start) + text + draft.slice(end);
77
+ setDraft(next);
78
+ requestAnimationFrame(() => {
79
+ el.focus();
80
+ const pos = start + text.length;
81
+ el.setSelectionRange(pos, pos);
82
+ });
83
+ };
84
+
85
+ const submit = () => {
86
+ const content = draft.trim();
87
+ if (!content) return;
88
+ addComment.mutate(
89
+ { recordingId, content, videoTimestampMs: atMs },
90
+ {
91
+ onSuccess: () => {
92
+ setDraft("");
93
+ onAdded?.();
94
+ onClose();
95
+ },
96
+ },
97
+ );
98
+ };
99
+
100
+ return (
101
+ <div className={cn("absolute inset-x-0 bottom-0 z-30 p-3", className)}>
102
+ <div className="rounded-xl border border-border bg-background/95 p-3 shadow-lg backdrop-blur">
103
+ <Textarea
104
+ ref={textareaRef}
105
+ value={draft}
106
+ onChange={(e) => setDraft(e.target.value)}
107
+ onKeyDown={(e) => {
108
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
109
+ e.preventDefault();
110
+ submit();
111
+ }
112
+ if (e.key === "Escape") {
113
+ e.preventDefault();
114
+ onClose();
115
+ }
116
+ }}
117
+ placeholder={t("commentsPanel.composerPlaceholder")}
118
+ rows={2}
119
+ className="min-h-[3rem] resize-none border-0 bg-transparent px-1 text-sm shadow-none focus-visible:ring-0 focus-visible:ring-offset-0"
120
+ />
121
+ <div className="mt-2 flex items-center justify-between">
122
+ <div className="flex items-center gap-1">
123
+ <Button
124
+ type="button"
125
+ variant="ghost"
126
+ size="icon"
127
+ className="h-8 w-8 text-muted-foreground"
128
+ aria-label={t("commentsPanel.mentionSomeone")}
129
+ onClick={() => insertAtCursor("@")}
130
+ >
131
+ <IconAt className="h-4 w-4" />
132
+ </Button>
133
+ <Button
134
+ type="button"
135
+ variant="ghost"
136
+ size="icon"
137
+ className="h-8 w-8 text-muted-foreground"
138
+ aria-label={t("commentsPanel.addEmoji")}
139
+ onClick={() => insertAtCursor("🙂")}
140
+ >
141
+ <IconMoodSmile className="h-4 w-4" />
142
+ </Button>
143
+ </div>
144
+ <div className="flex items-center gap-2">
145
+ <Button type="button" variant="ghost" size="sm" onClick={onClose}>
146
+ {t("common.cancel")}
147
+ </Button>
148
+ <Button
149
+ type="button"
150
+ size="sm"
151
+ className="rounded-full"
152
+ disabled={!draft.trim() || addComment.isPending}
153
+ onClick={submit}
154
+ >
155
+ {t("commentsPanel.commentAt")} {msToClock(atMs)}
156
+ </Button>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ );
162
+ }
@@ -194,7 +194,7 @@ const SCREEN_CAPTURE_MAX_HEIGHT = 1080;
194
194
  // client-side (ffmpeg.wasm re-encode is disabled — see COMPRESSION_ENABLED in
195
195
  // `@/lib/compress`) and the upload provider streams large files directly, so we
196
196
  // capture at a crisp 1080p bitrate instead of a tight budget. 1.2 Mbps left
197
- // dense UI (fine text, Figma, code) visibly fuzzy; 8 Mbps keeps it sharp.
197
+ // dense UI (fine text and code) visibly fuzzy; 8 Mbps keeps it sharp.
198
198
  // Dial down here if file sizes become a concern for a deployment.
199
199
  const RECORDING_VIDEO_BITRATE_BPS = 8_000_000;
200
200
  const RECORDING_AUDIO_BITRATE_BPS = 128_000;
@@ -850,6 +850,10 @@ const messages = {
850
850
  replyingTo: "الرد على",
851
851
  commentAt: "تعليق عند",
852
852
  writeReply: "اكتب ردًا...",
853
+ commentButton: "تعليق",
854
+ composerPlaceholder: "أضف تعليقًا…",
855
+ mentionSomeone: "أذكر شخصًا",
856
+ addEmoji: "أضف رمزًا تعبيريًا",
853
857
  },
854
858
  shareMeeting: {
855
859
  pageTitle: "ملاحظات الاجتماع · Clips",
@@ -878,6 +878,10 @@ Alle sichtbaren Änderungen für Clips-Nutzer werden hier dokumentiert. Du kanns
878
878
  replyingTo: "Antwort an",
879
879
  commentAt: "Kommentar bei",
880
880
  writeReply: "Antwort schreiben...",
881
+ commentButton: "Kommentar",
882
+ composerPlaceholder: "Kommentar hinzufügen…",
883
+ mentionSomeone: "Jemanden erwähnen",
884
+ addEmoji: "Emoji hinzufügen",
881
885
  },
882
886
  shareMeeting: {
883
887
  pageTitle: "Meeting-Notizen · Clips",
@@ -849,6 +849,10 @@ All notable user-facing changes to Clips are documented here. Open it any time f
849
849
  replyingTo: "Replying to",
850
850
  commentAt: "Comment at",
851
851
  writeReply: "Write a reply...",
852
+ commentButton: "Comment",
853
+ composerPlaceholder: "Add a comment…",
854
+ mentionSomeone: "Mention someone",
855
+ addEmoji: "Add emoji",
852
856
  },
853
857
  shareMeeting: {
854
858
  pageTitle: "Meeting notes · Clips",
@@ -870,6 +870,10 @@ Todos los cambios visibles para los usuarios de Clips se documentan aquí. Puede
870
870
  replyingTo: "Respondiendo a",
871
871
  commentAt: "Comentar en",
872
872
  writeReply: "Escribe una respuesta...",
873
+ commentButton: "Comentar",
874
+ composerPlaceholder: "Añadir un comentario…",
875
+ mentionSomeone: "Mencionar a alguien",
876
+ addEmoji: "Añadir emoji",
873
877
  },
874
878
  shareMeeting: {
875
879
  pageTitle: "Notas de reunión · Clips",
@@ -872,6 +872,10 @@ Tous les changements visibles par les utilisateurs de Clips sont documentés ici
872
872
  replyingTo: "Réponse à",
873
873
  commentAt: "Commentaire à",
874
874
  writeReply: "Écrire une réponse...",
875
+ commentButton: "Commenter",
876
+ composerPlaceholder: "Ajouter un commentaire…",
877
+ mentionSomeone: "Mentionner quelqu'un",
878
+ addEmoji: "Ajouter un emoji",
875
879
  },
876
880
  shareMeeting: {
877
881
  pageTitle: "Notes de réunion · Clips",
@@ -844,6 +844,10 @@ Clips में उपयोगकर्ताओं को दिखने व
844
844
  replyingTo: "जवाब दे रहे हैं",
845
845
  commentAt: "टिप्पणी करें",
846
846
  writeReply: "जवाब लिखें...",
847
+ commentButton: "टिप्पणी",
848
+ composerPlaceholder: "टिप्पणी जोड़ें…",
849
+ mentionSomeone: "किसी का उल्लेख करें",
850
+ addEmoji: "इमोजी जोड़ें",
847
851
  },
848
852
  shareMeeting: {
849
853
  pageTitle: "मीटिंग नोट्स · Clips",
@@ -860,6 +860,10 @@ Clips のユーザー向けの主な変更はここに記録されます。コ
860
860
  replyingTo: "返信先",
861
861
  commentAt: "コメント位置",
862
862
  writeReply: "返信を書く...",
863
+ commentButton: "コメント",
864
+ composerPlaceholder: "コメントを追加…",
865
+ mentionSomeone: "メンバーをメンション",
866
+ addEmoji: "絵文字を追加",
863
867
  },
864
868
  shareMeeting: {
865
869
  pageTitle: "会議メモ · Clips",
@@ -851,6 +851,10 @@ Clips의 모든 사용자 대상 변경 사항은 여기에 기록됩니다. 명
851
851
  replyingTo: "답글 대상",
852
852
  commentAt: "댓글 위치",
853
853
  writeReply: "답글 쓰기...",
854
+ commentButton: "댓글",
855
+ composerPlaceholder: "댓글 추가…",
856
+ mentionSomeone: "멘션하기",
857
+ addEmoji: "이모지 추가",
854
858
  },
855
859
  shareMeeting: {
856
860
  pageTitle: "회의 노트 · Clips",