@agent-native/core 0.80.8 → 0.80.9

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 (281) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +12 -0
  3. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +6 -0
  4. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +8 -0
  5. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +10 -2
  6. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +10 -2
  7. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +7 -0
  8. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +7 -0
  9. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +7 -0
  10. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +9 -2
  11. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +6 -0
  12. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +6 -0
  13. package/corpus/core/docs/content/template-design.mdx +9 -2
  14. package/corpus/core/package.json +1 -1
  15. package/corpus/core/src/cli/mcp.ts +10 -0
  16. package/corpus/core/src/cli/skills.ts +58 -12
  17. package/corpus/core/src/client/error-format.ts +25 -0
  18. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +13 -11
  19. package/corpus/core/src/client/guided-questions.tsx +32 -4
  20. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +33 -1
  21. package/corpus/core/src/client/resources/BuiltinCapabilityDetail.tsx +8 -0
  22. package/corpus/core/src/client/resources/use-builtin-capabilities.ts +4 -2
  23. package/corpus/core/src/client/session-replay.ts +34 -0
  24. package/corpus/core/src/client/sharing/ShareButton.tsx +106 -21
  25. package/corpus/core/src/coding-tools/index.ts +1 -1
  26. package/corpus/core/src/mcp/index.ts +2 -0
  27. package/corpus/core/src/mcp/screen-memory-stdio.ts +290 -0
  28. package/corpus/core/src/mcp-client/builtin-capabilities.ts +13 -1
  29. package/corpus/core/src/mcp-client/index.ts +9 -0
  30. package/corpus/core/src/mcp-client/screen-memory-local.ts +461 -0
  31. package/corpus/core/src/onboarding/types.ts +7 -0
  32. package/corpus/core/src/server/agent-chat-plugin.ts +25 -0
  33. package/corpus/core/src/server/agents-bundle.ts +35 -7
  34. package/corpus/core/src/styles/agent-native.css +5 -0
  35. package/corpus/core/src/templates/default/app/global.css +35 -35
  36. package/corpus/templates/analytics/AGENTS.md +6 -0
  37. package/corpus/templates/analytics/actions/github-repo-files.ts +9 -0
  38. package/corpus/templates/analytics/app/components/layout/Layout.tsx +4 -4
  39. package/corpus/templates/analytics/app/global.css +144 -40
  40. package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +1 -1
  41. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +1 -1
  42. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
  43. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +4 -4
  44. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -9
  45. package/corpus/templates/analytics/changelog/2026-06-29-agents-can-search-and-read-connected-github-repositories-whe.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-06-29-sessions-and-explorer-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  47. package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -1
  48. package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +1 -1
  49. package/corpus/templates/assets/app/global.css +99 -35
  50. package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
  51. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +4 -4
  52. package/corpus/templates/assets/app/routes/library.tsx +4 -4
  53. package/corpus/templates/assets/changelog/2026-06-29-asset-library-and-detail-layouts-adapt-when-the-agent-sidebar.md +6 -0
  54. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
  55. package/corpus/templates/brain/app/global.css +63 -35
  56. package/corpus/templates/brain/app/routes/search.tsx +1 -1
  57. package/corpus/templates/brain/app/routes/settings.tsx +1 -1
  58. package/corpus/templates/brain/app/routes/sources.tsx +2 -2
  59. package/corpus/templates/brain/changelog/2026-06-29-search-settings-and-source-layouts-adapt-when-the-agent-sidebar.md +6 -0
  60. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +4 -4
  61. package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +3 -2
  62. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -2
  63. package/corpus/templates/calendar/app/global.css +69 -35
  64. package/corpus/templates/calendar/changelog/2026-06-29-event-and-find-time-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  65. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  66. package/corpus/templates/chat/app/global.css +35 -35
  67. package/corpus/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  68. package/corpus/templates/clips/AGENTS.md +13 -0
  69. package/corpus/templates/clips/actions/get-screen-memory-status.ts +12 -0
  70. package/corpus/templates/clips/actions/query-screen-memory-context.ts +29 -0
  71. package/corpus/templates/clips/actions/view-screen.ts +2 -2
  72. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  73. package/corpus/templates/clips/app/global.css +47 -35
  74. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +3 -3
  75. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +45 -18
  76. package/corpus/templates/clips/changelog/2026-06-29-meeting-detail-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-06-29-screen-memory-keeps-a-local-rolling-screen-buffer-for-agent-context.md +5 -0
  78. package/corpus/templates/clips/changelog/2026-06-29-video-chat-is-easier-to-find-on-recording-pages-and-s3-setup.md +6 -0
  79. package/corpus/templates/clips/chrome-extension/src/styles.css +39 -39
  80. package/corpus/templates/clips/desktop/src/app.tsx +290 -1
  81. package/corpus/templates/clips/desktop/src/shared/config.ts +83 -0
  82. package/corpus/templates/clips/desktop/src/styles.css +67 -52
  83. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +50 -0
  84. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +17 -0
  85. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +13 -13
  86. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +990 -0
  87. package/corpus/templates/clips/server/plugins/onboarding.ts +2 -0
  88. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +3 -3
  89. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
  90. package/corpus/templates/content/app/global.css +29 -15
  91. package/corpus/templates/content/changelog/2026-06-29-database-gallery-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  92. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +25 -20
  93. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  94. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +8 -0
  95. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +13 -0
  96. package/corpus/templates/design/AGENTS.md +20 -12
  97. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1054 -0
  98. package/corpus/templates/design/actions/apply-visual-edit.ts +24 -4
  99. package/corpus/templates/design/actions/export-coding-handoff.ts +12 -4
  100. package/corpus/templates/design/actions/generate-design.ts +6 -21
  101. package/corpus/templates/design/actions/generate-screens.ts +43 -2
  102. package/corpus/templates/design/actions/get-design.ts +1 -0
  103. package/corpus/templates/design/actions/present-design-variants.ts +355 -30
  104. package/corpus/templates/design/actions/view-screen.ts +75 -31
  105. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +329 -69
  106. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
  107. package/corpus/templates/design/app/components/design/EditPanel.tsx +479 -77
  108. package/corpus/templates/design/app/components/design/LayersPanel.tsx +380 -216
  109. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1050 -196
  110. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +83 -206
  111. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +1 -1
  112. package/corpus/templates/design/app/components/design/index.ts +0 -1
  113. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +225 -133
  114. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +122 -11
  115. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +24 -5
  116. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -1
  117. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +37 -12
  118. package/corpus/templates/design/app/components/design/inspector/index.ts +1 -0
  119. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +12 -5
  120. package/corpus/templates/design/app/components/design/types.ts +9 -0
  121. package/corpus/templates/design/app/components/layout/Layout.tsx +23 -5
  122. package/corpus/templates/design/app/global.css +77 -49
  123. package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
  124. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +8 -1
  125. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  126. package/corpus/templates/design/app/i18n-data.ts +45 -3
  127. package/corpus/templates/design/app/pages/DesignEditor.tsx +2602 -657
  128. package/corpus/templates/design/app/root.tsx +1 -1
  129. package/corpus/templates/design/changelog/2026-06-29-containers-no-longer-block-selecting-nested-elements-and-nor.md +6 -0
  130. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-generate-and-refine-variants-from-stronger.md +6 -0
  131. package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +6 -0
  132. package/corpus/templates/design/changelog/2026-06-29-design-questions-now-appear-as-a-cleaner-canvas-intake-with-.md +6 -0
  133. package/corpus/templates/design/changelog/2026-06-29-design-variant-directions-now-appear-as-board-screens-with-chat-buttons.md +5 -0
  134. package/corpus/templates/design/changelog/2026-06-29-element-selection-no-longer-snaps-back-to-the-previous-layer.md +6 -0
  135. package/corpus/templates/design/changelog/2026-06-29-frame-resize-measurements-now-stay-beside-the-cursor-while-d.md +6 -0
  136. package/corpus/templates/design/changelog/2026-06-29-inspector-number-fields-have-cleaner-tooltips-and-draggable-.md +6 -0
  137. package/corpus/templates/design/changelog/2026-06-29-layer-locking-layer-nesting-generated-question-intake-and-im.md +6 -0
  138. package/corpus/templates/design/changelog/2026-06-29-layer-names-in-the-sidebar-can-scroll-horizontally-instead-o.md +6 -0
  139. package/corpus/templates/design/changelog/2026-06-29-layer-nesting-in-the-sidebar-now-uses-tighter-spacing-so-nam.md +6 -0
  140. package/corpus/templates/design/changelog/2026-06-29-layers-no-longer-repeat-document-wrapper-rows-when-a-screen-.md +6 -0
  141. package/corpus/templates/design/changelog/2026-06-29-overview-previews-now-keep-element-hover-and-selection-tied-.md +6 -0
  142. package/corpus/templates/design/changelog/2026-06-29-pressing-escape-now-cancels-a-stuck-screen-drag-in-the-overv.md +6 -0
  143. package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +6 -0
  144. package/corpus/templates/design/changelog/2026-06-29-screen-overview-only-highlights-screens-when-the-frame-or-ti.md +6 -0
  145. package/corpus/templates/design/changelog/2026-06-29-screen-overview-previews-now-resize-to-match-the-selected-de.md +6 -0
  146. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-now-uses-a-pointer-cursor-instead-.md +6 -0
  147. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-outlines-now-stay-locked-to-the-se.md +6 -0
  148. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zoom-now-reports-real-screen-scale-separatel.md +6 -0
  149. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-feels-smoother-and-selection-outline.md +6 -0
  150. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-now-stays-on-the-overview-canvas-ins.md +6 -0
  151. package/corpus/templates/design/changelog/2026-06-29-selecting-a-nested-layer-from-all-screens-now-keeps-you-in-a.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-29-share-now-groups-link-sharing-exports-and-agent-handoff.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-loading-skeleton-now-uses-a-softer-charcoa.md +6 -0
  154. package/corpus/templates/design/changelog/2026-06-29-the-device-preview-menu-now-sits-next-to-the-preview-button-.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-29-the-inspector-stays-read-only-while-an-empty-design-is-still.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-29-the-missing-design-view-now-matches-the-rest-of-the-editor-c.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-icon-and-tool-option-menus-better-match-the-edi.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-29-typography-controls-now-keep-the-font-name-visible-and-move-.md +6 -0
  159. package/corpus/templates/design/e2e/README.md +3 -3
  160. package/corpus/templates/design/e2e/global-setup.ts +11 -22
  161. package/corpus/templates/design/e2e/helpers.ts +122 -11
  162. package/corpus/templates/design/playwright.config.ts +9 -3
  163. package/corpus/templates/design/server/lib/coding-handoff.ts +126 -2
  164. package/corpus/templates/design/server/plugins/core-routes.ts +1 -2
  165. package/corpus/templates/design/server/routes/api/design-handoff/[id].zip.get.ts +86 -0
  166. package/corpus/templates/design/shared/code-layer.ts +125 -22
  167. package/corpus/templates/design/shared/generation-session.ts +41 -0
  168. package/corpus/templates/dispatch/app/global.css +79 -35
  169. package/corpus/templates/dispatch/app/routes/integrations.tsx +8 -7
  170. package/corpus/templates/dispatch/changelog/2026-06-29-integration-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  171. package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -2
  172. package/corpus/templates/forms/app/global.css +64 -35
  173. package/corpus/templates/forms/app/pages/FormsListPage.tsx +2 -2
  174. package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +3 -3
  175. package/corpus/templates/forms/changelog/2026-06-29-form-list-and-insight-layouts-adapt-when-the-agent-sidebar.md +6 -0
  176. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -1
  177. package/corpus/templates/macros/app/global.css +25 -9
  178. package/corpus/templates/macros/changelog/2026-06-29-macro-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  179. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -2
  180. package/corpus/templates/mail/app/global.css +42 -36
  181. package/corpus/templates/mail/app/pages/InboxPage.tsx +1 -1
  182. package/corpus/templates/mail/changelog/2026-06-29-the-contact-panel-now-adapts-to-the-available-mail-pane-width.md +6 -0
  183. package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -1
  184. package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +6 -7
  185. package/corpus/templates/plan/app/global.css +74 -42
  186. package/corpus/templates/plan/changelog/2026-06-29-plan-document-blocks-adapt-to-the-available-document-width.md +6 -0
  187. package/corpus/templates/plan/changelog/2026-06-29-plan-titles-and-summaries-can-be-edited-inline-without-focus.md +6 -0
  188. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -1
  189. package/corpus/templates/slides/app/global.css +49 -33
  190. package/corpus/templates/slides/changelog/2026-06-29-slide-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  191. package/corpus/templates/videos/app/components/layout/Layout.tsx +3 -1
  192. package/corpus/templates/videos/app/global.css +35 -35
  193. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  194. package/dist/cli/mcp.d.ts.map +1 -1
  195. package/dist/cli/mcp.js +10 -0
  196. package/dist/cli/mcp.js.map +1 -1
  197. package/dist/cli/skills.d.ts.map +1 -1
  198. package/dist/cli/skills.js +58 -12
  199. package/dist/cli/skills.js.map +1 -1
  200. package/dist/client/error-format.d.ts.map +1 -1
  201. package/dist/client/error-format.js +17 -0
  202. package/dist/client/error-format.js.map +1 -1
  203. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  204. package/dist/client/extensions/ExtensionViewer.js +3 -4
  205. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  206. package/dist/client/guided-questions.d.ts +4 -0
  207. package/dist/client/guided-questions.d.ts.map +1 -1
  208. package/dist/client/guided-questions.js +16 -7
  209. package/dist/client/guided-questions.js.map +1 -1
  210. package/dist/client/onboarding/OnboardingPanel.js +26 -1
  211. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  212. package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -1
  213. package/dist/client/resources/BuiltinCapabilityDetail.js +1 -1
  214. package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -1
  215. package/dist/client/resources/use-builtin-capabilities.d.ts +1 -1
  216. package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -1
  217. package/dist/client/resources/use-builtin-capabilities.js +2 -1
  218. package/dist/client/resources/use-builtin-capabilities.js.map +1 -1
  219. package/dist/client/session-replay.d.ts.map +1 -1
  220. package/dist/client/session-replay.js +31 -0
  221. package/dist/client/session-replay.js.map +1 -1
  222. package/dist/client/sharing/ShareButton.d.ts +14 -0
  223. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  224. package/dist/client/sharing/ShareButton.js +36 -7
  225. package/dist/client/sharing/ShareButton.js.map +1 -1
  226. package/dist/coding-tools/index.js +1 -1
  227. package/dist/coding-tools/index.js.map +1 -1
  228. package/dist/collab/routes.d.ts +1 -1
  229. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  230. package/dist/mcp/index.d.ts +2 -0
  231. package/dist/mcp/index.d.ts.map +1 -1
  232. package/dist/mcp/index.js +1 -0
  233. package/dist/mcp/index.js.map +1 -1
  234. package/dist/mcp/screen-memory-stdio.d.ts +6 -0
  235. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -0
  236. package/dist/mcp/screen-memory-stdio.js +213 -0
  237. package/dist/mcp/screen-memory-stdio.js.map +1 -0
  238. package/dist/mcp-client/builtin-capabilities.d.ts +1 -1
  239. package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -1
  240. package/dist/mcp-client/builtin-capabilities.js +10 -0
  241. package/dist/mcp-client/builtin-capabilities.js.map +1 -1
  242. package/dist/mcp-client/index.d.ts +1 -0
  243. package/dist/mcp-client/index.d.ts.map +1 -1
  244. package/dist/mcp-client/index.js +1 -0
  245. package/dist/mcp-client/index.js.map +1 -1
  246. package/dist/mcp-client/screen-memory-local.d.ts +61 -0
  247. package/dist/mcp-client/screen-memory-local.d.ts.map +1 -0
  248. package/dist/mcp-client/screen-memory-local.js +336 -0
  249. package/dist/mcp-client/screen-memory-local.js.map +1 -0
  250. package/dist/notifications/routes.d.ts +2 -2
  251. package/dist/observability/routes.d.ts +8 -8
  252. package/dist/onboarding/types.d.ts +7 -0
  253. package/dist/onboarding/types.d.ts.map +1 -1
  254. package/dist/onboarding/types.js.map +1 -1
  255. package/dist/resources/handlers.d.ts +2 -2
  256. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  257. package/dist/server/agent-chat-plugin.js +26 -0
  258. package/dist/server/agent-chat-plugin.js.map +1 -1
  259. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  260. package/dist/server/agents-bundle.d.ts.map +1 -1
  261. package/dist/server/agents-bundle.js +22 -7
  262. package/dist/server/agents-bundle.js.map +1 -1
  263. package/dist/server/transcribe-voice.d.ts +1 -1
  264. package/dist/styles/agent-native.css +5 -0
  265. package/dist/templates/default/app/global.css +35 -35
  266. package/docs/content/locales/ar-SA/template-design.mdx +6 -0
  267. package/docs/content/locales/de-DE/template-design.mdx +8 -0
  268. package/docs/content/locales/es-ES/template-design.mdx +10 -2
  269. package/docs/content/locales/fr-FR/template-design.mdx +10 -2
  270. package/docs/content/locales/hi-IN/template-design.mdx +7 -0
  271. package/docs/content/locales/ja-JP/template-design.mdx +7 -0
  272. package/docs/content/locales/ko-KR/template-design.mdx +7 -0
  273. package/docs/content/locales/pt-BR/template-design.mdx +9 -2
  274. package/docs/content/locales/zh-CN/template-design.mdx +6 -0
  275. package/docs/content/locales/zh-TW/template-design.mdx +6 -0
  276. package/docs/content/template-design.mdx +9 -2
  277. package/package.json +1 -1
  278. package/src/templates/default/app/global.css +35 -35
  279. package/corpus/templates/design/app/components/design/VariantGrid.tsx +0 -189
  280. package/corpus/templates/design/app/components/design/VariantHandoffCard.tsx +0 -115
  281. package/corpus/templates/design/app/hooks/use-variant-flow.ts +0 -342
@@ -57,6 +57,9 @@ const DEFAULT_LABELS: ExportSettingsPanelLabels = {
57
57
 
58
58
  const DEFAULT_FORMATS: ExportFormat[] = ["png", "jpg", "svg", "pdf", "webp"];
59
59
 
60
+ const controlChromeClass =
61
+ "border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] text-foreground shadow-none hover:bg-[var(--design-editor-panel-raised-bg)] hover:text-foreground focus:ring-1 focus:ring-[var(--design-editor-accent-color)] focus:ring-offset-0 focus-visible:ring-1 focus-visible:ring-[var(--design-editor-accent-color)] focus-visible:ring-offset-0";
62
+
60
63
  // Export scale bounds — must match the clamp in DesignEditor's PNG/SVG export
61
64
  // handlers so the panel never promises a range the exporter won't render.
62
65
  const MIN_EXPORT_SCALE = 0.1;
@@ -135,7 +138,12 @@ function ScaleSelect({
135
138
  }
136
139
  }}
137
140
  >
138
- <SelectTrigger className="h-6 w-14 shrink-0 px-1.5 text-[11px]">
141
+ <SelectTrigger
142
+ className={cn(
143
+ "h-6 w-14 shrink-0 px-1.5 text-[11px]",
144
+ controlChromeClass,
145
+ )}
146
+ >
139
147
  <SelectValue />
140
148
  </SelectTrigger>
141
149
  <SelectContent>
@@ -267,7 +275,7 @@ export function ExportSettingsPanel({
267
275
  variant="outline"
268
276
  disabled={isDisabled}
269
277
  onClick={handleExport}
270
- className="h-6 w-full px-2 text-[11px]"
278
+ className={cn("h-6 w-full px-2 text-[11px]", controlChromeClass)}
271
279
  >
272
280
  <IconDownload className="size-3.5" />
273
281
  {copy.export}
@@ -324,7 +332,10 @@ function ExportRow({
324
332
  onPatchRow(row.id, { customScale: false });
325
333
  }
326
334
  }}
327
- className="h-6 w-14 shrink-0 px-1.5 text-[11px] tabular-nums"
335
+ className={cn(
336
+ "h-6 w-14 shrink-0 px-1.5 text-[11px] tabular-nums",
337
+ controlChromeClass,
338
+ )}
328
339
  aria-label="Scale"
329
340
  // eslint-disable-next-line jsx-a11y/no-autofocus
330
341
  autoFocus
@@ -352,7 +363,12 @@ function ExportRow({
352
363
  onPatchRow(row.id, { format: format as ExportFormat })
353
364
  }
354
365
  >
355
- <SelectTrigger className="h-6 min-w-0 flex-1 px-1.5 text-[11px]">
366
+ <SelectTrigger
367
+ className={cn(
368
+ "h-6 min-w-0 flex-1 px-1.5 text-[11px]",
369
+ controlChromeClass,
370
+ )}
371
+ >
356
372
  <SelectValue />
357
373
  </SelectTrigger>
358
374
  <SelectContent>
@@ -376,7 +392,10 @@ function ExportRow({
376
392
  disabled={isDisabled}
377
393
  onChange={(e) => onPatchRow(row.id, { suffix: e.target.value })}
378
394
  placeholder={labels.suffix}
379
- className="h-6 min-w-0 flex-1 px-1.5 text-[11px]"
395
+ className={cn(
396
+ "h-6 min-w-0 flex-1 px-1.5 text-[11px]",
397
+ controlChromeClass,
398
+ )}
380
399
  aria-label={labels.suffix}
381
400
  />
382
401
 
@@ -80,6 +80,59 @@ export function imageFillToCss(value: ImageFillValue): string {
80
80
  }
81
81
  }
82
82
 
83
+ export function imageFillToBackgroundStyles(
84
+ value: ImageFillValue,
85
+ ): Record<
86
+ | "backgroundImage"
87
+ | "backgroundSize"
88
+ | "backgroundRepeat"
89
+ | "backgroundPosition",
90
+ string
91
+ > {
92
+ const url = value.url.trim();
93
+ if (!url) {
94
+ return {
95
+ backgroundImage: "none",
96
+ backgroundSize: "auto",
97
+ backgroundRepeat: "no-repeat",
98
+ backgroundPosition: "center",
99
+ };
100
+ }
101
+ const safeUrl = url.replace(/["')]/g, encodeURIComponent);
102
+ const backgroundImage = `url("${safeUrl}")`;
103
+ switch (value.fit) {
104
+ case "fit":
105
+ return {
106
+ backgroundImage,
107
+ backgroundSize: "contain",
108
+ backgroundRepeat: "no-repeat",
109
+ backgroundPosition: "center",
110
+ };
111
+ case "tile":
112
+ return {
113
+ backgroundImage,
114
+ backgroundSize: "auto",
115
+ backgroundRepeat: "repeat",
116
+ backgroundPosition: "top left",
117
+ };
118
+ case "crop":
119
+ return {
120
+ backgroundImage,
121
+ backgroundSize: "cover",
122
+ backgroundRepeat: "no-repeat",
123
+ backgroundPosition: "center",
124
+ };
125
+ case "fill":
126
+ default:
127
+ return {
128
+ backgroundImage,
129
+ backgroundSize: "cover",
130
+ backgroundRepeat: "no-repeat",
131
+ backgroundPosition: "center",
132
+ };
133
+ }
134
+ }
135
+
83
136
  // Matches url() in three forms:
84
137
  // group 1 — double-quoted: url("...anything...")
85
138
  // group 2 — single-quoted: url('...anything...')
@@ -249,7 +302,10 @@ export function ImageFillControls({
249
302
  onValueChange={(v) => onChange({ ...value, fit: v as ImageFitMode })}
250
303
  disabled={disabled}
251
304
  >
252
- <SelectTrigger className="h-6 w-full rounded-md border border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] px-2 text-[11px] shadow-none focus:ring-0 focus:ring-offset-0 focus-visible:ring-2 focus-visible:ring-ring [&>svg]:size-3 [&>svg]:shrink-0">
305
+ <SelectTrigger
306
+ aria-label={"Fill" /* i18n-ignore image fit selector */}
307
+ className="h-6 w-full rounded-md border border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] px-2 text-[11px] shadow-none focus:ring-0 focus:ring-offset-0 focus-visible:ring-2 focus-visible:ring-ring [&>svg]:size-3 [&>svg]:shrink-0"
308
+ >
253
309
  <SelectValue />
254
310
  </SelectTrigger>
255
311
  <SelectContent className="text-[11px]">
@@ -4,9 +4,9 @@ import {
4
4
  useId,
5
5
  useRef,
6
6
  useState,
7
- type ComponentType,
8
7
  type KeyboardEvent,
9
8
  type PointerEvent,
9
+ type ReactNode,
10
10
  } from "react";
11
11
 
12
12
  import { Input } from "@/components/ui/input";
@@ -26,7 +26,7 @@ import {
26
26
  type ScrubExpressionOptions,
27
27
  } from "./scrub-input-utils";
28
28
 
29
- type ScrubInputIcon = ComponentType<{ className?: string }>;
29
+ type ScrubInputIcon = (props: { className?: string }) => ReactNode;
30
30
 
31
31
  export interface ScrubInputChangeMeta {
32
32
  source: "commit" | "keyboard" | "scrub";
@@ -39,13 +39,14 @@ export interface ScrubInputProps extends ScrubExpressionOptions {
39
39
  onChange: (value: number, meta: ScrubInputChangeMeta) => void;
40
40
  id?: string;
41
41
  step?: number;
42
- icon?: ScrubInputIcon;
42
+ icon?: ScrubInputIcon | null;
43
43
  disabled?: boolean;
44
44
  placeholder?: string;
45
45
  className?: string;
46
46
  inputClassName?: string;
47
47
  labelClassName?: string;
48
48
  ariaLabel?: string;
49
+ tooltipLabel?: string;
49
50
  }
50
51
 
51
52
  export function ScrubInput({
@@ -65,12 +66,17 @@ export function ScrubInput({
65
66
  inputClassName,
66
67
  labelClassName,
67
68
  ariaLabel,
69
+ tooltipLabel,
68
70
  }: ScrubInputProps) {
69
71
  const generatedId = useId();
70
72
  const inputId = id ?? generatedId;
71
73
  const [draft, setDraft] = useState(() =>
72
74
  formatScrubValue(value, { unit, precision }),
73
75
  );
76
+ // Track the latest draft in a ref so commitDraft always reads the most
77
+ // up-to-date value even if the blur event fires before the React state
78
+ // update has been committed to the render tree (concurrent mode / batching).
79
+ const draftRef = useRef(draft);
74
80
  const [focused, setFocused] = useState(false);
75
81
  const [dragging, setDragging] = useState(false);
76
82
  const inputRef = useRef<HTMLInputElement>(null);
@@ -83,27 +89,41 @@ export function ScrubInput({
83
89
  });
84
90
 
85
91
  useEffect(() => {
86
- if (!focused) setDraft(formatScrubValue(value, { unit, precision }));
92
+ if (!focused) {
93
+ const formatted = formatScrubValue(value, { unit, precision });
94
+ draftRef.current = formatted;
95
+ setDraft(formatted);
96
+ }
87
97
  }, [focused, precision, unit, value]);
88
98
 
89
99
  const options = { unit, min, max, precision };
100
+ const resolvedTooltipLabel = tooltipLabel ?? ariaLabel ?? label;
90
101
 
91
102
  const setNextValue = (nextValue: number, meta: ScrubInputChangeMeta) => {
92
103
  const normalized = normalizeScrubNumber(nextValue, options);
93
104
  onChange(normalized, meta);
94
- setDraft(formatScrubValue(normalized, options));
105
+ const formatted = formatScrubValue(normalized, options);
106
+ draftRef.current = formatted;
107
+ setDraft(formatted);
95
108
  };
96
109
 
97
110
  const commitDraft = () => {
98
- const parsed = parseScrubExpression(draft, value, options);
111
+ // Always read from the ref so we use the latest typed value even if the
112
+ // React render with the updated draft state hasn't committed yet (e.g.
113
+ // when blur fires in the same synchronous batch as the last onChange).
114
+ const currentDraft = draftRef.current;
115
+ const parsed = parseScrubExpression(currentDraft, value, options);
99
116
  if (!parsed) {
100
- setDraft(formatScrubValue(value, options));
117
+ const reverted = formatScrubValue(value, options);
118
+ draftRef.current = reverted;
119
+ setDraft(reverted);
101
120
  return;
102
121
  }
103
122
 
123
+ draftRef.current = parsed.normalized;
104
124
  setDraft(parsed.normalized);
105
125
  if (parsed.value !== value) {
106
- onChange(parsed.value, { source: "commit", expression: draft });
126
+ onChange(parsed.value, { source: "commit", expression: currentDraft });
107
127
  }
108
128
  };
109
129
 
@@ -131,7 +151,9 @@ export function ScrubInput({
131
151
 
132
152
  if (event.key === "Escape") {
133
153
  event.preventDefault();
134
- setDraft(formatScrubValue(value, options));
154
+ const reverted = formatScrubValue(value, options);
155
+ draftRef.current = reverted;
156
+ setDraft(reverted);
135
157
  skipNextBlurCommitRef.current = true;
136
158
  event.currentTarget.blur();
137
159
  }
@@ -202,11 +224,11 @@ export function ScrubInput({
202
224
  labelClassName,
203
225
  )}
204
226
  >
205
- <Icon className="size-3 shrink-0" />
227
+ {Icon ? <Icon className="size-3 shrink-0" /> : null}
206
228
  <span className="truncate">{label}</span>
207
229
  </Label>
208
230
  </TooltipTrigger>
209
- <TooltipContent>{`${label} — drag to scrub · ↑↓ step · Shift ×10 · ⌥ fine`}</TooltipContent>
231
+ <TooltipContent>{resolvedTooltipLabel}</TooltipContent>
210
232
  </Tooltip>
211
233
  <Input
212
234
  ref={inputRef}
@@ -228,7 +250,10 @@ export function ScrubInput({
228
250
  }
229
251
  commitDraft();
230
252
  }}
231
- onChange={(event) => setDraft(event.target.value)}
253
+ onChange={(event) => {
254
+ draftRef.current = event.target.value;
255
+ setDraft(event.target.value);
256
+ }}
232
257
  onKeyDown={handleKeyDown}
233
258
  className={cn(
234
259
  // Compact design-editor: h-6, 11px tabular text, ring-1 with no offset.
@@ -60,6 +60,7 @@ export {
60
60
  } from "./GradientEditor";
61
61
  export {
62
62
  ImageFillControls,
63
+ imageFillToBackgroundStyles,
63
64
  imageFillToCss,
64
65
  parseImageFillCss,
65
66
  type ImageFillControlsProps,
@@ -60,11 +60,18 @@ export function formatScrubValue(
60
60
  const normalized = normalizeScrubNumber(value, options);
61
61
  let numeric: string;
62
62
  if (Number.isFinite(options.precision) && options.precision! >= 0) {
63
- const fixed = normalized.toFixed(options.precision);
64
- // Only strip trailing zeros when there's a fractional part. Stripping a bare
65
- // integer (precision 0, e.g. "100") would mangle it to "1" because the regex
66
- // eats the integer's own trailing zeros.
67
- numeric = fixed.includes(".") ? fixed.replace(/\.?0+$/, "") : fixed;
63
+ const fixed = normalized.toFixed(options.precision!);
64
+ if (options.unit) {
65
+ // For fields with units (px, %, °, etc.) collapse all trailing zeros
66
+ // including the decimal point: "12.30px" → "12.3px", "10.00px" → "10px".
67
+ // Leave integer strings alone; otherwise precision 0 turns "100" into "1".
68
+ numeric = fixed.includes(".") ? fixed.replace(/\.?0+$/, "") : fixed;
69
+ } else {
70
+ // For unitless fields (e.g. line-height), preserve at least one decimal
71
+ // digit so values like "2.0" stay "2.0" rather than collapsing to "2".
72
+ // Only strip redundant trailing zeros beyond the first decimal digit.
73
+ numeric = fixed.includes(".") ? fixed.replace(/(?<=\.\d)0+$/, "") : fixed;
74
+ }
68
75
  } else {
69
76
  numeric = String(normalized);
70
77
  }
@@ -36,6 +36,15 @@ export interface ElementInfo {
36
36
 
37
37
  export type DeviceFrameType = "none" | "desktop" | "tablet" | "mobile";
38
38
 
39
+ export const DEVICE_FRAME_VIEWPORTS = {
40
+ desktop: { width: 1280, height: 800 },
41
+ tablet: { width: 768, height: 1024 },
42
+ mobile: { width: 390, height: 844 },
43
+ } as const satisfies Record<
44
+ Exclude<DeviceFrameType, "none">,
45
+ { width: number; height: number }
46
+ >;
47
+
39
48
  export interface ViewportTab {
40
49
  id: string;
41
50
  filename: string;
@@ -2,6 +2,7 @@ import {
2
2
  AgentSidebar,
3
3
  isEmbedAuthActive,
4
4
  getBrowserTabId,
5
+ useGuidedQuestionFlow,
5
6
  useSession,
6
7
  useT,
7
8
  } from "@agent-native/core/client";
@@ -49,9 +50,13 @@ export function Layout({ children }: LayoutProps) {
49
50
  const t = useT();
50
51
  const { session } = useSession();
51
52
  const hasSession = Boolean(session?.email);
53
+ const embedded = isEmbedAuthActive();
52
54
  useNavigationState(hasSession);
53
55
  const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
54
56
  const openMobileSidebar = useCallback(() => setMobileSidebarOpen(true), []);
57
+ const isDesignEditor = location.pathname.startsWith("/design/");
58
+ const showMobileTopBar = !isDesignEditor;
59
+ const browserTabId = getBrowserTabId();
55
60
 
56
61
  // Bind chat to the currently-open design. Same pattern as slides — the
57
62
  // route is `/design/:id` for the editor and `/present/:id` for preview
@@ -64,6 +69,21 @@ export function Layout({ children }: LayoutProps) {
64
69
  if (!designId) return null;
65
70
  return { type: "design" as const, id: designId };
66
71
  }, [location.pathname]);
72
+ const designQuestionStateKey = designScope
73
+ ? `show-questions:${designScope.id}`
74
+ : "show-questions";
75
+ const { questions: pendingDesignQuestions } = useGuidedQuestionFlow({
76
+ stateKey: designQuestionStateKey,
77
+ queryKey: [designQuestionStateKey],
78
+ browserTabId,
79
+ refetchInterval: embedded || !isDesignEditor || !hasSession ? false : 2000,
80
+ });
81
+ const designQuestionsWaitingSlot =
82
+ isDesignEditor && pendingDesignQuestions?.length ? (
83
+ <div className="px-4 pb-2 pt-1 text-xs text-muted-foreground">
84
+ {"Waiting for your answers in the canvas." /* i18n-ignore */}
85
+ </div>
86
+ ) : null;
67
87
 
68
88
  useEffect(() => {
69
89
  setMobileSidebarOpen(false);
@@ -77,9 +97,6 @@ export function Layout({ children }: LayoutProps) {
77
97
  const hideHeader = EDITOR_PREFIXES.some((p) =>
78
98
  location.pathname.startsWith(p),
79
99
  );
80
- const isDesignEditor = location.pathname.startsWith("/design/");
81
- const showMobileTopBar = !isDesignEditor;
82
- const embedded = isEmbedAuthActive();
83
100
 
84
101
  if (embedded || (isDesignEditor && !hasSession)) {
85
102
  return (
@@ -114,7 +131,8 @@ export function Layout({ children }: LayoutProps) {
114
131
  t("chat.suggestionMobile"),
115
132
  ]}
116
133
  scope={designScope}
117
- browserTabId={getBrowserTabId()}
134
+ browserTabId={browserTabId}
135
+ threadFooterSlot={designQuestionsWaitingSlot}
118
136
  >
119
137
  <div className="agent-layout-shell flex h-screen w-full overflow-hidden bg-background text-foreground">
120
138
  {!isDesignEditor && mobileSidebarOpen && (
@@ -154,7 +172,7 @@ export function Layout({ children }: LayoutProps) {
154
172
  {!hideHeader && <Header />}
155
173
  <main
156
174
  className={cn(
157
- "flex-1",
175
+ "agent-native-app-main flex-1",
158
176
  isDesignEditor ? "overflow-hidden" : "overflow-y-auto",
159
177
  )}
160
178
  >
@@ -8,33 +8,33 @@
8
8
 
9
9
  :root {
10
10
  --background: 0 0% 100%;
11
- --foreground: 220 10% 10%;
11
+ --foreground: 0 0% 10%;
12
12
  --card: 0 0% 100%;
13
- --card-foreground: 220 10% 10%;
13
+ --card-foreground: 0 0% 10%;
14
14
  --popover: 0 0% 100%;
15
- --popover-foreground: 220 10% 10%;
16
- --primary: 220 10% 15%;
15
+ --popover-foreground: 0 0% 10%;
16
+ --primary: 0 0% 15%;
17
17
  --primary-foreground: 0 0% 100%;
18
- --secondary: 220 10% 95%;
19
- --secondary-foreground: 220 10% 15%;
20
- --muted: 220 10% 95%;
21
- --muted-foreground: 220 5% 45%;
22
- --accent: 220 10% 95%;
23
- --accent-foreground: 220 10% 15%;
18
+ --secondary: 0 0% 95%;
19
+ --secondary-foreground: 0 0% 15%;
20
+ --muted: 0 0% 95%;
21
+ --muted-foreground: 0 0% 45%;
22
+ --accent: 0 0% 95%;
23
+ --accent-foreground: 0 0% 15%;
24
24
  --destructive: 0 84% 60%;
25
25
  --destructive-foreground: 0 0% 98%;
26
- --border: 220 10% 90%;
27
- --input: 220 10% 90%;
28
- --ring: 220 10% 40%;
26
+ --border: 0 0% 90%;
27
+ --input: 0 0% 90%;
28
+ --ring: 0 0% 40%;
29
29
  --radius: 0.5rem;
30
- --sidebar-background: 220 10% 97%;
31
- --sidebar-foreground: 220 5% 45%;
32
- --sidebar-primary: 220 10% 15%;
30
+ --sidebar-background: 0 0% 97%;
31
+ --sidebar-foreground: 0 0% 45%;
32
+ --sidebar-primary: 0 0% 15%;
33
33
  --sidebar-primary-foreground: 0 0% 100%;
34
- --sidebar-accent: 220 10% 95%;
35
- --sidebar-accent-foreground: 220 10% 15%;
36
- --sidebar-border: 220 10% 90%;
37
- --sidebar-ring: 220 10% 40%;
34
+ --sidebar-accent: 0 0% 95%;
35
+ --sidebar-accent-foreground: 0 0% 15%;
36
+ --sidebar-border: 0 0% 90%;
37
+ --sidebar-ring: 0 0% 40%;
38
38
  --design-editor-accent-color: hsl(213 91% 67%);
39
39
  --design-editor-accent-hover-color: hsl(213 72% 56%);
40
40
  --design-editor-selection-color: color-mix(
@@ -44,12 +44,12 @@
44
44
  );
45
45
  --design-editor-active-row-color: color-mix(
46
46
  in srgb,
47
- hsl(220 10% 15%) 8%,
47
+ hsl(0 0% 15%) 8%,
48
48
  transparent
49
49
  );
50
50
  --design-editor-layer-hover-color: color-mix(
51
51
  in srgb,
52
- hsl(220 10% 15%) 6%,
52
+ hsl(0 0% 15%) 6%,
53
53
  transparent
54
54
  );
55
55
  --design-editor-selected-subtree-color: color-mix(
@@ -69,37 +69,38 @@
69
69
  --design-editor-panel-raised-bg: hsl(var(--secondary));
70
70
  --design-editor-control-bg: hsl(var(--muted));
71
71
  --design-editor-control-border: hsl(var(--border));
72
- --design-editor-canvas-bg: hsl(220 10% 92%);
72
+ --design-editor-canvas-bg: hsl(0 0% 92%);
73
+ --design-editor-skeleton-canvas-bg: hsl(0 0% 92%);
73
74
  }
74
75
 
75
76
  .dark {
76
- --background: 220 6% 6%;
77
+ --background: 0 0% 13%;
77
78
  --foreground: 0 0% 90%;
78
- --card: 220 5% 13%;
79
+ --card: 0 0% 15%;
79
80
  --card-foreground: 0 0% 90%;
80
- --popover: 220 6% 9%;
81
+ --popover: 0 0% 15%;
81
82
  --popover-foreground: 0 0% 90%;
82
83
  --primary: 0 0% 75%;
83
- --primary-foreground: 220 6% 6%;
84
- --secondary: 220 4% 12%;
84
+ --primary-foreground: 0 0% 10%;
85
+ --secondary: 0 0% 18%;
85
86
  --secondary-foreground: 0 0% 90%;
86
- --muted: 220 4% 10%;
87
- --muted-foreground: 220 4% 60%;
88
- --accent: 220 5% 20%;
87
+ --muted: 0 0% 16%;
88
+ --muted-foreground: 0 0% 60%;
89
+ --accent: 0 0% 18%;
89
90
  --accent-foreground: 0 0% 96%;
90
91
  --destructive: 0 63% 51%;
91
92
  --destructive-foreground: 0 0% 98%;
92
- --border: 220 4% 14%;
93
- --input: 220 4% 14%;
93
+ --border: 0 0% 24%;
94
+ --input: 0 0% 24%;
94
95
  --ring: 0 0% 60%;
95
96
  --radius: 0.5rem;
96
- --sidebar-background: 220 5% 13%;
97
- --sidebar-foreground: 220 4% 60%;
97
+ --sidebar-background: 0 0% 10%;
98
+ --sidebar-foreground: 0 0% 60%;
98
99
  --sidebar-primary: 0 0% 75%;
99
- --sidebar-primary-foreground: 220 6% 6%;
100
- --sidebar-accent: 220 4% 10%;
100
+ --sidebar-primary-foreground: 0 0% 10%;
101
+ --sidebar-accent: 0 0% 16%;
101
102
  --sidebar-accent-foreground: 0 0% 90%;
102
- --sidebar-border: 220 4% 10%;
103
+ --sidebar-border: 0 0% 20%;
103
104
  --sidebar-ring: 0 0% 60%;
104
105
  --design-editor-accent-color: hsl(213 91% 67%);
105
106
  --design-editor-accent-hover-color: hsl(213 72% 56%);
@@ -108,7 +109,7 @@
108
109
  hsl(213 91% 67%) 24%,
109
110
  transparent
110
111
  );
111
- --design-editor-active-row-color: hsl(220 4% 20%);
112
+ --design-editor-active-row-color: hsl(0 0% 20%);
112
113
  --design-editor-layer-hover-color: color-mix(
113
114
  in srgb,
114
115
  hsl(0 0% 100%) 8%,
@@ -119,15 +120,16 @@
119
120
  hsl(213 91% 67%) 18%,
120
121
  transparent
121
122
  );
122
- --design-editor-panel-divider-color: hsl(220 4% 22%);
123
+ --design-editor-panel-divider-color: hsl(0 0% 22%);
123
124
  --design-editor-accent-strong-color: var(--design-editor-accent-color);
124
125
  --design-editor-accent-contrast-color: #ffffff;
125
126
  --design-editor-measure-color: hsl(344 100% 63%);
126
- --design-editor-panel-bg: hsl(220 5% 13%);
127
- --design-editor-panel-raised-bg: hsl(220 4% 18%);
128
- --design-editor-control-bg: hsl(220 4% 18%);
129
- --design-editor-control-border: hsl(220 4% 24%);
130
- --design-editor-canvas-bg: hsl(220 6% 6%);
127
+ --design-editor-panel-bg: hsl(0 0% 13%);
128
+ --design-editor-panel-raised-bg: hsl(0 0% 18%);
129
+ --design-editor-control-bg: hsl(0 0% 18%);
130
+ --design-editor-control-border: hsl(0 0% 24%);
131
+ --design-editor-canvas-bg: hsl(0 0% 10%);
132
+ --design-editor-skeleton-canvas-bg: hsl(0 0% 11%);
131
133
  }
132
134
 
133
135
  @layer base {
@@ -176,12 +178,38 @@
176
178
  background: hsl(var(--muted-foreground) / 0.4);
177
179
  }
178
180
 
181
+ .design-editor-not-found-grid {
182
+ background-image:
183
+ linear-gradient(
184
+ var(--design-editor-panel-divider-color) 1px,
185
+ transparent 1px
186
+ ),
187
+ linear-gradient(
188
+ 90deg,
189
+ var(--design-editor-panel-divider-color) 1px,
190
+ transparent 1px
191
+ );
192
+ background-size: 36px 36px;
193
+ -webkit-mask-image: radial-gradient(
194
+ circle at center,
195
+ black 0,
196
+ black 34%,
197
+ transparent 72%
198
+ );
199
+ mask-image: radial-gradient(
200
+ circle at center,
201
+ black 0,
202
+ black 34%,
203
+ transparent 72%
204
+ );
205
+ }
206
+
179
207
  /* Design has a dense editor surface, so its side chrome needs more contrast
180
208
  than the shared shell defaults and a real divider in addition to shadow. */
181
209
  .agent-layout-shell,
182
210
  .agent-sidebar-shell {
183
- --design-shell-chrome-bg: hsl(220 9% 93%);
184
- --design-shell-divider: hsl(220 9% 79%);
211
+ --design-shell-chrome-bg: hsl(0 0% 93%);
212
+ --design-shell-divider: hsl(0 0% 79%);
185
213
  --agent-native-lower-surface: var(--design-shell-chrome-bg);
186
214
  --agent-native-raised-border: var(--design-shell-divider);
187
215
  --agent-native-raised-shadow-left: -1px 0 0 var(--design-shell-divider);
@@ -196,8 +224,8 @@
196
224
  .dark .agent-sidebar-shell,
197
225
  .dark.agent-layout-shell,
198
226
  .dark.agent-sidebar-shell {
199
- --design-shell-chrome-bg: hsl(220 5% 9%);
200
- --design-shell-divider: hsl(220 4% 20%);
227
+ --design-shell-chrome-bg: hsl(0 0% 10%);
228
+ --design-shell-divider: hsl(0 0% 22%);
201
229
  --agent-native-lower-surface: var(--design-shell-chrome-bg);
202
230
  --agent-native-raised-border: var(--design-shell-divider);
203
231
  }
@@ -40,7 +40,7 @@ export function useQuestionFlow(
40
40
  formattedAnswers,
41
41
  "",
42
42
  designId
43
- ? "Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 complete HTML directions and wait for their pick; otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing."
43
+ ? "Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 complete HTML directions, wait for their chat pick, delete the unchosen variant screens, then continue from the kept screen; otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing."
44
44
  : "Now continue the design. Honor any answer about variations: use variants only if requested; otherwise generate one polished direction.",
45
45
  ]
46
46
  .filter(Boolean)
@@ -78,7 +78,7 @@ export function useQuestionFlow(
78
78
  formattedAnswers,
79
79
  "",
80
80
  designId
81
- ? "Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 complete HTML directions and wait for their pick; otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing."
81
+ ? "Now continue the design. Honor any answer about variations: if the user asked to explore options, call present-design-variants with 2-5 complete HTML directions, wait for their chat pick, delete the unchosen variant screens, then continue from the kept screen; otherwise call generate-design with one complete, renderable index.html first. Do not ask another question unless a required decision is still genuinely missing."
82
82
  : "Now continue the design. Honor any answer about variations: use variants only if requested; otherwise generate one polished direction.",
83
83
  ]
84
84
  .filter(Boolean)
@@ -271,7 +271,14 @@ function handleDesignHotkey(
271
271
  if (
272
272
  event.key === "Tab" &&
273
273
  props.onTab &&
274
- !isFocusableChromeTarget(event.target)
274
+ // Ignore synthetic (non-trusted) Tab events dispatched by handleIframeHotkey
275
+ // unless they carry the iframe-hotkey marker. This keeps inspector field
276
+ // tabbing native while allowing real iframe canvas Tab presses to cycle files.
277
+ (event.isTrusted !== false ||
278
+ (event as KeyboardEvent & { __agentNativeIframeHotkey?: boolean })
279
+ .__agentNativeIframeHotkey === true) &&
280
+ !isFocusableChromeTarget(event.target) &&
281
+ !isDesignHotkeyEditableTarget(document.activeElement)
275
282
  ) {
276
283
  prevent();
277
284
  props.onTab({ ...details, backwards: event.shiftKey });
@@ -412,10 +412,13 @@ const messages = {
412
412
  duplicateElementFailed: "無法複製該元素",
413
413
  saveCopyError: "無法儲存這個設計的副本",
414
414
  },
415
+ inspectorLockedTitle: "產生中,檢查器已鎖定",
416
+ inspectorLockedDescription: "第一個畫面準備好後即可使用控制項。",
415
417
  },
416
418
  layersPanel: {
417
419
  title: "圖層",
418
420
  screens: "畫面",
421
+ allScreens: "所有畫面",
419
422
  thumbnail: "縮圖",
420
423
  addScreen: "新增畫面",
421
424
  searchPlaceholder: "搜尋圖層...",