@agent-native/core 0.90.1 → 0.90.3

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 (714) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +26 -0
  3. package/corpus/core/docs/content/agent-native-toolkit.mdx +87 -80
  4. package/corpus/core/docs/content/locales/ar-SA/agent-native-toolkit.mdx +89 -80
  5. package/corpus/core/docs/content/locales/de-DE/agent-native-toolkit.mdx +89 -80
  6. package/corpus/core/docs/content/locales/es-ES/agent-native-toolkit.mdx +89 -80
  7. package/corpus/core/docs/content/locales/fr-FR/agent-native-toolkit.mdx +89 -80
  8. package/corpus/core/docs/content/locales/hi-IN/agent-native-toolkit.mdx +89 -80
  9. package/corpus/core/docs/content/locales/ja-JP/agent-native-toolkit.mdx +89 -80
  10. package/corpus/core/docs/content/locales/ko-KR/agent-native-toolkit.mdx +89 -80
  11. package/corpus/core/docs/content/locales/pt-BR/agent-native-toolkit.mdx +89 -80
  12. package/corpus/core/docs/content/locales/zh-CN/agent-native-toolkit.mdx +89 -80
  13. package/corpus/core/docs/content/locales/zh-TW/agent-native-toolkit.mdx +89 -80
  14. package/corpus/core/docs/content/toolkit-agent-ux.mdx +43 -0
  15. package/corpus/core/docs/content/toolkit-app-adapters.mdx +9 -0
  16. package/corpus/core/docs/content/toolkit-collaboration-ui.mdx +12 -0
  17. package/corpus/core/docs/content/toolkit-collaboration.mdx +74 -0
  18. package/corpus/core/docs/content/toolkit-command-navigation.mdx +106 -0
  19. package/corpus/core/docs/content/toolkit-comments-review.mdx +98 -0
  20. package/corpus/core/docs/content/toolkit-history.mdx +95 -0
  21. package/corpus/core/docs/content/toolkit-observability.mdx +41 -0
  22. package/corpus/core/docs/content/toolkit-org-team.mdx +80 -0
  23. package/corpus/core/docs/content/toolkit-resources.mdx +57 -0
  24. package/corpus/core/docs/content/toolkit-settings.mdx +65 -0
  25. package/corpus/core/docs/content/toolkit-setup-connections.mdx +109 -0
  26. package/corpus/core/docs/content/toolkit-sharing-ui.mdx +18 -6
  27. package/corpus/core/docs/content/toolkit-sharing.mdx +81 -0
  28. package/corpus/core/docs/content/toolkit-shell-hooks.mdx +9 -0
  29. package/corpus/core/docs/content/toolkit-ui.mdx +9 -0
  30. package/corpus/core/package.json +35 -1
  31. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +19 -1
  32. package/corpus/core/src/agent/engine/anthropic-engine.ts +25 -1
  33. package/corpus/core/src/agent/engine/registry.ts +23 -16
  34. package/corpus/core/src/agent/production-agent.ts +37 -6
  35. package/corpus/core/src/client/AgentPanel.tsx +1 -1
  36. package/corpus/core/src/client/command-navigation/index.ts +15 -0
  37. package/corpus/core/src/client/comments-review/index.ts +1 -0
  38. package/corpus/core/src/client/history/VersionHistoryPanel.tsx +145 -0
  39. package/corpus/core/src/client/history/index.ts +18 -0
  40. package/corpus/core/src/client/history/use-history.ts +86 -0
  41. package/corpus/core/src/client/index.ts +76 -9
  42. package/corpus/core/src/client/org/OrgSwitcher.tsx +6 -6
  43. package/corpus/core/src/client/org/RequireActiveOrg.tsx +2 -2
  44. package/corpus/core/src/client/org/TeamPage.tsx +3 -3
  45. package/corpus/core/src/client/org/hooks.ts +32 -0
  46. package/corpus/core/src/client/org/index.ts +30 -1
  47. package/corpus/core/src/client/org-team/index.ts +1 -0
  48. package/corpus/core/src/client/review/ReviewStatusBadge.tsx +39 -0
  49. package/corpus/core/src/client/review/ReviewThreadPanel.tsx +278 -0
  50. package/corpus/core/src/client/review/index.ts +25 -0
  51. package/corpus/core/src/client/review/use-review.ts +114 -0
  52. package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +11 -6
  53. package/corpus/core/src/client/settings/index.ts +11 -1
  54. package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +94 -0
  55. package/corpus/core/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
  56. package/corpus/core/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
  57. package/corpus/core/src/client/setup-connections/index.ts +46 -0
  58. package/corpus/core/src/client/sharing/ShareButton.tsx +20 -14
  59. package/corpus/core/src/client/sharing/ShareDialog.tsx +3 -3
  60. package/corpus/core/src/client/use-action.ts +39 -2
  61. package/corpus/core/src/client/use-db-sync.ts +44 -18
  62. package/corpus/core/src/command-navigation/actions.ts +100 -0
  63. package/corpus/core/src/command-navigation/index.ts +12 -0
  64. package/corpus/core/src/comments-review/index.ts +1 -0
  65. package/corpus/core/src/db/create-get-db.ts +32 -2
  66. package/corpus/core/src/file-upload/builder.ts +24 -3
  67. package/corpus/core/src/file-upload/types.ts +3 -1
  68. package/corpus/core/src/history/actions/create-resource-version.ts +89 -0
  69. package/corpus/core/src/history/actions/get-resource-version.ts +60 -0
  70. package/corpus/core/src/history/actions/list-resource-history.ts +53 -0
  71. package/corpus/core/src/history/actions/list-resource-versions.ts +43 -0
  72. package/corpus/core/src/history/actions/restore-resource-version.ts +96 -0
  73. package/corpus/core/src/history/index.ts +27 -0
  74. package/corpus/core/src/history/registry.ts +99 -0
  75. package/corpus/core/src/history/store.ts +348 -0
  76. package/corpus/core/src/history/types.ts +69 -0
  77. package/corpus/core/src/index.ts +10 -0
  78. package/corpus/core/src/navigation/index.ts +170 -0
  79. package/corpus/core/src/org/index.ts +8 -0
  80. package/corpus/core/src/org/permissions.ts +30 -0
  81. package/corpus/core/src/org-team/index.ts +1 -0
  82. package/corpus/core/src/private-blob/registry.ts +1 -0
  83. package/corpus/core/src/review/actions/consume-review-feedback.ts +38 -0
  84. package/corpus/core/src/review/actions/create-review-comment.ts +107 -0
  85. package/corpus/core/src/review/actions/delete-review-comment.ts +55 -0
  86. package/corpus/core/src/review/actions/get-review-feedback.ts +54 -0
  87. package/corpus/core/src/review/actions/list-review-comments.ts +53 -0
  88. package/corpus/core/src/review/actions/reply-review-comment.ts +107 -0
  89. package/corpus/core/src/review/actions/resolve-review-thread.ts +60 -0
  90. package/corpus/core/src/review/actions/set-review-status.ts +58 -0
  91. package/corpus/core/src/review/index.ts +36 -0
  92. package/corpus/core/src/review/mentions.ts +44 -0
  93. package/corpus/core/src/review/registry.ts +99 -0
  94. package/corpus/core/src/review/store.ts +687 -0
  95. package/corpus/core/src/review/types.ts +97 -0
  96. package/corpus/core/src/server/action-discovery.ts +54 -0
  97. package/corpus/core/src/server/agent-engine-api-key-route.ts +5 -0
  98. package/corpus/core/src/server/credential-provider.ts +108 -0
  99. package/corpus/core/src/server/framework-request-handler.ts +52 -4
  100. package/corpus/core/src/setup-connections/index.ts +89 -0
  101. package/corpus/core/src/setup-connections/onboarding.ts +47 -0
  102. package/corpus/core/src/transcription/builder-transcription.ts +9 -2
  103. package/corpus/core/src/vite/action-types-plugin.ts +52 -0
  104. package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -1
  105. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +2 -2
  106. package/corpus/templates/analytics/app/global.css +22 -10
  107. package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -1
  108. package/corpus/templates/analytics/app/i18n-data.ts +81 -13
  109. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
  110. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
  111. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +528 -108
  112. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +466 -183
  113. package/corpus/templates/analytics/changelog/2026-07-07-session-replays-load-sooner-show-clearer-activity-timelines-.md +6 -0
  114. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +5 -0
  115. package/corpus/templates/assets/.agents/skills/logo-composite/SKILL.md +34 -6
  116. package/corpus/templates/assets/AGENTS.md +23 -4
  117. package/corpus/templates/assets/actions/_generation-preset-settings.ts +48 -0
  118. package/corpus/templates/assets/actions/_helpers.ts +8 -1
  119. package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +64 -0
  120. package/corpus/templates/assets/actions/create-generation-preset.ts +11 -3
  121. package/corpus/templates/assets/actions/generate-image-batch.ts +7 -2
  122. package/corpus/templates/assets/actions/generate-image.ts +342 -25
  123. package/corpus/templates/assets/actions/get-library.ts +4 -3
  124. package/corpus/templates/assets/actions/navigate.ts +2 -1
  125. package/corpus/templates/assets/actions/refresh-generation-run.ts +5 -1
  126. package/corpus/templates/assets/actions/update-asset.ts +1 -0
  127. package/corpus/templates/assets/actions/update-generation-preset.ts +8 -1
  128. package/corpus/templates/assets/actions/view-screen.ts +8 -1
  129. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +9 -1
  130. package/corpus/templates/assets/app/hooks/use-image-model-menu.ts +1 -0
  131. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +11 -0
  132. package/corpus/templates/assets/app/i18n/zh-TW.ts +64 -0
  133. package/corpus/templates/assets/app/i18n-data.ts +650 -0
  134. package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -1
  135. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +44 -33
  136. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1474 -0
  137. package/corpus/templates/assets/app/routes/library.tsx +43 -1
  138. package/corpus/templates/assets/server/lib/generation.ts +366 -44
  139. package/corpus/templates/assets/server/lib/image-processing.ts +252 -0
  140. package/corpus/templates/assets/server/lib/preset-skeleton.ts +137 -0
  141. package/corpus/templates/assets/shared/api.ts +47 -0
  142. package/corpus/templates/brain/app/routes/settings.tsx +2 -2
  143. package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +32 -6
  144. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +120 -40
  145. package/corpus/templates/calendar/app/hooks/use-people.ts +55 -0
  146. package/corpus/templates/calendar/changelog/2026-07-07-guest-suggestions-now-find-coworkers-from-your-google-worksp.md +6 -0
  147. package/corpus/templates/calendar/changelog/2026-07-07-zoom-stays-selected-after-connecting-it-from-a-draft-event.md +6 -0
  148. package/corpus/templates/clips/actions/create-recording.ts +5 -1
  149. package/corpus/templates/clips/actions/finalize-recording.ts +140 -1
  150. package/corpus/templates/clips/actions/import-loom-recording.ts +1 -0
  151. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +1 -0
  152. package/corpus/templates/clips/actions/request-transcript.ts +31 -0
  153. package/corpus/templates/clips/actions/set-thumbnail.ts +2 -0
  154. package/corpus/templates/clips/app/components/library/library-layout.tsx +7 -2
  155. package/corpus/templates/clips/app/components/library/organization-switcher.tsx +2 -2
  156. package/corpus/templates/clips/app/components/library/sort-menu.tsx +1 -1
  157. package/corpus/templates/clips/app/components/player/scrubber-position.ts +9 -0
  158. package/corpus/templates/clips/app/components/player/scrubber.tsx +5 -2
  159. package/corpus/templates/clips/app/components/player/share-dialog.tsx +69 -41
  160. package/corpus/templates/clips/app/components/player/video-player.tsx +38 -1
  161. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +114 -33
  162. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -3
  163. package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +9 -19
  164. package/corpus/templates/clips/app/routes/_app.library._index.tsx +27 -1
  165. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -3
  166. package/corpus/templates/clips/app/routes/record.tsx +178 -80
  167. package/corpus/templates/clips/changelog/2026-07-02-recordings-now-wait-for-storage-media-to-serve-before-finishing.md +6 -0
  168. package/corpus/templates/clips/changelog/2026-07-07-a-pending-app-update-no-longer-blocks-screen-recording-updat.md +6 -0
  169. package/corpus/templates/clips/changelog/2026-07-07-chrome-extension-recordings-keep-audio-after-refreshing-tab.md +6 -0
  170. package/corpus/templates/clips/changelog/2026-07-07-clip-playback-progress-now-starts-and-finishes-at-the-right-times.md +6 -0
  171. package/corpus/templates/clips/changelog/2026-07-07-sharing-public-clips-now-stays-focused-on-the-normal-link-wi.md +6 -0
  172. package/corpus/templates/clips/chrome-extension/src/background.ts +18 -0
  173. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +23 -8
  174. package/corpus/templates/clips/desktop/src/app.tsx +40 -3
  175. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +19 -7
  176. package/corpus/templates/clips/desktop/src/lib/permissions.ts +2 -0
  177. package/corpus/templates/clips/desktop/src/lib/updater.ts +25 -2
  178. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +7 -0
  179. package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +1 -0
  180. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +23 -6
  181. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +28 -3
  182. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +13 -6
  183. package/corpus/templates/clips/shared/finalize-recovery.ts +35 -3
  184. package/corpus/templates/content/AGENTS.md +52 -52
  185. package/corpus/templates/content/actions/_builder-cms-read-client.ts +188 -8
  186. package/corpus/templates/content/actions/_builder-docs-client.ts +41 -3
  187. package/corpus/templates/content/actions/_database-source-utils.ts +998 -160
  188. package/corpus/templates/content/actions/_database-utils.ts +44 -4
  189. package/corpus/templates/content/actions/_notion-action-utils.ts +6 -2
  190. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +23 -1
  191. package/corpus/templates/content/actions/attach-content-database-source.ts +85 -12
  192. package/corpus/templates/content/actions/change-content-database-source-role.ts +9 -1
  193. package/corpus/templates/content/actions/delete-content-database.ts +1 -0
  194. package/corpus/templates/content/actions/delete-document.ts +337 -52
  195. package/corpus/templates/content/actions/get-document.ts +11 -2
  196. package/corpus/templates/content/actions/list-content-databases.ts +57 -9
  197. package/corpus/templates/content/actions/prepare-builder-source-review.ts +23 -6
  198. package/corpus/templates/content/actions/refresh-content-database-source.ts +26 -3
  199. package/corpus/templates/content/actions/restore-content-database.ts +1 -0
  200. package/corpus/templates/content/actions/update-document.ts +43 -0
  201. package/corpus/templates/content/app/components/editor/BuilderBodySyncingNotice.tsx +21 -0
  202. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +0 -1
  203. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +70 -28
  204. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +69 -17
  205. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +4 -4
  206. package/corpus/templates/content/app/components/editor/body-hydration.ts +112 -0
  207. package/corpus/templates/content/app/components/editor/builder-body-hydration-pump.ts +52 -0
  208. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +9076 -2876
  209. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +41 -1
  210. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +36 -11
  211. package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +21 -1
  212. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +11 -1
  213. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +11 -8
  214. package/corpus/templates/content/app/global.css +41 -0
  215. package/corpus/templates/content/app/hooks/use-content-database.ts +346 -42
  216. package/corpus/templates/content/app/hooks/use-db-sync.ts +9 -0
  217. package/corpus/templates/content/app/hooks/use-documents.ts +47 -0
  218. package/corpus/templates/content/app/hooks/use-notion.ts +12 -10
  219. package/corpus/templates/content/app/i18n/zh-TW.ts +35 -0
  220. package/corpus/templates/content/app/i18n-data.ts +355 -0
  221. package/corpus/templates/content/app/root.tsx +22 -0
  222. package/corpus/templates/content/changelog/2026-07-01-builder-database-sources-keep-loading-rows-in-the-background.md +6 -0
  223. package/corpus/templates/content/changelog/2026-07-01-builder-source-attach-starts-with-usable-rows.md +6 -0
  224. package/corpus/templates/content/changelog/2026-07-01-builder-source-attachment-now-stays-connected-after-large.md +6 -0
  225. package/corpus/templates/content/changelog/2026-07-01-builder-source-refreshes-now-show-progress-for-large-docs-blog.md +6 -0
  226. package/corpus/templates/content/changelog/2026-07-01-database-pages-now-delete-to-trash-without-route-errors.md +6 -0
  227. package/corpus/templates/content/changelog/2026-07-02-builder-source-refreshes-recover-from-stalled-background-row.md +6 -0
  228. package/corpus/templates/content/changelog/2026-07-02-builder-sourced-rows-open-with-sync-protection.md +6 -0
  229. package/corpus/templates/content/changelog/2026-07-02-database-rows-and-pages-open-faster-from-recently-loaded-dat.md +6 -0
  230. package/corpus/templates/content/changelog/2026-07-02-preview-panels-close-reliably-narrow-sidebar-row-actions-sta.md +6 -0
  231. package/corpus/templates/content/changelog/2026-07-06-builder-sync-progress-no-longer-shows-continue.md +6 -0
  232. package/corpus/templates/content/changelog/2026-07-07-permanently-deleting-trashed-databases-now-finishes-reliably.md +6 -0
  233. package/corpus/templates/content/shared/api.ts +13 -0
  234. package/corpus/templates/content/shared/builder-mdx.ts +16 -3
  235. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +23 -13
  236. package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +98 -0
  237. package/corpus/templates/design/.agents/skills/shader-fills/SKILL.md +162 -0
  238. package/corpus/templates/design/AGENTS.md +9 -2
  239. package/corpus/templates/design/actions/add-breakpoint.ts +6 -3
  240. package/corpus/templates/design/actions/apply-a11y-fix.ts +57 -37
  241. package/corpus/templates/design/actions/apply-component-prop-edit.ts +41 -20
  242. package/corpus/templates/design/actions/apply-motion-edit.ts +251 -38
  243. package/corpus/templates/design/actions/apply-shader-fill.ts +90 -66
  244. package/corpus/templates/design/actions/apply-visual-edit.ts +282 -55
  245. package/corpus/templates/design/actions/create-component.ts +29 -60
  246. package/corpus/templates/design/actions/create-file.ts +9 -2
  247. package/corpus/templates/design/actions/duplicate-design.ts +31 -2
  248. package/corpus/templates/design/actions/edit-design.ts +36 -38
  249. package/corpus/templates/design/actions/generate-design-title.ts +87 -0
  250. package/corpus/templates/design/actions/generate-design.ts +53 -18
  251. package/corpus/templates/design/actions/generate-screens.ts +108 -4
  252. package/corpus/templates/design/actions/get-motion-timeline.ts +35 -7
  253. package/corpus/templates/design/actions/insert-asset.ts +34 -29
  254. package/corpus/templates/design/actions/insert-design-native-asset.ts +129 -32
  255. package/corpus/templates/design/actions/insert-figma-library-asset.ts +35 -30
  256. package/corpus/templates/design/actions/present-design-variants.ts +7 -2
  257. package/corpus/templates/design/actions/remove-motion-timeline.ts +31 -36
  258. package/corpus/templates/design/actions/update-file.ts +190 -75
  259. package/corpus/templates/design/app/components/design/BreakpointBar.tsx +403 -0
  260. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +469 -222
  261. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +708 -53
  262. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +83 -3
  263. package/corpus/templates/design/app/components/design/EditPanel.tsx +1091 -6948
  264. package/corpus/templates/design/app/components/design/LayersPanel.tsx +419 -85
  265. package/corpus/templates/design/app/components/design/MotionDock.tsx +1124 -103
  266. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2610 -1398
  267. package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +22 -0
  268. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2182 -235
  269. package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +187 -11
  270. package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +376 -1
  271. package/corpus/templates/design/app/components/design/bridge/shader-runtime.bridge.ts +746 -0
  272. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +17 -0
  273. package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +1 -1
  274. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +1 -3
  275. package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +1 -1
  276. package/corpus/templates/design/app/components/design/edit-panel/appearance-properties.tsx +518 -0
  277. package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +562 -0
  278. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +763 -0
  279. package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +94 -0
  280. package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +780 -0
  281. package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +446 -0
  282. package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +79 -0
  283. package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +315 -0
  284. package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +344 -0
  285. package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +594 -0
  286. package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +119 -0
  287. package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +248 -0
  288. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +45 -0
  289. package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +693 -0
  290. package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +724 -0
  291. package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +207 -0
  292. package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +628 -0
  293. package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +91 -0
  294. package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +649 -0
  295. package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +118 -0
  296. package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +88 -0
  297. package/corpus/templates/design/app/components/design/edit-panel/transform-helpers.ts +100 -0
  298. package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +117 -0
  299. package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +501 -0
  300. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +91 -40
  301. package/corpus/templates/design/app/components/design/inspector/BreakpointOverrideIndicator.tsx +82 -0
  302. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +189 -87
  303. package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +1097 -0
  304. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +44 -0
  305. package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +258 -0
  306. package/corpus/templates/design/app/components/design/inspector/MotionKeyframeDiamond.tsx +144 -0
  307. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +99 -9
  308. package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +116 -0
  309. package/corpus/templates/design/app/components/design/inspector/index.ts +26 -0
  310. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +29 -0
  311. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +171 -0
  312. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +220 -0
  313. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +35 -0
  314. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +134 -0
  315. package/corpus/templates/design/app/components/design/multi-screen/culling.ts +185 -0
  316. package/corpus/templates/design/app/components/design/multi-screen/gradient-overlay-geometry.ts +120 -0
  317. package/corpus/templates/design/app/components/design/multi-screen/types.ts +892 -0
  318. package/corpus/templates/design/app/components/design/multi-screen/vector-edit-geometry.ts +21 -0
  319. package/corpus/templates/design/app/components/design/types.ts +15 -0
  320. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +109 -5
  321. package/corpus/templates/design/app/global.css +8 -8
  322. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +259 -2
  323. package/corpus/templates/design/app/i18n/zh-TW.ts +163 -9
  324. package/corpus/templates/design/app/i18n-breakpoints.ts +205 -0
  325. package/corpus/templates/design/app/i18n-data.ts +1664 -152
  326. package/corpus/templates/design/app/i18n-motion.ts +563 -0
  327. package/corpus/templates/design/app/lib/design-import.ts +73 -0
  328. package/corpus/templates/design/app/pages/Index.tsx +41 -22
  329. package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +1 -1
  330. package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +1 -1
  331. package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +1 -1
  332. package/corpus/templates/design/changelog/2026-06-30-multi-select-outlines-now-stay-consistent-across-all-screens.md +1 -1
  333. package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +1 -1
  334. package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +1 -1
  335. package/corpus/templates/design/changelog/2026-07-05-designs-get-ai-generated-names-from-your-prompt.md +6 -0
  336. package/corpus/templates/design/changelog/2026-07-05-local-code-screens-keep-their-connection-when-duplicated-and.md +6 -0
  337. package/corpus/templates/design/changelog/2026-07-05-press-a-to-draw-screens-on-the-canvas-inside-a-screen-it-dr.md +6 -0
  338. package/corpus/templates/design/changelog/2026-07-06-3d-rotation-and-perspective-controls-on-every-element.md +6 -0
  339. package/corpus/templates/design/changelog/2026-07-06-ai-generated-and-duplicated-screens-now-get-their-editor-sel.md +6 -0
  340. package/corpus/templates/design/changelog/2026-07-06-applying-shaders-and-fills-in-quick-succession-can-no-longer.md +6 -0
  341. package/corpus/templates/design/changelog/2026-07-06-breakpoint-frames-in-the-overview-now-support-click-to-selec.md +6 -0
  342. package/corpus/templates/design/changelog/2026-07-06-breakpoint-segments-in-the-inspector-now-show-a-device-icon-.md +6 -0
  343. package/corpus/templates/design/changelog/2026-07-06-breakpoint-targeting-now-lives-in-one-compact-control-in-the.md +6 -0
  344. package/corpus/templates/design/changelog/2026-07-06-canvas-edits-can-no-longer-be-overwritten-by-stale-collabora.md +6 -0
  345. package/corpus/templates/design/changelog/2026-07-06-canvas-edits-inside-screens-save-reliably-again.md +6 -0
  346. package/corpus/templates/design/changelog/2026-07-06-cleaner-inspector-removed-the-ask-ai-box-from-the-design-tab.md +6 -0
  347. package/corpus/templates/design/changelog/2026-07-06-clicking-empty-canvas-space-now-deselects-an-element-inside-.md +6 -0
  348. package/corpus/templates/design/changelog/2026-07-06-dragging-an-element-onto-a-rectangle-now-nests-it-inside-wit.md +6 -0
  349. package/corpus/templates/design/changelog/2026-07-06-dragging-screens-and-objects-on-the-canvas-is-now-much-smoot.md +6 -0
  350. package/corpus/templates/design/changelog/2026-07-06-drawing-a-shape-or-text-on-the-canvas-no-longer-flashes-away.md +6 -0
  351. package/corpus/templates/design/changelog/2026-07-06-dropping-an-element-between-two-others-inside-a-screen-now-s.md +6 -0
  352. package/corpus/templates/design/changelog/2026-07-06-duplicating-a-screen-now-places-the-copy-exactly-where-you-d.md +6 -0
  353. package/corpus/templates/design/changelog/2026-07-06-edit-gradients-directly-on-elements-inside-screens-scale-str.md +6 -0
  354. package/corpus/templates/design/changelog/2026-07-06-edits-from-collaborators-and-the-agent-now-update-the-canvas.md +6 -0
  355. package/corpus/templates/design/changelog/2026-07-06-fixed-a-bug-where-most-style-position-and-text-edits-briefly.md +6 -0
  356. package/corpus/templates/design/changelog/2026-07-06-fixed-a-confusing-raw-error-message-when-a-file-upload-fails.md +6 -0
  357. package/corpus/templates/design/changelog/2026-07-06-fixed-a-rare-case-where-an-edit-could-be-silently-overwritte.md +6 -0
  358. package/corpus/templates/design/changelog/2026-07-06-fixed-inserted-assets-sometimes-disappearing-reappearing-or-.md +6 -0
  359. package/corpus/templates/design/changelog/2026-07-06-fixed-inspector-value-scrubbing-producing-erratic-numbers-an.md +6 -0
  360. package/corpus/templates/design/changelog/2026-07-06-fixed-padding-gap-and-min-max-size-scrubbing-not-updating-th.md +6 -0
  361. package/corpus/templates/design/changelog/2026-07-06-fixed-text-stroke-color-turning-black-and-glyphs-disappearin.md +6 -0
  362. package/corpus/templates/design/changelog/2026-07-06-fixed-the-collapsed-effects-and-stroke-inspector-sections-sh.md +6 -0
  363. package/corpus/templates/design/changelog/2026-07-06-fixed-the-new-design-dialog-closing-unexpectedly-when-using-.md +6 -0
  364. package/corpus/templates/design/changelog/2026-07-06-fixed-the-typography-section-missing-when-selecting-text-nes.md +6 -0
  365. package/corpus/templates/design/changelog/2026-07-06-full-view-no-longer-flashes-back-to-the-overview-on-entry-no.md +6 -0
  366. package/corpus/templates/design/changelog/2026-07-06-keyframe-animation-timeline-per-property-keyframes-easing-cu.md +6 -0
  367. package/corpus/templates/design/changelog/2026-07-06-moving-restyling-and-scrubbing-values-on-elements-in-ai-gene.md +6 -0
  368. package/corpus/templates/design/changelog/2026-07-06-padding-and-corner-radius-value-scrubbing-now-snaps-to-whole.md +6 -0
  369. package/corpus/templates/design/changelog/2026-07-06-padding-handles-now-only-resize-on-the-handle-line-itself-sh.md +6 -0
  370. package/corpus/templates/design/changelog/2026-07-06-preview-and-edit-hover-focus-and-pressed-states-with-real-cs.md +6 -0
  371. package/corpus/templates/design/changelog/2026-07-06-promoting-an-element-to-a-component-now-works-correctly-for-.md +6 -0
  372. package/corpus/templates/design/changelog/2026-07-06-reduced-url-history-churn-and-selection-overlay-flicker-whil.md +6 -0
  373. package/corpus/templates/design/changelog/2026-07-06-removed-the-decorative-dot-before-screen-names-in-the-overvi.md +6 -0
  374. package/corpus/templates/design/changelog/2026-07-06-responsive-breakpoints-edit-at-any-width-with-cascading-over.md +6 -0
  375. package/corpus/templates/design/changelog/2026-07-06-screen-labels-no-longer-turn-blue-when-you-hover-inside-the-.md +6 -0
  376. package/corpus/templates/design/changelog/2026-07-06-scrolling-a-screen-with-an-element-selected-stays-smooth-on-.md +6 -0
  377. package/corpus/templates/design/changelog/2026-07-06-selecting-multiple-elements-and-dragging-now-moves-the-whole.md +6 -0
  378. package/corpus/templates/design/changelog/2026-07-06-selection-borders-handles-and-value-readouts-now-stay-the-sa.md +6 -0
  379. package/corpus/templates/design/changelog/2026-07-06-selection-handles-and-editing-chrome-now-stay-a-constant-siz.md +6 -0
  380. package/corpus/templates/design/changelog/2026-07-06-shader-fills-and-effects-ai-authored-or-preset-glsl-shaders-.md +6 -0
  381. package/corpus/templates/design/changelog/2026-07-06-text-drawn-on-the-canvas-now-defaults-to-white-and-inter-in-.md +6 -0
  382. package/corpus/templates/design/changelog/2026-07-06-text-dropped-into-a-shape-now-stays-readable-instead-of-disa.md +6 -0
  383. package/corpus/templates/design/changelog/2026-07-06-the-add-tweak-controls-prompt-no-longer-jumps-to-the-corner-.md +6 -0
  384. package/corpus/templates/design/changelog/2026-07-06-the-padding-value-readout-now-stays-visible-while-you-hover-.md +6 -0
  385. package/corpus/templates/design/changelog/2026-07-06-the-selected-element-attachment-now-clears-from-the-chat-com.md +6 -0
  386. package/corpus/templates/design/changelog/2026-07-06-the-zoom-menu-is-more-compact-with-tight-rows-and-right-alig.md +6 -0
  387. package/corpus/templates/design/changelog/2026-07-06-undo-and-redo-no-longer-flash-the-screen-changes-now-apply-i.md +6 -0
  388. package/corpus/templates/design/changelog/2026-07-06-zoom-presets-like-zoom-to-50-now-stay-on-the-focused-screen-.md +6 -0
  389. package/corpus/templates/design/server/lib/import-design-files.ts +11 -2
  390. package/corpus/templates/design/server/source-workspace.ts +139 -59
  391. package/corpus/templates/design/shared/board-file.ts +11 -2
  392. package/corpus/templates/design/shared/breakpoint-media.ts +543 -0
  393. package/corpus/templates/design/shared/canvas-math.ts +354 -35
  394. package/corpus/templates/design/shared/code-layer.ts +277 -8
  395. package/corpus/templates/design/shared/design-state.ts +11 -4
  396. package/corpus/templates/design/shared/interaction-states.ts +548 -0
  397. package/corpus/templates/design/shared/motion-compiler.ts +186 -23
  398. package/corpus/templates/design/shared/motion-easing.ts +294 -0
  399. package/corpus/templates/design/shared/motion-timeline.ts +400 -34
  400. package/corpus/templates/design/shared/prompt-title.ts +95 -0
  401. package/corpus/templates/design/shared/responsive-classes.ts +448 -10
  402. package/corpus/templates/design/shared/screen-annotation.ts +46 -0
  403. package/corpus/templates/design/shared/shader-fills.ts +1009 -0
  404. package/corpus/templates/design/shared/shader-presets.ts +852 -4
  405. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +15 -2
  406. package/corpus/templates/slides/app/components/editor/ImportButton.tsx +10 -1
  407. package/corpus/templates/slides/app/lib/upload-response.ts +71 -0
  408. package/corpus/templates/slides/app/pages/DeckEditor.tsx +2 -2
  409. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  410. package/dist/agent/engine/ai-sdk-engine.js +15 -1
  411. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  412. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  413. package/dist/agent/engine/anthropic-engine.js +20 -1
  414. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  415. package/dist/agent/engine/registry.d.ts.map +1 -1
  416. package/dist/agent/engine/registry.js +22 -14
  417. package/dist/agent/engine/registry.js.map +1 -1
  418. package/dist/agent/production-agent.d.ts.map +1 -1
  419. package/dist/agent/production-agent.js +27 -7
  420. package/dist/agent/production-agent.js.map +1 -1
  421. package/dist/client/AgentPanel.js +1 -1
  422. package/dist/client/AgentPanel.js.map +1 -1
  423. package/dist/client/command-navigation/index.d.ts +4 -0
  424. package/dist/client/command-navigation/index.d.ts.map +1 -0
  425. package/dist/client/command-navigation/index.js +4 -0
  426. package/dist/client/command-navigation/index.js.map +1 -0
  427. package/dist/client/comments-review/index.d.ts +2 -0
  428. package/dist/client/comments-review/index.d.ts.map +1 -0
  429. package/dist/client/comments-review/index.js +2 -0
  430. package/dist/client/comments-review/index.js.map +1 -0
  431. package/dist/client/history/VersionHistoryPanel.d.ts +18 -0
  432. package/dist/client/history/VersionHistoryPanel.d.ts.map +1 -0
  433. package/dist/client/history/VersionHistoryPanel.js +24 -0
  434. package/dist/client/history/VersionHistoryPanel.js.map +1 -0
  435. package/dist/client/history/index.d.ts +3 -0
  436. package/dist/client/history/index.d.ts.map +1 -0
  437. package/dist/client/history/index.js +3 -0
  438. package/dist/client/history/index.js.map +1 -0
  439. package/dist/client/history/use-history.d.ts +46 -0
  440. package/dist/client/history/use-history.d.ts.map +1 -0
  441. package/dist/client/history/use-history.js +18 -0
  442. package/dist/client/history/use-history.js.map +1 -0
  443. package/dist/client/index.d.ts +6 -4
  444. package/dist/client/index.d.ts.map +1 -1
  445. package/dist/client/index.js +6 -4
  446. package/dist/client/index.js.map +1 -1
  447. package/dist/client/org/OrgSwitcher.js +5 -5
  448. package/dist/client/org/OrgSwitcher.js.map +1 -1
  449. package/dist/client/org/RequireActiveOrg.js +2 -2
  450. package/dist/client/org/RequireActiveOrg.js.map +1 -1
  451. package/dist/client/org/TeamPage.js +3 -3
  452. package/dist/client/org/TeamPage.js.map +1 -1
  453. package/dist/client/org/hooks.d.ts +12 -1
  454. package/dist/client/org/hooks.d.ts.map +1 -1
  455. package/dist/client/org/hooks.js +15 -0
  456. package/dist/client/org/hooks.js.map +1 -1
  457. package/dist/client/org/index.d.ts +4 -2
  458. package/dist/client/org/index.d.ts.map +1 -1
  459. package/dist/client/org/index.js +3 -1
  460. package/dist/client/org/index.js.map +1 -1
  461. package/dist/client/org-team/index.d.ts +2 -0
  462. package/dist/client/org-team/index.d.ts.map +1 -0
  463. package/dist/client/org-team/index.js +2 -0
  464. package/dist/client/org-team/index.js.map +1 -0
  465. package/dist/client/review/ReviewStatusBadge.d.ts +7 -0
  466. package/dist/client/review/ReviewStatusBadge.d.ts.map +1 -0
  467. package/dist/client/review/ReviewStatusBadge.js +19 -0
  468. package/dist/client/review/ReviewStatusBadge.js.map +1 -0
  469. package/dist/client/review/ReviewThreadPanel.d.ts +20 -0
  470. package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -0
  471. package/dist/client/review/ReviewThreadPanel.js +84 -0
  472. package/dist/client/review/ReviewThreadPanel.js.map +1 -0
  473. package/dist/client/review/index.d.ts +4 -0
  474. package/dist/client/review/index.d.ts.map +1 -0
  475. package/dist/client/review/index.js +4 -0
  476. package/dist/client/review/index.js.map +1 -0
  477. package/dist/client/review/use-review.d.ts +68 -0
  478. package/dist/client/review/use-review.d.ts.map +1 -0
  479. package/dist/client/review/use-review.js +22 -0
  480. package/dist/client/review/use-review.js.map +1 -0
  481. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  482. package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -6
  483. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  484. package/dist/client/settings/index.d.ts +1 -1
  485. package/dist/client/settings/index.d.ts.map +1 -1
  486. package/dist/client/settings/index.js +1 -1
  487. package/dist/client/settings/index.js.map +1 -1
  488. package/dist/client/setup-connections/BuilderConnectCard.d.ts +9 -0
  489. package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -0
  490. package/dist/client/setup-connections/BuilderConnectCard.js +25 -0
  491. package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -0
  492. package/dist/client/setup-connections/ProviderReadinessBadge.d.ts +8 -0
  493. package/dist/client/setup-connections/ProviderReadinessBadge.d.ts.map +1 -0
  494. package/dist/client/setup-connections/ProviderReadinessBadge.js +32 -0
  495. package/dist/client/setup-connections/ProviderReadinessBadge.js.map +1 -0
  496. package/dist/client/setup-connections/SetupConnectionsPage.d.ts +17 -0
  497. package/dist/client/setup-connections/SetupConnectionsPage.d.ts.map +1 -0
  498. package/dist/client/setup-connections/SetupConnectionsPage.js +10 -0
  499. package/dist/client/setup-connections/SetupConnectionsPage.js.map +1 -0
  500. package/dist/client/setup-connections/index.d.ts +7 -0
  501. package/dist/client/setup-connections/index.d.ts.map +1 -0
  502. package/dist/client/setup-connections/index.js +7 -0
  503. package/dist/client/setup-connections/index.js.map +1 -0
  504. package/dist/client/sharing/ShareButton.d.ts +4 -4
  505. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  506. package/dist/client/sharing/ShareButton.js +13 -7
  507. package/dist/client/sharing/ShareButton.js.map +1 -1
  508. package/dist/client/sharing/ShareDialog.js +3 -3
  509. package/dist/client/sharing/ShareDialog.js.map +1 -1
  510. package/dist/client/use-action.d.ts +3 -0
  511. package/dist/client/use-action.d.ts.map +1 -1
  512. package/dist/client/use-action.js +34 -3
  513. package/dist/client/use-action.js.map +1 -1
  514. package/dist/client/use-db-sync.d.ts +4 -0
  515. package/dist/client/use-db-sync.d.ts.map +1 -1
  516. package/dist/client/use-db-sync.js +37 -18
  517. package/dist/client/use-db-sync.js.map +1 -1
  518. package/dist/collab/routes.d.ts +1 -1
  519. package/dist/command-navigation/actions.d.ts +25 -0
  520. package/dist/command-navigation/actions.d.ts.map +1 -0
  521. package/dist/command-navigation/actions.js +64 -0
  522. package/dist/command-navigation/actions.js.map +1 -0
  523. package/dist/command-navigation/index.d.ts +4 -0
  524. package/dist/command-navigation/index.d.ts.map +1 -0
  525. package/dist/command-navigation/index.js +4 -0
  526. package/dist/command-navigation/index.js.map +1 -0
  527. package/dist/comments-review/index.d.ts +2 -0
  528. package/dist/comments-review/index.d.ts.map +1 -0
  529. package/dist/comments-review/index.js +2 -0
  530. package/dist/comments-review/index.js.map +1 -0
  531. package/dist/db/create-get-db.d.ts +25 -0
  532. package/dist/db/create-get-db.d.ts.map +1 -1
  533. package/dist/db/create-get-db.js +25 -2
  534. package/dist/db/create-get-db.js.map +1 -1
  535. package/dist/file-upload/builder.d.ts.map +1 -1
  536. package/dist/file-upload/builder.js +18 -2
  537. package/dist/file-upload/builder.js.map +1 -1
  538. package/dist/file-upload/types.d.ts +3 -0
  539. package/dist/file-upload/types.d.ts.map +1 -1
  540. package/dist/file-upload/types.js.map +1 -1
  541. package/dist/history/actions/create-resource-version.d.ts +10 -0
  542. package/dist/history/actions/create-resource-version.d.ts.map +1 -0
  543. package/dist/history/actions/create-resource-version.js +65 -0
  544. package/dist/history/actions/create-resource-version.js.map +1 -0
  545. package/dist/history/actions/get-resource-version.d.ts +10 -0
  546. package/dist/history/actions/get-resource-version.d.ts.map +1 -0
  547. package/dist/history/actions/get-resource-version.js +38 -0
  548. package/dist/history/actions/get-resource-version.js.map +1 -0
  549. package/dist/history/actions/list-resource-history.d.ts +10 -0
  550. package/dist/history/actions/list-resource-history.d.ts.map +1 -0
  551. package/dist/history/actions/list-resource-history.js +45 -0
  552. package/dist/history/actions/list-resource-history.js.map +1 -0
  553. package/dist/history/actions/list-resource-versions.d.ts +10 -0
  554. package/dist/history/actions/list-resource-versions.d.ts.map +1 -0
  555. package/dist/history/actions/list-resource-versions.js +35 -0
  556. package/dist/history/actions/list-resource-versions.js.map +1 -0
  557. package/dist/history/actions/restore-resource-version.d.ts +11 -0
  558. package/dist/history/actions/restore-resource-version.d.ts.map +1 -0
  559. package/dist/history/actions/restore-resource-version.js +59 -0
  560. package/dist/history/actions/restore-resource-version.js.map +1 -0
  561. package/dist/history/index.d.ts +4 -0
  562. package/dist/history/index.d.ts.map +1 -0
  563. package/dist/history/index.js +3 -0
  564. package/dist/history/index.js.map +1 -0
  565. package/dist/history/registry.d.ts +10 -0
  566. package/dist/history/registry.d.ts.map +1 -0
  567. package/dist/history/registry.js +61 -0
  568. package/dist/history/registry.js.map +1 -0
  569. package/dist/history/store.d.ts +34 -0
  570. package/dist/history/store.d.ts.map +1 -0
  571. package/dist/history/store.js +265 -0
  572. package/dist/history/store.js.map +1 -0
  573. package/dist/history/types.d.ts +55 -0
  574. package/dist/history/types.d.ts.map +1 -0
  575. package/dist/history/types.js +2 -0
  576. package/dist/history/types.js.map +1 -0
  577. package/dist/index.d.ts +6 -0
  578. package/dist/index.d.ts.map +1 -1
  579. package/dist/index.js +6 -0
  580. package/dist/index.js.map +1 -1
  581. package/dist/navigation/index.d.ts +53 -0
  582. package/dist/navigation/index.d.ts.map +1 -0
  583. package/dist/navigation/index.js +105 -0
  584. package/dist/navigation/index.js.map +1 -0
  585. package/dist/observability/routes.d.ts +3 -3
  586. package/dist/org/index.d.ts +1 -0
  587. package/dist/org/index.d.ts.map +1 -1
  588. package/dist/org/index.js +1 -0
  589. package/dist/org/index.js.map +1 -1
  590. package/dist/org/permissions.d.ts +7 -0
  591. package/dist/org/permissions.d.ts.map +1 -0
  592. package/dist/org/permissions.js +21 -0
  593. package/dist/org/permissions.js.map +1 -0
  594. package/dist/org-team/index.d.ts +2 -0
  595. package/dist/org-team/index.d.ts.map +1 -0
  596. package/dist/org-team/index.js +2 -0
  597. package/dist/org-team/index.js.map +1 -0
  598. package/dist/private-blob/registry.d.ts.map +1 -1
  599. package/dist/private-blob/registry.js +1 -0
  600. package/dist/private-blob/registry.js.map +1 -1
  601. package/dist/resources/handlers.d.ts +2 -2
  602. package/dist/review/actions/consume-review-feedback.d.ts +9 -0
  603. package/dist/review/actions/consume-review-feedback.d.ts.map +1 -0
  604. package/dist/review/actions/consume-review-feedback.js +29 -0
  605. package/dist/review/actions/consume-review-feedback.js.map +1 -0
  606. package/dist/review/actions/create-review-comment.d.ts +18 -0
  607. package/dist/review/actions/create-review-comment.d.ts.map +1 -0
  608. package/dist/review/actions/create-review-comment.js +81 -0
  609. package/dist/review/actions/create-review-comment.js.map +1 -0
  610. package/dist/review/actions/delete-review-comment.d.ts +10 -0
  611. package/dist/review/actions/delete-review-comment.d.ts.map +1 -0
  612. package/dist/review/actions/delete-review-comment.js +45 -0
  613. package/dist/review/actions/delete-review-comment.js.map +1 -0
  614. package/dist/review/actions/get-review-feedback.d.ts +10 -0
  615. package/dist/review/actions/get-review-feedback.d.ts.map +1 -0
  616. package/dist/review/actions/get-review-feedback.js +45 -0
  617. package/dist/review/actions/get-review-feedback.js.map +1 -0
  618. package/dist/review/actions/list-review-comments.d.ts +13 -0
  619. package/dist/review/actions/list-review-comments.d.ts.map +1 -0
  620. package/dist/review/actions/list-review-comments.js +44 -0
  621. package/dist/review/actions/list-review-comments.js.map +1 -0
  622. package/dist/review/actions/reply-review-comment.d.ts +16 -0
  623. package/dist/review/actions/reply-review-comment.d.ts.map +1 -0
  624. package/dist/review/actions/reply-review-comment.js +84 -0
  625. package/dist/review/actions/reply-review-comment.js.map +1 -0
  626. package/dist/review/actions/resolve-review-thread.d.ts +11 -0
  627. package/dist/review/actions/resolve-review-thread.d.ts.map +1 -0
  628. package/dist/review/actions/resolve-review-thread.js +46 -0
  629. package/dist/review/actions/resolve-review-thread.js.map +1 -0
  630. package/dist/review/actions/set-review-status.d.ts +9 -0
  631. package/dist/review/actions/set-review-status.d.ts.map +1 -0
  632. package/dist/review/actions/set-review-status.js +43 -0
  633. package/dist/review/actions/set-review-status.js.map +1 -0
  634. package/dist/review/index.d.ts +5 -0
  635. package/dist/review/index.d.ts.map +1 -0
  636. package/dist/review/index.js +4 -0
  637. package/dist/review/index.js.map +1 -0
  638. package/dist/review/mentions.d.ts +4 -0
  639. package/dist/review/mentions.d.ts.map +1 -0
  640. package/dist/review/mentions.js +39 -0
  641. package/dist/review/mentions.js.map +1 -0
  642. package/dist/review/registry.d.ts +10 -0
  643. package/dist/review/registry.d.ts.map +1 -0
  644. package/dist/review/registry.js +61 -0
  645. package/dist/review/registry.js.map +1 -0
  646. package/dist/review/store.d.ts +63 -0
  647. package/dist/review/store.d.ts.map +1 -0
  648. package/dist/review/store.js +558 -0
  649. package/dist/review/store.js.map +1 -0
  650. package/dist/review/types.d.ts +77 -0
  651. package/dist/review/types.d.ts.map +1 -0
  652. package/dist/review/types.js +2 -0
  653. package/dist/review/types.js.map +1 -0
  654. package/dist/secrets/routes.d.ts +9 -9
  655. package/dist/server/action-discovery.d.ts.map +1 -1
  656. package/dist/server/action-discovery.js +54 -0
  657. package/dist/server/action-discovery.js.map +1 -1
  658. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  659. package/dist/server/agent-engine-api-key-route.d.ts.map +1 -1
  660. package/dist/server/agent-engine-api-key-route.js +5 -0
  661. package/dist/server/agent-engine-api-key-route.js.map +1 -1
  662. package/dist/server/credential-provider.d.ts +26 -0
  663. package/dist/server/credential-provider.d.ts.map +1 -1
  664. package/dist/server/credential-provider.js +82 -0
  665. package/dist/server/credential-provider.js.map +1 -1
  666. package/dist/server/framework-request-handler.d.ts.map +1 -1
  667. package/dist/server/framework-request-handler.js +37 -1
  668. package/dist/server/framework-request-handler.js.map +1 -1
  669. package/dist/setup-connections/index.d.ts +6 -0
  670. package/dist/setup-connections/index.d.ts.map +1 -0
  671. package/dist/setup-connections/index.js +6 -0
  672. package/dist/setup-connections/index.js.map +1 -0
  673. package/dist/setup-connections/onboarding.d.ts +14 -0
  674. package/dist/setup-connections/onboarding.d.ts.map +1 -0
  675. package/dist/setup-connections/onboarding.js +23 -0
  676. package/dist/setup-connections/onboarding.js.map +1 -0
  677. package/dist/transcription/builder-transcription.d.ts +1 -0
  678. package/dist/transcription/builder-transcription.d.ts.map +1 -1
  679. package/dist/transcription/builder-transcription.js +5 -2
  680. package/dist/transcription/builder-transcription.js.map +1 -1
  681. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  682. package/dist/vite/action-types-plugin.js +52 -0
  683. package/dist/vite/action-types-plugin.js.map +1 -1
  684. package/docs/content/agent-native-toolkit.mdx +87 -80
  685. package/docs/content/locales/ar-SA/agent-native-toolkit.mdx +89 -80
  686. package/docs/content/locales/de-DE/agent-native-toolkit.mdx +89 -80
  687. package/docs/content/locales/es-ES/agent-native-toolkit.mdx +89 -80
  688. package/docs/content/locales/fr-FR/agent-native-toolkit.mdx +89 -80
  689. package/docs/content/locales/hi-IN/agent-native-toolkit.mdx +89 -80
  690. package/docs/content/locales/ja-JP/agent-native-toolkit.mdx +89 -80
  691. package/docs/content/locales/ko-KR/agent-native-toolkit.mdx +89 -80
  692. package/docs/content/locales/pt-BR/agent-native-toolkit.mdx +89 -80
  693. package/docs/content/locales/zh-CN/agent-native-toolkit.mdx +89 -80
  694. package/docs/content/locales/zh-TW/agent-native-toolkit.mdx +89 -80
  695. package/docs/content/toolkit-agent-ux.mdx +43 -0
  696. package/docs/content/toolkit-app-adapters.mdx +9 -0
  697. package/docs/content/toolkit-collaboration-ui.mdx +12 -0
  698. package/docs/content/toolkit-collaboration.mdx +74 -0
  699. package/docs/content/toolkit-command-navigation.mdx +106 -0
  700. package/docs/content/toolkit-comments-review.mdx +98 -0
  701. package/docs/content/toolkit-history.mdx +95 -0
  702. package/docs/content/toolkit-observability.mdx +41 -0
  703. package/docs/content/toolkit-org-team.mdx +80 -0
  704. package/docs/content/toolkit-resources.mdx +57 -0
  705. package/docs/content/toolkit-settings.mdx +65 -0
  706. package/docs/content/toolkit-setup-connections.mdx +109 -0
  707. package/docs/content/toolkit-sharing-ui.mdx +18 -6
  708. package/docs/content/toolkit-sharing.mdx +81 -0
  709. package/docs/content/toolkit-shell-hooks.mdx +9 -0
  710. package/docs/content/toolkit-ui.mdx +9 -0
  711. package/package.json +36 -2
  712. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +0 -153
  713. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +0 -133
  714. package/corpus/templates/design/app/pages/DesignEditor.tsx +0 -22924
@@ -14,12 +14,19 @@
14
14
  * - **No dependencies**: uses djb2 (not crypto) for hashing.
15
15
  */
16
16
 
17
+ import { motionEaseToCss } from "./motion-easing";
17
18
  import type {
18
19
  MotionEase,
19
20
  MotionKeyframe,
21
+ MotionPlaybackMode,
20
22
  MotionTimeline,
21
23
  MotionTrack,
22
24
  } from "./motion-timeline";
25
+ import {
26
+ MOTION_DEFAULT_PLAYBACK_MODE,
27
+ getMotionTrackTiming,
28
+ readTimelinePlaybackMode,
29
+ } from "./motion-timeline";
23
30
 
24
31
  // ─── Public API ───────────────────────────────────────────────────────────────
25
32
 
@@ -54,6 +61,13 @@ export function compile(timeline: MotionTimeline): CompileResult {
54
61
  return { css, hash: djb2(css) };
55
62
  }
56
63
 
64
+ // Timeline-level playback mode: explicit field first, then the stamp
65
+ // persisted in the tracks JSON, then the legacy default ("once").
66
+ const playbackMode: MotionPlaybackMode =
67
+ timeline.playbackMode ??
68
+ readTimelinePlaybackMode(tracks) ??
69
+ MOTION_DEFAULT_PLAYBACK_MODE;
70
+
57
71
  const kfBlocks: string[] = [];
58
72
  const rulesByTarget = new Map<
59
73
  string,
@@ -62,6 +76,8 @@ export function compile(timeline: MotionTimeline): CompileResult {
62
76
  durations: string[];
63
77
  timings: string[];
64
78
  fillModes: string[];
79
+ delays: string[];
80
+ hasDelay: boolean;
65
81
  }
66
82
  >();
67
83
 
@@ -83,7 +99,8 @@ export function compile(timeline: MotionTimeline): CompileResult {
83
99
  const name = animationName(targetNodeId, property);
84
100
  kfBlocks.push(keyframesBlock(name, property, sortedKeyframes, defaultEase));
85
101
 
86
- const dur = formatDuration(durationMs);
102
+ const timing = getMotionTrackTiming(track, durationMs);
103
+ const dur = formatDuration(timing.durationMs);
87
104
  const ease = sortedKeyframes[0]?.ease ?? defaultEase;
88
105
  assertSafeMotionCssToken(ease, "track ease");
89
106
  const targetRule = rulesByTarget.get(targetNodeId) ?? {
@@ -91,26 +108,53 @@ export function compile(timeline: MotionTimeline): CompileResult {
91
108
  durations: [],
92
109
  timings: [],
93
110
  fillModes: [],
111
+ delays: [],
112
+ hasDelay: false,
94
113
  };
95
114
  targetRule.names.push(name);
96
115
  targetRule.durations.push(dur);
97
- targetRule.timings.push(ease);
116
+ targetRule.timings.push(cssEase(ease));
98
117
  targetRule.fillModes.push("both");
118
+ targetRule.delays.push(formatDuration(timing.startMs));
119
+ if (timing.startMs > 0) targetRule.hasDelay = true;
99
120
  rulesByTarget.set(targetNodeId, targetRule);
100
121
  }
101
122
 
102
123
  const sortedTargets = [...rulesByTarget.entries()].sort(([a], [b]) =>
103
124
  a.localeCompare(b),
104
125
  );
105
- const ruleBlocks = sortedTargets.map(
106
- ([targetNodeId, rule]) =>
126
+ const ruleBlocks = sortedTargets.map(([targetNodeId, rule]) => {
127
+ const lines = [
128
+ ` animation-name: ${rule.names.join(", ")};`,
129
+ ` animation-duration: ${rule.durations.join(", ")};`,
130
+ ` animation-timing-function: ${rule.timings.join(", ")};`,
131
+ ` animation-fill-mode: ${rule.fillModes.join(", ")};`,
132
+ ];
133
+ // Emit optional lines only when used, keeping legacy timelines
134
+ // byte-identical to the previous compiler output.
135
+ if (rule.hasDelay) {
136
+ lines.push(` animation-delay: ${rule.delays.join(", ")};`);
137
+ }
138
+ if (playbackMode !== "once") {
139
+ lines.push(
140
+ ` animation-iteration-count: ${rule.names
141
+ .map(() => "infinite")
142
+ .join(", ")};`,
143
+ );
144
+ if (playbackMode === "ping-pong") {
145
+ lines.push(
146
+ ` animation-direction: ${rule.names
147
+ .map(() => "alternate")
148
+ .join(", ")};`,
149
+ );
150
+ }
151
+ }
152
+ return (
107
153
  `[data-agent-native-node-id="${escAttr(targetNodeId)}"] {\n` +
108
- ` animation-name: ${rule.names.join(", ")};\n` +
109
- ` animation-duration: ${rule.durations.join(", ")};\n` +
110
- ` animation-timing-function: ${rule.timings.join(", ")};\n` +
111
- ` animation-fill-mode: ${rule.fillModes.join(", ")};\n` +
112
- `}`,
113
- );
154
+ `${lines.join("\n")}\n` +
155
+ `}`
156
+ );
157
+ });
114
158
 
115
159
  const css = [
116
160
  ...kfBlocks,
@@ -130,7 +174,8 @@ export function compile(timeline: MotionTimeline): CompileResult {
130
174
  */
131
175
  export function parse(css: string): MotionTrack[] {
132
176
  const tracks: MotionTrack[] = [];
133
- const targetByAnimationName = parseAnimationTargets(css);
177
+ const rules = parseAnimationRules(css);
178
+ const timelineDurationMs = timelineSpanFromRules(rules);
134
179
  const kfRe = /@keyframes\s+(an-motion-[^\s{]+)\s*\{/g;
135
180
  let m: RegExpExecArray | null;
136
181
 
@@ -143,16 +188,60 @@ export function parse(css: string): MotionTrack[] {
143
188
  const body = extractBlock(css, bodyStart);
144
189
  if (body === null) continue;
145
190
 
146
- tracks.push({
147
- targetNodeId: targetByAnimationName.get(fullName) ?? decoded.targetNodeId,
191
+ const info = rules.byName.get(fullName);
192
+ const track: MotionTrack = {
193
+ targetNodeId: info?.targetNodeId ?? decoded.targetNodeId,
148
194
  property: decoded.property,
149
195
  keyframes: parseKeyframeBody(body, decoded.property),
150
- });
196
+ };
197
+ if (info?.delayMs !== undefined && info.delayMs > 0) {
198
+ track.delayMs = info.delayMs;
199
+ }
200
+ // Only surface an explicit per-track duration when it differs from the
201
+ // timeline duration (the first animation-duration in the CSS, which
202
+ // CSS-recovery also uses as the recovered timeline duration).
203
+ if (
204
+ info?.durationMs !== undefined &&
205
+ timelineDurationMs !== null &&
206
+ info.durationMs !== timelineDurationMs
207
+ ) {
208
+ track.durationMs = info.durationMs;
209
+ }
210
+ tracks.push(track);
211
+ }
212
+
213
+ if (
214
+ tracks.length > 0 &&
215
+ rules.playbackMode &&
216
+ rules.playbackMode !== "once"
217
+ ) {
218
+ tracks[0] = { ...tracks[0], timelinePlaybackMode: rules.playbackMode };
151
219
  }
152
220
 
153
221
  return tracks;
154
222
  }
155
223
 
224
+ /**
225
+ * Recover the timeline playback mode from a managed motion CSS body:
226
+ * `animation-iteration-count: infinite` + `animation-direction: alternate`
227
+ * → "ping-pong"; infinite alone → "loop"; finite/absent → "once". Returns
228
+ * `null` when the CSS contains no element animation rules at all.
229
+ */
230
+ export function parsePlaybackMode(css: string): MotionPlaybackMode | null {
231
+ return parseAnimationRules(css).playbackMode;
232
+ }
233
+
234
+ /**
235
+ * Recover the timeline's total span from a managed motion CSS body: the
236
+ * maximum `animation-delay + animation-duration` across all compiled rules
237
+ * (i.e. when the last track finishes). More robust than the first
238
+ * `animation-duration` when tracks carry per-track offsets/durations.
239
+ * Returns `null` when the CSS has no parsable durations.
240
+ */
241
+ export function parseTimelineSpanMs(css: string): number | null {
242
+ return timelineSpanFromRules(parseAnimationRules(css));
243
+ }
244
+
156
245
  /**
157
246
  * Extract the CSS body from a managed `<style data-agent-native-motion>` block
158
247
  * inside an HTML document. Returns `null` when the document has no managed block
@@ -317,13 +406,28 @@ function keyframesBlock(
317
406
  return (
318
407
  ` ${pct} {\n` +
319
408
  ` ${property}: ${kf.value};\n` +
320
- ` animation-timing-function: ${ease};\n` +
409
+ ` animation-timing-function: ${cssEase(ease)};\n` +
321
410
  ` }`
322
411
  );
323
412
  });
324
413
  return `@keyframes ${name} {\n${stops.join("\n")}\n}`;
325
414
  }
326
415
 
416
+ /**
417
+ * Convert a model ease token to its CSS form for emission. `spring(...)`
418
+ * tokens (not valid CSS) compile to sampled `linear(...)` stop lists; all
419
+ * other tokens pass through unchanged. The converted output is re-validated
420
+ * so nothing unsafe can enter the managed stylesheet.
421
+ */
422
+ function cssEase(ease: MotionEase): string {
423
+ const raw = String(ease);
424
+ const converted = motionEaseToCss(raw);
425
+ if (converted !== raw) {
426
+ assertSafeMotionCssToken(converted, "compiled spring ease");
427
+ }
428
+ return converted;
429
+ }
430
+
327
431
  /**
328
432
  * Build the `@media (prefers-reduced-motion: reduce)` block.
329
433
  * Always emitted so managed blocks are easily identified by parsers.
@@ -381,24 +485,83 @@ function unescAttr(value: string): string {
381
485
  return value.replace(/\\"/g, '"').replace(/\\\\/g, "\\");
382
486
  }
383
487
 
384
- function parseAnimationTargets(css: string): Map<string, string> {
385
- const targets = new Map<string, string>();
488
+ interface ParsedAnimationRuleEntry {
489
+ targetNodeId: string;
490
+ /** Recovered `animation-delay` for this animation name, ms. */
491
+ delayMs?: number;
492
+ /** Recovered `animation-duration` for this animation name, ms. */
493
+ durationMs?: number;
494
+ }
495
+
496
+ interface ParsedAnimationRules {
497
+ byName: Map<string, ParsedAnimationRuleEntry>;
498
+ /** Recovered playback mode, or null when no element rules exist. */
499
+ playbackMode: MotionPlaybackMode | null;
500
+ }
501
+
502
+ /** Parse a CSS `<time>` (e.g. "0.4s", "250ms") into milliseconds, or null. */
503
+ function parseCssTimeMs(value: string): number | null {
504
+ const m = /^([\d.]+)(ms|s)$/.exec(value.trim());
505
+ if (!m) return null;
506
+ const n = parseFloat(m[1]);
507
+ if (!Number.isFinite(n)) return null;
508
+ return Math.round(m[2] === "ms" ? n : n * 1000);
509
+ }
510
+
511
+ /** Max (delay + duration) across all parsed rules, or null when none. */
512
+ function timelineSpanFromRules(rules: ParsedAnimationRules): number | null {
513
+ let span: number | null = null;
514
+ for (const entry of rules.byName.values()) {
515
+ if (entry.durationMs === undefined) continue;
516
+ const end = (entry.delayMs ?? 0) + entry.durationMs;
517
+ if (span === null || end > span) span = end;
518
+ }
519
+ return span !== null && span > 0 ? span : null;
520
+ }
521
+
522
+ function parseAnimationRules(css: string): ParsedAnimationRules {
523
+ const byName = new Map<string, ParsedAnimationRuleEntry>();
524
+ let playbackMode: MotionPlaybackMode | null = null;
386
525
  const ruleRe =
387
526
  /\[data-agent-native-node-id="((?:\\.|[^"\\])*)"\]\s*\{([^}]*)\}/g;
388
527
  let m: RegExpExecArray | null;
389
528
 
529
+ const listOf = (body: string, prop: string): string[] => {
530
+ const match = body.match(
531
+ new RegExp(`${prop.replace(/-/g, "\\-")}\\s*:\\s*([^;]+)`),
532
+ );
533
+ if (!match) return [];
534
+ return match[1].split(",").map((part) => part.trim());
535
+ };
536
+
390
537
  while ((m = ruleRe.exec(css)) !== null) {
391
538
  const targetNodeId = unescAttr(m[1]);
392
539
  const body = m[2];
393
- const nameMatch = body.match(/animation-name\s*:\s*([^;]+)/);
394
- if (!nameMatch) continue;
395
- for (const name of nameMatch[1].split(",")) {
396
- const trimmed = name.trim();
397
- if (trimmed) targets.set(trimmed, targetNodeId);
540
+ const names = listOf(body, "animation-name");
541
+ if (names.length === 0) continue;
542
+ const durations = listOf(body, "animation-duration");
543
+ const delays = listOf(body, "animation-delay");
544
+ const iterations = listOf(body, "animation-iteration-count");
545
+ const directions = listOf(body, "animation-direction");
546
+
547
+ if (playbackMode === null) {
548
+ const infinite = iterations[0] === "infinite";
549
+ const alternate = directions[0] === "alternate";
550
+ playbackMode = infinite ? (alternate ? "ping-pong" : "loop") : "once";
398
551
  }
552
+
553
+ names.forEach((name, index) => {
554
+ if (!name) return;
555
+ const entry: ParsedAnimationRuleEntry = { targetNodeId };
556
+ const duration = parseCssTimeMs(durations[index] ?? durations[0] ?? "");
557
+ if (duration !== null) entry.durationMs = duration;
558
+ const delay = parseCssTimeMs(delays[index] ?? delays[0] ?? "");
559
+ if (delay !== null) entry.delayMs = delay;
560
+ byName.set(name, entry);
561
+ });
399
562
  }
400
563
 
401
- return targets;
564
+ return { byName, playbackMode };
402
565
  }
403
566
 
404
567
  /**
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Motion easing engine — Figma Motion parity (curves + springs).
3
+ *
4
+ * Pure, dependency-free helpers shared by the MotionDock easing panel, the
5
+ * shared timeline evaluator, and the motion compiler:
6
+ *
7
+ * - **Curve presets** matching Figma Motion's easing panel verbatim
8
+ * (Hold, Linear, Ease in, Ease out, Ease in and out, the three "back"
9
+ * overshoot curves, and Custom bezier).
10
+ * - **Spring easing** stored in the timeline model as a compact
11
+ * `spring(bounce[, settle])` token (bounce ∈ [0, 1], like Figma's single
12
+ * normalized "Bounce" control) and compiled to pure CSS via the
13
+ * `linear(...)` timing function — sampled from a real damped-oscillator
14
+ * solution, so the persisted artifact stays plain CSS.
15
+ * - **`linear(...)` evaluation** so scrub previews and CSS-recovered
16
+ * timelines replay spring easings exactly as the compiled stylesheet does.
17
+ *
18
+ * The canvas preview bridge (app/components/design/bridge/
19
+ * motion-preview.bridge.ts) carries a dependency-free copy of the sampling
20
+ * and evaluation algorithms below — keep the two in sync.
21
+ */
22
+
23
+ // ─── Curve presets (Figma Motion easing panel, Curve tab) ────────────────────
24
+
25
+ export interface MotionCurvePreset {
26
+ /** Menu label, verbatim from the Figma Motion easing panel. */
27
+ label: string;
28
+ /** CSS timing-function value stored on the keyframe. */
29
+ value: string;
30
+ }
31
+
32
+ /**
33
+ * Bezier-family presets exactly as labeled in Figma Motion's easing panel.
34
+ *
35
+ * - "Hold" jumps immediately to the segment's end value and stays
36
+ * (a discontinuous step) → CSS `step-start`.
37
+ * - "Ease in and out" is the live-verified (.42, 0, .58, 1).
38
+ * - The three "back" curves are overshoot beziers (control-point y outside
39
+ * [0, 1]); Figma's exact numbers are not published, so these use the
40
+ * canonical easeInBack / easeOutBack / easeInOutBack values.
41
+ * - "Custom bezier" is not listed here: the easing panel switches to editable
42
+ * x1,y1,x2,y2 fields + a draggable curve for any unrecognised
43
+ * `cubic-bezier(...)` value.
44
+ */
45
+ export const MOTION_CURVE_PRESETS: MotionCurvePreset[] = [
46
+ { label: "Hold", value: "step-start" },
47
+ { label: "Linear", value: "linear" },
48
+ { label: "Ease in", value: "cubic-bezier(0.42, 0, 1, 1)" },
49
+ { label: "Ease out", value: "cubic-bezier(0, 0, 0.58, 1)" },
50
+ { label: "Ease in and out", value: "cubic-bezier(0.42, 0, 0.58, 1)" },
51
+ { label: "Ease in back", value: "cubic-bezier(0.36, 0, 0.66, -0.56)" },
52
+ { label: "Ease out back", value: "cubic-bezier(0.34, 1.56, 0.64, 1)" },
53
+ {
54
+ label: "Ease in and out back",
55
+ value: "cubic-bezier(0.68, -0.6, 0.32, 1.6)",
56
+ },
57
+ ];
58
+
59
+ // ─── Spring model ─────────────────────────────────────────────────────────────
60
+
61
+ /**
62
+ * Editable spring parameters, matching Figma Motion's normalized spring UI:
63
+ * a single "Bounce" value in [0, 1]. `settle` is the fraction of the segment
64
+ * by which the spring reaches rest (1 = uses the whole segment) — it lets the
65
+ * named presets differ in perceived speed while remaining segment-normalized.
66
+ */
67
+ export interface MotionSpring {
68
+ /** Normalized bounciness in [0, 1]. 0 = no overshoot. */
69
+ bounce: number;
70
+ /** Fraction of the segment at which the spring settles, in (0, 1]. */
71
+ settle: number;
72
+ }
73
+
74
+ /** Default bounce for "Custom spring" (matches Figma's default of 0.25). */
75
+ export const MOTION_SPRING_DEFAULT_BOUNCE = 0.25;
76
+
77
+ export interface MotionSpringPreset {
78
+ /** Menu label, verbatim from the Figma Motion easing panel (Spring tab). */
79
+ label: string;
80
+ spring: MotionSpring;
81
+ /** The `spring(...)` token stored on the keyframe for this preset. */
82
+ value: string;
83
+ }
84
+
85
+ function roundParam(n: number): number {
86
+ return Math.round(n * 1000) / 1000;
87
+ }
88
+
89
+ /** Serialize spring params into the timeline's `spring(...)` ease token. */
90
+ export function springToken(spring: MotionSpring): string {
91
+ const bounce = roundParam(clamp01(spring.bounce));
92
+ const settle = roundParam(Math.min(1, Math.max(0.05, spring.settle)));
93
+ return settle === 1 ? `spring(${bounce})` : `spring(${bounce}, ${settle})`;
94
+ }
95
+
96
+ /**
97
+ * Spring presets as named in Figma Motion's easing panel. "Bouncy" uses the
98
+ * live-verified bounce of 0.69; Gentle/Quick/Slow expose no numbers in the
99
+ * Figma UI, so their params are tuned approximations of the described feel
100
+ * (Gentle: soft, no overshoot; Quick: fast settle; Slow: full-length glide).
101
+ */
102
+ export const MOTION_SPRING_PRESETS: MotionSpringPreset[] = [
103
+ { label: "Gentle", spring: { bounce: 0, settle: 0.8 } },
104
+ { label: "Quick", spring: { bounce: 0.2, settle: 0.5 } },
105
+ { label: "Bouncy", spring: { bounce: 0.69, settle: 1 } },
106
+ { label: "Slow", spring: { bounce: 0, settle: 1 } },
107
+ ].map((preset) => ({ ...preset, value: springToken(preset.spring) }));
108
+
109
+ function clamp01(x: number): number {
110
+ return x < 0 ? 0 : x > 1 ? 1 : x;
111
+ }
112
+
113
+ /**
114
+ * Parse a `spring(bounce[, settle])` ease token (or the bare keyword
115
+ * `spring`, which maps to the default custom spring). Returns `null` when the
116
+ * string is not a spring token.
117
+ */
118
+ export function parseSpringToken(ease: string): MotionSpring | null {
119
+ const raw = String(ease ?? "").trim();
120
+ if (/^spring$/i.test(raw)) {
121
+ return { bounce: MOTION_SPRING_DEFAULT_BOUNCE, settle: 1 };
122
+ }
123
+ const m = /^spring\(\s*([+-]?[\d.]+)\s*(?:,\s*([+-]?[\d.]+)\s*)?\)$/i.exec(
124
+ raw,
125
+ );
126
+ if (!m) return null;
127
+ const bounce = parseFloat(m[1]);
128
+ if (!Number.isFinite(bounce)) return null;
129
+ let settle = m[2] === undefined ? 1 : parseFloat(m[2]);
130
+ if (!Number.isFinite(settle)) return null;
131
+ settle = Math.min(1, Math.max(0.05, settle));
132
+ return { bounce: clamp01(bounce), settle };
133
+ }
134
+
135
+ /**
136
+ * Sample a normalized spring at progress `x ∈ [0, 1]`.
137
+ *
138
+ * Damped-oscillator position response scaled so the spring starts at 0,
139
+ * ends at 1, and is at rest by `x = settle`:
140
+ * - damping ratio ζ = 1 − bounce (underdamped when bounce > 0)
141
+ * - natural frequency ω chosen so the decay envelope ≈ 0 at the settle point
142
+ *
143
+ * Output may overshoot above 1 for bounce > 0 (by design — that is the
144
+ * bounce). Values at or after `settle` are exactly 1.
145
+ */
146
+ export function sampleSpring(spring: MotionSpring, x: number): number {
147
+ if (x <= 0) return 0;
148
+ const settle = Math.min(1, Math.max(0.05, spring.settle));
149
+ const u = x / settle;
150
+ if (u >= 1) return 1;
151
+ const zeta = Math.min(1, Math.max(0.02, 1 - clamp01(spring.bounce)));
152
+ // Envelope e^(-ζω) ≈ EPS at u = 1 so the motion is visually at rest there.
153
+ const EPS = 0.001;
154
+ const omega = Math.log(1 / EPS) / zeta;
155
+ if (zeta >= 1) {
156
+ // Critically damped: y = 1 − e^(−ωu)(1 + ωu).
157
+ return 1 - Math.exp(-omega * u) * (1 + omega * u);
158
+ }
159
+ const omegaD = omega * Math.sqrt(1 - zeta * zeta);
160
+ const decay = Math.exp(-zeta * omega * u);
161
+ return (
162
+ 1 -
163
+ decay *
164
+ (Math.cos(omegaD * u) + ((zeta * omega) / omegaD) * Math.sin(omegaD * u))
165
+ );
166
+ }
167
+
168
+ function formatStop(n: number): string {
169
+ if (!Number.isFinite(n)) return "0";
170
+ return (Math.round(n * 10000) / 10000).toString();
171
+ }
172
+
173
+ /**
174
+ * Compile a spring into a CSS `linear(...)` timing function by sampling the
175
+ * spring curve at evenly spaced stops. Deterministic: the same spring always
176
+ * produces byte-identical CSS. Bouncier springs get more stops so the
177
+ * oscillation survives the piecewise-linear approximation.
178
+ */
179
+ export function springToCssLinear(spring: MotionSpring): string {
180
+ const bounce = clamp01(spring.bounce);
181
+ const samples = 16 + Math.round(bounce * 34); // 16 … 50 interior steps
182
+ const stops: string[] = [];
183
+ for (let i = 0; i <= samples; i++) {
184
+ const x = i / samples;
185
+ stops.push(formatStop(i === samples ? 1 : sampleSpring(spring, x)));
186
+ }
187
+ return `linear(${stops.join(", ")})`;
188
+ }
189
+
190
+ /**
191
+ * Convert a timeline ease token into a CSS-valid timing function.
192
+ * `spring(...)` tokens compile to `linear(...)`; everything else (keywords,
193
+ * `cubic-bezier(...)`, `steps(...)`, `linear(...)`) passes through untouched.
194
+ */
195
+ export function motionEaseToCss(ease: string): string {
196
+ const spring = parseSpringToken(ease);
197
+ return spring ? springToCssLinear(spring) : ease;
198
+ }
199
+
200
+ // ─── CSS linear() evaluation ─────────────────────────────────────────────────
201
+
202
+ interface LinearStop {
203
+ value: number;
204
+ /** Input position in [0, 1], or null when the stop omitted a percentage. */
205
+ position: number | null;
206
+ }
207
+
208
+ /**
209
+ * Parse the argument list of a CSS `linear(...)` timing function. Each entry
210
+ * is `<number> <percentage>{0,2}`; a stop with two percentages expands into
211
+ * two stops. Returns `null` when `raw` is not a linear() function or has
212
+ * fewer than two stops.
213
+ */
214
+ export function parseCssLinearStops(raw: string): LinearStop[] | null {
215
+ const m = /^linear\(([^)]*)\)$/i.exec(String(raw ?? "").trim());
216
+ if (!m) return null;
217
+ const entries = m[1]
218
+ .split(",")
219
+ .map((entry) => entry.trim())
220
+ .filter((entry) => entry.length > 0);
221
+ if (entries.length < 2) return null;
222
+ const stops: LinearStop[] = [];
223
+ for (const entry of entries) {
224
+ const parts = entry.split(/\s+/);
225
+ const value = parseFloat(parts[0]);
226
+ if (!Number.isFinite(value)) return null;
227
+ const positions: number[] = [];
228
+ for (let i = 1; i < parts.length && i <= 2; i++) {
229
+ if (!/%$/.test(parts[i])) return null;
230
+ const pct = parseFloat(parts[i]);
231
+ if (!Number.isFinite(pct)) return null;
232
+ positions.push(pct / 100);
233
+ }
234
+ if (positions.length === 0) {
235
+ stops.push({ value, position: null });
236
+ } else {
237
+ for (const position of positions) stops.push({ value, position });
238
+ }
239
+ }
240
+ // Resolve omitted positions per the CSS spec: first defaults to 0, last to
241
+ // 1, interior stops distribute evenly between the surrounding known
242
+ // positions. Positions are also forced monotonic.
243
+ if (stops[0].position === null) stops[0].position = 0;
244
+ const last = stops[stops.length - 1];
245
+ if (last.position === null) last.position = 1;
246
+ let runningMax = stops[0].position as number;
247
+ for (let i = 0; i < stops.length; i++) {
248
+ const pos = stops[i].position;
249
+ if (pos !== null) {
250
+ const clamped = Math.max(runningMax, pos);
251
+ stops[i].position = clamped;
252
+ runningMax = clamped;
253
+ continue;
254
+ }
255
+ // Find the next stop with a known position.
256
+ let nextIdx = i + 1;
257
+ while (nextIdx < stops.length && stops[nextIdx].position === null) {
258
+ nextIdx++;
259
+ }
260
+ const prevPos = runningMax;
261
+ const nextPos = Math.max(prevPos, stops[nextIdx].position as number);
262
+ const span = nextIdx - (i - 1);
263
+ for (let j = i; j < nextIdx; j++) {
264
+ stops[j].position =
265
+ prevPos + ((j - (i - 1)) / span) * (nextPos - prevPos);
266
+ }
267
+ i = nextIdx - 1;
268
+ runningMax = nextPos;
269
+ }
270
+ return stops;
271
+ }
272
+
273
+ /**
274
+ * Evaluate a CSS `linear(...)` timing function at progress `x ∈ [0, 1]`.
275
+ * Returns `null` when `raw` is not a valid linear() function (so callers can
276
+ * fall through to other easing forms).
277
+ */
278
+ export function evaluateCssLinear(raw: string, x: number): number | null {
279
+ const stops = parseCssLinearStops(raw);
280
+ if (!stops) return null;
281
+ const clamped = clamp01(x);
282
+ if (clamped <= (stops[0].position as number)) return stops[0].value;
283
+ for (let i = 0; i < stops.length - 1; i++) {
284
+ const a = stops[i];
285
+ const b = stops[i + 1];
286
+ const aPos = a.position as number;
287
+ const bPos = b.position as number;
288
+ if (clamped > bPos) continue;
289
+ if (bPos === aPos) return b.value;
290
+ const ratio = (clamped - aPos) / (bPos - aPos);
291
+ return a.value + (b.value - a.value) * ratio;
292
+ }
293
+ return stops[stops.length - 1].value;
294
+ }