@agent-native/core 0.85.7 → 0.86.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 (1019) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +124 -1
  3. package/corpus/core/README.md +0 -11
  4. package/corpus/core/docs/content/cloneable-saas.mdx +0 -1
  5. package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
  6. package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
  7. package/corpus/core/docs/content/locales/ar-SA/sharing.mdx +1 -2
  8. package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
  9. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +23 -7
  10. package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +1 -1
  11. package/corpus/core/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
  12. package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
  13. package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
  14. package/corpus/core/docs/content/locales/de-DE/sharing.mdx +1 -2
  15. package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +2 -3
  16. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +23 -7
  17. package/corpus/core/docs/content/locales/de-DE/tracking.mdx +1 -1
  18. package/corpus/core/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
  19. package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
  20. package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
  21. package/corpus/core/docs/content/locales/es-ES/sharing.mdx +1 -2
  22. package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +2 -3
  23. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +23 -7
  24. package/corpus/core/docs/content/locales/es-ES/tracking.mdx +1 -1
  25. package/corpus/core/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
  26. package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
  27. package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
  28. package/corpus/core/docs/content/locales/fr-FR/sharing.mdx +1 -2
  29. package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
  30. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +23 -7
  31. package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +1 -1
  32. package/corpus/core/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
  33. package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
  34. package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
  35. package/corpus/core/docs/content/locales/hi-IN/sharing.mdx +1 -2
  36. package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
  37. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +23 -7
  38. package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +1 -1
  39. package/corpus/core/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
  40. package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
  41. package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
  42. package/corpus/core/docs/content/locales/ja-JP/sharing.mdx +1 -2
  43. package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
  44. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +23 -7
  45. package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +1 -1
  46. package/corpus/core/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
  47. package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
  48. package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
  49. package/corpus/core/docs/content/locales/ko-KR/sharing.mdx +1 -2
  50. package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
  51. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +23 -7
  52. package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +1 -1
  53. package/corpus/core/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
  54. package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
  55. package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
  56. package/corpus/core/docs/content/locales/pt-BR/sharing.mdx +1 -2
  57. package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
  58. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +23 -7
  59. package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +1 -1
  60. package/corpus/core/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
  61. package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
  62. package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
  63. package/corpus/core/docs/content/locales/zh-CN/sharing.mdx +1 -2
  64. package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
  65. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +23 -7
  66. package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +1 -1
  67. package/corpus/core/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
  68. package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
  69. package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
  70. package/corpus/core/docs/content/locales/zh-TW/sharing.mdx +1 -2
  71. package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
  72. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +23 -7
  73. package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +1 -1
  74. package/corpus/core/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
  75. package/corpus/core/docs/content/plan-plugin.mdx +12 -11
  76. package/corpus/core/docs/content/sharing.mdx +1 -2
  77. package/corpus/core/docs/content/skills-guide.mdx +4 -3
  78. package/corpus/core/docs/content/template-plan.mdx +37 -6
  79. package/corpus/core/docs/content/tracking.mdx +1 -1
  80. package/corpus/core/docs/content/workspace-connections.mdx +1 -1
  81. package/corpus/core/package.json +6 -6
  82. package/corpus/core/src/agent/run-store.ts +1 -1
  83. package/corpus/core/src/chat-threads/store.ts +73 -11
  84. package/corpus/core/src/checkpoints/store.ts +13 -2
  85. package/corpus/core/src/cli/create.ts +3 -4
  86. package/corpus/core/src/cli/design-connect.ts +469 -9
  87. package/corpus/core/src/cli/index.ts +13 -0
  88. package/corpus/core/src/cli/plan-local.ts +281 -24
  89. package/corpus/core/src/cli/skills.ts +177 -21
  90. package/corpus/core/src/cli/templates-meta.ts +0 -13
  91. package/corpus/core/src/cli/visualize-repo.ts +715 -0
  92. package/corpus/core/src/client/AssistantChat.tsx +126 -17
  93. package/corpus/core/src/client/agent-chat-adapter.ts +6 -5
  94. package/corpus/core/src/client/app-providers.tsx +2 -2
  95. package/corpus/core/src/client/collab/index.ts +31 -0
  96. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +16 -1
  97. package/corpus/core/src/client/components/PresenceBar.tsx +14 -1
  98. package/corpus/core/src/client/components/RecentEditHighlights.tsx +219 -0
  99. package/corpus/core/src/client/components/RemoteSelectionRings.tsx +40 -6
  100. package/corpus/core/src/client/index.ts +48 -0
  101. package/corpus/core/src/client/org/OrgSwitcher.tsx +0 -4
  102. package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +49 -32
  103. package/corpus/core/src/client/rich-markdown-editor/index.ts +6 -0
  104. package/corpus/core/src/client/rich-markdown-editor/surgical-apply.ts +192 -0
  105. package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +59 -8
  106. package/corpus/core/src/client/session-replay.ts +181 -15
  107. package/corpus/core/src/client/sse-event-processor.ts +90 -1
  108. package/corpus/core/src/client/use-action.ts +123 -25
  109. package/corpus/core/src/client/use-agent-engine-configured.ts +7 -1
  110. package/corpus/core/src/client/use-chat-threads.ts +18 -7
  111. package/corpus/core/src/client/use-db-sync.ts +104 -19
  112. package/corpus/core/src/client/visual-style-controls.tsx +475 -0
  113. package/corpus/core/src/collab/agent-presence.ts +191 -62
  114. package/corpus/core/src/collab/awareness.ts +83 -6
  115. package/corpus/core/src/collab/client.ts +89 -146
  116. package/corpus/core/src/collab/index.ts +34 -0
  117. package/corpus/core/src/collab/recent-edits.ts +171 -0
  118. package/corpus/core/src/collab/undo.ts +432 -0
  119. package/corpus/core/src/collab/ydoc-manager.ts +68 -0
  120. package/corpus/core/src/connections/catalog.ts +2 -3
  121. package/corpus/core/src/db/create-get-db.ts +86 -1
  122. package/corpus/core/src/db/ensure-additive-columns.ts +430 -0
  123. package/corpus/core/src/db/index.ts +6 -0
  124. package/corpus/core/src/db/migrations.ts +236 -35
  125. package/corpus/core/src/jobs/scheduler.ts +17 -14
  126. package/corpus/core/src/observability/traces.ts +182 -1
  127. package/corpus/core/src/org/context.ts +79 -2
  128. package/corpus/core/src/server/agent-chat-plugin.ts +10 -6
  129. package/corpus/core/src/server/auth-marketing.ts +0 -11
  130. package/corpus/core/src/server/auth.ts +11 -4
  131. package/corpus/core/src/server/collab-plugin.ts +56 -13
  132. package/corpus/core/src/server/design-token-utils.ts +1 -1
  133. package/corpus/core/src/server/fusion-app.ts +447 -0
  134. package/corpus/core/src/server/index.ts +13 -0
  135. package/corpus/core/src/server/onboarding-html.ts +3 -4
  136. package/corpus/core/src/server/poll-events.ts +14 -2
  137. package/corpus/core/src/server/poll.ts +219 -12
  138. package/corpus/core/src/server/schema-prompt.ts +28 -9
  139. package/corpus/core/src/settings/store.ts +33 -2
  140. package/corpus/core/src/sharing/actions/set-resource-visibility.ts +2 -0
  141. package/corpus/core/src/sharing/actions/share-resource.ts +3 -0
  142. package/corpus/core/src/sharing/actions/unshare-resource.ts +2 -0
  143. package/corpus/core/src/styles/agent-native.css +0 -5
  144. package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  145. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  146. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  147. package/corpus/core/src/templates/default/package.json +3 -3
  148. package/corpus/core/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  149. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  150. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  151. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  152. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  153. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  154. package/corpus/core/src/tracking/providers.ts +22 -1
  155. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +15 -0
  156. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +20 -5
  157. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +8 -0
  158. package/corpus/templates/analytics/AGENTS.md +33 -6
  159. package/corpus/templates/analytics/actions/navigate.ts +14 -4
  160. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  161. package/corpus/templates/analytics/actions/view-screen.ts +57 -0
  162. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +23 -1
  163. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  164. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -0
  165. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -0
  166. package/corpus/templates/analytics/app/i18n/zh-TW.ts +15 -1
  167. package/corpus/templates/analytics/app/i18n-data.ts +151 -10
  168. package/corpus/templates/analytics/app/pages/Agents.tsx +118 -0
  169. package/corpus/templates/analytics/app/pages/DataSources.tsx +11 -1
  170. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +76 -40
  171. package/corpus/templates/analytics/app/pages/sessions/session-replay-devtools.ts +5 -0
  172. package/corpus/templates/analytics/app/routes/agents.tsx +10 -0
  173. package/corpus/templates/analytics/changelog/2026-07-03-agent-admin-tools-page.md +6 -0
  174. package/corpus/templates/analytics/changelog/2026-07-03-agent-llm-observability-dashboard.md +6 -0
  175. package/corpus/templates/analytics/changelog/2026-07-03-session-recordings-now-include-response-bodies-for-5xx-error.md +6 -0
  176. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +34 -0
  177. package/corpus/templates/analytics/docs/schemas/tracked-events.md +6 -0
  178. package/corpus/templates/analytics/package.json +3 -3
  179. package/corpus/templates/analytics/seeds/dashboards/agent-observability-llm.json +173 -0
  180. package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +23 -5
  181. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +58 -13
  182. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +23 -0
  183. package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +5 -0
  184. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +120 -8
  185. package/corpus/templates/analytics/server/lib/session-replay.ts +3 -2
  186. package/corpus/templates/analytics/server/plugins/db.ts +93 -2
  187. package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +45 -1
  188. package/corpus/templates/analytics/shared/session-replay-diagnostics.ts +10 -0
  189. package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +82 -19
  190. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +15 -0
  191. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +8 -0
  192. package/corpus/templates/assets/package.json +3 -3
  193. package/corpus/templates/assets/server/plugins/db.ts +63 -2
  194. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +15 -0
  195. package/corpus/templates/brain/package.json +3 -3
  196. package/corpus/templates/brain/server/plugins/db.ts +75 -2
  197. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +15 -0
  198. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +8 -0
  199. package/corpus/templates/calendar/package.json +3 -3
  200. package/corpus/templates/calendar/server/plugins/db.ts +64 -2
  201. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +15 -0
  202. package/corpus/templates/chat/package.json +3 -3
  203. package/corpus/templates/clips/actions/finalize-recording.ts +50 -40
  204. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +8 -6
  205. package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -3
  206. package/corpus/templates/clips/changelog/2026-07-03-mobile-recording-pages-keep-videos-in-a-16-9-player-with-act.md +6 -0
  207. package/corpus/templates/clips/package.json +3 -3
  208. package/corpus/templates/clips/server/lib/recording-upload-state.ts +56 -0
  209. package/corpus/templates/clips/server/plugins/db.ts +68 -1
  210. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +27 -3
  211. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +15 -0
  212. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +8 -0
  213. package/corpus/templates/content/actions/edit-document.ts +48 -1
  214. package/corpus/templates/content/actions/list-documents.ts +101 -94
  215. package/corpus/templates/content/actions/search-documents.ts +19 -3
  216. package/corpus/templates/content/actions/update-document.ts +54 -1
  217. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -7
  218. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +97 -2
  219. package/corpus/templates/content/changelog/2026-07-03-agent-document-edits-now-appear-as-a-live-collaborator-prese.md +6 -0
  220. package/corpus/templates/content/changelog/2026-07-03-document-search-and-list-views-load-faster-on-large-workspac.md +6 -0
  221. package/corpus/templates/content/package.json +3 -3
  222. package/corpus/templates/content/server/plugins/db.ts +57 -1
  223. package/corpus/templates/design/.agents/skills/full-app-build/SKILL.md +140 -0
  224. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +20 -0
  225. package/corpus/templates/design/AGENTS.md +50 -12
  226. package/corpus/templates/design/actions/add-fusion-screens.ts +91 -0
  227. package/corpus/templates/design/actions/apply-a11y-fix.ts +5 -1
  228. package/corpus/templates/design/actions/apply-component-prop-edit.ts +10 -2
  229. package/corpus/templates/design/actions/apply-fusion-edits.ts +161 -0
  230. package/corpus/templates/design/actions/apply-visual-edit.ts +34 -1
  231. package/corpus/templates/design/actions/create-component.ts +5 -1
  232. package/corpus/templates/design/actions/create-fusion-app.ts +202 -0
  233. package/corpus/templates/design/actions/deploy-fusion-app.ts +123 -0
  234. package/corpus/templates/design/actions/edit-design.ts +13 -16
  235. package/corpus/templates/design/actions/get-fusion-deploy-status.ts +86 -0
  236. package/corpus/templates/design/actions/list-fusion-edits.ts +96 -0
  237. package/corpus/templates/design/actions/list-local-files.ts +133 -0
  238. package/corpus/templates/design/actions/push-fusion-app.ts +62 -0
  239. package/corpus/templates/design/actions/queue-fusion-edit.ts +112 -0
  240. package/corpus/templates/design/actions/read-local-file.ts +139 -0
  241. package/corpus/templates/design/actions/send-fusion-message.ts +69 -0
  242. package/corpus/templates/design/actions/sync-fusion-app.ts +196 -0
  243. package/corpus/templates/design/actions/write-local-file.ts +115 -14
  244. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +12 -0
  245. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +379 -0
  246. package/corpus/templates/design/app/components/design/EditPanel.tsx +149 -73
  247. package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +328 -0
  248. package/corpus/templates/design/app/components/design/LayersPanel.tsx +148 -30
  249. package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +1 -1
  250. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +567 -6
  251. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -98
  252. package/corpus/templates/design/app/components/design/code-workbench/ActivityBar.tsx +85 -0
  253. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +466 -0
  254. package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +53 -0
  255. package/corpus/templates/design/app/components/design/code-workbench/commands.ts +339 -0
  256. package/corpus/templates/design/app/components/design/code-workbench/editor/Breadcrumbs.tsx +42 -0
  257. package/corpus/templates/design/app/components/design/code-workbench/editor/BufferSync.tsx +128 -0
  258. package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +363 -0
  259. package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +268 -0
  260. package/corpus/templates/design/app/components/design/code-workbench/editor/StatusBar.tsx +208 -0
  261. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +61 -0
  262. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme-palette.ts +191 -0
  263. package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme.ts +29 -0
  264. package/corpus/templates/design/app/components/design/code-workbench/editor/status-bar-lang.ts +21 -0
  265. package/corpus/templates/design/app/components/design/code-workbench/editor/tab-drag.ts +27 -0
  266. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +155 -0
  267. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +551 -0
  268. package/corpus/templates/design/app/components/design/code-workbench/explorer/file-icons.tsx +115 -0
  269. package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +65 -0
  270. package/corpus/templates/design/app/components/design/code-workbench/format/prettier-format.ts +182 -0
  271. package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +133 -0
  272. package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +563 -0
  273. package/corpus/templates/design/app/components/design/code-workbench/quickinput/fuzzy.ts +170 -0
  274. package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +508 -0
  275. package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +280 -0
  276. package/corpus/templates/design/app/components/design/code-workbench/store.tsx +734 -0
  277. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +39 -0
  278. package/corpus/templates/design/app/components/design/code-workbench/workspace/inline-provider.ts +196 -0
  279. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +177 -0
  280. package/corpus/templates/design/app/components/design/code-workbench/workspace/tree.ts +110 -0
  281. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +103 -0
  282. package/corpus/templates/design/app/components/design/code-workbench-theme.ts +68 -0
  283. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +127 -10
  284. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +52 -29
  285. package/corpus/templates/design/app/components/design/inspector/index.ts +9 -0
  286. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +56 -0
  287. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +80 -1
  288. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +6 -16
  289. package/corpus/templates/design/app/i18n/zh-TW.ts +2 -1
  290. package/corpus/templates/design/app/i18n-data.ts +31 -18
  291. package/corpus/templates/design/app/pages/DesignEditor.tsx +1474 -175
  292. package/corpus/templates/design/app/pages/Index.tsx +90 -17
  293. package/corpus/templates/design/changelog/2026-07-03-the-ai-now-edits-like-a-collaborator-on-canvas-its-cursor-gl.md +6 -0
  294. package/corpus/templates/design/changelog/2026-07-03-the-code-panel-is-now-a-full-vs-code-style-editor-with-a-fil.md +6 -0
  295. package/corpus/templates/design/package.json +4 -3
  296. package/corpus/templates/design/server/db/schema.ts +31 -0
  297. package/corpus/templates/design/server/lib/fusion-screens.ts +246 -0
  298. package/corpus/templates/design/server/plugins/db.ts +89 -2
  299. package/corpus/templates/design/shared/collab-selection.ts +52 -0
  300. package/corpus/templates/design/shared/full-app.ts +126 -0
  301. package/corpus/templates/design/shared/pen-path.ts +296 -0
  302. package/corpus/templates/dispatch/package.json +3 -3
  303. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +15 -0
  304. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +8 -0
  305. package/corpus/templates/forms/package.json +3 -3
  306. package/corpus/templates/forms/server/plugins/db.ts +62 -2
  307. package/corpus/templates/macros/package.json +3 -3
  308. package/corpus/templates/macros/server/plugins/db.ts +63 -2
  309. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +15 -0
  310. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +8 -0
  311. package/corpus/templates/mail/package.json +3 -3
  312. package/corpus/templates/mail/server/lib/contact-frequency.ts +42 -15
  313. package/corpus/templates/mail/server/plugins/db.ts +63 -2
  314. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +15 -0
  315. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +9 -3
  316. package/corpus/templates/plan/.agents/skills/visualize-repo/SKILL.md +92 -0
  317. package/corpus/templates/plan/actions/export-visual-plan.ts +5 -0
  318. package/corpus/templates/plan/actions/get-local-plan-folder.ts +4 -22
  319. package/corpus/templates/plan/actions/get-plan-version.ts +6 -16
  320. package/corpus/templates/plan/actions/list-plan-versions.ts +48 -20
  321. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +41 -1
  322. package/corpus/templates/plan/actions/promote-local-plan-folder.ts +4 -22
  323. package/corpus/templates/plan/actions/update-local-plan-comments.ts +4 -2
  324. package/corpus/templates/plan/actions/update-local-plan-folder.ts +4 -22
  325. package/corpus/templates/plan/actions/update-visual-plan.ts +60 -1
  326. package/corpus/templates/plan/agent-native.app-skill.json +10 -0
  327. package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +138 -39
  328. package/corpus/templates/plan/app/components/editor/usePlanUndoStack.ts +165 -23
  329. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +80 -4
  330. package/corpus/templates/plan/app/global.css +11 -9
  331. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +10 -1
  332. package/corpus/templates/plan/app/hooks/use-plan-presence.ts +66 -0
  333. package/corpus/templates/plan/app/pages/PlansPage.tsx +215 -63
  334. package/corpus/templates/plan/changelog/2026-07-03-local-visual-plans-and-recaps-can-save-comments-without-sign.md +6 -0
  335. package/corpus/templates/plan/changelog/2026-07-03-plan-tabs-render-nested-text-instead-of-raw-json.md +6 -0
  336. package/corpus/templates/plan/changelog/2026-07-03-plans-are-now-fully-real-time-collaborative-multiple-people-.md +6 -0
  337. package/corpus/templates/plan/changelog/2026-07-03-plans-open-and-refresh-faster-especially-long-lived-plans-wi.md +6 -0
  338. package/corpus/templates/plan/changelog/2026-07-03-undo-now-survives-agent-edits-cmd-z-keeps-working-on-your-ow.md +6 -0
  339. package/corpus/templates/plan/package.json +5 -3
  340. package/corpus/templates/plan/server/db/schema.ts +12 -0
  341. package/corpus/templates/plan/server/lib/local-plan-kind.ts +25 -0
  342. package/corpus/templates/plan/server/lib/plan-versions.ts +83 -1
  343. package/corpus/templates/plan/server/lib/public-action-paths.ts +0 -2
  344. package/corpus/templates/plan/server/plans.ts +26 -3
  345. package/corpus/templates/plan/server/plugins/db.ts +105 -2
  346. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +8 -4
  347. package/corpus/templates/slides/AGENTS.md +4 -0
  348. package/corpus/templates/slides/actions/_agent-presence.ts +48 -0
  349. package/corpus/templates/slides/actions/add-slide.ts +16 -18
  350. package/corpus/templates/slides/actions/patch-deck.ts +4 -2
  351. package/corpus/templates/slides/actions/update-slide.ts +114 -77
  352. package/corpus/templates/slides/actions/view-screen.ts +39 -0
  353. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +47 -3
  354. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +32 -35
  355. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +625 -199
  356. package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +342 -0
  357. package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +46 -96
  358. package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +8 -1
  359. package/corpus/templates/slides/app/context/DeckContext.tsx +589 -176
  360. package/corpus/templates/slides/app/hooks/use-deck-presence.ts +84 -42
  361. package/corpus/templates/slides/app/i18n/ar-SA.ts +46 -0
  362. package/corpus/templates/slides/app/i18n/de-DE.ts +46 -0
  363. package/corpus/templates/slides/app/i18n/en-US.ts +46 -0
  364. package/corpus/templates/slides/app/i18n/es-ES.ts +46 -0
  365. package/corpus/templates/slides/app/i18n/fr-FR.ts +46 -0
  366. package/corpus/templates/slides/app/i18n/hi-IN.ts +46 -0
  367. package/corpus/templates/slides/app/i18n/ja-JP.ts +46 -0
  368. package/corpus/templates/slides/app/i18n/ko-KR.ts +46 -0
  369. package/corpus/templates/slides/app/i18n/pt-BR.ts +46 -0
  370. package/corpus/templates/slides/app/i18n/zh-CN.ts +46 -0
  371. package/corpus/templates/slides/app/i18n/zh-TW.ts +46 -0
  372. package/corpus/templates/slides/app/pages/DeckEditor.tsx +25 -13
  373. package/corpus/templates/slides/changelog/2026-07-03-figma-style-slide-editing.md +6 -0
  374. package/corpus/templates/slides/changelog/2026-07-03-see-the-ai-working-with-you-when-the-agent-edits-a-slide-it-.md +6 -0
  375. package/corpus/templates/slides/changelog/2026-07-03-undo-redo-is-now-precise-and-safe-with-collaborators-it-only.md +6 -0
  376. package/corpus/templates/slides/package.json +3 -3
  377. package/corpus/templates/slides/server/handlers/decks.ts +31 -3
  378. package/corpus/templates/slides/server/plugins/db.ts +65 -2
  379. package/corpus/templates/videos/netlify.toml +1 -12
  380. package/dist/agent/run-store.js +1 -1
  381. package/dist/agent/run-store.js.map +1 -1
  382. package/dist/chat-threads/store.d.ts +9 -1
  383. package/dist/chat-threads/store.d.ts.map +1 -1
  384. package/dist/chat-threads/store.js +63 -11
  385. package/dist/chat-threads/store.js.map +1 -1
  386. package/dist/checkpoints/store.d.ts.map +1 -1
  387. package/dist/checkpoints/store.js +10 -2
  388. package/dist/checkpoints/store.js.map +1 -1
  389. package/dist/cli/create.d.ts.map +1 -1
  390. package/dist/cli/create.js +3 -5
  391. package/dist/cli/create.js.map +1 -1
  392. package/dist/cli/design-connect.d.ts +49 -1
  393. package/dist/cli/design-connect.d.ts.map +1 -1
  394. package/dist/cli/design-connect.js +414 -9
  395. package/dist/cli/design-connect.js.map +1 -1
  396. package/dist/cli/index.js +12 -0
  397. package/dist/cli/index.js.map +1 -1
  398. package/dist/cli/plan-local.d.ts +24 -0
  399. package/dist/cli/plan-local.d.ts.map +1 -1
  400. package/dist/cli/plan-local.js +188 -20
  401. package/dist/cli/plan-local.js.map +1 -1
  402. package/dist/cli/skills.d.ts +3 -1
  403. package/dist/cli/skills.d.ts.map +1 -1
  404. package/dist/cli/skills.js +173 -21
  405. package/dist/cli/skills.js.map +1 -1
  406. package/dist/cli/templates-meta.d.ts.map +1 -1
  407. package/dist/cli/templates-meta.js +0 -14
  408. package/dist/cli/templates-meta.js.map +1 -1
  409. package/dist/cli/visualize-repo.d.ts +49 -0
  410. package/dist/cli/visualize-repo.d.ts.map +1 -0
  411. package/dist/cli/visualize-repo.js +561 -0
  412. package/dist/cli/visualize-repo.js.map +1 -0
  413. package/dist/client/AssistantChat.d.ts.map +1 -1
  414. package/dist/client/AssistantChat.js +120 -15
  415. package/dist/client/AssistantChat.js.map +1 -1
  416. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  417. package/dist/client/agent-chat-adapter.js +6 -5
  418. package/dist/client/agent-chat-adapter.js.map +1 -1
  419. package/dist/client/app-providers.d.ts +2 -2
  420. package/dist/client/app-providers.js.map +1 -1
  421. package/dist/client/collab/index.d.ts +4 -1
  422. package/dist/client/collab/index.d.ts.map +1 -1
  423. package/dist/client/collab/index.js +3 -0
  424. package/dist/client/collab/index.js.map +1 -1
  425. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  426. package/dist/client/components/LiveCursorOverlay.js +11 -3
  427. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  428. package/dist/client/components/PresenceBar.d.ts.map +1 -1
  429. package/dist/client/components/PresenceBar.js +6 -1
  430. package/dist/client/components/PresenceBar.js.map +1 -1
  431. package/dist/client/components/RecentEditHighlights.d.ts +43 -0
  432. package/dist/client/components/RecentEditHighlights.d.ts.map +1 -0
  433. package/dist/client/components/RecentEditHighlights.js +146 -0
  434. package/dist/client/components/RecentEditHighlights.js.map +1 -0
  435. package/dist/client/components/RemoteSelectionRings.d.ts +9 -0
  436. package/dist/client/components/RemoteSelectionRings.d.ts.map +1 -1
  437. package/dist/client/components/RemoteSelectionRings.js +22 -8
  438. package/dist/client/components/RemoteSelectionRings.js.map +1 -1
  439. package/dist/client/index.d.ts +6 -1
  440. package/dist/client/index.d.ts.map +1 -1
  441. package/dist/client/index.js +7 -0
  442. package/dist/client/index.js.map +1 -1
  443. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  444. package/dist/client/org/OrgSwitcher.js +1 -3
  445. package/dist/client/org/OrgSwitcher.js.map +1 -1
  446. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +8 -1
  447. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
  448. package/dist/client/rich-markdown-editor/SharedRichEditor.js +8 -2
  449. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
  450. package/dist/client/rich-markdown-editor/index.d.ts +1 -0
  451. package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
  452. package/dist/client/rich-markdown-editor/index.js +1 -0
  453. package/dist/client/rich-markdown-editor/index.js.map +1 -1
  454. package/dist/client/rich-markdown-editor/surgical-apply.d.ts +66 -0
  455. package/dist/client/rich-markdown-editor/surgical-apply.d.ts.map +1 -0
  456. package/dist/client/rich-markdown-editor/surgical-apply.js +147 -0
  457. package/dist/client/rich-markdown-editor/surgical-apply.js.map +1 -0
  458. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +18 -2
  459. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  460. package/dist/client/rich-markdown-editor/useCollabReconcile.js +39 -8
  461. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  462. package/dist/client/session-replay.d.ts +10 -1
  463. package/dist/client/session-replay.d.ts.map +1 -1
  464. package/dist/client/session-replay.js +134 -7
  465. package/dist/client/session-replay.js.map +1 -1
  466. package/dist/client/sse-event-processor.d.ts.map +1 -1
  467. package/dist/client/sse-event-processor.js +81 -1
  468. package/dist/client/sse-event-processor.js.map +1 -1
  469. package/dist/client/use-action.d.ts +24 -0
  470. package/dist/client/use-action.d.ts.map +1 -1
  471. package/dist/client/use-action.js +109 -27
  472. package/dist/client/use-action.js.map +1 -1
  473. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  474. package/dist/client/use-agent-engine-configured.js +7 -1
  475. package/dist/client/use-agent-engine-configured.js.map +1 -1
  476. package/dist/client/use-chat-threads.d.ts.map +1 -1
  477. package/dist/client/use-chat-threads.js +11 -3
  478. package/dist/client/use-chat-threads.js.map +1 -1
  479. package/dist/client/use-db-sync.d.ts +36 -0
  480. package/dist/client/use-db-sync.d.ts.map +1 -1
  481. package/dist/client/use-db-sync.js +68 -12
  482. package/dist/client/use-db-sync.js.map +1 -1
  483. package/dist/client/visual-style-controls.d.ts +79 -0
  484. package/dist/client/visual-style-controls.d.ts.map +1 -0
  485. package/dist/client/visual-style-controls.js +150 -0
  486. package/dist/client/visual-style-controls.js.map +1 -0
  487. package/dist/collab/agent-presence.d.ts +51 -5
  488. package/dist/collab/agent-presence.d.ts.map +1 -1
  489. package/dist/collab/agent-presence.js +144 -58
  490. package/dist/collab/agent-presence.js.map +1 -1
  491. package/dist/collab/awareness-store.d.ts +32 -0
  492. package/dist/collab/awareness-store.d.ts.map +1 -0
  493. package/dist/collab/awareness-store.js +0 -0
  494. package/dist/collab/awareness-store.js.map +1 -0
  495. package/dist/collab/awareness.d.ts +12 -1
  496. package/dist/collab/awareness.d.ts.map +1 -1
  497. package/dist/collab/awareness.js +53 -5
  498. package/dist/collab/awareness.js.map +1 -1
  499. package/dist/collab/client.d.ts +2 -0
  500. package/dist/collab/client.d.ts.map +1 -1
  501. package/dist/collab/client.js +79 -119
  502. package/dist/collab/client.js.map +1 -1
  503. package/dist/collab/index.d.ts +3 -1
  504. package/dist/collab/index.d.ts.map +1 -1
  505. package/dist/collab/index.js +5 -1
  506. package/dist/collab/index.js.map +1 -1
  507. package/dist/collab/recent-edits.d.ts +87 -0
  508. package/dist/collab/recent-edits.d.ts.map +1 -0
  509. package/dist/collab/recent-edits.js +116 -0
  510. package/dist/collab/recent-edits.js.map +1 -0
  511. package/dist/collab/routes.d.ts +2 -2
  512. package/dist/collab/struct-routes.d.ts +1 -1
  513. package/dist/collab/undo.d.ts +121 -0
  514. package/dist/collab/undo.d.ts.map +1 -0
  515. package/dist/collab/undo.js +244 -0
  516. package/dist/collab/undo.js.map +1 -0
  517. package/dist/collab/ydoc-manager.d.ts +10 -0
  518. package/dist/collab/ydoc-manager.d.ts.map +1 -1
  519. package/dist/collab/ydoc-manager.js +57 -0
  520. package/dist/collab/ydoc-manager.js.map +1 -1
  521. package/dist/connections/catalog.d.ts +2 -2
  522. package/dist/connections/catalog.d.ts.map +1 -1
  523. package/dist/connections/catalog.js +1 -1
  524. package/dist/connections/catalog.js.map +1 -1
  525. package/dist/db/create-get-db.d.ts +22 -0
  526. package/dist/db/create-get-db.d.ts.map +1 -1
  527. package/dist/db/create-get-db.js +73 -1
  528. package/dist/db/create-get-db.js.map +1 -1
  529. package/dist/db/ensure-additive-columns.d.ts +93 -0
  530. package/dist/db/ensure-additive-columns.d.ts.map +1 -0
  531. package/dist/db/ensure-additive-columns.js +355 -0
  532. package/dist/db/ensure-additive-columns.js.map +1 -0
  533. package/dist/db/index.d.ts +1 -0
  534. package/dist/db/index.d.ts.map +1 -1
  535. package/dist/db/index.js +1 -0
  536. package/dist/db/index.js.map +1 -1
  537. package/dist/db/migrations.d.ts +70 -0
  538. package/dist/db/migrations.d.ts.map +1 -1
  539. package/dist/db/migrations.js +196 -33
  540. package/dist/db/migrations.js.map +1 -1
  541. package/dist/jobs/scheduler.js +17 -10
  542. package/dist/jobs/scheduler.js.map +1 -1
  543. package/dist/notifications/routes.d.ts +3 -3
  544. package/dist/observability/routes.d.ts +2 -2
  545. package/dist/observability/traces.d.ts.map +1 -1
  546. package/dist/observability/traces.js +155 -1
  547. package/dist/observability/traces.js.map +1 -1
  548. package/dist/org/context.d.ts +7 -0
  549. package/dist/org/context.d.ts.map +1 -1
  550. package/dist/org/context.js +54 -2
  551. package/dist/org/context.js.map +1 -1
  552. package/dist/resources/handlers.d.ts +1 -1
  553. package/dist/secrets/routes.d.ts +9 -9
  554. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  555. package/dist/server/agent-chat-plugin.js +10 -6
  556. package/dist/server/agent-chat-plugin.js.map +1 -1
  557. package/dist/server/auth-marketing.d.ts.map +1 -1
  558. package/dist/server/auth-marketing.js +0 -10
  559. package/dist/server/auth-marketing.js.map +1 -1
  560. package/dist/server/auth.d.ts.map +1 -1
  561. package/dist/server/auth.js +6 -4
  562. package/dist/server/auth.js.map +1 -1
  563. package/dist/server/collab-plugin.d.ts.map +1 -1
  564. package/dist/server/collab-plugin.js +45 -13
  565. package/dist/server/collab-plugin.js.map +1 -1
  566. package/dist/server/design-token-utils.d.ts +1 -1
  567. package/dist/server/design-token-utils.js +1 -1
  568. package/dist/server/design-token-utils.js.map +1 -1
  569. package/dist/server/fusion-app.d.ts +107 -0
  570. package/dist/server/fusion-app.d.ts.map +1 -0
  571. package/dist/server/fusion-app.js +371 -0
  572. package/dist/server/fusion-app.js.map +1 -0
  573. package/dist/server/index.d.ts +1 -0
  574. package/dist/server/index.d.ts.map +1 -1
  575. package/dist/server/index.js +1 -0
  576. package/dist/server/index.js.map +1 -1
  577. package/dist/server/onboarding-html.d.ts.map +1 -1
  578. package/dist/server/onboarding-html.js +3 -4
  579. package/dist/server/onboarding-html.js.map +1 -1
  580. package/dist/server/poll-events.d.ts +2 -0
  581. package/dist/server/poll-events.d.ts.map +1 -1
  582. package/dist/server/poll-events.js +7 -2
  583. package/dist/server/poll-events.js.map +1 -1
  584. package/dist/server/poll.d.ts +47 -3
  585. package/dist/server/poll.d.ts.map +1 -1
  586. package/dist/server/poll.js +176 -10
  587. package/dist/server/poll.js.map +1 -1
  588. package/dist/server/schema-prompt.d.ts.map +1 -1
  589. package/dist/server/schema-prompt.js +24 -7
  590. package/dist/server/schema-prompt.js.map +1 -1
  591. package/dist/server/transcribe-voice.d.ts +1 -1
  592. package/dist/settings/store.d.ts.map +1 -1
  593. package/dist/settings/store.js +32 -3
  594. package/dist/settings/store.js.map +1 -1
  595. package/dist/sharing/actions/set-resource-visibility.js +2 -0
  596. package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
  597. package/dist/sharing/actions/share-resource.d.ts.map +1 -1
  598. package/dist/sharing/actions/share-resource.js +3 -0
  599. package/dist/sharing/actions/share-resource.js.map +1 -1
  600. package/dist/sharing/actions/unshare-resource.js +2 -0
  601. package/dist/sharing/actions/unshare-resource.js.map +1 -1
  602. package/dist/styles/agent-native.css +0 -5
  603. package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  604. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  605. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  606. package/dist/templates/default/package.json +3 -3
  607. package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  608. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  609. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  610. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  611. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  612. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  613. package/dist/tracking/providers.d.ts.map +1 -1
  614. package/dist/tracking/providers.js +17 -1
  615. package/dist/tracking/providers.js.map +1 -1
  616. package/docs/content/cloneable-saas.mdx +0 -1
  617. package/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
  618. package/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
  619. package/docs/content/locales/ar-SA/sharing.mdx +1 -2
  620. package/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
  621. package/docs/content/locales/ar-SA/template-plan.mdx +23 -7
  622. package/docs/content/locales/ar-SA/tracking.mdx +1 -1
  623. package/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
  624. package/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
  625. package/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
  626. package/docs/content/locales/de-DE/sharing.mdx +1 -2
  627. package/docs/content/locales/de-DE/skills-guide.mdx +2 -3
  628. package/docs/content/locales/de-DE/template-plan.mdx +23 -7
  629. package/docs/content/locales/de-DE/tracking.mdx +1 -1
  630. package/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
  631. package/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
  632. package/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
  633. package/docs/content/locales/es-ES/sharing.mdx +1 -2
  634. package/docs/content/locales/es-ES/skills-guide.mdx +2 -3
  635. package/docs/content/locales/es-ES/template-plan.mdx +23 -7
  636. package/docs/content/locales/es-ES/tracking.mdx +1 -1
  637. package/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
  638. package/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
  639. package/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
  640. package/docs/content/locales/fr-FR/sharing.mdx +1 -2
  641. package/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
  642. package/docs/content/locales/fr-FR/template-plan.mdx +23 -7
  643. package/docs/content/locales/fr-FR/tracking.mdx +1 -1
  644. package/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
  645. package/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
  646. package/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
  647. package/docs/content/locales/hi-IN/sharing.mdx +1 -2
  648. package/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
  649. package/docs/content/locales/hi-IN/template-plan.mdx +23 -7
  650. package/docs/content/locales/hi-IN/tracking.mdx +1 -1
  651. package/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
  652. package/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
  653. package/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
  654. package/docs/content/locales/ja-JP/sharing.mdx +1 -2
  655. package/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
  656. package/docs/content/locales/ja-JP/template-plan.mdx +23 -7
  657. package/docs/content/locales/ja-JP/tracking.mdx +1 -1
  658. package/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
  659. package/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
  660. package/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
  661. package/docs/content/locales/ko-KR/sharing.mdx +1 -2
  662. package/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
  663. package/docs/content/locales/ko-KR/template-plan.mdx +23 -7
  664. package/docs/content/locales/ko-KR/tracking.mdx +1 -1
  665. package/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
  666. package/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
  667. package/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
  668. package/docs/content/locales/pt-BR/sharing.mdx +1 -2
  669. package/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
  670. package/docs/content/locales/pt-BR/template-plan.mdx +23 -7
  671. package/docs/content/locales/pt-BR/tracking.mdx +1 -1
  672. package/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
  673. package/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
  674. package/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
  675. package/docs/content/locales/zh-CN/sharing.mdx +1 -2
  676. package/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
  677. package/docs/content/locales/zh-CN/template-plan.mdx +23 -7
  678. package/docs/content/locales/zh-CN/tracking.mdx +1 -1
  679. package/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
  680. package/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
  681. package/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
  682. package/docs/content/locales/zh-TW/sharing.mdx +1 -2
  683. package/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
  684. package/docs/content/locales/zh-TW/template-plan.mdx +23 -7
  685. package/docs/content/locales/zh-TW/tracking.mdx +1 -1
  686. package/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
  687. package/docs/content/plan-plugin.mdx +12 -11
  688. package/docs/content/sharing.mdx +1 -2
  689. package/docs/content/skills-guide.mdx +4 -3
  690. package/docs/content/template-plan.mdx +37 -6
  691. package/docs/content/tracking.mdx +1 -1
  692. package/docs/content/workspace-connections.mdx +1 -1
  693. package/package.json +6 -6
  694. package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
  695. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
  696. package/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
  697. package/src/templates/default/package.json +3 -3
  698. package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
  699. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
  700. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
  701. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
  702. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
  703. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
  704. package/corpus/core/docs/content/locales/ar-SA/template-videos.mdx +0 -336
  705. package/corpus/core/docs/content/locales/de-DE/template-videos.mdx +0 -336
  706. package/corpus/core/docs/content/locales/es-ES/template-videos.mdx +0 -336
  707. package/corpus/core/docs/content/locales/fr-FR/template-videos.mdx +0 -336
  708. package/corpus/core/docs/content/locales/hi-IN/template-videos.mdx +0 -336
  709. package/corpus/core/docs/content/locales/ja-JP/template-videos.mdx +0 -336
  710. package/corpus/core/docs/content/locales/ko-KR/template-videos.mdx +0 -336
  711. package/corpus/core/docs/content/locales/pt-BR/template-videos.mdx +0 -336
  712. package/corpus/core/docs/content/locales/zh-CN/template-videos.mdx +0 -334
  713. package/corpus/core/docs/content/locales/zh-TW/template-videos.mdx +0 -334
  714. package/corpus/core/docs/content/template-videos.mdx +0 -332
  715. package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +0 -697
  716. package/corpus/templates/slides/app/components/editor/CodeEditor.tsx +0 -49
  717. package/corpus/templates/videos/.agents/skills/actions/SKILL.md +0 -432
  718. package/corpus/templates/videos/.agents/skills/animation-tracks/SKILL.md +0 -99
  719. package/corpus/templates/videos/.agents/skills/capture-learnings/SKILL.md +0 -76
  720. package/corpus/templates/videos/.agents/skills/composition-management/SKILL.md +0 -106
  721. package/corpus/templates/videos/.agents/skills/create-skill/SKILL.md +0 -221
  722. package/corpus/templates/videos/.agents/skills/delegate-to-agent/SKILL.md +0 -263
  723. package/corpus/templates/videos/.agents/skills/frontend-design/SKILL.md +0 -112
  724. package/corpus/templates/videos/.agents/skills/security/SKILL.md +0 -263
  725. package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +0 -88
  726. package/corpus/templates/videos/.agents/skills/shadcn-ui/SKILL.md +0 -95
  727. package/corpus/templates/videos/.builder/ANIMATED_PROPERTIES.md +0 -335
  728. package/corpus/templates/videos/.builder/KEYFRAME_SYNC.md +0 -166
  729. package/corpus/templates/videos/.builder/SEAMLESS_SYNC.md +0 -211
  730. package/corpus/templates/videos/.builder/rules/deploy-app.mdc +0 -22
  731. package/corpus/templates/videos/.builder/rules/organize-ui.mdc +0 -9
  732. package/corpus/templates/videos/.builder/skills/remotion/SKILL.md +0 -29
  733. package/corpus/templates/videos/.builder/skills/remotion/rules/animations.md +0 -27
  734. package/corpus/templates/videos/.builder/skills/remotion/rules/assets.md +0 -43
  735. package/corpus/templates/videos/.builder/skills/remotion/rules/audio.md +0 -58
  736. package/corpus/templates/videos/.builder/skills/remotion/rules/compositions.md +0 -129
  737. package/corpus/templates/videos/.builder/skills/remotion/rules/fonts.md +0 -47
  738. package/corpus/templates/videos/.builder/skills/remotion/rules/images.md +0 -41
  739. package/corpus/templates/videos/.builder/skills/remotion/rules/parameters.md +0 -59
  740. package/corpus/templates/videos/.builder/skills/remotion/rules/sequencing.md +0 -54
  741. package/corpus/templates/videos/.builder/skills/remotion/rules/tailwind.md +0 -11
  742. package/corpus/templates/videos/.builder/skills/remotion/rules/text-animations.md +0 -18
  743. package/corpus/templates/videos/.builder/skills/remotion/rules/timing.md +0 -103
  744. package/corpus/templates/videos/.builder/skills/remotion/rules/transparent-videos.md +0 -35
  745. package/corpus/templates/videos/.builder/skills/remotion/rules/trimming.md +0 -38
  746. package/corpus/templates/videos/.builder/skills/remotion/rules/videos.md +0 -54
  747. package/corpus/templates/videos/.dockerignore +0 -62
  748. package/corpus/templates/videos/.env.example +0 -4
  749. package/corpus/templates/videos/.oxfmtrc.json +0 -8
  750. package/corpus/templates/videos/AGENTS.md +0 -46
  751. package/corpus/templates/videos/CHANGELOG.md +0 -10
  752. package/corpus/templates/videos/DEVELOPING.md +0 -143
  753. package/corpus/templates/videos/README.md +0 -33
  754. package/corpus/templates/videos/actions/analyze-brand-assets.ts +0 -151
  755. package/corpus/templates/videos/actions/apply-design-system.ts +0 -35
  756. package/corpus/templates/videos/actions/create-design-system.ts +0 -84
  757. package/corpus/templates/videos/actions/create-folder.ts +0 -48
  758. package/corpus/templates/videos/actions/db-connect.ts +0 -45
  759. package/corpus/templates/videos/actions/db-health.ts +0 -24
  760. package/corpus/templates/videos/actions/db-status.ts +0 -28
  761. package/corpus/templates/videos/actions/delete-composition.ts +0 -272
  762. package/corpus/templates/videos/actions/delete-folder.ts +0 -27
  763. package/corpus/templates/videos/actions/generate-animated-component.ts +0 -470
  764. package/corpus/templates/videos/actions/get-composition.ts +0 -36
  765. package/corpus/templates/videos/actions/get-design-system.ts +0 -35
  766. package/corpus/templates/videos/actions/import-code.ts +0 -67
  767. package/corpus/templates/videos/actions/import-design-project.ts +0 -42
  768. package/corpus/templates/videos/actions/import-document.ts +0 -125
  769. package/corpus/templates/videos/actions/import-from-url.ts +0 -18
  770. package/corpus/templates/videos/actions/import-github.ts +0 -182
  771. package/corpus/templates/videos/actions/list-compositions.ts +0 -32
  772. package/corpus/templates/videos/actions/list-design-systems.ts +0 -66
  773. package/corpus/templates/videos/actions/list-folders.ts +0 -61
  774. package/corpus/templates/videos/actions/move-composition-to-folder.ts +0 -59
  775. package/corpus/templates/videos/actions/navigate.ts +0 -40
  776. package/corpus/templates/videos/actions/rename-folder.ts +0 -41
  777. package/corpus/templates/videos/actions/run.ts +0 -2
  778. package/corpus/templates/videos/actions/save-composition.ts +0 -114
  779. package/corpus/templates/videos/actions/set-default-design-system.ts +0 -40
  780. package/corpus/templates/videos/actions/update-composition.ts +0 -81
  781. package/corpus/templates/videos/actions/update-design-system.ts +0 -68
  782. package/corpus/templates/videos/actions/validate-compositions.ts +0 -502
  783. package/corpus/templates/videos/actions/view-screen.ts +0 -48
  784. package/corpus/templates/videos/app/components/CameraControls.tsx +0 -442
  785. package/corpus/templates/videos/app/components/CameraToolbar.tsx +0 -437
  786. package/corpus/templates/videos/app/components/CloudUpgrade.tsx +0 -287
  787. package/corpus/templates/videos/app/components/CollabPresenceBar.tsx +0 -81
  788. package/corpus/templates/videos/app/components/CompSettingsEditor.tsx +0 -107
  789. package/corpus/templates/videos/app/components/ComponentLibrarySidebar.tsx +0 -457
  790. package/corpus/templates/videos/app/components/ComponentPropsPanel.tsx +0 -227
  791. package/corpus/templates/videos/app/components/ComponentsSidebar.tsx +0 -70
  792. package/corpus/templates/videos/app/components/CompositionCard.tsx +0 -147
  793. package/corpus/templates/videos/app/components/CurrentElementPanel.tsx +0 -835
  794. package/corpus/templates/videos/app/components/CursorControls.tsx +0 -664
  795. package/corpus/templates/videos/app/components/CursorPositioningOverlay.tsx +0 -238
  796. package/corpus/templates/videos/app/components/LibraryFolderRow.tsx +0 -235
  797. package/corpus/templates/videos/app/components/MotionCurveSelect.tsx +0 -61
  798. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +0 -192
  799. package/corpus/templates/videos/app/components/PropsEditor.tsx +0 -210
  800. package/corpus/templates/videos/app/components/QuestionFlow.tsx +0 -40
  801. package/corpus/templates/videos/app/components/Sidebar.tsx +0 -609
  802. package/corpus/templates/videos/app/components/StudioHeader.tsx +0 -109
  803. package/corpus/templates/videos/app/components/Timeline.tsx +0 -2067
  804. package/corpus/templates/videos/app/components/TrackPropertiesPanel.tsx +0 -922
  805. package/corpus/templates/videos/app/components/TweaksPanel.tsx +0 -277
  806. package/corpus/templates/videos/app/components/VideoPlayer.tsx +0 -487
  807. package/corpus/templates/videos/app/components/design-system/DesignSystemCard.tsx +0 -134
  808. package/corpus/templates/videos/app/components/design-system/DesignSystemPreview.tsx +0 -176
  809. package/corpus/templates/videos/app/components/design-system/DesignSystemSetup.tsx +0 -707
  810. package/corpus/templates/videos/app/components/keyframes/KeyframeActionButtons.tsx +0 -78
  811. package/corpus/templates/videos/app/components/keyframes/KeyframeNavigation.tsx +0 -59
  812. package/corpus/templates/videos/app/components/keyframes/PropertyNumberInput.tsx +0 -56
  813. package/corpus/templates/videos/app/components/layout/Header.tsx +0 -64
  814. package/corpus/templates/videos/app/components/layout/HeaderActions.tsx +0 -84
  815. package/corpus/templates/videos/app/components/layout/Layout.tsx +0 -132
  816. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -180
  817. package/corpus/templates/videos/app/components/ui/accordion.tsx +0 -56
  818. package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +0 -139
  819. package/corpus/templates/videos/app/components/ui/alert.tsx +0 -59
  820. package/corpus/templates/videos/app/components/ui/aspect-ratio.tsx +0 -5
  821. package/corpus/templates/videos/app/components/ui/avatar.tsx +0 -48
  822. package/corpus/templates/videos/app/components/ui/badge.tsx +0 -37
  823. package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +0 -115
  824. package/corpus/templates/videos/app/components/ui/button.tsx +0 -57
  825. package/corpus/templates/videos/app/components/ui/calendar.tsx +0 -68
  826. package/corpus/templates/videos/app/components/ui/card.tsx +0 -86
  827. package/corpus/templates/videos/app/components/ui/carousel.tsx +0 -260
  828. package/corpus/templates/videos/app/components/ui/chart.tsx +0 -375
  829. package/corpus/templates/videos/app/components/ui/checkbox.tsx +0 -28
  830. package/corpus/templates/videos/app/components/ui/collapsible.tsx +0 -9
  831. package/corpus/templates/videos/app/components/ui/command.tsx +0 -154
  832. package/corpus/templates/videos/app/components/ui/context-menu.tsx +0 -202
  833. package/corpus/templates/videos/app/components/ui/dialog.tsx +0 -130
  834. package/corpus/templates/videos/app/components/ui/drawer.tsx +0 -116
  835. package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +0 -212
  836. package/corpus/templates/videos/app/components/ui/form.tsx +0 -177
  837. package/corpus/templates/videos/app/components/ui/hover-card.tsx +0 -27
  838. package/corpus/templates/videos/app/components/ui/input-otp.tsx +0 -69
  839. package/corpus/templates/videos/app/components/ui/input.tsx +0 -22
  840. package/corpus/templates/videos/app/components/ui/label.tsx +0 -24
  841. package/corpus/templates/videos/app/components/ui/menubar.tsx +0 -234
  842. package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +0 -128
  843. package/corpus/templates/videos/app/components/ui/pagination.tsx +0 -121
  844. package/corpus/templates/videos/app/components/ui/popover.tsx +0 -44
  845. package/corpus/templates/videos/app/components/ui/progress.tsx +0 -26
  846. package/corpus/templates/videos/app/components/ui/radio-group.tsx +0 -42
  847. package/corpus/templates/videos/app/components/ui/resizable.tsx +0 -43
  848. package/corpus/templates/videos/app/components/ui/scroll-area.tsx +0 -46
  849. package/corpus/templates/videos/app/components/ui/select.tsx +0 -158
  850. package/corpus/templates/videos/app/components/ui/separator.tsx +0 -29
  851. package/corpus/templates/videos/app/components/ui/sheet.tsx +0 -160
  852. package/corpus/templates/videos/app/components/ui/sidebar.tsx +0 -782
  853. package/corpus/templates/videos/app/components/ui/skeleton.tsx +0 -15
  854. package/corpus/templates/videos/app/components/ui/slider.tsx +0 -26
  855. package/corpus/templates/videos/app/components/ui/sonner.tsx +0 -58
  856. package/corpus/templates/videos/app/components/ui/spinner.tsx +0 -17
  857. package/corpus/templates/videos/app/components/ui/switch.tsx +0 -27
  858. package/corpus/templates/videos/app/components/ui/table.tsx +0 -117
  859. package/corpus/templates/videos/app/components/ui/tabs.tsx +0 -53
  860. package/corpus/templates/videos/app/components/ui/textarea.tsx +0 -23
  861. package/corpus/templates/videos/app/components/ui/toast.tsx +0 -127
  862. package/corpus/templates/videos/app/components/ui/toaster.tsx +0 -33
  863. package/corpus/templates/videos/app/components/ui/toggle-group.tsx +0 -59
  864. package/corpus/templates/videos/app/components/ui/toggle.tsx +0 -43
  865. package/corpus/templates/videos/app/components/ui/tooltip.tsx +0 -30
  866. package/corpus/templates/videos/app/components/ui/use-toast.ts +0 -3
  867. package/corpus/templates/videos/app/config/constants.ts +0 -204
  868. package/corpus/templates/videos/app/contexts/CompositionContext.tsx +0 -437
  869. package/corpus/templates/videos/app/contexts/CurrentElementContext.tsx +0 -247
  870. package/corpus/templates/videos/app/contexts/PlaybackContext.tsx +0 -65
  871. package/corpus/templates/videos/app/contexts/TimelineContext.tsx +0 -433
  872. package/corpus/templates/videos/app/entry.client.tsx +0 -19
  873. package/corpus/templates/videos/app/entry.server.tsx +0 -10
  874. package/corpus/templates/videos/app/global.css +0 -171
  875. package/corpus/templates/videos/app/hooks/use-composition-collab.ts +0 -269
  876. package/corpus/templates/videos/app/hooks/use-composition-design-system.ts +0 -47
  877. package/corpus/templates/videos/app/hooks/use-database-compositions.ts +0 -144
  878. package/corpus/templates/videos/app/hooks/use-db-status.ts +0 -30
  879. package/corpus/templates/videos/app/hooks/use-design-systems.ts +0 -21
  880. package/corpus/templates/videos/app/hooks/use-folders.ts +0 -199
  881. package/corpus/templates/videos/app/hooks/use-mobile.tsx +0 -21
  882. package/corpus/templates/videos/app/hooks/use-navigation-state.ts +0 -52
  883. package/corpus/templates/videos/app/hooks/use-question-flow.ts +0 -14
  884. package/corpus/templates/videos/app/hooks/use-toast.ts +0 -188
  885. package/corpus/templates/videos/app/hooks/useUnsavedChanges.ts +0 -48
  886. package/corpus/templates/videos/app/i18n/ar-SA.ts +0 -446
  887. package/corpus/templates/videos/app/i18n/de-DE.ts +0 -470
  888. package/corpus/templates/videos/app/i18n/en-US.ts +0 -452
  889. package/corpus/templates/videos/app/i18n/es-ES.ts +0 -468
  890. package/corpus/templates/videos/app/i18n/fr-FR.ts +0 -469
  891. package/corpus/templates/videos/app/i18n/hi-IN.ts +0 -446
  892. package/corpus/templates/videos/app/i18n/index.ts +0 -34
  893. package/corpus/templates/videos/app/i18n/ja-JP.ts +0 -460
  894. package/corpus/templates/videos/app/i18n/ko-KR.ts +0 -453
  895. package/corpus/templates/videos/app/i18n/pt-BR.ts +0 -461
  896. package/corpus/templates/videos/app/i18n/zh-CN.ts +0 -437
  897. package/corpus/templates/videos/app/i18n/zh-TW.ts +0 -437
  898. package/corpus/templates/videos/app/lib/database-compositions.ts +0 -67
  899. package/corpus/templates/videos/app/lib/design-systems.ts +0 -234
  900. package/corpus/templates/videos/app/lib/tab-id.ts +0 -1
  901. package/corpus/templates/videos/app/lib/utils.ts +0 -1
  902. package/corpus/templates/videos/app/pages/ComponentLibrary.tsx +0 -134
  903. package/corpus/templates/videos/app/pages/ComponentLibraryView.tsx +0 -362
  904. package/corpus/templates/videos/app/pages/CompositionView.tsx +0 -715
  905. package/corpus/templates/videos/app/pages/DesignSystems.tsx +0 -180
  906. package/corpus/templates/videos/app/pages/Index.tsx +0 -258
  907. package/corpus/templates/videos/app/pages/NewComposition.tsx +0 -95
  908. package/corpus/templates/videos/app/pages/NotFound.tsx +0 -36
  909. package/corpus/templates/videos/app/remotion/CameraHost.tsx +0 -223
  910. package/corpus/templates/videos/app/remotion/animations/useElementAnimations.ts +0 -231
  911. package/corpus/templates/videos/app/remotion/componentRegistry.ts +0 -473
  912. package/corpus/templates/videos/app/remotion/components/AnimatedElement.tsx +0 -436
  913. package/corpus/templates/videos/app/remotion/components/InteractiveElement.tsx +0 -159
  914. package/corpus/templates/videos/app/remotion/components/InteractiveZoneEditor.tsx +0 -273
  915. package/corpus/templates/videos/app/remotion/compositions/BlankComposition.tsx +0 -204
  916. package/corpus/templates/videos/app/remotion/compositions/index.ts +0 -2
  917. package/corpus/templates/videos/app/remotion/createComponentCursorTrack.ts +0 -132
  918. package/corpus/templates/videos/app/remotion/docs/CURSOR_TRACKS.md +0 -285
  919. package/corpus/templates/videos/app/remotion/easingFunctions.ts +0 -255
  920. package/corpus/templates/videos/app/remotion/hooks/createInteractiveComposition.tsx +0 -283
  921. package/corpus/templates/videos/app/remotion/hooks/useCursorHistory.ts +0 -72
  922. package/corpus/templates/videos/app/remotion/hooks/useCursorTypeFromHover.ts +0 -35
  923. package/corpus/templates/videos/app/remotion/hooks/useEditableZones.tsx +0 -267
  924. package/corpus/templates/videos/app/remotion/hooks/useHoverAnimation.ts +0 -90
  925. package/corpus/templates/videos/app/remotion/hooks/useHoverAnimationSmooth.ts +0 -146
  926. package/corpus/templates/videos/app/remotion/hooks/useInteractiveComponent.ts +0 -711
  927. package/corpus/templates/videos/app/remotion/hooks/useRegisterInteractiveElement.ts +0 -56
  928. package/corpus/templates/videos/app/remotion/library-components/Button.tsx +0 -252
  929. package/corpus/templates/videos/app/remotion/library-components/Card.tsx +0 -241
  930. package/corpus/templates/videos/app/remotion/library-components/CodePanel.tsx +0 -1005
  931. package/corpus/templates/videos/app/remotion/library-components/FileItem.tsx +0 -196
  932. package/corpus/templates/videos/app/remotion/library-components/FolderItem.tsx +0 -199
  933. package/corpus/templates/videos/app/remotion/library-components/PrimaryButton.tsx +0 -177
  934. package/corpus/templates/videos/app/remotion/library-components/SecondaryButton.tsx +0 -167
  935. package/corpus/templates/videos/app/remotion/library-components/SectionHeader.tsx +0 -108
  936. package/corpus/templates/videos/app/remotion/library-components/TEMPLATE.tsx +0 -211
  937. package/corpus/templates/videos/app/remotion/library-components/index.ts +0 -10
  938. package/corpus/templates/videos/app/remotion/registry.ts +0 -91
  939. package/corpus/templates/videos/app/remotion/testing/animationTestUtils.ts +0 -366
  940. package/corpus/templates/videos/app/remotion/trackAnimation.ts +0 -179
  941. package/corpus/templates/videos/app/remotion/trackHelpers.ts +0 -110
  942. package/corpus/templates/videos/app/remotion/ui-components/Cursor.tsx +0 -182
  943. package/corpus/templates/videos/app/remotion/ui-components/InteractiveButton.tsx +0 -116
  944. package/corpus/templates/videos/app/remotion/ui-components/InteractiveCard.tsx +0 -126
  945. package/corpus/templates/videos/app/remotion/ui-components/index.ts +0 -16
  946. package/corpus/templates/videos/app/remotion/utils/animationHelpers.ts +0 -444
  947. package/corpus/templates/videos/app/remotion/utils/interactiveElements.ts +0 -235
  948. package/corpus/templates/videos/app/remotion/utils/springAnimation.ts +0 -76
  949. package/corpus/templates/videos/app/root.tsx +0 -165
  950. package/corpus/templates/videos/app/routes/$.tsx +0 -10
  951. package/corpus/templates/videos/app/routes/_index.tsx +0 -25
  952. package/corpus/templates/videos/app/routes/c.$compositionId.tsx +0 -10
  953. package/corpus/templates/videos/app/routes/components.tsx +0 -10
  954. package/corpus/templates/videos/app/routes/design-systems.tsx +0 -10
  955. package/corpus/templates/videos/app/routes/extensions.$id.$slug.tsx +0 -2
  956. package/corpus/templates/videos/app/routes/extensions.$id.tsx +0 -5
  957. package/corpus/templates/videos/app/routes/extensions._index.tsx +0 -5
  958. package/corpus/templates/videos/app/routes/extensions.tsx +0 -5
  959. package/corpus/templates/videos/app/routes/settings.tsx +0 -88
  960. package/corpus/templates/videos/app/routes/team.tsx +0 -11
  961. package/corpus/templates/videos/app/routes.ts +0 -4
  962. package/corpus/templates/videos/app/state.ts +0 -77
  963. package/corpus/templates/videos/app/types/elementAnimations.ts +0 -121
  964. package/corpus/templates/videos/app/types.ts +0 -200
  965. package/corpus/templates/videos/app/utils/compositionHelpers.ts +0 -445
  966. package/corpus/templates/videos/app/utils/debug.ts +0 -63
  967. package/corpus/templates/videos/app/utils/keyframeUtils.ts +0 -331
  968. package/corpus/templates/videos/app/utils/timelineCoordinates.ts +0 -79
  969. package/corpus/templates/videos/app/vite-env.d.ts +0 -6
  970. package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
  971. package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
  972. package/corpus/templates/videos/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
  973. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +0 -6
  974. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
  975. package/corpus/templates/videos/components.json +0 -20
  976. package/corpus/templates/videos/data/sync-config.json +0 -3
  977. package/corpus/templates/videos/docs/examples/create-composition.example.ts +0 -128
  978. package/corpus/templates/videos/drizzle.config.ts +0 -3
  979. package/corpus/templates/videos/learnings.defaults.md +0 -5
  980. package/corpus/templates/videos/package.json +0 -114
  981. package/corpus/templates/videos/public/agent-native-icon-dark.svg +0 -10
  982. package/corpus/templates/videos/public/agent-native-icon-light.svg +0 -10
  983. package/corpus/templates/videos/public/agent-native-logo-dark.svg +0 -21
  984. package/corpus/templates/videos/public/agent-native-logo-light.svg +0 -21
  985. package/corpus/templates/videos/public/favicon.svg +0 -1
  986. package/corpus/templates/videos/public/icon-180.svg +0 -1
  987. package/corpus/templates/videos/public/icon-192.svg +0 -1
  988. package/corpus/templates/videos/public/icon-512.svg +0 -1
  989. package/corpus/templates/videos/public/manifest.json +0 -21
  990. package/corpus/templates/videos/public/placeholder.svg +0 -1
  991. package/corpus/templates/videos/public/robots.txt +0 -14
  992. package/corpus/templates/videos/react-router.config.ts +0 -7
  993. package/corpus/templates/videos/server/db/index.ts +0 -37
  994. package/corpus/templates/videos/server/db/schema.ts +0 -55
  995. package/corpus/templates/videos/server/middleware/auth.ts +0 -15
  996. package/corpus/templates/videos/server/plugins/agent-chat.ts +0 -29
  997. package/corpus/templates/videos/server/plugins/auth.ts +0 -14
  998. package/corpus/templates/videos/server/plugins/collab.ts +0 -11
  999. package/corpus/templates/videos/server/plugins/core-routes.ts +0 -22
  1000. package/corpus/templates/videos/server/plugins/db.ts +0 -160
  1001. package/corpus/templates/videos/server/routes/[...page].get.ts +0 -5
  1002. package/corpus/templates/videos/server/routes/[...page].head.ts +0 -1
  1003. package/corpus/templates/videos/server/routes/api/save-composition-defaults.post.ts +0 -274
  1004. package/corpus/templates/videos/shared/api.ts +0 -75
  1005. package/corpus/templates/videos/ssr-entry.ts +0 -15
  1006. package/corpus/templates/videos/tsconfig.json +0 -21
  1007. package/corpus/templates/videos/vite.config.ts +0 -19
  1008. package/corpus/templates/videos/vitest.config.ts +0 -16
  1009. package/docs/content/locales/ar-SA/template-videos.mdx +0 -336
  1010. package/docs/content/locales/de-DE/template-videos.mdx +0 -336
  1011. package/docs/content/locales/es-ES/template-videos.mdx +0 -336
  1012. package/docs/content/locales/fr-FR/template-videos.mdx +0 -336
  1013. package/docs/content/locales/hi-IN/template-videos.mdx +0 -336
  1014. package/docs/content/locales/ja-JP/template-videos.mdx +0 -336
  1015. package/docs/content/locales/ko-KR/template-videos.mdx +0 -336
  1016. package/docs/content/locales/pt-BR/template-videos.mdx +0 -336
  1017. package/docs/content/locales/zh-CN/template-videos.mdx +0 -334
  1018. package/docs/content/locales/zh-TW/template-videos.mdx +0 -334
  1019. package/docs/content/template-videos.mdx +0 -332
@@ -54,8 +54,8 @@ export interface AppProvidersProps {
54
54
  queryClient: QueryClient;
55
55
  /**
56
56
  * Default theme passed to next-themes `ThemeProvider`.
57
- * Defaults to `"system"`. Dark-first templates (videos, slides, macros,
58
- * analytics) pass `"dark"`.
57
+ * Defaults to `"system"`. Dark-first templates (slides, macros, analytics)
58
+ * pass `"dark"`.
59
59
  */
60
60
  defaultTheme?: string;
61
61
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"app-providers.js","sourceRoot":"","sources":["../../src/client/app-providers.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAoB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAkB,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,uBAAuB,GAExB,MAAM,WAAW,CAAC;AAiEnB,MAAM,eAAe,GAAG,KAAC,OAAO,IAAC,UAAU,QAAC,QAAQ,EAAC,aAAa,GAAG,CAAC;AAEtE,SAAS,cAAc,CAAC,EACtB,WAAW,EACX,YAAY,GAAG,QAAQ,EACvB,cAAc,GAAG,OAAO,EACxB,oBAAoB,EACpB,OAAO,GAAG,eAAe,EACzB,uBAAuB,GAAG,IAAI,EAC9B,IAAI,EACJ,QAAQ,GAUT;IACC,MAAM,iBAAiB,GACrB,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CACf,QAAQ,CACT,CAAC,CAAC,CAAC,CACF,KAAC,uBAAuB,OAAK,CAAC,IAAI,IAAI,EAAE,CAAC,YACtC,QAAQ,GACe,CAC3B,CAAC;IAEJ,OAAO,CACL,KAAC,mBAAmB,IAAC,MAAM,EAAE,WAAW,YACtC,KAAC,aAAa,IACZ,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,YAAY,EAC1B,YAAY,QACZ,yBAAyB,EAAE,uBAAuB,YAElD,MAAC,eAAe,IAAC,aAAa,EAAE,oBAAoB,aACjD,iBAAiB,EACjB,OAAO,IACQ,GACJ,GACI,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAC3B,WAAW,EACX,YAAY,GAAG,KAAK,EACpB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,OAAO,EACP,uBAAuB,EACvB,IAAI,EACJ,QAAQ,GACU;IAClB,MAAM,QAAQ,GAAG,kBAAkB,IAAI,KAAC,cAAc,KAAG,CAAC;IAE1D,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CACL,KAAC,cAAc,IACb,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,oBAAoB,EAAE,oBAAoB,EAC1C,OAAO,EAAE,OAAO,EAChB,uBAAuB,EAAE,uBAAuB,EAChD,IAAI,EAAE,IAAI,YAET,QAAQ,GACM,CAClB,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,UAAU,IAAC,QAAQ,EAAE,QAAQ,YAC5B,KAAC,cAAc,IACb,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,oBAAoB,EAAE,oBAAoB,EAC1C,OAAO,EAAE,OAAO,EAChB,uBAAuB,EAAE,uBAAuB,EAChD,IAAI,EAAE,IAAI,YAET,QAAQ,GACM,GACN,CACd,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Shared provider shell for agent-native template roots.\n *\n * Composes the providers every template needs:\n * QueryClientProvider → ThemeProvider → TooltipProvider → Toaster\n *\n * Templates keep their own `createAgentNativeQueryClient(overrides)` call and\n * pass the result in as `queryClient`. AppProviders never creates a client\n * internally so each template can apply its own query defaults (e.g. calendar's\n * `refetchOnWindowFocus: true`, mail's focus-refresh throttle).\n *\n * Public-path SSR pattern (calendar/clips/content):\n * Some templates have routes that must SSR real content for first-visit\n * signed-out users and crawlers, bypassing the `<ClientOnly>` gate.\n * Pass `isPublicPath` and `clientOnlyFallback` to activate this branch:\n *\n * <AppProviders\n * queryClient={queryClient}\n * isPublicPath={isPublicBookingPath(location.pathname)}\n * clientOnlyFallback={<DefaultSpinner />}\n * >\n * ...\n * </AppProviders>\n *\n * When `isPublicPath` is true the providers render without `<ClientOnly>`,\n * streaming real markup to the client. When false (the default) the standard\n * `<ClientOnly fallback={clientOnlyFallback}>` gate wraps everything.\n * When `clientOnlyFallback` is omitted, `<DefaultSpinner />` is used.\n *\n * Customisation props:\n * themeAttribute — passed to next-themes ThemeProvider `attribute`.\n * Defaults to \"class\". Use [\"class\", \"data-theme\"]\n * when CSS variables are also keyed off a data-theme\n * attribute (mail template).\n * tooltipDelayDuration — passed to Radix TooltipProvider `delayDuration`\n * (ms). Omit to use the Radix default (700 ms).\n * toaster — custom Toaster element rendered after children.\n * Pass `null` to suppress the built-in Toaster when\n * children already include a styled one.\n * Defaults to `<Toaster richColors position=\"bottom-left\" />`.\n * disableThemeTransitions — passed to next-themes ThemeProvider\n * `disableTransitionOnChange`. Defaults to `true`\n * (suppresses CSS transitions during theme switches,\n * which is the shadcn recommendation and avoids\n * flash artefacts). Set to `false` when the template\n * intentionally animates theme changes (e.g. content).\n */\n\nimport { TooltipProvider } from \"@radix-ui/react-tooltip\";\nimport { QueryClientProvider, type QueryClient } from \"@tanstack/react-query\";\nimport { ThemeProvider, type Attribute } from \"next-themes\";\nimport React from \"react\";\nimport { Toaster } from \"sonner\";\n\nimport { ClientOnly } from \"./ClientOnly.js\";\nimport { DefaultSpinner } from \"./DefaultSpinner.js\";\nimport {\n AgentNativeI18nProvider,\n type AgentNativeI18nProviderProps,\n} from \"./i18n.js\";\n\nexport interface AppProvidersProps {\n /** QueryClient instance — create with `createAgentNativeQueryClient()`. */\n queryClient: QueryClient;\n\n /**\n * Default theme passed to next-themes `ThemeProvider`.\n * Defaults to `\"system\"`. Dark-first templates (videos, slides, macros,\n * analytics) pass `\"dark\"`.\n */\n defaultTheme?: string;\n\n /**\n * Passed to next-themes ThemeProvider `attribute`.\n * Defaults to \"class\". Pass [\"class\", \"data-theme\"] when your CSS variables\n * are also keyed off a data-theme attribute (mail template).\n */\n themeAttribute?: Attribute | Attribute[];\n\n /**\n * Passed to Radix TooltipProvider `delayDuration` (ms).\n * Omit to use the Radix default (700 ms).\n */\n tooltipDelayDuration?: number;\n\n /**\n * Custom Toaster element rendered after children inside TooltipProvider.\n * Pass `null` to suppress the built-in Toaster when children already\n * include a styled one.\n * Defaults to `<Toaster richColors position=\"bottom-left\" />`.\n */\n toaster?: React.ReactNode | null;\n\n /**\n * Passed to next-themes ThemeProvider `disableTransitionOnChange`.\n * Defaults to `true` (suppresses CSS transitions on theme switch, per the\n * shadcn recommendation). Set to `false` when the template intentionally\n * animates theme changes (e.g. content's 3-way theme cycle).\n */\n disableThemeTransitions?: boolean;\n\n /**\n * Optional localization runtime configuration. When omitted, AppProviders\n * still mounts the i18n provider with an English fallback so templates can\n * call useT/useLocale before they add catalogs. Pass false to opt out.\n */\n i18n?: Omit<AgentNativeI18nProviderProps, \"children\"> | false;\n\n /**\n * When true the providers render without a `<ClientOnly>` gate so SSR\n * streams real markup for public/unauthenticated paths.\n * Defaults to false (authenticated app shell, ClientOnly-gated).\n */\n isPublicPath?: boolean;\n\n /**\n * Fallback rendered by `<ClientOnly>` while JS hydrates on private paths.\n * Defaults to `<DefaultSpinner />`.\n */\n clientOnlyFallback?: React.ReactNode;\n\n children: React.ReactNode;\n}\n\nconst DEFAULT_TOASTER = <Toaster richColors position=\"bottom-left\" />;\n\nfunction ProvidersInner({\n queryClient,\n defaultTheme = \"system\",\n themeAttribute = \"class\",\n tooltipDelayDuration,\n toaster = DEFAULT_TOASTER,\n disableThemeTransitions = true,\n i18n,\n children,\n}: {\n queryClient: QueryClient;\n defaultTheme?: string;\n themeAttribute?: Attribute | Attribute[];\n tooltipDelayDuration?: number;\n toaster?: React.ReactNode | null;\n disableThemeTransitions?: boolean;\n i18n?: Omit<AgentNativeI18nProviderProps, \"children\"> | false;\n children: React.ReactNode;\n}) {\n const localizedChildren =\n i18n === false ? (\n children\n ) : (\n <AgentNativeI18nProvider {...(i18n ?? {})}>\n {children}\n </AgentNativeI18nProvider>\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <ThemeProvider\n attribute={themeAttribute}\n defaultTheme={defaultTheme}\n enableSystem\n disableTransitionOnChange={disableThemeTransitions}\n >\n <TooltipProvider delayDuration={tooltipDelayDuration}>\n {localizedChildren}\n {toaster}\n </TooltipProvider>\n </ThemeProvider>\n </QueryClientProvider>\n );\n}\n\nexport function AppProviders({\n queryClient,\n isPublicPath = false,\n clientOnlyFallback,\n defaultTheme,\n themeAttribute,\n tooltipDelayDuration,\n toaster,\n disableThemeTransitions,\n i18n,\n children,\n}: AppProvidersProps) {\n const fallback = clientOnlyFallback ?? <DefaultSpinner />;\n\n if (isPublicPath) {\n return (\n <ProvidersInner\n queryClient={queryClient}\n defaultTheme={defaultTheme}\n themeAttribute={themeAttribute}\n tooltipDelayDuration={tooltipDelayDuration}\n toaster={toaster}\n disableThemeTransitions={disableThemeTransitions}\n i18n={i18n}\n >\n {children}\n </ProvidersInner>\n );\n }\n\n return (\n <ClientOnly fallback={fallback}>\n <ProvidersInner\n queryClient={queryClient}\n defaultTheme={defaultTheme}\n themeAttribute={themeAttribute}\n tooltipDelayDuration={tooltipDelayDuration}\n toaster={toaster}\n disableThemeTransitions={disableThemeTransitions}\n i18n={i18n}\n >\n {children}\n </ProvidersInner>\n </ClientOnly>\n );\n}\n"]}
1
+ {"version":3,"file":"app-providers.js","sourceRoot":"","sources":["../../src/client/app-providers.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAoB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAkB,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,uBAAuB,GAExB,MAAM,WAAW,CAAC;AAiEnB,MAAM,eAAe,GAAG,KAAC,OAAO,IAAC,UAAU,QAAC,QAAQ,EAAC,aAAa,GAAG,CAAC;AAEtE,SAAS,cAAc,CAAC,EACtB,WAAW,EACX,YAAY,GAAG,QAAQ,EACvB,cAAc,GAAG,OAAO,EACxB,oBAAoB,EACpB,OAAO,GAAG,eAAe,EACzB,uBAAuB,GAAG,IAAI,EAC9B,IAAI,EACJ,QAAQ,GAUT;IACC,MAAM,iBAAiB,GACrB,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CACf,QAAQ,CACT,CAAC,CAAC,CAAC,CACF,KAAC,uBAAuB,OAAK,CAAC,IAAI,IAAI,EAAE,CAAC,YACtC,QAAQ,GACe,CAC3B,CAAC;IAEJ,OAAO,CACL,KAAC,mBAAmB,IAAC,MAAM,EAAE,WAAW,YACtC,KAAC,aAAa,IACZ,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,YAAY,EAC1B,YAAY,QACZ,yBAAyB,EAAE,uBAAuB,YAElD,MAAC,eAAe,IAAC,aAAa,EAAE,oBAAoB,aACjD,iBAAiB,EACjB,OAAO,IACQ,GACJ,GACI,CACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAC3B,WAAW,EACX,YAAY,GAAG,KAAK,EACpB,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,OAAO,EACP,uBAAuB,EACvB,IAAI,EACJ,QAAQ,GACU;IAClB,MAAM,QAAQ,GAAG,kBAAkB,IAAI,KAAC,cAAc,KAAG,CAAC;IAE1D,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CACL,KAAC,cAAc,IACb,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,oBAAoB,EAAE,oBAAoB,EAC1C,OAAO,EAAE,OAAO,EAChB,uBAAuB,EAAE,uBAAuB,EAChD,IAAI,EAAE,IAAI,YAET,QAAQ,GACM,CAClB,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,UAAU,IAAC,QAAQ,EAAE,QAAQ,YAC5B,KAAC,cAAc,IACb,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,oBAAoB,EAAE,oBAAoB,EAC1C,OAAO,EAAE,OAAO,EAChB,uBAAuB,EAAE,uBAAuB,EAChD,IAAI,EAAE,IAAI,YAET,QAAQ,GACM,GACN,CACd,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Shared provider shell for agent-native template roots.\n *\n * Composes the providers every template needs:\n * QueryClientProvider → ThemeProvider → TooltipProvider → Toaster\n *\n * Templates keep their own `createAgentNativeQueryClient(overrides)` call and\n * pass the result in as `queryClient`. AppProviders never creates a client\n * internally so each template can apply its own query defaults (e.g. calendar's\n * `refetchOnWindowFocus: true`, mail's focus-refresh throttle).\n *\n * Public-path SSR pattern (calendar/clips/content):\n * Some templates have routes that must SSR real content for first-visit\n * signed-out users and crawlers, bypassing the `<ClientOnly>` gate.\n * Pass `isPublicPath` and `clientOnlyFallback` to activate this branch:\n *\n * <AppProviders\n * queryClient={queryClient}\n * isPublicPath={isPublicBookingPath(location.pathname)}\n * clientOnlyFallback={<DefaultSpinner />}\n * >\n * ...\n * </AppProviders>\n *\n * When `isPublicPath` is true the providers render without `<ClientOnly>`,\n * streaming real markup to the client. When false (the default) the standard\n * `<ClientOnly fallback={clientOnlyFallback}>` gate wraps everything.\n * When `clientOnlyFallback` is omitted, `<DefaultSpinner />` is used.\n *\n * Customisation props:\n * themeAttribute — passed to next-themes ThemeProvider `attribute`.\n * Defaults to \"class\". Use [\"class\", \"data-theme\"]\n * when CSS variables are also keyed off a data-theme\n * attribute (mail template).\n * tooltipDelayDuration — passed to Radix TooltipProvider `delayDuration`\n * (ms). Omit to use the Radix default (700 ms).\n * toaster — custom Toaster element rendered after children.\n * Pass `null` to suppress the built-in Toaster when\n * children already include a styled one.\n * Defaults to `<Toaster richColors position=\"bottom-left\" />`.\n * disableThemeTransitions — passed to next-themes ThemeProvider\n * `disableTransitionOnChange`. Defaults to `true`\n * (suppresses CSS transitions during theme switches,\n * which is the shadcn recommendation and avoids\n * flash artefacts). Set to `false` when the template\n * intentionally animates theme changes (e.g. content).\n */\n\nimport { TooltipProvider } from \"@radix-ui/react-tooltip\";\nimport { QueryClientProvider, type QueryClient } from \"@tanstack/react-query\";\nimport { ThemeProvider, type Attribute } from \"next-themes\";\nimport React from \"react\";\nimport { Toaster } from \"sonner\";\n\nimport { ClientOnly } from \"./ClientOnly.js\";\nimport { DefaultSpinner } from \"./DefaultSpinner.js\";\nimport {\n AgentNativeI18nProvider,\n type AgentNativeI18nProviderProps,\n} from \"./i18n.js\";\n\nexport interface AppProvidersProps {\n /** QueryClient instance — create with `createAgentNativeQueryClient()`. */\n queryClient: QueryClient;\n\n /**\n * Default theme passed to next-themes `ThemeProvider`.\n * Defaults to `\"system\"`. Dark-first templates (slides, macros, analytics)\n * pass `\"dark\"`.\n */\n defaultTheme?: string;\n\n /**\n * Passed to next-themes ThemeProvider `attribute`.\n * Defaults to \"class\". Pass [\"class\", \"data-theme\"] when your CSS variables\n * are also keyed off a data-theme attribute (mail template).\n */\n themeAttribute?: Attribute | Attribute[];\n\n /**\n * Passed to Radix TooltipProvider `delayDuration` (ms).\n * Omit to use the Radix default (700 ms).\n */\n tooltipDelayDuration?: number;\n\n /**\n * Custom Toaster element rendered after children inside TooltipProvider.\n * Pass `null` to suppress the built-in Toaster when children already\n * include a styled one.\n * Defaults to `<Toaster richColors position=\"bottom-left\" />`.\n */\n toaster?: React.ReactNode | null;\n\n /**\n * Passed to next-themes ThemeProvider `disableTransitionOnChange`.\n * Defaults to `true` (suppresses CSS transitions on theme switch, per the\n * shadcn recommendation). Set to `false` when the template intentionally\n * animates theme changes (e.g. content's 3-way theme cycle).\n */\n disableThemeTransitions?: boolean;\n\n /**\n * Optional localization runtime configuration. When omitted, AppProviders\n * still mounts the i18n provider with an English fallback so templates can\n * call useT/useLocale before they add catalogs. Pass false to opt out.\n */\n i18n?: Omit<AgentNativeI18nProviderProps, \"children\"> | false;\n\n /**\n * When true the providers render without a `<ClientOnly>` gate so SSR\n * streams real markup for public/unauthenticated paths.\n * Defaults to false (authenticated app shell, ClientOnly-gated).\n */\n isPublicPath?: boolean;\n\n /**\n * Fallback rendered by `<ClientOnly>` while JS hydrates on private paths.\n * Defaults to `<DefaultSpinner />`.\n */\n clientOnlyFallback?: React.ReactNode;\n\n children: React.ReactNode;\n}\n\nconst DEFAULT_TOASTER = <Toaster richColors position=\"bottom-left\" />;\n\nfunction ProvidersInner({\n queryClient,\n defaultTheme = \"system\",\n themeAttribute = \"class\",\n tooltipDelayDuration,\n toaster = DEFAULT_TOASTER,\n disableThemeTransitions = true,\n i18n,\n children,\n}: {\n queryClient: QueryClient;\n defaultTheme?: string;\n themeAttribute?: Attribute | Attribute[];\n tooltipDelayDuration?: number;\n toaster?: React.ReactNode | null;\n disableThemeTransitions?: boolean;\n i18n?: Omit<AgentNativeI18nProviderProps, \"children\"> | false;\n children: React.ReactNode;\n}) {\n const localizedChildren =\n i18n === false ? (\n children\n ) : (\n <AgentNativeI18nProvider {...(i18n ?? {})}>\n {children}\n </AgentNativeI18nProvider>\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <ThemeProvider\n attribute={themeAttribute}\n defaultTheme={defaultTheme}\n enableSystem\n disableTransitionOnChange={disableThemeTransitions}\n >\n <TooltipProvider delayDuration={tooltipDelayDuration}>\n {localizedChildren}\n {toaster}\n </TooltipProvider>\n </ThemeProvider>\n </QueryClientProvider>\n );\n}\n\nexport function AppProviders({\n queryClient,\n isPublicPath = false,\n clientOnlyFallback,\n defaultTheme,\n themeAttribute,\n tooltipDelayDuration,\n toaster,\n disableThemeTransitions,\n i18n,\n children,\n}: AppProvidersProps) {\n const fallback = clientOnlyFallback ?? <DefaultSpinner />;\n\n if (isPublicPath) {\n return (\n <ProvidersInner\n queryClient={queryClient}\n defaultTheme={defaultTheme}\n themeAttribute={themeAttribute}\n tooltipDelayDuration={tooltipDelayDuration}\n toaster={toaster}\n disableThemeTransitions={disableThemeTransitions}\n i18n={i18n}\n >\n {children}\n </ProvidersInner>\n );\n }\n\n return (\n <ClientOnly fallback={fallback}>\n <ProvidersInner\n queryClient={queryClient}\n defaultTheme={defaultTheme}\n themeAttribute={themeAttribute}\n tooltipDelayDuration={tooltipDelayDuration}\n toaster={toaster}\n disableThemeTransitions={disableThemeTransitions}\n i18n={i18n}\n >\n {children}\n </ProvidersInner>\n </ClientOnly>\n );\n}\n"]}
@@ -6,5 +6,8 @@ export { useCollaborativeMap, useCollaborativeArray, type UseCollaborativeMapOpt
6
6
  export { PresenceBar, type PresenceBarProps, } from "../components/PresenceBar.js";
7
7
  export { AgentPresenceChip, type AgentPresenceChipProps, } from "../components/AgentPresenceChip.js";
8
8
  export { LiveCursorOverlay, type LiveCursorOverlayProps, type CursorMapFn, } from "../components/LiveCursorOverlay.js";
9
- export { RemoteSelectionRings, type RemoteSelectionRingsProps, } from "../components/RemoteSelectionRings.js";
9
+ export { RemoteSelectionRings, type RemoteSelectionRingsProps, type SelectionDescriptor, } from "../components/RemoteSelectionRings.js";
10
+ export { RecentEditHighlights, type RecentEditHighlightsProps, } from "../components/RecentEditHighlights.js";
11
+ export { appendRecentEdit, collectRecentEdits, publishRecentEdit, useRecentEdits, RECENT_EDITS_MAX, RECENT_EDIT_TTL_MS, type RecentEdit, type RecentEditDescriptor, type AttributedRecentEdit, type UseRecentEditsOptions, } from "../../collab/recent-edits.js";
12
+ export { useCollabUndo, useLocalOpUndo, createLocalOpUndoController, type UseCollabUndoOptions, type UseCollabUndoResult, type CollabUndoScope, type UseLocalOpUndoOptions, type UseLocalOpUndoResult, type LocalOpUndoEntry, type LocalOpUndoController, type CreateLocalOpUndoOptions, type UndoKeyboardOptions, } from "../../collab/undo.js";
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/collab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,wBAAwB,EACxB,KAAK,UAAU,EACf,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,GACjC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,GACjB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,oBAAoB,EACpB,KAAK,yBAAyB,GAC/B,MAAM,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/collab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,wBAAwB,EACxB,KAAK,UAAU,EACf,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,GACjC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,WAAW,GACjB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,oBAAoB,EACpB,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,GACzB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,oBAAoB,EACpB,KAAK,yBAAyB,GAC/B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,aAAa,EACb,cAAc,EACd,2BAA2B,EAC3B,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,sBAAsB,CAAC"}
@@ -7,4 +7,7 @@ export { PresenceBar, } from "../components/PresenceBar.js";
7
7
  export { AgentPresenceChip, } from "../components/AgentPresenceChip.js";
8
8
  export { LiveCursorOverlay, } from "../components/LiveCursorOverlay.js";
9
9
  export { RemoteSelectionRings, } from "../components/RemoteSelectionRings.js";
10
+ export { RecentEditHighlights, } from "../components/RecentEditHighlights.js";
11
+ export { appendRecentEdit, collectRecentEdits, publishRecentEdit, useRecentEdits, RECENT_EDITS_MAX, RECENT_EDIT_TTL_MS, } from "../../collab/recent-edits.js";
12
+ export { useCollabUndo, useLocalOpUndo, createLocalOpUndoController, } from "../../collab/undo.js";
10
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/collab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,wBAAwB,GAIzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,GAKf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,GAId,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GAKtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,WAAW,GAEZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,GAElB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,iBAAiB,GAGlB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,oBAAoB,GAErB,MAAM,uCAAuC,CAAC","sourcesContent":["export {\n useCollaborativeDoc,\n isReconcileLeadClient,\n emailToColor,\n emailToName,\n dedupeCollabUsersByEmail,\n type CollabUser,\n type UseCollaborativeDocOptions,\n type UseCollaborativeDocResult,\n} from \"../../collab/client.js\";\nexport { AGENT_CLIENT_ID } from \"../../collab/agent-identity.js\";\nexport {\n usePresence,\n toNormalized,\n fromNormalized,\n type OtherPresence,\n type PresencePayload,\n type UsePresenceResult,\n type NormalizedPoint,\n} from \"../../collab/presence.js\";\nexport {\n useFollowUser,\n type UseFollowUserOptions,\n type UseFollowUserResult,\n type ViewportDescriptor,\n} from \"../../collab/follow-mode.js\";\nexport {\n useCollaborativeMap,\n useCollaborativeArray,\n type UseCollaborativeMapOptions,\n type UseCollaborativeMapResult,\n type UseCollaborativeArrayOptions,\n type UseCollaborativeArrayResult,\n} from \"../../collab/client-struct.js\";\nexport {\n PresenceBar,\n type PresenceBarProps,\n} from \"../components/PresenceBar.js\";\nexport {\n AgentPresenceChip,\n type AgentPresenceChipProps,\n} from \"../components/AgentPresenceChip.js\";\nexport {\n LiveCursorOverlay,\n type LiveCursorOverlayProps,\n type CursorMapFn,\n} from \"../components/LiveCursorOverlay.js\";\nexport {\n RemoteSelectionRings,\n type RemoteSelectionRingsProps,\n} from \"../components/RemoteSelectionRings.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/collab/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,wBAAwB,GAIzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,GAKf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,GAId,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GAKtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,WAAW,GAEZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,GAElB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,iBAAiB,GAGlB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,oBAAoB,GAGrB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,oBAAoB,GAErB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,GAKnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,aAAa,EACb,cAAc,EACd,2BAA2B,GAU5B,MAAM,sBAAsB,CAAC","sourcesContent":["export {\n useCollaborativeDoc,\n isReconcileLeadClient,\n emailToColor,\n emailToName,\n dedupeCollabUsersByEmail,\n type CollabUser,\n type UseCollaborativeDocOptions,\n type UseCollaborativeDocResult,\n} from \"../../collab/client.js\";\nexport { AGENT_CLIENT_ID } from \"../../collab/agent-identity.js\";\nexport {\n usePresence,\n toNormalized,\n fromNormalized,\n type OtherPresence,\n type PresencePayload,\n type UsePresenceResult,\n type NormalizedPoint,\n} from \"../../collab/presence.js\";\nexport {\n useFollowUser,\n type UseFollowUserOptions,\n type UseFollowUserResult,\n type ViewportDescriptor,\n} from \"../../collab/follow-mode.js\";\nexport {\n useCollaborativeMap,\n useCollaborativeArray,\n type UseCollaborativeMapOptions,\n type UseCollaborativeMapResult,\n type UseCollaborativeArrayOptions,\n type UseCollaborativeArrayResult,\n} from \"../../collab/client-struct.js\";\nexport {\n PresenceBar,\n type PresenceBarProps,\n} from \"../components/PresenceBar.js\";\nexport {\n AgentPresenceChip,\n type AgentPresenceChipProps,\n} from \"../components/AgentPresenceChip.js\";\nexport {\n LiveCursorOverlay,\n type LiveCursorOverlayProps,\n type CursorMapFn,\n} from \"../components/LiveCursorOverlay.js\";\nexport {\n RemoteSelectionRings,\n type RemoteSelectionRingsProps,\n type SelectionDescriptor,\n} from \"../components/RemoteSelectionRings.js\";\nexport {\n RecentEditHighlights,\n type RecentEditHighlightsProps,\n} from \"../components/RecentEditHighlights.js\";\nexport {\n appendRecentEdit,\n collectRecentEdits,\n publishRecentEdit,\n useRecentEdits,\n RECENT_EDITS_MAX,\n RECENT_EDIT_TTL_MS,\n type RecentEdit,\n type RecentEditDescriptor,\n type AttributedRecentEdit,\n type UseRecentEditsOptions,\n} from \"../../collab/recent-edits.js\";\nexport {\n useCollabUndo,\n useLocalOpUndo,\n createLocalOpUndoController,\n type UseCollabUndoOptions,\n type UseCollabUndoResult,\n type CollabUndoScope,\n type UseLocalOpUndoOptions,\n type UseLocalOpUndoResult,\n type LocalOpUndoEntry,\n type LocalOpUndoController,\n type CreateLocalOpUndoOptions,\n type UndoKeyboardOptions,\n} from \"../../collab/undo.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"LiveCursorOverlay.d.ts","sourceRoot":"","sources":["../../../src/client/components/LiveCursorOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE/E,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,CAAC,IAAI,EAAE,eAAe,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACnD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuFD,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,SAAoB,EACpB,SAAS,EACT,YAAY,EACZ,SAAS,GACV,EAAE,sBAAsB,+BAuFxB"}
1
+ {"version":3,"file":"LiveCursorOverlay.d.ts","sourceRoot":"","sources":["../../../src/client/components/LiveCursorOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE/E,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,CAAC,IAAI,EAAE,eAAe,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACnD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsGD,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,SAAoB,EACpB,SAAS,EACT,YAAY,EACZ,SAAS,GACV,EAAE,sBAAsB,+BAuFxB"}
@@ -35,10 +35,13 @@ const CursorLabel = memo(function CursorLabel({ entry, }) {
35
35
  transition: "left 120ms linear, top 120ms linear",
36
36
  width: 0,
37
37
  height: 0,
38
- }, children: [_jsx(CursorPointer, { color: color }), _jsx("div", { style: {
38
+ }, children: [_jsx(CursorPointer, { color: color }), _jsxs("div", { style: {
39
39
  position: "absolute",
40
40
  left: 31,
41
41
  top: 31,
42
+ display: "flex",
43
+ alignItems: "center",
44
+ gap: 5,
42
45
  backgroundColor: color,
43
46
  color: "#fff",
44
47
  fontSize: 12,
@@ -48,10 +51,15 @@ const CursorLabel = memo(function CursorLabel({ entry, }) {
48
51
  borderRadius: 2,
49
52
  whiteSpace: "nowrap",
50
53
  boxShadow: "0 5px 12px rgba(15, 23, 42, 0.16)",
51
- maxWidth: 120,
54
+ maxWidth: 150,
52
55
  overflow: "hidden",
53
56
  textOverflow: "ellipsis",
54
- }, children: label })] }));
57
+ }, children: [other.user.avatarUrl ? (_jsx("img", { src: other.user.avatarUrl, alt: "", style: {
58
+ width: 14,
59
+ height: 14,
60
+ borderRadius: "50%",
61
+ flexShrink: 0,
62
+ } })) : null, label] })] }));
55
63
  });
56
64
  export function LiveCursorOverlay({ others, cursorKey = "cursor", mapCoords, containerRef, className, }) {
57
65
  const overlayRef = useRef(null);
@@ -1 +1 @@
1
- {"version":3,"file":"LiveCursorOverlay.js","sourceRoot":"","sources":["../../../src/client/components/LiveCursorOverlay.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * LiveCursorOverlay — renders remote users' cursors over an absolutely-\n * positioned container.\n *\n * Cursor positions are expected as normalized coordinates (0–1 relative to\n * the container's content size) so different zoom/scroll positions map\n * correctly. Pass a `mapCoords` prop to handle non-identity transforms\n * (e.g. a zoomed canvas).\n *\n * The agent uses the same pointer shape with an \"AI\" label.\n *\n * Cursors fade out after 10 seconds of no movement.\n */\n\nimport { useState, useEffect, useRef, memo } from \"react\";\n\nimport type { OtherPresence, NormalizedPoint } from \"../../collab/presence.js\";\n\nexport interface CursorMapFn {\n /** Convert normalized coords to pixel offsets within the overlay container. */\n (norm: NormalizedPoint): { x: number; y: number };\n}\n\nexport interface LiveCursorOverlayProps {\n /** Remote participants with presence payload. */\n others: OtherPresence[];\n /**\n * Key inside presence payload that carries the cursor position.\n * Default: \"cursor\"\n * Expected shape: { x: number; y: number } (normalized 0–1).\n */\n cursorKey?: string;\n /**\n * Override coordinate mapping. Default: scale by container clientWidth/Height.\n * Pass this when the container uses transform: scale() or has virtual scroll.\n */\n mapCoords?: CursorMapFn;\n /**\n * Container element ref. Required when mapCoords is not provided —\n * used to compute pixel positions from normalized coords.\n */\n containerRef?: React.RefObject<HTMLElement | null>;\n /** Additional CSS class for the overlay div. */\n className?: string;\n}\n\nconst STALE_MS = 10_000; // Fade out cursors older than 10s\n\nfunction CursorPointer({ color }: { color: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"25\"\n height=\"29\"\n viewBox=\"0 0 25 29\"\n fill=\"none\"\n aria-hidden\n style={{\n display: \"block\",\n filter: \"drop-shadow(0 2px 3px rgba(15, 23, 42, 0.3))\",\n }}\n >\n <path\n d=\"M2.5 2.5L21.5 11L12.6 14.1L8.3 24.5L2.5 2.5Z\"\n fill={color}\n stroke=\"white\"\n strokeLinejoin=\"round\"\n strokeWidth=\"3\"\n />\n </svg>\n );\n}\n\ninterface CursorEntry {\n other: OtherPresence;\n x: number;\n y: number;\n lastSeen: number;\n}\n\nconst CursorLabel = memo(function CursorLabel({\n entry,\n}: {\n entry: CursorEntry;\n}) {\n const { other, x, y } = entry;\n const color = other.user.color || \"#94a3b8\";\n const label = other.isAgent ? \"AI\" : other.user.name || other.user.email;\n\n return (\n <div\n aria-label={`${label} cursor`}\n style={{\n position: \"absolute\",\n left: x,\n top: y,\n pointerEvents: \"none\",\n userSelect: \"none\",\n transform: \"translate(-2px, -2px)\",\n zIndex: 9999,\n transition: \"left 120ms linear, top 120ms linear\",\n width: 0,\n height: 0,\n }}\n >\n <CursorPointer color={color} />\n <div\n style={{\n position: \"absolute\",\n left: 31,\n top: 31,\n backgroundColor: color,\n color: \"#fff\",\n fontSize: 12,\n fontWeight: 500,\n lineHeight: \"16px\",\n padding: \"2px 7px\",\n borderRadius: 2,\n whiteSpace: \"nowrap\",\n boxShadow: \"0 5px 12px rgba(15, 23, 42, 0.16)\",\n maxWidth: 120,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {label}\n </div>\n </div>\n );\n});\n\nexport function LiveCursorOverlay({\n others,\n cursorKey = \"cursor\",\n mapCoords,\n containerRef,\n className,\n}: LiveCursorOverlayProps) {\n const overlayRef = useRef<HTMLDivElement>(null);\n const [, tick] = useState(0); // Force re-render to prune stale cursors\n const entriesRef = useRef<Map<number, CursorEntry>>(new Map());\n\n // Tick every 5s to prune stale cursors (no re-render storm).\n useEffect(() => {\n const id = setInterval(() => tick((n) => n + 1), 5_000);\n return () => clearInterval(id);\n }, []);\n\n // Build entries from others, computing pixel positions.\n const now = Date.now();\n const visible: CursorEntry[] = [];\n\n for (const other of others) {\n const pos = other.presence[cursorKey] as NormalizedPoint | undefined;\n if (!pos || typeof pos.x !== \"number\" || typeof pos.y !== \"number\")\n continue;\n\n // Compute pixel position.\n let px: number;\n let py: number;\n if (mapCoords) {\n const mapped = mapCoords(pos);\n px = mapped.x;\n py = mapped.y;\n } else {\n const container =\n containerRef?.current ?? overlayRef.current?.parentElement;\n const w = container ? container.clientWidth : 0;\n const h = container ? container.clientHeight : 0;\n px = pos.x * w;\n py = pos.y * h;\n }\n\n const prev = entriesRef.current.get(other.clientId);\n const lastSeen =\n prev && prev.x === px && prev.y === py ? prev.lastSeen : now;\n const entry: CursorEntry = { other, x: px, y: py, lastSeen };\n entriesRef.current.set(other.clientId, entry);\n\n if (now - lastSeen < STALE_MS) {\n visible.push(entry);\n }\n }\n\n // Remove entries for participants who left.\n for (const clientId of entriesRef.current.keys()) {\n if (!others.find((o) => o.clientId === clientId)) {\n entriesRef.current.delete(clientId);\n }\n }\n\n if (visible.length === 0) {\n return (\n <div\n ref={overlayRef}\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n />\n );\n }\n\n return (\n <div\n ref={overlayRef}\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n >\n {visible.map((entry) => (\n <CursorLabel key={entry.other.clientId} entry={entry} />\n ))}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"LiveCursorOverlay.js","sourceRoot":"","sources":["../../../src/client/components/LiveCursorOverlay.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * LiveCursorOverlay — renders remote users' cursors over an absolutely-\n * positioned container.\n *\n * Cursor positions are expected as normalized coordinates (0–1 relative to\n * the container's content size) so different zoom/scroll positions map\n * correctly. Pass a `mapCoords` prop to handle non-identity transforms\n * (e.g. a zoomed canvas).\n *\n * The agent uses the same pointer shape with an \"AI\" label.\n *\n * Cursors fade out after 10 seconds of no movement.\n */\n\nimport { useState, useEffect, useRef, memo } from \"react\";\n\nimport type { OtherPresence, NormalizedPoint } from \"../../collab/presence.js\";\n\nexport interface CursorMapFn {\n /** Convert normalized coords to pixel offsets within the overlay container. */\n (norm: NormalizedPoint): { x: number; y: number };\n}\n\nexport interface LiveCursorOverlayProps {\n /** Remote participants with presence payload. */\n others: OtherPresence[];\n /**\n * Key inside presence payload that carries the cursor position.\n * Default: \"cursor\"\n * Expected shape: { x: number; y: number } (normalized 0–1).\n */\n cursorKey?: string;\n /**\n * Override coordinate mapping. Default: scale by container clientWidth/Height.\n * Pass this when the container uses transform: scale() or has virtual scroll.\n */\n mapCoords?: CursorMapFn;\n /**\n * Container element ref. Required when mapCoords is not provided —\n * used to compute pixel positions from normalized coords.\n */\n containerRef?: React.RefObject<HTMLElement | null>;\n /** Additional CSS class for the overlay div. */\n className?: string;\n}\n\nconst STALE_MS = 10_000; // Fade out cursors older than 10s\n\nfunction CursorPointer({ color }: { color: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"25\"\n height=\"29\"\n viewBox=\"0 0 25 29\"\n fill=\"none\"\n aria-hidden\n style={{\n display: \"block\",\n filter: \"drop-shadow(0 2px 3px rgba(15, 23, 42, 0.3))\",\n }}\n >\n <path\n d=\"M2.5 2.5L21.5 11L12.6 14.1L8.3 24.5L2.5 2.5Z\"\n fill={color}\n stroke=\"white\"\n strokeLinejoin=\"round\"\n strokeWidth=\"3\"\n />\n </svg>\n );\n}\n\ninterface CursorEntry {\n other: OtherPresence;\n x: number;\n y: number;\n lastSeen: number;\n}\n\nconst CursorLabel = memo(function CursorLabel({\n entry,\n}: {\n entry: CursorEntry;\n}) {\n const { other, x, y } = entry;\n const color = other.user.color || \"#94a3b8\";\n const label = other.isAgent ? \"AI\" : other.user.name || other.user.email;\n\n return (\n <div\n aria-label={`${label} cursor`}\n style={{\n position: \"absolute\",\n left: x,\n top: y,\n pointerEvents: \"none\",\n userSelect: \"none\",\n transform: \"translate(-2px, -2px)\",\n zIndex: 9999,\n transition: \"left 120ms linear, top 120ms linear\",\n width: 0,\n height: 0,\n }}\n >\n <CursorPointer color={color} />\n <div\n style={{\n position: \"absolute\",\n left: 31,\n top: 31,\n display: \"flex\",\n alignItems: \"center\",\n gap: 5,\n backgroundColor: color,\n color: \"#fff\",\n fontSize: 12,\n fontWeight: 500,\n lineHeight: \"16px\",\n padding: \"2px 7px\",\n borderRadius: 2,\n whiteSpace: \"nowrap\",\n boxShadow: \"0 5px 12px rgba(15, 23, 42, 0.16)\",\n maxWidth: 150,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {(other.user as { avatarUrl?: string }).avatarUrl ? (\n <img\n src={(other.user as { avatarUrl?: string }).avatarUrl}\n alt=\"\"\n style={{\n width: 14,\n height: 14,\n borderRadius: \"50%\",\n flexShrink: 0,\n }}\n />\n ) : null}\n {label}\n </div>\n </div>\n );\n});\n\nexport function LiveCursorOverlay({\n others,\n cursorKey = \"cursor\",\n mapCoords,\n containerRef,\n className,\n}: LiveCursorOverlayProps) {\n const overlayRef = useRef<HTMLDivElement>(null);\n const [, tick] = useState(0); // Force re-render to prune stale cursors\n const entriesRef = useRef<Map<number, CursorEntry>>(new Map());\n\n // Tick every 5s to prune stale cursors (no re-render storm).\n useEffect(() => {\n const id = setInterval(() => tick((n) => n + 1), 5_000);\n return () => clearInterval(id);\n }, []);\n\n // Build entries from others, computing pixel positions.\n const now = Date.now();\n const visible: CursorEntry[] = [];\n\n for (const other of others) {\n const pos = other.presence[cursorKey] as NormalizedPoint | undefined;\n if (!pos || typeof pos.x !== \"number\" || typeof pos.y !== \"number\")\n continue;\n\n // Compute pixel position.\n let px: number;\n let py: number;\n if (mapCoords) {\n const mapped = mapCoords(pos);\n px = mapped.x;\n py = mapped.y;\n } else {\n const container =\n containerRef?.current ?? overlayRef.current?.parentElement;\n const w = container ? container.clientWidth : 0;\n const h = container ? container.clientHeight : 0;\n px = pos.x * w;\n py = pos.y * h;\n }\n\n const prev = entriesRef.current.get(other.clientId);\n const lastSeen =\n prev && prev.x === px && prev.y === py ? prev.lastSeen : now;\n const entry: CursorEntry = { other, x: px, y: py, lastSeen };\n entriesRef.current.set(other.clientId, entry);\n\n if (now - lastSeen < STALE_MS) {\n visible.push(entry);\n }\n }\n\n // Remove entries for participants who left.\n for (const clientId of entriesRef.current.keys()) {\n if (!others.find((o) => o.clientId === clientId)) {\n entriesRef.current.delete(clientId);\n }\n }\n\n if (visible.length === 0) {\n return (\n <div\n ref={overlayRef}\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n />\n );\n }\n\n return (\n <div\n ref={overlayRef}\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n >\n {visible.map((entry) => (\n <CursorLabel key={entry.other.clientId} entry={entry} />\n ))}\n </div>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"PresenceBar.d.ts","sourceRoot":"","sources":["../../../src/client/components/PresenceBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,wBAAwB,CAAC;AAQhC,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AA8ND,wBAAgB,WAAW,CAAC,EAC1B,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,UAAc,EACd,SAAS,EACT,aAAa,EACb,cAAc,GACf,EAAE,gBAAgB,sCA+DlB"}
1
+ {"version":3,"file":"PresenceBar.d.ts","sourceRoot":"","sources":["../../../src/client/components/PresenceBar.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,UAAU,EAIhB,MAAM,wBAAwB,CAAC;AAQhC,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,4DAA4D;IAC5D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AA2OD,wBAAgB,WAAW,CAAC,EAC1B,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,UAAc,EACd,SAAS,EACT,aAAa,EACb,cAAc,GACf,EAAE,gBAAgB,sCA+DlB"}
@@ -58,7 +58,12 @@ function UserAvatar({ user, isFirst, onClick, isFollowing, }) {
58
58
  }, "aria-label": `${name} (${user.email})${isFollowing ? " — following" : ""}`, tabIndex: onClick ? 0 : undefined, role: onClick ? "button" : undefined, onClick: onClick, onKeyDown: (e) => {
59
59
  if (e.key === "Enter" || e.key === " ")
60
60
  onClick?.();
61
- }, children: initial }) }), _jsx(TooltipContent, { side: "bottom", children: isFollowing
61
+ }, children: user.avatarUrl ? (_jsx("img", { src: user.avatarUrl, alt: "", style: {
62
+ width: "100%",
63
+ height: "100%",
64
+ borderRadius: "50%",
65
+ objectFit: "cover",
66
+ } })) : (initial) }) }), _jsx(TooltipContent, { side: "bottom", children: isFollowing
62
67
  ? `Following ${name} — click to stop`
63
68
  : onClick
64
69
  ? `${name} — click to follow`
@@ -1 +1 @@
1
- {"version":3,"file":"PresenceBar.js","sourceRoot":"","sources":["../../../src/client/components/PresenceBar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from \"react\";\n\nimport {\n type CollabUser,\n dedupeCollabUsersByEmail,\n emailToColor,\n emailToName,\n} from \"../../collab/client.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"./ui/tooltip.js\";\n\nexport interface PresenceBarProps {\n /** Active collaborators on this document. */\n activeUsers: CollabUser[];\n /** Whether the agent has a durable presence entry. */\n agentPresent?: boolean;\n /** Whether the agent is actively making edits right now. */\n agentActive?: boolean;\n /** Current user's email (to exclude from the list). */\n currentUserEmail?: string;\n /** Max visible avatars before \"+N\" overflow. Default: 5 */\n maxVisible?: number;\n /** Additional CSS classes. */\n className?: string;\n /**\n * Called when an avatar is clicked. Receives the user being clicked\n * (or null for the agent avatar). Use this to start/stop follow mode.\n */\n onAvatarClick?: (user: CollabUser | null) => void;\n /**\n * The email of the user currently being followed. Highlighted with a\n * blue ring to indicate active follow mode.\n */\n followingEmail?: string | null;\n}\n\nconst AVATAR_SIZE = 28;\nconst OVERLAP = -8;\nconst BORDER_WIDTH = 2;\nconst FONT_SIZE = 12;\nconst AGENT_COLOR = \"#00B5FF\";\n\nconst baseAvatarStyle: React.CSSProperties = {\n width: AVATAR_SIZE,\n height: AVATAR_SIZE,\n borderRadius: \"50%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: FONT_SIZE,\n fontWeight: 700,\n color: \"#fff\",\n border: `${BORDER_WIDTH}px solid #fff`,\n flexShrink: 0,\n position: \"relative\",\n cursor: \"default\",\n boxSizing: \"border-box\",\n};\n\nconst containerStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n flexDirection: \"row\",\n};\n\nconst pulseKeyframes = `\n@keyframes _anPresencePulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n}\n`;\n\nlet styleInjected = false;\n\nfunction injectStyles() {\n if (styleInjected || typeof document === \"undefined\") return;\n const style = document.createElement(\"style\");\n style.textContent = pulseKeyframes;\n document.head.appendChild(style);\n styleInjected = true;\n}\n\nfunction UserAvatar({\n user,\n isFirst,\n onClick,\n isFollowing,\n}: {\n user: CollabUser;\n isFirst: boolean;\n onClick?: () => void;\n isFollowing?: boolean;\n}) {\n const color = user.color || emailToColor(user.email);\n const name = user.name || emailToName(user.email);\n const initial = name.charAt(0).toUpperCase();\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <div\n style={{\n ...baseAvatarStyle,\n backgroundColor: color,\n marginLeft: isFirst ? 0 : OVERLAP,\n cursor: onClick ? \"pointer\" : \"default\",\n boxShadow: isFollowing\n ? `0 0 0 2px #3b82f6, 0 0 0 4px #fff`\n : `0 0 0 2px #fff`,\n }}\n aria-label={`${name} (${user.email})${isFollowing ? \" — following\" : \"\"}`}\n tabIndex={onClick ? 0 : undefined}\n role={onClick ? \"button\" : undefined}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") onClick?.();\n }}\n >\n {initial}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n {isFollowing\n ? `Following ${name} — click to stop`\n : onClick\n ? `${name} — click to follow`\n : user.email}\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction AgentAvatar({\n active,\n onClick,\n isFollowing,\n}: {\n active: boolean;\n onClick?: () => void;\n isFollowing?: boolean;\n}) {\n injectStyles();\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n <div\n style={{\n ...baseAvatarStyle,\n backgroundColor: AGENT_COLOR,\n marginLeft: 0,\n animation: active ? \"_anPresencePulse 2s infinite\" : undefined,\n cursor: onClick ? \"pointer\" : \"default\",\n boxShadow: isFollowing\n ? `0 0 0 2px #3b82f6, 0 0 0 4px #fff`\n : undefined,\n }}\n title={\n isFollowing\n ? \"Following AI — click to stop\"\n : active\n ? \"AI is editing\"\n : \"AI agent\"\n }\n onClick={onClick}\n tabIndex={onClick ? 0 : undefined}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") onClick?.();\n }}\n role={onClick ? \"button\" : undefined}\n >\n A\n </div>\n {active && !isFollowing && <AgentEditingChip />}\n {isFollowing && (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n height: 20,\n padding: \"0 8px\",\n borderRadius: 9999,\n backgroundColor: `#3b82f620`,\n color: \"#3b82f6\",\n fontSize: 11,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n Following AI\n </span>\n )}\n </div>\n );\n}\n\nfunction AgentEditingChip() {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 4,\n height: 20,\n padding: \"0 8px\",\n borderRadius: 9999,\n backgroundColor: `${AGENT_COLOR}20`,\n color: AGENT_COLOR,\n fontSize: 11,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n backgroundColor: AGENT_COLOR,\n animation: \"_anPresencePulse 2s infinite\",\n flexShrink: 0,\n }}\n />\n AI editing\n </span>\n );\n}\n\nfunction OverflowBadge({\n count,\n isFirst,\n}: {\n count: number;\n isFirst: boolean;\n}) {\n return (\n <div\n style={{\n ...baseAvatarStyle,\n backgroundColor: \"rgba(255,255,255,0.1)\",\n color: \"rgba(255,255,255,0.5)\",\n marginLeft: isFirst ? 0 : OVERLAP,\n fontSize: 10,\n }}\n title={`${count} more collaborator${count === 1 ? \"\" : \"s\"}`}\n >\n +{count}\n </div>\n );\n}\n\nexport function PresenceBar({\n activeUsers,\n agentPresent,\n agentActive,\n currentUserEmail,\n maxVisible = 5,\n className,\n onAvatarClick,\n followingEmail,\n}: PresenceBarProps) {\n const { humanUsers, showAgent } = useMemo(() => {\n const currentEmail = currentUserEmail?.trim().toLowerCase();\n const uniqueUsers = dedupeCollabUsersByEmail(activeUsers);\n const humans = uniqueUsers.filter((u) => {\n const email = u.email.trim().toLowerCase();\n return email !== currentEmail && email !== \"agent@system\";\n });\n const hasAgentUser = uniqueUsers.some(\n (u) => u.email.trim().toLowerCase() === \"agent@system\",\n );\n return {\n humanUsers: humans,\n showAgent: agentPresent || agentActive || hasAgentUser,\n };\n }, [activeUsers, currentUserEmail, agentPresent, agentActive]);\n\n const visibleUsers = humanUsers.slice(0, maxVisible);\n const overflowCount = humanUsers.length - visibleUsers.length;\n\n if (!showAgent && humanUsers.length === 0) return null;\n\n const followingLower = followingEmail?.trim().toLowerCase() ?? null;\n const isFollowingAgent = followingLower === \"agent@system\";\n\n return (\n <TooltipProvider delayDuration={150}>\n <div style={containerStyle} className={className}>\n {showAgent && (\n <AgentAvatar\n active={!!agentActive}\n onClick={onAvatarClick ? () => onAvatarClick(null) : undefined}\n isFollowing={isFollowingAgent}\n />\n )}\n {visibleUsers.length > 0 && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n marginLeft: showAgent ? 6 : 0,\n }}\n >\n {visibleUsers.map((u, i) => (\n <UserAvatar\n key={u.email}\n user={u}\n isFirst={i === 0}\n onClick={onAvatarClick ? () => onAvatarClick(u) : undefined}\n isFollowing={\n followingLower != null &&\n u.email.trim().toLowerCase() === followingLower\n }\n />\n ))}\n {overflowCount > 0 && (\n <OverflowBadge count={overflowCount} isFirst={false} />\n )}\n </div>\n )}\n </div>\n </TooltipProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"PresenceBar.js","sourceRoot":"","sources":["../../../src/client/components/PresenceBar.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from \"react\";\n\nimport {\n type CollabUser,\n dedupeCollabUsersByEmail,\n emailToColor,\n emailToName,\n} from \"../../collab/client.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"./ui/tooltip.js\";\n\nexport interface PresenceBarProps {\n /** Active collaborators on this document. */\n activeUsers: CollabUser[];\n /** Whether the agent has a durable presence entry. */\n agentPresent?: boolean;\n /** Whether the agent is actively making edits right now. */\n agentActive?: boolean;\n /** Current user's email (to exclude from the list). */\n currentUserEmail?: string;\n /** Max visible avatars before \"+N\" overflow. Default: 5 */\n maxVisible?: number;\n /** Additional CSS classes. */\n className?: string;\n /**\n * Called when an avatar is clicked. Receives the user being clicked\n * (or null for the agent avatar). Use this to start/stop follow mode.\n */\n onAvatarClick?: (user: CollabUser | null) => void;\n /**\n * The email of the user currently being followed. Highlighted with a\n * blue ring to indicate active follow mode.\n */\n followingEmail?: string | null;\n}\n\nconst AVATAR_SIZE = 28;\nconst OVERLAP = -8;\nconst BORDER_WIDTH = 2;\nconst FONT_SIZE = 12;\nconst AGENT_COLOR = \"#00B5FF\";\n\nconst baseAvatarStyle: React.CSSProperties = {\n width: AVATAR_SIZE,\n height: AVATAR_SIZE,\n borderRadius: \"50%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: FONT_SIZE,\n fontWeight: 700,\n color: \"#fff\",\n border: `${BORDER_WIDTH}px solid #fff`,\n flexShrink: 0,\n position: \"relative\",\n cursor: \"default\",\n boxSizing: \"border-box\",\n};\n\nconst containerStyle: React.CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n flexDirection: \"row\",\n};\n\nconst pulseKeyframes = `\n@keyframes _anPresencePulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n}\n`;\n\nlet styleInjected = false;\n\nfunction injectStyles() {\n if (styleInjected || typeof document === \"undefined\") return;\n const style = document.createElement(\"style\");\n style.textContent = pulseKeyframes;\n document.head.appendChild(style);\n styleInjected = true;\n}\n\nfunction UserAvatar({\n user,\n isFirst,\n onClick,\n isFollowing,\n}: {\n user: CollabUser;\n isFirst: boolean;\n onClick?: () => void;\n isFollowing?: boolean;\n}) {\n const color = user.color || emailToColor(user.email);\n const name = user.name || emailToName(user.email);\n const initial = name.charAt(0).toUpperCase();\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <div\n style={{\n ...baseAvatarStyle,\n backgroundColor: color,\n marginLeft: isFirst ? 0 : OVERLAP,\n cursor: onClick ? \"pointer\" : \"default\",\n boxShadow: isFollowing\n ? `0 0 0 2px #3b82f6, 0 0 0 4px #fff`\n : `0 0 0 2px #fff`,\n }}\n aria-label={`${name} (${user.email})${isFollowing ? \" — following\" : \"\"}`}\n tabIndex={onClick ? 0 : undefined}\n role={onClick ? \"button\" : undefined}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") onClick?.();\n }}\n >\n {user.avatarUrl ? (\n <img\n src={user.avatarUrl}\n alt=\"\"\n style={{\n width: \"100%\",\n height: \"100%\",\n borderRadius: \"50%\",\n objectFit: \"cover\",\n }}\n />\n ) : (\n initial\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n {isFollowing\n ? `Following ${name} — click to stop`\n : onClick\n ? `${name} — click to follow`\n : user.email}\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction AgentAvatar({\n active,\n onClick,\n isFollowing,\n}: {\n active: boolean;\n onClick?: () => void;\n isFollowing?: boolean;\n}) {\n injectStyles();\n\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n <div\n style={{\n ...baseAvatarStyle,\n backgroundColor: AGENT_COLOR,\n marginLeft: 0,\n animation: active ? \"_anPresencePulse 2s infinite\" : undefined,\n cursor: onClick ? \"pointer\" : \"default\",\n boxShadow: isFollowing\n ? `0 0 0 2px #3b82f6, 0 0 0 4px #fff`\n : undefined,\n }}\n title={\n isFollowing\n ? \"Following AI — click to stop\"\n : active\n ? \"AI is editing\"\n : \"AI agent\"\n }\n onClick={onClick}\n tabIndex={onClick ? 0 : undefined}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") onClick?.();\n }}\n role={onClick ? \"button\" : undefined}\n >\n A\n </div>\n {active && !isFollowing && <AgentEditingChip />}\n {isFollowing && (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n height: 20,\n padding: \"0 8px\",\n borderRadius: 9999,\n backgroundColor: `#3b82f620`,\n color: \"#3b82f6\",\n fontSize: 11,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n Following AI\n </span>\n )}\n </div>\n );\n}\n\nfunction AgentEditingChip() {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 4,\n height: 20,\n padding: \"0 8px\",\n borderRadius: 9999,\n backgroundColor: `${AGENT_COLOR}20`,\n color: AGENT_COLOR,\n fontSize: 11,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n backgroundColor: AGENT_COLOR,\n animation: \"_anPresencePulse 2s infinite\",\n flexShrink: 0,\n }}\n />\n AI editing\n </span>\n );\n}\n\nfunction OverflowBadge({\n count,\n isFirst,\n}: {\n count: number;\n isFirst: boolean;\n}) {\n return (\n <div\n style={{\n ...baseAvatarStyle,\n backgroundColor: \"rgba(255,255,255,0.1)\",\n color: \"rgba(255,255,255,0.5)\",\n marginLeft: isFirst ? 0 : OVERLAP,\n fontSize: 10,\n }}\n title={`${count} more collaborator${count === 1 ? \"\" : \"s\"}`}\n >\n +{count}\n </div>\n );\n}\n\nexport function PresenceBar({\n activeUsers,\n agentPresent,\n agentActive,\n currentUserEmail,\n maxVisible = 5,\n className,\n onAvatarClick,\n followingEmail,\n}: PresenceBarProps) {\n const { humanUsers, showAgent } = useMemo(() => {\n const currentEmail = currentUserEmail?.trim().toLowerCase();\n const uniqueUsers = dedupeCollabUsersByEmail(activeUsers);\n const humans = uniqueUsers.filter((u) => {\n const email = u.email.trim().toLowerCase();\n return email !== currentEmail && email !== \"agent@system\";\n });\n const hasAgentUser = uniqueUsers.some(\n (u) => u.email.trim().toLowerCase() === \"agent@system\",\n );\n return {\n humanUsers: humans,\n showAgent: agentPresent || agentActive || hasAgentUser,\n };\n }, [activeUsers, currentUserEmail, agentPresent, agentActive]);\n\n const visibleUsers = humanUsers.slice(0, maxVisible);\n const overflowCount = humanUsers.length - visibleUsers.length;\n\n if (!showAgent && humanUsers.length === 0) return null;\n\n const followingLower = followingEmail?.trim().toLowerCase() ?? null;\n const isFollowingAgent = followingLower === \"agent@system\";\n\n return (\n <TooltipProvider delayDuration={150}>\n <div style={containerStyle} className={className}>\n {showAgent && (\n <AgentAvatar\n active={!!agentActive}\n onClick={onAvatarClick ? () => onAvatarClick(null) : undefined}\n isFollowing={isFollowingAgent}\n />\n )}\n {visibleUsers.length > 0 && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n marginLeft: showAgent ? 6 : 0,\n }}\n >\n {visibleUsers.map((u, i) => (\n <UserAvatar\n key={u.email}\n user={u}\n isFirst={i === 0}\n onClick={onAvatarClick ? () => onAvatarClick(u) : undefined}\n isFollowing={\n followingLower != null &&\n u.email.trim().toLowerCase() === followingLower\n }\n />\n ))}\n {overflowCount > 0 && (\n <OverflowBadge count={overflowCount} isFirst={false} />\n )}\n </div>\n )}\n </div>\n </TooltipProvider>\n );\n}\n"]}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * RecentEditHighlights — lingering, fading highlights over regions another
3
+ * participant (human or agent) just edited, with their name/avatar flag.
4
+ *
5
+ * The Google-Docs/Figma feel: when a collaborator or the AI edits something,
6
+ * the changed region glows in their color and the flag identifies them; the
7
+ * highlight fades out over the last portion of its lifetime instead of
8
+ * vanishing.
9
+ *
10
+ * Feed it `useRecentEdits(others)` (which reads participants' `recentEdits`
11
+ * awareness rings) and a `resolveRect` that maps an edit descriptor to a
12
+ * viewport DOMRect for your surface:
13
+ *
14
+ * const others = usePresence(awareness, ydoc?.clientID).others;
15
+ * const edits = useRecentEdits(others);
16
+ * <RecentEditHighlights
17
+ * edits={edits}
18
+ * resolveRect={(edit) =>
19
+ * edit.descriptor.kind === "selector"
20
+ * ? container.querySelector(edit.descriptor.selector)?.getBoundingClientRect() ?? null
21
+ * : null
22
+ * }
23
+ * containerRef={containerRef}
24
+ * />
25
+ */
26
+ import type { AttributedRecentEdit } from "../../collab/recent-edits.js";
27
+ export interface RecentEditHighlightsProps {
28
+ /** Attributed recent edits (from `useRecentEdits`). */
29
+ edits: AttributedRecentEdit[];
30
+ /**
31
+ * Resolver: maps an edit to a viewport-relative DOMRect, or null when the
32
+ * region can't be located (the edit is skipped).
33
+ */
34
+ resolveRect: (edit: AttributedRecentEdit) => DOMRect | null;
35
+ /** Container the highlights are positioned within (position: relative). */
36
+ containerRef: React.RefObject<HTMLElement | null>;
37
+ /** Highlight lifetime; should match useRecentEdits ttlMs. Default 6000. */
38
+ ttlMs?: number;
39
+ /** Additional CSS class for the overlay div. */
40
+ className?: string;
41
+ }
42
+ export declare function RecentEditHighlights({ edits, resolveRect, containerRef, ttlMs, className, }: RecentEditHighlightsProps): import("react").JSX.Element;
43
+ //# sourceMappingURL=RecentEditHighlights.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecentEditHighlights.d.ts","sourceRoot":"","sources":["../../../src/client/components/RecentEditHighlights.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B;;;OAGG;IACH,WAAW,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,OAAO,GAAG,IAAI,CAAC;IAC5D,2EAA2E;IAC3E,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuED,wBAAgB,oBAAoB,CAAC,EACnC,KAAK,EACL,WAAW,EACX,YAAY,EACZ,KAA0B,EAC1B,SAAS,GACV,EAAE,yBAAyB,+BAgG3B"}
@@ -0,0 +1,146 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * RecentEditHighlights — lingering, fading highlights over regions another
4
+ * participant (human or agent) just edited, with their name/avatar flag.
5
+ *
6
+ * The Google-Docs/Figma feel: when a collaborator or the AI edits something,
7
+ * the changed region glows in their color and the flag identifies them; the
8
+ * highlight fades out over the last portion of its lifetime instead of
9
+ * vanishing.
10
+ *
11
+ * Feed it `useRecentEdits(others)` (which reads participants' `recentEdits`
12
+ * awareness rings) and a `resolveRect` that maps an edit descriptor to a
13
+ * viewport DOMRect for your surface:
14
+ *
15
+ * const others = usePresence(awareness, ydoc?.clientID).others;
16
+ * const edits = useRecentEdits(others);
17
+ * <RecentEditHighlights
18
+ * edits={edits}
19
+ * resolveRect={(edit) =>
20
+ * edit.descriptor.kind === "selector"
21
+ * ? container.querySelector(edit.descriptor.selector)?.getBoundingClientRect() ?? null
22
+ * : null
23
+ * }
24
+ * containerRef={containerRef}
25
+ * />
26
+ */
27
+ import { memo, useEffect, useLayoutEffect, useRef, useState } from "react";
28
+ import { RECENT_EDIT_TTL_MS } from "../../collab/recent-edits.js";
29
+ const HighlightItem = memo(function HighlightItem({ h }) {
30
+ return (_jsx("div", { "aria-label": `${h.label} edited this`, style: {
31
+ position: "absolute",
32
+ top: h.rect.top,
33
+ left: h.rect.left,
34
+ width: h.rect.width,
35
+ height: h.rect.height,
36
+ borderRadius: 4,
37
+ pointerEvents: "none",
38
+ zIndex: 9997,
39
+ opacity: h.opacity,
40
+ transition: "opacity 400ms ease-out",
41
+ outline: `2px solid ${h.color}`,
42
+ outlineOffset: 2,
43
+ backgroundColor: `${h.color}1A`,
44
+ boxShadow: `0 0 0 1px ${h.color}33, 0 0 12px ${h.color}40`,
45
+ }, children: _jsxs("div", { style: {
46
+ position: "absolute",
47
+ top: -22,
48
+ left: 0,
49
+ display: "flex",
50
+ alignItems: "center",
51
+ gap: 4,
52
+ backgroundColor: h.color,
53
+ color: "#fff",
54
+ fontSize: 10,
55
+ fontWeight: 600,
56
+ padding: "2px 6px",
57
+ borderRadius: 3,
58
+ whiteSpace: "nowrap",
59
+ maxWidth: 180,
60
+ overflow: "hidden",
61
+ textOverflow: "ellipsis",
62
+ }, children: [h.avatarUrl ? (_jsx("img", { src: h.avatarUrl, alt: "", style: {
63
+ width: 12,
64
+ height: 12,
65
+ borderRadius: "50%",
66
+ flexShrink: 0,
67
+ } })) : null, h.label] }) }));
68
+ });
69
+ export function RecentEditHighlights({ edits, resolveRect, containerRef, ttlMs = RECENT_EDIT_TTL_MS, className, }) {
70
+ const [highlights, setHighlights] = useState([]);
71
+ const editsRef = useRef(edits);
72
+ editsRef.current = edits;
73
+ const resolveRef = useRef(resolveRect);
74
+ resolveRef.current = resolveRect;
75
+ const recompute = () => {
76
+ const container = containerRef.current;
77
+ if (!container) {
78
+ setHighlights([]);
79
+ return;
80
+ }
81
+ const containerRect = container.getBoundingClientRect();
82
+ const now = Date.now();
83
+ const next = [];
84
+ for (const edit of editsRef.current) {
85
+ const domRect = resolveRef.current(edit);
86
+ if (!domRect)
87
+ continue;
88
+ const top = domRect.top - containerRect.top;
89
+ const left = domRect.left - containerRect.left;
90
+ if (left + domRect.width < 0 ||
91
+ top + domRect.height < 0 ||
92
+ left > containerRect.width ||
93
+ top > containerRect.height) {
94
+ continue;
95
+ }
96
+ // Fade over the final 40% of the lifetime.
97
+ const age = now - edit.at;
98
+ const fadeStart = ttlMs * 0.6;
99
+ const opacity = age <= fadeStart
100
+ ? 1
101
+ : Math.max(0, 1 - (age - fadeStart) / (ttlMs - fadeStart));
102
+ next.push({
103
+ key: `${edit.clientId}:${edit.at}`,
104
+ color: edit.user.color || "#94a3b8",
105
+ label: edit.isAgent
106
+ ? edit.label
107
+ ? `AI — ${edit.label}`
108
+ : "AI edited"
109
+ : edit.label
110
+ ? `${edit.user.name} — ${edit.label}`
111
+ : edit.user.name,
112
+ avatarUrl: edit.user.avatarUrl,
113
+ isAgent: edit.isAgent,
114
+ opacity,
115
+ rect: { top, left, width: domRect.width, height: domRect.height },
116
+ });
117
+ }
118
+ setHighlights(next);
119
+ };
120
+ useLayoutEffect(() => {
121
+ recompute();
122
+ // eslint-disable-next-line react-hooks/exhaustive-deps
123
+ }, [edits, ttlMs]);
124
+ useEffect(() => {
125
+ const container = containerRef.current;
126
+ if (!container)
127
+ return;
128
+ const observer = new ResizeObserver(() => recompute());
129
+ observer.observe(container);
130
+ container.addEventListener("scroll", recompute, { passive: true });
131
+ window.addEventListener("scroll", recompute, { passive: true });
132
+ return () => {
133
+ observer.disconnect();
134
+ container.removeEventListener("scroll", recompute);
135
+ window.removeEventListener("scroll", recompute);
136
+ };
137
+ // eslint-disable-next-line react-hooks/exhaustive-deps
138
+ }, [containerRef]);
139
+ return (_jsx("div", { "aria-hidden": true, style: {
140
+ position: "absolute",
141
+ inset: 0,
142
+ pointerEvents: "none",
143
+ overflow: "hidden",
144
+ }, className: className, children: highlights.map((h) => (_jsx(HighlightItem, { h: h }, h.key))) }));
145
+ }
146
+ //# sourceMappingURL=RecentEditHighlights.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecentEditHighlights.js","sourceRoot":"","sources":["../../../src/client/components/RecentEditHighlights.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * RecentEditHighlights — lingering, fading highlights over regions another\n * participant (human or agent) just edited, with their name/avatar flag.\n *\n * The Google-Docs/Figma feel: when a collaborator or the AI edits something,\n * the changed region glows in their color and the flag identifies them; the\n * highlight fades out over the last portion of its lifetime instead of\n * vanishing.\n *\n * Feed it `useRecentEdits(others)` (which reads participants' `recentEdits`\n * awareness rings) and a `resolveRect` that maps an edit descriptor to a\n * viewport DOMRect for your surface:\n *\n * const others = usePresence(awareness, ydoc?.clientID).others;\n * const edits = useRecentEdits(others);\n * <RecentEditHighlights\n * edits={edits}\n * resolveRect={(edit) =>\n * edit.descriptor.kind === \"selector\"\n * ? container.querySelector(edit.descriptor.selector)?.getBoundingClientRect() ?? null\n * : null\n * }\n * containerRef={containerRef}\n * />\n */\n\nimport { memo, useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\nimport type { AttributedRecentEdit } from \"../../collab/recent-edits.js\";\nimport { RECENT_EDIT_TTL_MS } from \"../../collab/recent-edits.js\";\n\nexport interface RecentEditHighlightsProps {\n /** Attributed recent edits (from `useRecentEdits`). */\n edits: AttributedRecentEdit[];\n /**\n * Resolver: maps an edit to a viewport-relative DOMRect, or null when the\n * region can't be located (the edit is skipped).\n */\n resolveRect: (edit: AttributedRecentEdit) => DOMRect | null;\n /** Container the highlights are positioned within (position: relative). */\n containerRef: React.RefObject<HTMLElement | null>;\n /** Highlight lifetime; should match useRecentEdits ttlMs. Default 6000. */\n ttlMs?: number;\n /** Additional CSS class for the overlay div. */\n className?: string;\n}\n\ninterface Highlight {\n key: string;\n color: string;\n label: string;\n avatarUrl?: string;\n isAgent: boolean;\n opacity: number;\n rect: { top: number; left: number; width: number; height: number };\n}\n\nconst HighlightItem = memo(function HighlightItem({ h }: { h: Highlight }) {\n return (\n <div\n aria-label={`${h.label} edited this`}\n style={{\n position: \"absolute\",\n top: h.rect.top,\n left: h.rect.left,\n width: h.rect.width,\n height: h.rect.height,\n borderRadius: 4,\n pointerEvents: \"none\",\n zIndex: 9997,\n opacity: h.opacity,\n transition: \"opacity 400ms ease-out\",\n outline: `2px solid ${h.color}`,\n outlineOffset: 2,\n backgroundColor: `${h.color}1A`,\n boxShadow: `0 0 0 1px ${h.color}33, 0 0 12px ${h.color}40`,\n }}\n >\n <div\n style={{\n position: \"absolute\",\n top: -22,\n left: 0,\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n backgroundColor: h.color,\n color: \"#fff\",\n fontSize: 10,\n fontWeight: 600,\n padding: \"2px 6px\",\n borderRadius: 3,\n whiteSpace: \"nowrap\",\n maxWidth: 180,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {h.avatarUrl ? (\n <img\n src={h.avatarUrl}\n alt=\"\"\n style={{\n width: 12,\n height: 12,\n borderRadius: \"50%\",\n flexShrink: 0,\n }}\n />\n ) : null}\n {h.label}\n </div>\n </div>\n );\n});\n\nexport function RecentEditHighlights({\n edits,\n resolveRect,\n containerRef,\n ttlMs = RECENT_EDIT_TTL_MS,\n className,\n}: RecentEditHighlightsProps) {\n const [highlights, setHighlights] = useState<Highlight[]>([]);\n const editsRef = useRef(edits);\n editsRef.current = edits;\n const resolveRef = useRef(resolveRect);\n resolveRef.current = resolveRect;\n\n const recompute = () => {\n const container = containerRef.current;\n if (!container) {\n setHighlights([]);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const now = Date.now();\n const next: Highlight[] = [];\n\n for (const edit of editsRef.current) {\n const domRect = resolveRef.current(edit);\n if (!domRect) continue;\n\n const top = domRect.top - containerRect.top;\n const left = domRect.left - containerRect.left;\n if (\n left + domRect.width < 0 ||\n top + domRect.height < 0 ||\n left > containerRect.width ||\n top > containerRect.height\n ) {\n continue;\n }\n\n // Fade over the final 40% of the lifetime.\n const age = now - edit.at;\n const fadeStart = ttlMs * 0.6;\n const opacity =\n age <= fadeStart\n ? 1\n : Math.max(0, 1 - (age - fadeStart) / (ttlMs - fadeStart));\n\n next.push({\n key: `${edit.clientId}:${edit.at}`,\n color: edit.user.color || \"#94a3b8\",\n label: edit.isAgent\n ? edit.label\n ? `AI — ${edit.label}`\n : \"AI edited\"\n : edit.label\n ? `${edit.user.name} — ${edit.label}`\n : edit.user.name,\n avatarUrl: (edit.user as { avatarUrl?: string }).avatarUrl,\n isAgent: edit.isAgent,\n opacity,\n rect: { top, left, width: domRect.width, height: domRect.height },\n });\n }\n\n setHighlights(next);\n };\n\n useLayoutEffect(() => {\n recompute();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [edits, ttlMs]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() => recompute());\n observer.observe(container);\n container.addEventListener(\"scroll\", recompute, { passive: true });\n window.addEventListener(\"scroll\", recompute, { passive: true });\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", recompute);\n window.removeEventListener(\"scroll\", recompute);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [containerRef]);\n\n return (\n <div\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n >\n {highlights.map((h) => (\n <HighlightItem key={h.key} h={h} />\n ))}\n </div>\n );\n}\n"]}
@@ -18,6 +18,15 @@
18
18
  * </div>
19
19
  */
20
20
  import type { OtherPresence } from "../../collab/presence.js";
21
+ /**
22
+ * Selection descriptors may be a plain string (treated as the resolver
23
+ * input) or an object carrying a resolver input plus a human label
24
+ * ("Editing hero section").
25
+ */
26
+ export type SelectionDescriptor = string | {
27
+ selector: string;
28
+ label?: string;
29
+ };
21
30
  export interface RemoteSelectionRingsProps {
22
31
  /** Remote participants. */
23
32
  others: OtherPresence[];
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteSelectionRings.d.ts","sourceRoot":"","sources":["../../../src/client/components/RemoteSelectionRings.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,WAAW,yBAAyB;IACxC,2BAA2B;IAC3B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACpD;;;OAGG;IACH,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoDD,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,YAA0B,EAC1B,WAAW,EACX,YAAY,EACZ,SAAS,GACV,EAAE,yBAAyB,+BAmF3B"}
1
+ {"version":3,"file":"RemoteSelectionRings.d.ts","sourceRoot":"","sources":["../../../src/client/components/RemoteSelectionRings.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,WAAW,yBAAyB;IACxC,2BAA2B;IAC3B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACpD;;;OAGG;IACH,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAClD,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoED,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,YAA0B,EAC1B,WAAW,EACX,YAAY,EACZ,SAAS,GACV,EAAE,yBAAyB,+BA8F3B"}