@agent-native/core 0.80.10 → 0.81.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 (267) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +53 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/agent/production-agent.ts +108 -15
  5. package/corpus/core/src/cli/design-connect.ts +419 -19
  6. package/corpus/core/src/client/AssistantChat.tsx +123 -26
  7. package/corpus/core/src/client/ConnectBuilderCard.tsx +1 -0
  8. package/corpus/core/src/client/chat/index.ts +1 -0
  9. package/corpus/core/src/client/chat/run-recovery.tsx +9 -7
  10. package/corpus/core/src/client/chat-view-transition.ts +33 -2
  11. package/corpus/core/src/client/composer/PromptComposer.tsx +21 -2
  12. package/corpus/core/src/client/index.ts +1 -0
  13. package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -4
  14. package/corpus/core/src/client/sharing/ShareButton.tsx +3 -3
  15. package/corpus/core/src/client/sse-event-processor.ts +9 -0
  16. package/corpus/core/src/client/use-agent-chat-home-handoff.ts +31 -3
  17. package/corpus/core/src/db/client.ts +29 -2
  18. package/corpus/core/src/provider-api/index.ts +29 -0
  19. package/corpus/core/src/server/core-routes-plugin.ts +58 -20
  20. package/corpus/core/src/styles/agent-native.css +54 -0
  21. package/corpus/core/src/usage/store.ts +2 -2
  22. package/corpus/templates/analytics/app/components/layout/Layout.tsx +118 -10
  23. package/corpus/templates/analytics/app/components/layout/layout-route-policy.ts +7 -0
  24. package/corpus/templates/analytics/app/global.css +8 -0
  25. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -1
  26. package/corpus/templates/analytics/app/lib/chat-handoff.ts +34 -0
  27. package/corpus/templates/analytics/app/pages/Ask.tsx +9 -18
  28. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
  29. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +109 -21
  30. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
  31. package/corpus/templates/analytics/changelog/2026-06-30-ask-opens-a-fresh-chat-unless-you-were-just-chatting-and-das.md +6 -0
  32. package/corpus/templates/analytics/changelog/2026-06-30-dashboard-email-reports-are-more-reliable-and-use-cleaner.md +6 -0
  33. package/corpus/templates/analytics/changelog/2026-06-30-dashboard-toolbar-controls-use-a-quieter-share-button-and-ve.md +6 -0
  34. package/corpus/templates/analytics/changelog/2026-06-30-session-replay-rows-show-whole-minute-durations-in-the-playl.md +6 -0
  35. package/corpus/templates/analytics/changelog/2026-06-30-session-replays-now-render-captured-styling-and-keep-the-eve.md +6 -0
  36. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +16 -3
  37. package/corpus/templates/analytics/server/lib/dashboard-report.ts +31 -14
  38. package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +9 -2
  39. package/corpus/templates/assets/AGENTS.md +4 -0
  40. package/corpus/templates/assets/actions/_tool-activity.ts +46 -0
  41. package/corpus/templates/assets/actions/generate-image-batch.ts +26 -5
  42. package/corpus/templates/assets/actions/generate-image.ts +118 -67
  43. package/corpus/templates/assets/actions/list-draft-assets.ts +50 -0
  44. package/corpus/templates/assets/actions/open-asset-picker.ts +9 -0
  45. package/corpus/templates/assets/actions/rerun-generation-run.ts +52 -31
  46. package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +100 -0
  47. package/corpus/templates/assets/app/global.css +15 -0
  48. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +4 -0
  49. package/corpus/templates/assets/app/i18n/zh-TW.ts +7 -0
  50. package/corpus/templates/assets/app/i18n-data.ts +61 -0
  51. package/corpus/templates/assets/app/routes/_index.tsx +4 -0
  52. package/corpus/templates/assets/app/routes/library.tsx +233 -52
  53. package/corpus/templates/assets/changelog/2026-06-29-image-generation-can-now-render-requested-text-and-respect-b.md +6 -0
  54. package/corpus/templates/assets/changelog/2026-06-30-image-generation-no-longer-looks-stuck-while-the-provider-is-still-working.md +6 -0
  55. package/corpus/templates/assets/changelog/2026-06-30-tagged-presets-now-control-the-image-aspect-ratio.md +6 -0
  56. package/corpus/templates/assets/changelog/2026-06-30-the-assets-picker-now-supports-a-vertical-embedded-layout-fo.md +6 -0
  57. package/corpus/templates/assets/server/lib/generation.ts +135 -11
  58. package/corpus/templates/assets/shared/api.ts +4 -0
  59. package/corpus/templates/clips/actions/finalize-recording.ts +1 -12
  60. package/corpus/templates/clips/actions/list-ai-requests.ts +60 -0
  61. package/corpus/templates/clips/app/hooks/use-auto-title.ts +24 -25
  62. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -5
  63. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -8
  64. package/corpus/templates/clips/changelog/2026-06-30-extension-save-recovery-avoids-false-upload-failures.md +6 -0
  65. package/corpus/templates/clips/changelog/2026-06-30-longer-chrome-extension-recordings-now-keep-saving-reliably-.md +6 -0
  66. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  67. package/corpus/templates/clips/chrome-extension/src/background.ts +19 -10
  68. package/corpus/templates/clips/chrome-extension/src/content-script.ts +38 -12
  69. package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +224 -0
  70. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +119 -16
  71. package/corpus/templates/clips/chrome-extension/src/overlay.ts +16 -0
  72. package/corpus/templates/clips/server/lib/recording-upload-state.ts +48 -0
  73. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +9 -1
  74. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +63 -13
  75. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +74 -0
  76. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +32 -0
  77. package/corpus/templates/design/AGENTS.md +27 -0
  78. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -1
  79. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -5
  80. package/corpus/templates/design/actions/apply-component-prop-edit.ts +76 -25
  81. package/corpus/templates/design/actions/apply-design-state.ts +17 -4
  82. package/corpus/templates/design/actions/apply-motion-edit.ts +76 -115
  83. package/corpus/templates/design/actions/apply-shader-fill.ts +148 -56
  84. package/corpus/templates/design/actions/capture-design-state.ts +27 -4
  85. package/corpus/templates/design/actions/connect-localhost.ts +59 -22
  86. package/corpus/templates/design/actions/delete-design.ts +20 -0
  87. package/corpus/templates/design/actions/export-zip.ts +23 -8
  88. package/corpus/templates/design/actions/generate-design.ts +53 -1
  89. package/corpus/templates/design/actions/get-component-details.ts +21 -26
  90. package/corpus/templates/design/actions/get-motion-timeline.ts +135 -10
  91. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +116 -0
  92. package/corpus/templates/design/actions/import-design-tokens.ts +521 -0
  93. package/corpus/templates/design/actions/index-design-tokens.ts +18 -5
  94. package/corpus/templates/design/actions/insert-design-native-asset.ts +268 -0
  95. package/corpus/templates/design/actions/insert-figma-library-asset.ts +233 -0
  96. package/corpus/templates/design/actions/list-design-extensions.ts +32 -10
  97. package/corpus/templates/design/actions/list-design-native-assets.ts +105 -0
  98. package/corpus/templates/design/actions/list-design-states.ts +19 -1
  99. package/corpus/templates/design/actions/list-figma-library-assets.ts +292 -0
  100. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +238 -0
  101. package/corpus/templates/design/actions/navigate.ts +18 -3
  102. package/corpus/templates/design/actions/open-component-source.ts +7 -2
  103. package/corpus/templates/design/actions/preview-component-prop-edit.ts +32 -26
  104. package/corpus/templates/design/actions/preview-shader-fill.ts +9 -11
  105. package/corpus/templates/design/actions/provider-api-catalog.ts +2 -2
  106. package/corpus/templates/design/actions/provider-api-docs.ts +1 -1
  107. package/corpus/templates/design/actions/provider-api-request.ts +3 -3
  108. package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +48 -0
  109. package/corpus/templates/design/actions/run-design-audit.ts +74 -10
  110. package/corpus/templates/design/actions/run-design-extension-action.ts +1 -1
  111. package/corpus/templates/design/actions/view-screen.ts +1 -1
  112. package/corpus/templates/design/actions/write-local-file.ts +213 -0
  113. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +244 -3197
  114. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +30 -20
  115. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +795 -289
  116. package/corpus/templates/design/app/components/design/EditPanel.tsx +635 -234
  117. package/corpus/templates/design/app/components/design/LayersPanel.tsx +124 -32
  118. package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +161 -0
  119. package/corpus/templates/design/app/components/design/MotionDock.tsx +244 -266
  120. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +491 -56
  121. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +55 -67
  122. package/corpus/templates/design/app/components/design/StatesPanel.tsx +38 -63
  123. package/corpus/templates/design/app/components/design/TokensPanel.tsx +264 -8
  124. package/corpus/templates/design/app/components/design/bridge/codegen.ts +125 -0
  125. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4037 -0
  126. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +62 -0
  127. package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +272 -0
  128. package/corpus/templates/design/app/components/design/bridge/nav.bridge.ts +116 -0
  129. package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +24 -0
  130. package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +78 -0
  131. package/corpus/templates/design/app/components/design/bridge/tsconfig.json +17 -0
  132. package/corpus/templates/design/app/components/design/bridge/tweak.bridge.ts +28 -0
  133. package/corpus/templates/design/app/components/design/bridge/zoom.bridge.ts +43 -0
  134. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +45 -16
  135. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +88 -9
  136. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +94 -9
  137. package/corpus/templates/design/app/components/layout/Layout.tsx +19 -3
  138. package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
  139. package/corpus/templates/design/app/global.css +7 -0
  140. package/corpus/templates/design/app/hooks/use-navigation-state.ts +23 -0
  141. package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
  142. package/corpus/templates/design/app/i18n-data.ts +369 -0
  143. package/corpus/templates/design/app/lib/pending-generation.ts +1 -0
  144. package/corpus/templates/design/app/pages/DesignEditor.tsx +3024 -616
  145. package/corpus/templates/design/app/pages/Index.tsx +5 -1
  146. package/corpus/templates/design/changelog/2026-06-30-applying-the-one-click-fix-for-a-small-tap-target-accessibil.md +6 -0
  147. package/corpus/templates/design/changelog/2026-06-30-canvas-creation-screen-dragging-undo-redo-and-image-fill-edi.md +6 -0
  148. package/corpus/templates/design/changelog/2026-06-30-component-prop-edits-and-shader-fills-now-preserve-rapid-sam.md +6 -0
  149. package/corpus/templates/design/changelog/2026-06-30-design-can-browse-figma-library-components-and-insert-them-i.md +6 -0
  150. package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +6 -0
  151. package/corpus/templates/design/changelog/2026-06-30-design-now-has-native-components-embedded-media-and-figma-im.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-30-design-preview-now-includes-a-publish-app-waitlist-option-fr.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-30-design-s-left-rail-now-matches-the-sidebar-chrome-and-uses-t.md +6 -0
  154. package/corpus/templates/design/changelog/2026-06-30-design-s-tools-create-menu-now-stays-compact-instead-of-rend.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-30-design-starter-prompts-now-begin-generating-immediately-and-.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-30-design-token-edits-now-stay-visible-in-previews-and-token-li.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-30-drawing-rectangles-on-the-all-screens-canvas-no-longer-flash.md +6 -0
  159. package/corpus/templates/design/changelog/2026-06-30-fixed-code-native-design-studio-edits-so-component-props-mot.md +6 -0
  160. package/corpus/templates/design/changelog/2026-06-30-fixed-visual-editing-hover-overlays-and-spacing-handles-so-s.md +6 -0
  161. package/corpus/templates/design/changelog/2026-06-30-motion-edits-now-save-automatically-without-a-separate-css-a.md +6 -0
  162. package/corpus/templates/design/changelog/2026-06-30-motion-timelines-now-reopen-as-editable-tracks-after-writing.md +6 -0
  163. package/corpus/templates/design/changelog/2026-06-30-new-design-prompts-with-uploaded-screenshots-work-reliably-o.md +6 -0
  164. package/corpus/templates/design/changelog/2026-06-30-screen-previews-in-all-screens-view-now-keep-rounded-outline.md +6 -0
  165. package/corpus/templates/design/changelog/2026-06-30-selection-outlines-now-sit-flush-on-rectangles-drawn-directl.md +6 -0
  166. package/corpus/templates/design/changelog/2026-06-30-share-options-use-a-tighter-design-editor-popover-with-compa.md +6 -0
  167. package/corpus/templates/design/changelog/2026-06-30-the-collapsed-motion-panel-now-stays-tucked-under-the-left-s.md +6 -0
  168. package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-now-shows-states-and-review-in-a-tighte.md +6 -0
  169. package/corpus/templates/design/changelog/2026-06-30-the-sidebar-keeps-the-organization-picker-space-stable-while.md +6 -0
  170. package/corpus/templates/design/changelog/2026-06-30-tokens-can-now-be-imported-from-pasted-notes-code-files-fold.md +6 -0
  171. package/corpus/templates/design/e2e/global-setup.ts +94 -2
  172. package/corpus/templates/design/e2e/helpers.ts +168 -65
  173. package/corpus/templates/design/package.json +3 -1
  174. package/corpus/templates/design/server/db/schema.ts +23 -0
  175. package/corpus/templates/design/server/handlers/uploads.ts +22 -1
  176. package/corpus/templates/design/server/lib/provider-api.ts +7 -4
  177. package/corpus/templates/design/server/lib/verify-write-grant.ts +108 -0
  178. package/corpus/templates/design/server/plugins/db.ts +39 -0
  179. package/corpus/templates/design/server/register-secrets.ts +38 -0
  180. package/corpus/templates/design/shared/board-file.ts +228 -0
  181. package/corpus/templates/design/shared/board-objects.ts +288 -0
  182. package/corpus/templates/design/shared/code-layer.ts +52 -0
  183. package/corpus/templates/design/shared/component-model.ts +35 -0
  184. package/corpus/templates/design/shared/motion-compiler.ts +137 -15
  185. package/corpus/templates/design/shared/motion-timeline.ts +2 -2
  186. package/corpus/templates/design/shared/resolve-tweaks.ts +32 -9
  187. package/corpus/templates/design/tsconfig.json +2 -1
  188. package/corpus/templates/slides/AGENTS.md +9 -0
  189. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -0
  190. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +4 -24
  191. package/corpus/templates/slides/app/lib/export-pdf-client.ts +29 -20
  192. package/corpus/templates/slides/app/lib/export-pptx-client.ts +365 -0
  193. package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -9
  194. package/corpus/templates/slides/app/vite-env.d.ts +18 -0
  195. package/corpus/templates/slides/changelog/2026-06-30-powerpoint-downloads-now-preserve-the-rendered-slide-layout-.md +6 -0
  196. package/corpus/templates/slides/changelog/2026-06-30-unavailable-decks-open-in-a-cleaner-full-height-centered-sta.md +6 -0
  197. package/corpus/templates/slides/package.json +1 -0
  198. package/corpus/templates/slides/vite.config.ts +1 -0
  199. package/dist/agent/production-agent.d.ts.map +1 -1
  200. package/dist/agent/production-agent.js +94 -10
  201. package/dist/agent/production-agent.js.map +1 -1
  202. package/dist/cli/design-connect.d.ts +25 -0
  203. package/dist/cli/design-connect.d.ts.map +1 -1
  204. package/dist/cli/design-connect.js +357 -18
  205. package/dist/cli/design-connect.js.map +1 -1
  206. package/dist/client/AssistantChat.d.ts +14 -0
  207. package/dist/client/AssistantChat.d.ts.map +1 -1
  208. package/dist/client/AssistantChat.js +115 -22
  209. package/dist/client/AssistantChat.js.map +1 -1
  210. package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
  211. package/dist/client/ConnectBuilderCard.js +1 -0
  212. package/dist/client/ConnectBuilderCard.js.map +1 -1
  213. package/dist/client/chat/index.d.ts +1 -1
  214. package/dist/client/chat/index.d.ts.map +1 -1
  215. package/dist/client/chat/index.js +1 -1
  216. package/dist/client/chat/index.js.map +1 -1
  217. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  218. package/dist/client/chat/run-recovery.js +5 -5
  219. package/dist/client/chat/run-recovery.js.map +1 -1
  220. package/dist/client/chat-view-transition.d.ts +6 -0
  221. package/dist/client/chat-view-transition.d.ts.map +1 -1
  222. package/dist/client/chat-view-transition.js +23 -2
  223. package/dist/client/chat-view-transition.js.map +1 -1
  224. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  225. package/dist/client/composer/PromptComposer.js +3 -2
  226. package/dist/client/composer/PromptComposer.js.map +1 -1
  227. package/dist/client/index.d.ts +1 -1
  228. package/dist/client/index.d.ts.map +1 -1
  229. package/dist/client/index.js +1 -1
  230. package/dist/client/index.js.map +1 -1
  231. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  232. package/dist/client/org/OrgSwitcher.js +11 -4
  233. package/dist/client/org/OrgSwitcher.js.map +1 -1
  234. package/dist/client/sharing/ShareButton.js +3 -3
  235. package/dist/client/sharing/ShareButton.js.map +1 -1
  236. package/dist/client/sse-event-processor.d.ts.map +1 -1
  237. package/dist/client/sse-event-processor.js +10 -0
  238. package/dist/client/sse-event-processor.js.map +1 -1
  239. package/dist/client/use-agent-chat-home-handoff.d.ts +8 -2
  240. package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
  241. package/dist/client/use-agent-chat-home-handoff.js +20 -6
  242. package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
  243. package/dist/collab/awareness.d.ts +2 -2
  244. package/dist/collab/awareness.d.ts.map +1 -1
  245. package/dist/collab/routes.d.ts +2 -2
  246. package/dist/db/client.d.ts +1 -0
  247. package/dist/db/client.d.ts.map +1 -1
  248. package/dist/db/client.js +28 -2
  249. package/dist/db/client.js.map +1 -1
  250. package/dist/notifications/routes.d.ts +3 -3
  251. package/dist/observability/routes.d.ts +3 -3
  252. package/dist/progress/routes.d.ts +1 -1
  253. package/dist/provider-api/index.d.ts +5 -4
  254. package/dist/provider-api/index.d.ts.map +1 -1
  255. package/dist/provider-api/index.js +28 -0
  256. package/dist/provider-api/index.js.map +1 -1
  257. package/dist/resources/handlers.d.ts +3 -3
  258. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  259. package/dist/server/core-routes-plugin.d.ts +25 -0
  260. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  261. package/dist/server/core-routes-plugin.js +43 -18
  262. package/dist/server/core-routes-plugin.js.map +1 -1
  263. package/dist/server/transcribe-voice.d.ts +1 -1
  264. package/dist/styles/agent-native.css +54 -0
  265. package/dist/usage/store.js +2 -2
  266. package/dist/usage/store.js.map +1 -1
  267. package/package.json +1 -1
@@ -826,6 +826,13 @@ const enUS = {
826
826
  noMatchingAssets: "No matching assets across your kits.",
827
827
  noMatchingLibraryAssets:
828
828
  "No matching {{mediaLabel}} assets in this library.",
829
+ drafts: "Drafts",
830
+ allLibraries: "All libraries",
831
+ noDrafts: "No drafts yet.",
832
+ noMatchingDrafts: "No matching drafts.",
833
+ recentDrafts: "Recent Drafts",
834
+ viewAllDrafts: "View all drafts",
835
+ draftAsset: "Draft asset",
829
836
  noReusableAssets:
830
837
  "No reusable assets yet. Select a kit to upload references or generate assets.",
831
838
  noNewAssetsUploaded: "No new assets were uploaded.",
@@ -2762,6 +2769,12 @@ export const messagesByLocale = {
2762
2769
  "zh-TW": mergeMessages(zhTW),
2763
2770
  "zh-CN": mergeMessages({
2764
2771
  library: {
2772
+ allLibraries: "所有库",
2773
+ noDrafts: "暂无草稿。",
2774
+ noMatchingDrafts: "没有匹配的草稿。",
2775
+ recentDrafts: "最近草稿",
2776
+ viewAllDrafts: "查看所有草稿",
2777
+ draftAsset: "草稿资产",
2765
2778
  addAssets: "添加资产",
2766
2779
  addAssetsDescription:
2767
2780
  "上传源素材或生成候选项,然后只将应指导未来生成的资产标记为参考。",
@@ -3500,6 +3513,12 @@ export const messagesByLocale = {
3500
3513
  }),
3501
3514
  "es-ES": mergeMessages({
3502
3515
  library: {
3516
+ allLibraries: "Todas las bibliotecas",
3517
+ noDrafts: "Aún no hay borradores.",
3518
+ noMatchingDrafts: "No hay borradores coincidentes.",
3519
+ recentDrafts: "Borradores recientes",
3520
+ viewAllDrafts: "Ver todos los borradores",
3521
+ draftAsset: "Borrador",
3503
3522
  addAssets: "Agregar activos",
3504
3523
  addAssetsDescription:
3505
3524
  "Cargue material fuente o genere candidatos, luego marque solo los activos que deberían guiar a las generaciones futuras como referencias.",
@@ -3963,6 +3982,12 @@ export const messagesByLocale = {
3963
3982
  }),
3964
3983
  "fr-FR": mergeMessages({
3965
3984
  library: {
3985
+ allLibraries: "Toutes les bibliothèques",
3986
+ noDrafts: "Aucun brouillon pour l'instant.",
3987
+ noMatchingDrafts: "Aucun brouillon correspondant.",
3988
+ recentDrafts: "Brouillons récents",
3989
+ viewAllDrafts: "Voir tous les brouillons",
3990
+ draftAsset: "Brouillon",
3966
3991
  addAssets: "Ajouter des éléments",
3967
3992
  addAssetsDescription:
3968
3993
  "Téléchargez le matériel source ou générez des candidats, puis marquez uniquement les atouts qui devraient guider les générations futures comme références.",
@@ -4404,6 +4429,12 @@ export const messagesByLocale = {
4404
4429
  }),
4405
4430
  "de-DE": mergeMessages({
4406
4431
  library: {
4432
+ allLibraries: "Alle Bibliotheken",
4433
+ noDrafts: "Noch keine Entwürfe.",
4434
+ noMatchingDrafts: "Keine passenden Entwürfe.",
4435
+ recentDrafts: "Letzte Entwürfe",
4436
+ viewAllDrafts: "Alle Entwürfe anzeigen",
4437
+ draftAsset: "Entwurf",
4407
4438
  addAssets: "Assets hinzufügen",
4408
4439
  addAssetsDescription:
4409
4440
  "Laden Sie Quellmaterial hoch oder generieren Sie Kandidaten und markieren Sie dann nur die Assets, die künftigen Generationen als Referenz dienen sollen.",
@@ -4753,6 +4784,12 @@ export const messagesByLocale = {
4753
4784
  }),
4754
4785
  "ja-JP": mergeMessages({
4755
4786
  library: {
4787
+ allLibraries: "すべてのライブラリ",
4788
+ noDrafts: "下書きはまだありません。",
4789
+ noMatchingDrafts: "一致する下書きはありません。",
4790
+ recentDrafts: "最近の下書き",
4791
+ viewAllDrafts: "すべての下書きを表示",
4792
+ draftAsset: "下書きアセット",
4756
4793
  addAssets: "アセットの追加",
4757
4794
  addAssetsDescription:
4758
4795
  "ソース素材をアップロードするか候補を生成し、将来の世代を導く必要がある資産のみを参照としてマークします。",
@@ -5092,6 +5129,12 @@ export const messagesByLocale = {
5092
5129
  }),
5093
5130
  "ko-KR": mergeMessages({
5094
5131
  library: {
5132
+ allLibraries: "모든 라이브러리",
5133
+ noDrafts: "아직 초안이 없습니다.",
5134
+ noMatchingDrafts: "일치하는 초안이 없습니다.",
5135
+ recentDrafts: "최근 초안",
5136
+ viewAllDrafts: "모든 초안 보기",
5137
+ draftAsset: "초안 자산",
5095
5138
  addAssets: "자산 추가",
5096
5139
  addAssetsDescription:
5097
5140
  "원본 자료를 업로드하거나 후보를 생성한 후, 미래 세대를 이끌어야 할 자산만 참고 자료로 표시하세요.",
@@ -5430,6 +5473,12 @@ export const messagesByLocale = {
5430
5473
  }),
5431
5474
  "pt-BR": mergeMessages({
5432
5475
  library: {
5476
+ allLibraries: "Todas as bibliotecas",
5477
+ noDrafts: "Ainda não há rascunhos.",
5478
+ noMatchingDrafts: "Nenhum rascunho correspondente.",
5479
+ recentDrafts: "Rascunhos recentes",
5480
+ viewAllDrafts: "Ver todos os rascunhos",
5481
+ draftAsset: "Rascunho",
5433
5482
  addAssets: "Adicionar recursos",
5434
5483
  addAssetsDescription:
5435
5484
  "Carregue o material de origem ou gere candidatos e marque apenas os ativos que devem orientar as gerações futuras como referências.",
@@ -5870,6 +5919,12 @@ export const messagesByLocale = {
5870
5919
  }),
5871
5920
  "hi-IN": mergeMessages({
5872
5921
  library: {
5922
+ allLibraries: "सभी लाइब्रेरी",
5923
+ noDrafts: "अभी तक कोई ड्राफ़्ट नहीं।",
5924
+ noMatchingDrafts: "कोई मिलान वाला ड्राफ़्ट नहीं।",
5925
+ recentDrafts: "हाल के ड्राफ़्ट",
5926
+ viewAllDrafts: "सभी ड्राफ़्ट देखें",
5927
+ draftAsset: "ड्राफ़्ट एसेट",
5873
5928
  addAssets: "संपत्तियां जोड़ें",
5874
5929
  addAssetsDescription:
5875
5930
  "स्रोत सामग्री अपलोड करें या उम्मीदवार तैयार करें, फिर केवल उन संपत्तियों को चिह्नित करें जो भविष्य की पीढ़ियों को संदर्भ के रूप में मार्गदर्शन करें।",
@@ -6206,6 +6261,12 @@ export const messagesByLocale = {
6206
6261
  }),
6207
6262
  "ar-SA": mergeMessages({
6208
6263
  library: {
6264
+ allLibraries: "جميع المكتبات",
6265
+ noDrafts: "لا توجد مسودات بعد.",
6266
+ noMatchingDrafts: "لا توجد مسودات مطابقة.",
6267
+ recentDrafts: "المسودات الأخيرة",
6268
+ viewAllDrafts: "عرض جميع المسودات",
6269
+ draftAsset: "مسودة",
6209
6270
  addAssets: "أضف الأصول",
6210
6271
  addAssetsDescription:
6211
6272
  "قم بتحميل المواد المصدرية أو قم بإنشاء مرشحين، ثم حدد فقط الأصول التي يجب أن توجه الأجيال القادمة كمراجع.",
@@ -9,6 +9,7 @@ import { IconPhoto, IconSparkles, IconVideo } from "@tabler/icons-react";
9
9
  import { useEffect } from "react";
10
10
  import { useNavigate, useParams } from "react-router";
11
11
 
12
+ import { RecentDraftsSection } from "@/components/create/RecentDraftsSection";
12
13
  import { GenerationResults } from "@/components/generation/GenerationResults";
13
14
  import { useImageModelMenu } from "@/hooks/use-image-model-menu";
14
15
  import { ASSETS_CHAT_STORAGE_KEY } from "@/lib/chat";
@@ -122,6 +123,9 @@ export default function CreatePage() {
122
123
  </button>
123
124
  ))}
124
125
  </div>
126
+ <div className="mt-8 w-full text-left">
127
+ <RecentDraftsSection />
128
+ </div>
125
129
  </div>
126
130
  }
127
131
  />
@@ -102,16 +102,22 @@ import {
102
102
  type VariantSlot,
103
103
  } from "./brand-kits.$id";
104
104
 
105
- type AssetTab = "all" | "generated" | "references";
105
+ type AssetTab = "all" | "generated" | "drafts" | "references";
106
106
 
107
107
  function isGeneratedAsset(asset: Asset) {
108
108
  const role = asset.role ?? "";
109
109
  return role === "generated" || role === "active" || role === "candidate";
110
110
  }
111
111
 
112
+ function isDraftAsset(asset: Asset) {
113
+ return asset.role === "generated" && asset.status === "candidate";
114
+ }
115
+
112
116
  function assetMatchesTab(asset: Asset, tab: AssetTab) {
113
117
  if (tab === "all") return true;
114
- if (tab === "generated") return isGeneratedAsset(asset);
118
+ if (tab === "drafts") return isDraftAsset(asset);
119
+ if (tab === "generated")
120
+ return isGeneratedAsset(asset) && !isDraftAsset(asset);
115
121
  return !isGeneratedAsset(asset);
116
122
  }
117
123
 
@@ -123,6 +129,7 @@ const MCP_APP_CHAT_BRIDGE_QUERY_PARAM = "__an_mcp_chat_bridge";
123
129
  const PICKER_INLINE_SELECT_CLASS =
124
130
  "h-7 w-auto min-w-0 max-w-full rounded-md border-0 bg-transparent px-1.5 py-1 text-xs font-medium text-muted-foreground shadow-none ring-offset-transparent transition hover:bg-accent/50 hover:text-foreground focus:ring-0 focus:ring-offset-0 sm:px-2 [&>svg]:ms-1 [&>svg]:size-3.5 [&>svg]:opacity-60";
125
131
  type PickerMediaType = "image" | "video";
132
+ type PickerLayout = "default" | "vertical";
126
133
 
127
134
  type Asset = {
128
135
  id: string;
@@ -187,6 +194,7 @@ type HostConfig = {
187
194
  styleStrength?: StyleStrength;
188
195
  includeLogo?: boolean;
189
196
  callerAppId?: string;
197
+ layout?: PickerLayout;
190
198
  autoGenerate?: boolean;
191
199
  candidateRunIds?: string[];
192
200
  };
@@ -238,6 +246,10 @@ function normalizeMediaType(value: unknown): PickerMediaType {
238
246
  return value === "video" ? "video" : "image";
239
247
  }
240
248
 
249
+ function normalizePickerLayout(value: unknown): PickerLayout | undefined {
250
+ return value === "vertical" ? "vertical" : undefined;
251
+ }
252
+
241
253
  function normalizeBoolean(value: unknown): boolean | undefined {
242
254
  if (typeof value === "boolean") return value;
243
255
  if (typeof value !== "string") return undefined;
@@ -314,6 +326,7 @@ function normalizeHostConfig(value: unknown): HostConfig {
314
326
  includeLogo: normalizeBoolean(record.includeLogo),
315
327
  callerAppId:
316
328
  typeof record.callerAppId === "string" ? record.callerAppId : undefined,
329
+ layout: normalizePickerLayout(record.layout),
317
330
  candidateRunIds: normalizeCandidateRunIds(record.candidateRunIds),
318
331
  };
319
332
  if (Object.prototype.hasOwnProperty.call(record, "autoGenerate")) {
@@ -1957,12 +1970,29 @@ export function LibraryWorkspace({
1957
1970
 
1958
1971
  export function AssetPickerSurface() {
1959
1972
  const t = useT();
1960
- const [searchParams] = useSearchParams();
1973
+ const [searchParams, setSearchParams] = useSearchParams();
1961
1974
  const searchParamsKey = searchParams.toString();
1975
+ const urlAssetTab = useMemo<AssetTab | null>(() => {
1976
+ const tab = new URLSearchParams(searchParamsKey).get("tab");
1977
+ return tab === "all" ||
1978
+ tab === "generated" ||
1979
+ tab === "drafts" ||
1980
+ tab === "references"
1981
+ ? tab
1982
+ : null;
1983
+ }, [searchParamsKey]);
1984
+ // The active tab is the only host-irrelevant search param. Exclude it from the
1985
+ // host-config key so toggling tabs (which writes `?tab=`) doesn't retrigger the
1986
+ // effect that resets media type / query / library from the URL.
1987
+ const hostParamsKey = useMemo(() => {
1988
+ const params = new URLSearchParams(searchParamsKey);
1989
+ params.delete("tab");
1990
+ return params.toString();
1991
+ }, [searchParamsKey]);
1962
1992
  const mcpChatBridgeActive =
1963
1993
  searchParamsRequestPicker(searchParams) || isEmbedMcpChatBridgeActive();
1964
1994
  const urlHostConfig = useMemo(() => {
1965
- const params = new URLSearchParams(searchParamsKey);
1995
+ const params = new URLSearchParams(hostParamsKey);
1966
1996
  return {
1967
1997
  mediaType: normalizeMediaType(params.get("mediaType")),
1968
1998
  prompt: params.get("prompt") ?? undefined,
@@ -1976,6 +2006,7 @@ export function AssetPickerSurface() {
1976
2006
  styleStrength: normalizeStyleStrength(params.get("styleStrength")),
1977
2007
  includeLogo: normalizeBoolean(params.get("includeLogo")),
1978
2008
  callerAppId: params.get("callerAppId") ?? undefined,
2009
+ layout: normalizePickerLayout(params.get("layout")),
1979
2010
  candidateRunIds: normalizeCandidateRunIds(
1980
2011
  params.getAll("candidateRunIds").length > 0
1981
2012
  ? params.getAll("candidateRunIds")
@@ -1983,7 +2014,7 @@ export function AssetPickerSurface() {
1983
2014
  ),
1984
2015
  autoGenerate: normalizeBoolean(params.get("autoGenerate")) ?? false,
1985
2016
  } satisfies HostConfig;
1986
- }, [searchParamsKey]);
2017
+ }, [hostParamsKey]);
1987
2018
  const bridgeRef = useRef<EmbeddedAppBridge | null>(null);
1988
2019
  const embedded = useMemo(
1989
2020
  () =>
@@ -2001,6 +2032,9 @@ export function AssetPickerSurface() {
2001
2032
  const [mediaType, setMediaType] = useState<PickerMediaType>(
2002
2033
  () => hostConfig.mediaType ?? "image",
2003
2034
  );
2035
+ const [pickerLayout, setPickerLayout] = useState<PickerLayout>(
2036
+ () => hostConfig.layout ?? "default",
2037
+ );
2004
2038
  const [query, setQuery] = useState(() => hostConfig.query ?? "");
2005
2039
  const [prompt, setPrompt] = useState(() => hostConfig.prompt ?? "");
2006
2040
  const [aspectRatio, setAspectRatio] = useState<string>(
@@ -2008,7 +2042,7 @@ export function AssetPickerSurface() {
2008
2042
  );
2009
2043
  const [presetId, setPresetId] = useState(() => hostConfig.presetId ?? "none");
2010
2044
  const [count, setCount] = useState(() => hostConfig.count ?? 3);
2011
- const [assetTab, setAssetTab] = useState<AssetTab>("all");
2045
+ const [assetTab, setAssetTab] = useState<AssetTab>(urlAssetTab ?? "all");
2012
2046
  const [selectedLibraryId, setSelectedLibraryId] = useState(
2013
2047
  () => hostConfig.libraryId ?? "",
2014
2048
  );
@@ -2023,6 +2057,7 @@ export function AssetPickerSurface() {
2023
2057
  useEffect(() => {
2024
2058
  setHostConfig((current) => ({ ...current, ...urlHostConfig }));
2025
2059
  setMediaType(urlHostConfig.mediaType ?? "image");
2060
+ setPickerLayout(urlHostConfig.layout ?? "default");
2026
2061
  setQuery(urlHostConfig.query ?? "");
2027
2062
  setPrompt(urlHostConfig.prompt ?? "");
2028
2063
  setSelectedLibraryId(urlHostConfig.libraryId ?? "");
@@ -2032,6 +2067,30 @@ export function AssetPickerSurface() {
2032
2067
  setVisibleCandidateRunIds(urlHostConfig.candidateRunIds ?? []);
2033
2068
  }, [urlHostConfig]);
2034
2069
 
2070
+ useEffect(() => {
2071
+ // Reset to "all" when the tab param is removed (e.g. back/forward nav)
2072
+ // since the component stays mounted across search-param changes.
2073
+ setAssetTab(urlAssetTab ?? "all");
2074
+ }, [urlAssetTab]);
2075
+
2076
+ const handleAssetTabChange = useCallback(
2077
+ (value: AssetTab) => {
2078
+ setAssetTab(value);
2079
+ // Keep the tab reflected in the URL so it survives refresh/share and
2080
+ // stays consistent with the `?tab=` deep link from the home page.
2081
+ setSearchParams(
2082
+ (prev) => {
2083
+ const next = new URLSearchParams(prev);
2084
+ if (value === "all") next.delete("tab");
2085
+ else next.set("tab", value);
2086
+ return next;
2087
+ },
2088
+ { replace: true },
2089
+ );
2090
+ },
2091
+ [setSearchParams],
2092
+ );
2093
+
2035
2094
  const librariesQuery = useActionQuery("list-libraries", {
2036
2095
  compact: true,
2037
2096
  } as any) as {
@@ -2116,23 +2175,54 @@ export function AssetPickerSurface() {
2116
2175
  !selectedPreset &&
2117
2176
  Boolean(waitingForPresetData);
2118
2177
  const mediaLabel = mediaType === "video" ? "video" : "image";
2178
+ const viewingDrafts = assetTab === "drafts";
2179
+ // The standalone Library "Drafts" tab mirrors the home Recent Drafts section:
2180
+ // every unsaved draft across all accessible libraries, regardless of media
2181
+ // type. The embedded picker keeps its library + media-type scope so an
2182
+ // image-only picker never surfaces video drafts.
2183
+ const draftsGlobalView = viewingDrafts && !embedded;
2119
2184
  const assetsParams = useMemo(
2120
2185
  () => ({
2121
2186
  libraryId: selectedLibraryId,
2122
2187
  mediaType,
2188
+ // Drafts are exactly generated candidates — filter them server-side
2189
+ // instead of fetching the whole library and filtering on the client.
2190
+ role: viewingDrafts ? "generated" : undefined,
2191
+ status: viewingDrafts ? "candidate" : undefined,
2123
2192
  query: query.trim() || undefined,
2124
2193
  includeCandidates:
2125
- mediaType === "image" && visibleCandidateRunIds.length > 0,
2194
+ viewingDrafts ||
2195
+ (mediaType === "image" && visibleCandidateRunIds.length > 0),
2196
+ // The Drafts tab shows every unsaved draft, not just the latest run batch.
2126
2197
  candidateRunIds:
2127
- visibleCandidateRunIds.length > 0 ? visibleCandidateRunIds : undefined,
2198
+ !viewingDrafts && visibleCandidateRunIds.length > 0
2199
+ ? visibleCandidateRunIds
2200
+ : undefined,
2128
2201
  }),
2129
- [mediaType, query, selectedLibraryId, visibleCandidateRunIds],
2202
+ [
2203
+ viewingDrafts,
2204
+ mediaType,
2205
+ query,
2206
+ selectedLibraryId,
2207
+ visibleCandidateRunIds,
2208
+ ],
2130
2209
  );
2131
2210
  const { data: assetData, isLoading: assetsLoading } = useActionQuery(
2132
2211
  "list-assets",
2133
2212
  assetsParams as any,
2134
- { enabled: Boolean(selectedLibraryId) && !usingStarterLibrary } as any,
2213
+ {
2214
+ enabled:
2215
+ Boolean(selectedLibraryId) && !usingStarterLibrary && !draftsGlobalView,
2216
+ } as any,
2135
2217
  ) as { data?: { assets?: Asset[] }; isLoading: boolean };
2218
+ const { data: globalDraftsData, isLoading: globalDraftsLoading } =
2219
+ useActionQuery(
2220
+ "list-draft-assets",
2221
+ { limit: 500 } as any,
2222
+ {
2223
+ enabled: draftsGlobalView,
2224
+ } as any,
2225
+ ) as { data?: { assets?: Asset[] }; isLoading: boolean };
2136
2226
  const starterAssets: Asset[] = useMemo(
2137
2227
  () =>
2138
2228
  STARTER_PRESET.referenceImages.map((reference) => ({
@@ -2159,11 +2249,23 @@ export function AssetPickerSurface() {
2159
2249
  .some((value) => String(value).toLowerCase().includes(needle)),
2160
2250
  );
2161
2251
  }, [query, starterAssets]);
2162
- const allAssets = usingStarterLibrary
2163
- ? mediaType === "image"
2164
- ? visibleStarterAssets
2165
- : []
2166
- : (assetData?.assets ?? []);
2252
+ const globalDrafts = useMemo(() => {
2253
+ const drafts = globalDraftsData?.assets ?? [];
2254
+ const needle = query.trim().toLowerCase();
2255
+ if (!needle) return drafts;
2256
+ return drafts.filter((asset) =>
2257
+ [asset.title, asset.description, asset.prompt]
2258
+ .filter(Boolean)
2259
+ .some((value) => String(value).toLowerCase().includes(needle)),
2260
+ );
2261
+ }, [globalDraftsData, query]);
2262
+ const allAssets = draftsGlobalView
2263
+ ? globalDrafts
2264
+ : usingStarterLibrary
2265
+ ? mediaType === "image"
2266
+ ? visibleStarterAssets
2267
+ : []
2268
+ : (assetData?.assets ?? []);
2167
2269
  const currentLibrary = useMemo(
2168
2270
  () =>
2169
2271
  displayLibraries.find((library) => library.id === selectedLibraryId) ??
@@ -2174,6 +2276,7 @@ export function AssetPickerSurface() {
2174
2276
  () => allAssets.filter((asset) => assetMatchesTab(asset, assetTab)),
2175
2277
  [allAssets, assetTab],
2176
2278
  );
2279
+ const listLoading = draftsGlobalView ? globalDraftsLoading : assetsLoading;
2177
2280
  const [previewAsset, setPreviewAsset] = useState<Asset | null>(null);
2178
2281
  const [standaloneSelection, setStandaloneSelection] = useState<ReturnType<
2179
2282
  typeof assetPayload
@@ -2413,6 +2516,7 @@ export function AssetPickerSurface() {
2413
2516
  const next = normalizeHostConfig(payload);
2414
2517
  setHostConfig((current) => ({ ...current, ...next }));
2415
2518
  if (next.mediaType !== undefined) setMediaType(next.mediaType);
2519
+ if (next.layout !== undefined) setPickerLayout(next.layout);
2416
2520
  if (next.query !== undefined) setQuery(next.query);
2417
2521
  if (next.prompt !== undefined) setPrompt(next.prompt);
2418
2522
  if (next.libraryId !== undefined) setSelectedLibraryId(next.libraryId);
@@ -2442,10 +2546,11 @@ export function AssetPickerSurface() {
2442
2546
  query,
2443
2547
  prompt,
2444
2548
  aspectRatio,
2549
+ layout: pickerLayout,
2445
2550
  },
2446
2551
  { requestSource: "assets-picker-ui" },
2447
2552
  ).catch(() => {});
2448
- }, [aspectRatio, mediaType, prompt, query, selectedLibraryId]);
2553
+ }, [aspectRatio, mediaType, pickerLayout, prompt, query, selectedLibraryId]);
2449
2554
 
2450
2555
  const canGenerate =
2451
2556
  mediaType === "image" &&
@@ -2561,14 +2666,22 @@ export function AssetPickerSurface() {
2561
2666
  waitingForRequestedPreset,
2562
2667
  ]);
2563
2668
 
2669
+ const verticalLayout = pickerLayout === "vertical";
2670
+
2564
2671
  return (
2565
2672
  <div
2566
2673
  className={cn(
2567
2674
  "flex flex-col overflow-hidden bg-background text-foreground",
2568
2675
  embedded ? "h-screen w-screen" : "h-full w-full",
2676
+ verticalLayout && "assets-picker-vertical",
2569
2677
  )}
2570
2678
  >
2571
- <header className="flex h-12 shrink-0 items-center justify-between gap-3 border-b border-border px-3">
2679
+ <header
2680
+ className={cn(
2681
+ "flex shrink-0 items-center justify-between gap-3 border-b border-border",
2682
+ verticalLayout ? "h-10 px-2" : "h-12 px-3",
2683
+ )}
2684
+ >
2572
2685
  <div className="min-w-0 truncate text-sm font-semibold">
2573
2686
  {embedded ? t("navigation.brand") : t("library.library")}
2574
2687
  </div>
@@ -2577,7 +2690,7 @@ export function AssetPickerSurface() {
2577
2690
  <Button
2578
2691
  variant={showCreatePane ? "secondary" : "default"}
2579
2692
  size="sm"
2580
- className="h-8 gap-1.5"
2693
+ className={cn("gap-1.5", verticalLayout ? "h-7 px-2" : "h-8")}
2581
2694
  onClick={() => setShowCreatePane((open) => !open)}
2582
2695
  >
2583
2696
  {showCreatePane ? (
@@ -2585,7 +2698,9 @@ export function AssetPickerSurface() {
2585
2698
  ) : (
2586
2699
  <IconPhotoPlus className="h-3.5 w-3.5" />
2587
2700
  )}
2588
- {showCreatePane ? t("library.close") : t("library.createPane")}
2701
+ <span className={verticalLayout ? "sr-only" : undefined}>
2702
+ {showCreatePane ? t("library.close") : t("library.createPane")}
2703
+ </span>
2589
2704
  </Button>
2590
2705
  )}
2591
2706
  {embedded && (
@@ -2614,9 +2729,14 @@ export function AssetPickerSurface() {
2614
2729
  </header>
2615
2730
 
2616
2731
  {showCreatePane && mediaType === "image" && (
2617
- <section className="shrink-0 border-b border-border px-3 py-3">
2732
+ <section
2733
+ className={cn(
2734
+ "shrink-0 border-b border-border",
2735
+ verticalLayout ? "px-2 py-2" : "px-3 py-3",
2736
+ )}
2737
+ >
2618
2738
  {mediaType === "image" ? (
2619
- <div className="mt-2 rounded-lg border border-border/80 bg-background focus-within:ring-1 focus-within:ring-ring">
2739
+ <div className="rounded-lg border border-border/80 bg-background focus-within:ring-1 focus-within:ring-ring">
2620
2740
  <Input
2621
2741
  type="text"
2622
2742
  value={prompt}
@@ -2633,10 +2753,23 @@ export function AssetPickerSurface() {
2633
2753
  if (canGenerate) runGenerate();
2634
2754
  }}
2635
2755
  placeholder={t("library.generateImagePlaceholder")}
2636
- className="h-11 border-0 bg-transparent px-3 py-2.5 leading-6 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0"
2756
+ className={cn(
2757
+ "border-0 bg-transparent px-3 leading-6 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0",
2758
+ verticalLayout ? "h-9 py-2 text-xs" : "h-11 py-2.5",
2759
+ )}
2637
2760
  />
2638
- <div className="flex items-center gap-1 px-2 pb-2">
2639
- <div className="flex min-w-0 flex-1 items-center justify-end gap-0.5 sm:gap-1">
2761
+ <div
2762
+ className={cn(
2763
+ "flex gap-1 px-2 pb-2",
2764
+ verticalLayout ? "flex-col items-stretch" : "items-center",
2765
+ )}
2766
+ >
2767
+ <div
2768
+ className={cn(
2769
+ "flex min-w-0 flex-1 items-center gap-0.5 sm:gap-1",
2770
+ verticalLayout ? "justify-between" : "justify-end",
2771
+ )}
2772
+ >
2640
2773
  <Select value={aspectRatio} onValueChange={setAspectRatio}>
2641
2774
  <SelectTrigger
2642
2775
  aria-label={t("brandKitDetail.aspectRatio")}
@@ -2701,7 +2834,10 @@ export function AssetPickerSurface() {
2701
2834
  ) : null}
2702
2835
  </div>
2703
2836
  <Button
2704
- className="h-7 min-w-[5.75rem] shrink-0 px-3 text-xs"
2837
+ className={cn(
2838
+ "h-7 shrink-0 px-3 text-xs",
2839
+ !verticalLayout && "min-w-[5.75rem]",
2840
+ )}
2705
2841
  disabled={!canGenerate}
2706
2842
  onClick={runGenerate}
2707
2843
  >
@@ -2841,31 +2977,65 @@ export function AssetPickerSurface() {
2841
2977
  </section>
2842
2978
  )}
2843
2979
 
2844
- <main className="min-h-0 flex-1 overflow-y-auto p-3">
2980
+ <main
2981
+ className={cn(
2982
+ "min-h-0 flex-1 overflow-y-auto",
2983
+ verticalLayout ? "p-2" : "p-3",
2984
+ )}
2985
+ >
2845
2986
  {displayLibraries.length > 0 && (
2846
- <div className="mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
2847
- <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
2848
- <Select
2849
- value={selectedLibraryId}
2850
- onValueChange={setSelectedLibraryId}
2851
- >
2852
- <SelectTrigger className="h-9 w-full border-border/70 bg-background sm:w-48">
2853
- <SelectValue placeholder={t("library.library")} />
2854
- </SelectTrigger>
2855
- <SelectContent>
2856
- <SelectGroup>
2857
- {displayLibraries.map((library) => (
2858
- <SelectItem key={library.id} value={library.id}>
2859
- {library.title}
2860
- </SelectItem>
2861
- ))}
2862
- </SelectGroup>
2863
- </SelectContent>
2864
- </Select>
2987
+ <div
2988
+ className={cn(
2989
+ "mb-3 flex flex-col gap-2",
2990
+ !verticalLayout &&
2991
+ "sm:flex-row sm:items-center sm:justify-between",
2992
+ )}
2993
+ >
2994
+ <div
2995
+ className={cn(
2996
+ "flex flex-col gap-2",
2997
+ !verticalLayout && "sm:flex-row sm:items-center",
2998
+ )}
2999
+ >
3000
+ {draftsGlobalView ? (
3001
+ <div
3002
+ className={cn(
3003
+ "flex h-9 items-center rounded-md border border-border/70 bg-background px-3 text-sm text-muted-foreground",
3004
+ !verticalLayout && "sm:w-48",
3005
+ )}
3006
+ >
3007
+ {t("library.allLibraries")}
3008
+ </div>
3009
+ ) : (
3010
+ <Select
3011
+ value={selectedLibraryId}
3012
+ onValueChange={setSelectedLibraryId}
3013
+ >
3014
+ <SelectTrigger
3015
+ className={cn(
3016
+ "h-9 w-full border-border/70 bg-background",
3017
+ !verticalLayout && "sm:w-48",
3018
+ )}
3019
+ >
3020
+ <SelectValue placeholder={t("library.library")} />
3021
+ </SelectTrigger>
3022
+ <SelectContent>
3023
+ <SelectGroup>
3024
+ {displayLibraries.map((library) => (
3025
+ <SelectItem key={library.id} value={library.id}>
3026
+ {library.title}
3027
+ </SelectItem>
3028
+ ))}
3029
+ </SelectGroup>
3030
+ </SelectContent>
3031
+ </Select>
3032
+ )}
2865
3033
  {selectedLibraryId && (
2866
3034
  <Tabs
2867
3035
  value={assetTab}
2868
- onValueChange={(value) => setAssetTab(value as AssetTab)}
3036
+ onValueChange={(value) =>
3037
+ handleAssetTabChange(value as AssetTab)
3038
+ }
2869
3039
  >
2870
3040
  <TabsList>
2871
3041
  <TabsTrigger value="all">
@@ -2874,6 +3044,9 @@ export function AssetPickerSurface() {
2874
3044
  <TabsTrigger value="generated">
2875
3045
  {t("library.generated")}
2876
3046
  </TabsTrigger>
3047
+ <TabsTrigger value="drafts">
3048
+ {t("library.drafts")}
3049
+ </TabsTrigger>
2877
3050
  <TabsTrigger value="references">
2878
3051
  {t("library.references")}
2879
3052
  </TabsTrigger>
@@ -2888,7 +3061,10 @@ export function AssetPickerSurface() {
2888
3061
  onInput={(event) => setQuery(event.currentTarget.value)}
2889
3062
  onChange={(event) => setQuery(event.target.value)}
2890
3063
  placeholder={t("library.searchMedia", { mediaLabel })}
2891
- className="h-9 border-border/70 bg-background sm:max-w-xs"
3064
+ className={cn(
3065
+ "h-9 border-border/70 bg-background",
3066
+ !verticalLayout && "sm:max-w-xs",
3067
+ )}
2892
3068
  />
2893
3069
  )}
2894
3070
  </div>
@@ -2897,6 +3073,7 @@ export function AssetPickerSurface() {
2897
3073
  {mediaType === "image" &&
2898
3074
  selectedLibraryId &&
2899
3075
  !usingStarterLibrary &&
3076
+ !viewingDrafts &&
2900
3077
  pickerVariantScopeId && (
2901
3078
  <LibraryCandidateStage
2902
3079
  activeLibraryId={selectedLibraryId}
@@ -2914,7 +3091,7 @@ export function AssetPickerSurface() {
2914
3091
  </div>
2915
3092
  )}
2916
3093
 
2917
- {selectedLibraryId && assetsLoading && (
3094
+ {selectedLibraryId && listLoading && (
2918
3095
  <div className="assets-library-dense-grid grid grid-cols-2 gap-3">
2919
3096
  {Array.from({ length: 8 }).map((_, index) => (
2920
3097
  <Skeleton key={index} className="aspect-square rounded-md" />
@@ -2922,12 +3099,16 @@ export function AssetPickerSurface() {
2922
3099
  </div>
2923
3100
  )}
2924
3101
 
2925
- {selectedLibraryId && !assetsLoading && assets.length === 0 && (
3102
+ {selectedLibraryId && !listLoading && assets.length === 0 && (
2926
3103
  <div className="flex h-full items-center justify-center text-center">
2927
3104
  <div className="max-w-sm text-sm text-muted-foreground">
2928
- {query
2929
- ? t("library.noMatchingLibraryAssets", { mediaLabel })
2930
- : t("library.noAssetsInLibrary", { mediaLabel })}
3105
+ {draftsGlobalView
3106
+ ? query
3107
+ ? t("library.noMatchingDrafts")
3108
+ : t("library.noDrafts")
3109
+ : query
3110
+ ? t("library.noMatchingLibraryAssets", { mediaLabel })
3111
+ : t("library.noAssetsInLibrary", { mediaLabel })}
2931
3112
  </div>
2932
3113
  </div>
2933
3114
  )}
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-29
4
+ ---
5
+
6
+ Image generation can now render requested text and respect brand fonts