@agent-native/core 0.80.8 → 0.80.10

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 (359) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +19 -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/design-connect.ts +28 -2
  16. package/corpus/core/src/cli/mcp.ts +10 -0
  17. package/corpus/core/src/cli/skills.ts +103 -36
  18. package/corpus/core/src/client/error-format.ts +25 -0
  19. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +13 -11
  20. package/corpus/core/src/client/guided-questions.tsx +32 -4
  21. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +33 -1
  22. package/corpus/core/src/client/resources/BuiltinCapabilityDetail.tsx +8 -0
  23. package/corpus/core/src/client/resources/use-builtin-capabilities.ts +4 -2
  24. package/corpus/core/src/client/session-replay.ts +34 -0
  25. package/corpus/core/src/client/sharing/ShareButton.tsx +106 -21
  26. package/corpus/core/src/coding-tools/index.ts +1 -1
  27. package/corpus/core/src/mcp/index.ts +2 -0
  28. package/corpus/core/src/mcp/screen-memory-stdio.ts +290 -0
  29. package/corpus/core/src/mcp-client/builtin-capabilities.ts +13 -1
  30. package/corpus/core/src/mcp-client/index.ts +9 -0
  31. package/corpus/core/src/mcp-client/screen-memory-local.ts +461 -0
  32. package/corpus/core/src/onboarding/types.ts +7 -0
  33. package/corpus/core/src/server/agent-chat-plugin.ts +25 -0
  34. package/corpus/core/src/server/agents-bundle.ts +35 -7
  35. package/corpus/core/src/styles/agent-native.css +5 -0
  36. package/corpus/core/src/templates/default/app/global.css +35 -35
  37. package/corpus/templates/analytics/AGENTS.md +6 -0
  38. package/corpus/templates/analytics/actions/github-repo-files.ts +9 -0
  39. package/corpus/templates/analytics/app/components/layout/Layout.tsx +4 -4
  40. package/corpus/templates/analytics/app/global.css +144 -40
  41. package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +1 -1
  42. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +1 -1
  43. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
  44. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +4 -4
  45. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -9
  46. package/corpus/templates/analytics/changelog/2026-06-29-agents-can-search-and-read-connected-github-repositories-whe.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-06-29-sessions-and-explorer-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  48. package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -1
  49. package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +1 -1
  50. package/corpus/templates/assets/app/global.css +99 -35
  51. package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
  52. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +4 -4
  53. package/corpus/templates/assets/app/routes/library.tsx +4 -4
  54. package/corpus/templates/assets/changelog/2026-06-29-asset-library-and-detail-layouts-adapt-when-the-agent-sidebar.md +6 -0
  55. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
  56. package/corpus/templates/brain/app/global.css +63 -35
  57. package/corpus/templates/brain/app/routes/search.tsx +1 -1
  58. package/corpus/templates/brain/app/routes/settings.tsx +1 -1
  59. package/corpus/templates/brain/app/routes/sources.tsx +2 -2
  60. package/corpus/templates/brain/changelog/2026-06-29-search-settings-and-source-layouts-adapt-when-the-agent-sidebar.md +6 -0
  61. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +4 -4
  62. package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +3 -2
  63. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -2
  64. package/corpus/templates/calendar/app/global.css +69 -35
  65. package/corpus/templates/calendar/changelog/2026-06-29-event-and-find-time-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  66. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  67. package/corpus/templates/chat/app/global.css +35 -35
  68. package/corpus/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  69. package/corpus/templates/clips/AGENTS.md +13 -0
  70. package/corpus/templates/clips/actions/get-screen-memory-status.ts +12 -0
  71. package/corpus/templates/clips/actions/query-screen-memory-context.ts +29 -0
  72. package/corpus/templates/clips/actions/view-screen.ts +2 -2
  73. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  74. package/corpus/templates/clips/app/global.css +47 -35
  75. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +3 -3
  76. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +45 -18
  77. package/corpus/templates/clips/changelog/2026-06-29-meeting-detail-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-06-29-screen-memory-keeps-a-local-rolling-screen-buffer-for-agent-context.md +5 -0
  79. package/corpus/templates/clips/changelog/2026-06-29-video-chat-is-easier-to-find-on-recording-pages-and-s3-setup.md +6 -0
  80. package/corpus/templates/clips/chrome-extension/src/styles.css +39 -39
  81. package/corpus/templates/clips/desktop/src/app.tsx +290 -1
  82. package/corpus/templates/clips/desktop/src/shared/config.ts +83 -0
  83. package/corpus/templates/clips/desktop/src/styles.css +67 -52
  84. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +50 -0
  85. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +17 -0
  86. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +13 -13
  87. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +990 -0
  88. package/corpus/templates/clips/server/plugins/onboarding.ts +2 -0
  89. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +3 -3
  90. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
  91. package/corpus/templates/content/app/global.css +29 -15
  92. package/corpus/templates/content/changelog/2026-06-29-database-gallery-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  93. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +25 -20
  94. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  95. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +8 -0
  96. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +13 -0
  97. package/corpus/templates/design/AGENTS.md +20 -12
  98. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1054 -0
  99. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +717 -0
  100. package/corpus/templates/design/actions/add-breakpoint.ts +143 -0
  101. package/corpus/templates/design/actions/add-localhost-screens.ts +5 -0
  102. package/corpus/templates/design/actions/apply-a11y-fix.ts +317 -0
  103. package/corpus/templates/design/actions/apply-component-prop-edit.ts +433 -0
  104. package/corpus/templates/design/actions/apply-design-state.ts +200 -0
  105. package/corpus/templates/design/actions/apply-design-token-edit.ts +202 -0
  106. package/corpus/templates/design/actions/apply-motion-edit.ts +450 -0
  107. package/corpus/templates/design/actions/apply-shader-fill.ts +404 -0
  108. package/corpus/templates/design/actions/apply-visual-edit.ts +214 -8
  109. package/corpus/templates/design/actions/capture-design-state.ts +224 -0
  110. package/corpus/templates/design/actions/connect-builder-app.ts +162 -0
  111. package/corpus/templates/design/actions/create-component.ts +447 -0
  112. package/corpus/templates/design/actions/create-design-branch.ts +263 -0
  113. package/corpus/templates/design/actions/create-design-state.ts +162 -0
  114. package/corpus/templates/design/actions/delete-design-state.ts +55 -0
  115. package/corpus/templates/design/actions/deploy-design-preview.ts +275 -0
  116. package/corpus/templates/design/actions/export-coding-handoff.ts +12 -4
  117. package/corpus/templates/design/actions/generate-design.ts +6 -21
  118. package/corpus/templates/design/actions/generate-screens.ts +43 -2
  119. package/corpus/templates/design/actions/get-component-details.ts +242 -0
  120. package/corpus/templates/design/actions/get-design-branch-diff.ts +362 -0
  121. package/corpus/templates/design/actions/get-design-review.ts +314 -0
  122. package/corpus/templates/design/actions/get-design-surface-index.ts +582 -0
  123. package/corpus/templates/design/actions/get-design.ts +1 -0
  124. package/corpus/templates/design/actions/get-motion-timeline.ts +99 -0
  125. package/corpus/templates/design/actions/index-components.ts +258 -0
  126. package/corpus/templates/design/actions/index-design-tokens.ts +273 -0
  127. package/corpus/templates/design/actions/list-design-extensions.ts +309 -0
  128. package/corpus/templates/design/actions/list-design-source-capabilities.ts +153 -0
  129. package/corpus/templates/design/actions/list-design-states.ts +72 -0
  130. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +298 -0
  131. package/corpus/templates/design/actions/open-component-source.ts +237 -0
  132. package/corpus/templates/design/actions/present-design-variants.ts +355 -30
  133. package/corpus/templates/design/actions/preview-component-prop-edit.ts +254 -0
  134. package/corpus/templates/design/actions/preview-design-token-edit.ts +113 -0
  135. package/corpus/templates/design/actions/preview-shader-fill.ts +189 -0
  136. package/corpus/templates/design/actions/remove-breakpoint.ts +103 -0
  137. package/corpus/templates/design/actions/remove-motion-timeline.ts +196 -0
  138. package/corpus/templates/design/actions/run-design-audit.ts +421 -0
  139. package/corpus/templates/design/actions/run-design-extension-action.ts +284 -0
  140. package/corpus/templates/design/actions/set-active-breakpoint.ts +39 -0
  141. package/corpus/templates/design/actions/view-screen.ts +75 -31
  142. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1738 -135
  143. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
  144. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +632 -43
  145. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +1 -1
  146. package/corpus/templates/design/app/components/design/EditPanel.tsx +1873 -132
  147. package/corpus/templates/design/app/components/design/LayersPanel.tsx +384 -219
  148. package/corpus/templates/design/app/components/design/LocalSourceEditBanner.tsx +157 -0
  149. package/corpus/templates/design/app/components/design/MotionDock.tsx +1062 -0
  150. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2103 -295
  151. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +83 -206
  152. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +759 -0
  153. package/corpus/templates/design/app/components/design/StatesPanel.tsx +579 -0
  154. package/corpus/templates/design/app/components/design/TokensPanel.tsx +573 -0
  155. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +1 -1
  156. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +241 -0
  157. package/corpus/templates/design/app/components/design/index.ts +16 -1
  158. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +238 -137
  159. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +188 -14
  160. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +24 -5
  161. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -1
  162. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +145 -0
  163. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +42 -12
  164. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +37 -12
  165. package/corpus/templates/design/app/components/design/inspector/index.ts +1 -0
  166. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +12 -5
  167. package/corpus/templates/design/app/components/design/types.ts +9 -0
  168. package/corpus/templates/design/app/components/layout/Layout.tsx +23 -5
  169. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +1 -1
  170. package/corpus/templates/design/app/global.css +77 -49
  171. package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
  172. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +131 -0
  173. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -2
  174. package/corpus/templates/design/app/i18n/zh-TW.ts +34 -0
  175. package/corpus/templates/design/app/i18n-data.ts +314 -3
  176. package/corpus/templates/design/app/pages/DesignEditor.tsx +4929 -892
  177. package/corpus/templates/design/app/root.tsx +1 -1
  178. package/corpus/templates/design/changelog/2026-06-29-added-a-review-panel-in-the-design-editor-s-inspector-with-a.md +6 -0
  179. package/corpus/templates/design/changelog/2026-06-29-containers-no-longer-block-selecting-nested-elements-and-nor.md +6 -0
  180. package/corpus/templates/design/changelog/2026-06-29-copying-and-pasting-layers-no-longer-shows-success-notificat.md +6 -0
  181. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-generate-and-refine-variants-from-stronger.md +6 -0
  182. package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +6 -0
  183. package/corpus/templates/design/changelog/2026-06-29-design-questions-now-appear-as-a-cleaner-canvas-intake-with-.md +6 -0
  184. package/corpus/templates/design/changelog/2026-06-29-design-variant-directions-now-appear-as-board-screens-with-chat-buttons.md +5 -0
  185. package/corpus/templates/design/changelog/2026-06-29-device-presets-in-all-screens-view-resize-the-selected-previ.md +6 -0
  186. package/corpus/templates/design/changelog/2026-06-29-element-selection-no-longer-snaps-back-to-the-previous-layer.md +6 -0
  187. package/corpus/templates/design/changelog/2026-06-29-frame-resize-measurements-now-stay-beside-the-cursor-while-d.md +6 -0
  188. package/corpus/templates/design/changelog/2026-06-29-inspector-number-fields-have-cleaner-tooltips-and-draggable-.md +6 -0
  189. package/corpus/templates/design/changelog/2026-06-29-layer-and-canvas-drags-keep-the-layer-list-stable-while-chan.md +6 -0
  190. package/corpus/templates/design/changelog/2026-06-29-layer-locking-layer-nesting-generated-question-intake-and-im.md +6 -0
  191. package/corpus/templates/design/changelog/2026-06-29-layer-moves-can-be-undone-and-redone-without-flashing-the-ca.md +6 -0
  192. package/corpus/templates/design/changelog/2026-06-29-layer-names-in-the-sidebar-can-scroll-horizontally-instead-o.md +6 -0
  193. package/corpus/templates/design/changelog/2026-06-29-layer-nesting-in-the-sidebar-now-uses-tighter-spacing-so-nam.md +6 -0
  194. package/corpus/templates/design/changelog/2026-06-29-layers-no-longer-repeat-document-wrapper-rows-when-a-screen-.md +6 -0
  195. package/corpus/templates/design/changelog/2026-06-29-overview-previews-now-keep-element-hover-and-selection-tied-.md +6 -0
  196. package/corpus/templates/design/changelog/2026-06-29-pressing-escape-now-cancels-a-stuck-screen-drag-in-the-overv.md +6 -0
  197. package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +6 -0
  198. package/corpus/templates/design/changelog/2026-06-29-screen-overview-only-highlights-screens-when-the-frame-or-ti.md +6 -0
  199. package/corpus/templates/design/changelog/2026-06-29-screen-overview-previews-now-resize-to-match-the-selected-de.md +6 -0
  200. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-now-uses-a-pointer-cursor-instead-.md +6 -0
  201. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-outlines-now-stay-locked-to-the-se.md +6 -0
  202. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zoom-now-reports-real-screen-scale-separatel.md +6 -0
  203. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-feels-smoother-and-selection-outline.md +6 -0
  204. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-now-stays-on-the-overview-canvas-ins.md +6 -0
  205. package/corpus/templates/design/changelog/2026-06-29-screen-previews-use-a-single-blue-hover-border-in-all-screen.md +6 -0
  206. package/corpus/templates/design/changelog/2026-06-29-selected-containers-show-draggable-padding-and-gap-guides-on.md +6 -0
  207. package/corpus/templates/design/changelog/2026-06-29-selecting-a-nested-layer-from-all-screens-now-keeps-you-in-a.md +6 -0
  208. package/corpus/templates/design/changelog/2026-06-29-share-now-groups-link-sharing-exports-and-agent-handoff.md +6 -0
  209. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-adds-a-studio-layer-with-tokens-respon.md +6 -0
  210. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-loading-skeleton-now-uses-a-softer-charcoa.md +6 -0
  211. package/corpus/templates/design/changelog/2026-06-29-the-device-preview-menu-now-sits-next-to-the-preview-button-.md +6 -0
  212. package/corpus/templates/design/changelog/2026-06-29-the-inspector-stays-read-only-while-an-empty-design-is-still.md +6 -0
  213. package/corpus/templates/design/changelog/2026-06-29-the-missing-design-view-now-matches-the-rest-of-the-editor-c.md +6 -0
  214. package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-icon-and-tool-option-menus-better-match-the-edi.md +6 -0
  215. package/corpus/templates/design/changelog/2026-06-29-typography-controls-now-keep-the-font-name-visible-and-move-.md +6 -0
  216. package/corpus/templates/design/changelog/2026-06-30-accessibility-findings-now-offer-a-one-click-fix.md +6 -0
  217. package/corpus/templates/design/changelog/2026-06-30-component-instances-now-have-editable-props-in-the-inspe.md +6 -0
  218. package/corpus/templates/design/changelog/2026-06-30-inspect-code-now-shows-the-elements-opening-tag-at-a-gla.md +6 -0
  219. package/corpus/templates/design/changelog/2026-06-30-shader-fill-presets-can-now-be-applied-to-an-element.md +6 -0
  220. package/corpus/templates/design/changelog/2026-06-30-the-motion-timeline-can-now-add-a-track-to-any-element-a.md +6 -0
  221. package/corpus/templates/design/changelog/2026-06-30-visual-editor-selection-layer-paint-and-drawing-controls-are-more-reliable.md +6 -0
  222. package/corpus/templates/design/e2e/README.md +3 -3
  223. package/corpus/templates/design/e2e/global-setup.ts +11 -22
  224. package/corpus/templates/design/e2e/helpers.ts +128 -11
  225. package/corpus/templates/design/playwright.config.ts +9 -3
  226. package/corpus/templates/design/server/db/schema.ts +123 -0
  227. package/corpus/templates/design/server/lib/coding-handoff.ts +126 -2
  228. package/corpus/templates/design/server/plugins/core-routes.ts +1 -2
  229. package/corpus/templates/design/server/plugins/db.ts +90 -0
  230. package/corpus/templates/design/server/routes/api/design-handoff/[id].zip.get.ts +86 -0
  231. package/corpus/templates/design/shared/builder-app.ts +297 -0
  232. package/corpus/templates/design/shared/capability-resolver.ts +123 -0
  233. package/corpus/templates/design/shared/capture-sanitize.ts +70 -0
  234. package/corpus/templates/design/shared/code-layer.ts +1141 -93
  235. package/corpus/templates/design/shared/component-model.ts +239 -0
  236. package/corpus/templates/design/shared/design-review.ts +275 -0
  237. package/corpus/templates/design/shared/design-source-capabilities.ts +286 -0
  238. package/corpus/templates/design/shared/design-state.ts +112 -0
  239. package/corpus/templates/design/shared/design-surface-index.ts +258 -0
  240. package/corpus/templates/design/shared/generation-session.ts +41 -0
  241. package/corpus/templates/design/shared/motion-compiler.ts +278 -0
  242. package/corpus/templates/design/shared/motion-timeline.ts +193 -0
  243. package/corpus/templates/design/shared/responsive-classes.ts +452 -0
  244. package/corpus/templates/design/shared/shader-fill.ts +323 -0
  245. package/corpus/templates/design/shared/source-mode.ts +245 -0
  246. package/corpus/templates/dispatch/app/global.css +79 -35
  247. package/corpus/templates/dispatch/app/routes/integrations.tsx +8 -7
  248. package/corpus/templates/dispatch/changelog/2026-06-29-integration-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  249. package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -2
  250. package/corpus/templates/forms/app/global.css +64 -35
  251. package/corpus/templates/forms/app/pages/FormsListPage.tsx +2 -2
  252. package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +3 -3
  253. package/corpus/templates/forms/changelog/2026-06-29-form-list-and-insight-layouts-adapt-when-the-agent-sidebar.md +6 -0
  254. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -1
  255. package/corpus/templates/macros/app/global.css +25 -9
  256. package/corpus/templates/macros/changelog/2026-06-29-macro-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  257. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -2
  258. package/corpus/templates/mail/app/global.css +42 -36
  259. package/corpus/templates/mail/app/pages/InboxPage.tsx +1 -1
  260. package/corpus/templates/mail/changelog/2026-06-29-the-contact-panel-now-adapts-to-the-available-mail-pane-width.md +6 -0
  261. package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -1
  262. package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +6 -2
  263. package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +6 -7
  264. package/corpus/templates/plan/app/global.css +74 -42
  265. package/corpus/templates/plan/changelog/2026-06-29-plan-canvases-open-without-an-initial-pan-and-zoom-flicker.md +6 -0
  266. package/corpus/templates/plan/changelog/2026-06-29-plan-document-blocks-adapt-to-the-available-document-width.md +6 -0
  267. package/corpus/templates/plan/changelog/2026-06-29-plan-titles-and-summaries-can-be-edited-inline-without-focus.md +6 -0
  268. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -1
  269. package/corpus/templates/slides/app/global.css +49 -33
  270. package/corpus/templates/slides/changelog/2026-06-29-slide-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  271. package/corpus/templates/videos/app/components/layout/Layout.tsx +3 -1
  272. package/corpus/templates/videos/app/global.css +35 -35
  273. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  274. package/dist/cli/design-connect.d.ts.map +1 -1
  275. package/dist/cli/design-connect.js +28 -2
  276. package/dist/cli/design-connect.js.map +1 -1
  277. package/dist/cli/mcp.d.ts.map +1 -1
  278. package/dist/cli/mcp.js +10 -0
  279. package/dist/cli/mcp.js.map +1 -1
  280. package/dist/cli/skills.d.ts.map +1 -1
  281. package/dist/cli/skills.js +95 -33
  282. package/dist/cli/skills.js.map +1 -1
  283. package/dist/client/error-format.d.ts.map +1 -1
  284. package/dist/client/error-format.js +17 -0
  285. package/dist/client/error-format.js.map +1 -1
  286. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  287. package/dist/client/extensions/ExtensionViewer.js +3 -4
  288. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  289. package/dist/client/guided-questions.d.ts +4 -0
  290. package/dist/client/guided-questions.d.ts.map +1 -1
  291. package/dist/client/guided-questions.js +16 -7
  292. package/dist/client/guided-questions.js.map +1 -1
  293. package/dist/client/onboarding/OnboardingPanel.js +26 -1
  294. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  295. package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -1
  296. package/dist/client/resources/BuiltinCapabilityDetail.js +1 -1
  297. package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -1
  298. package/dist/client/resources/use-builtin-capabilities.d.ts +1 -1
  299. package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -1
  300. package/dist/client/resources/use-builtin-capabilities.js +2 -1
  301. package/dist/client/resources/use-builtin-capabilities.js.map +1 -1
  302. package/dist/client/session-replay.d.ts.map +1 -1
  303. package/dist/client/session-replay.js +31 -0
  304. package/dist/client/session-replay.js.map +1 -1
  305. package/dist/client/sharing/ShareButton.d.ts +14 -0
  306. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  307. package/dist/client/sharing/ShareButton.js +36 -7
  308. package/dist/client/sharing/ShareButton.js.map +1 -1
  309. package/dist/coding-tools/index.js +1 -1
  310. package/dist/coding-tools/index.js.map +1 -1
  311. package/dist/mcp/index.d.ts +2 -0
  312. package/dist/mcp/index.d.ts.map +1 -1
  313. package/dist/mcp/index.js +1 -0
  314. package/dist/mcp/index.js.map +1 -1
  315. package/dist/mcp/screen-memory-stdio.d.ts +6 -0
  316. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -0
  317. package/dist/mcp/screen-memory-stdio.js +213 -0
  318. package/dist/mcp/screen-memory-stdio.js.map +1 -0
  319. package/dist/mcp-client/builtin-capabilities.d.ts +1 -1
  320. package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -1
  321. package/dist/mcp-client/builtin-capabilities.js +10 -0
  322. package/dist/mcp-client/builtin-capabilities.js.map +1 -1
  323. package/dist/mcp-client/index.d.ts +1 -0
  324. package/dist/mcp-client/index.d.ts.map +1 -1
  325. package/dist/mcp-client/index.js +1 -0
  326. package/dist/mcp-client/index.js.map +1 -1
  327. package/dist/mcp-client/screen-memory-local.d.ts +61 -0
  328. package/dist/mcp-client/screen-memory-local.d.ts.map +1 -0
  329. package/dist/mcp-client/screen-memory-local.js +336 -0
  330. package/dist/mcp-client/screen-memory-local.js.map +1 -0
  331. package/dist/observability/routes.d.ts +3 -3
  332. package/dist/onboarding/types.d.ts +7 -0
  333. package/dist/onboarding/types.d.ts.map +1 -1
  334. package/dist/onboarding/types.js.map +1 -1
  335. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  336. package/dist/server/agent-chat-plugin.js +26 -0
  337. package/dist/server/agent-chat-plugin.js.map +1 -1
  338. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  339. package/dist/server/agents-bundle.d.ts.map +1 -1
  340. package/dist/server/agents-bundle.js +22 -7
  341. package/dist/server/agents-bundle.js.map +1 -1
  342. package/dist/styles/agent-native.css +5 -0
  343. package/dist/templates/default/app/global.css +35 -35
  344. package/docs/content/locales/ar-SA/template-design.mdx +6 -0
  345. package/docs/content/locales/de-DE/template-design.mdx +8 -0
  346. package/docs/content/locales/es-ES/template-design.mdx +10 -2
  347. package/docs/content/locales/fr-FR/template-design.mdx +10 -2
  348. package/docs/content/locales/hi-IN/template-design.mdx +7 -0
  349. package/docs/content/locales/ja-JP/template-design.mdx +7 -0
  350. package/docs/content/locales/ko-KR/template-design.mdx +7 -0
  351. package/docs/content/locales/pt-BR/template-design.mdx +9 -2
  352. package/docs/content/locales/zh-CN/template-design.mdx +6 -0
  353. package/docs/content/locales/zh-TW/template-design.mdx +6 -0
  354. package/docs/content/template-design.mdx +9 -2
  355. package/package.json +1 -1
  356. package/src/templates/default/app/global.css +35 -35
  357. package/corpus/templates/design/app/components/design/VariantGrid.tsx +0 -189
  358. package/corpus/templates/design/app/components/design/VariantHandoffCard.tsx +0 -115
  359. package/corpus/templates/design/app/hooks/use-variant-flow.ts +0 -342
@@ -14,6 +14,7 @@ import type { ShaderDescriptor } from "@shared/shader-presets";
14
14
  import { IconChevronDown, IconColorPicker } from "@tabler/icons-react";
15
15
  import {
16
16
  useEffect,
17
+ useMemo,
17
18
  useRef,
18
19
  useState,
19
20
  type JSX,
@@ -27,6 +28,13 @@ import {
27
28
  PopoverContent,
28
29
  PopoverTrigger,
29
30
  } from "@/components/ui/popover";
31
+ import {
32
+ Select,
33
+ SelectContent,
34
+ SelectItem,
35
+ SelectTrigger,
36
+ SelectValue,
37
+ } from "@/components/ui/select";
30
38
  import {
31
39
  Tooltip,
32
40
  TooltipContent,
@@ -130,6 +138,7 @@ export interface DesignColorPickerProps {
130
138
  value: string;
131
139
  onChange: (value: string) => void;
132
140
  onPaintValueChange?: (value: string) => void;
141
+ onImageFillChange?: (value: ImageFillValue) => void;
133
142
  label?: string;
134
143
  opacity?: number;
135
144
  onOpacityChange?: (opacity: number) => void;
@@ -191,6 +200,87 @@ interface HsvaColor {
191
200
 
192
201
  const FALLBACK_COLOR: RgbaColor = { r: 0, g: 0, b: 0, a: 1 };
193
202
 
203
+ // ─── Extended CSS color parser ──────────────────────────────────────────────────
204
+ //
205
+ // `parseCssColor` from color-utils handles hex, comma-separated rgb/rgba, and
206
+ // hsl/hsla. Browsers increasingly emit modern CSS Level 4 formats from
207
+ // getComputedStyle: space-separated `rgb(R G B)`, `rgb(R G B / A)`, and
208
+ // opaque formats like `oklch(...)` or `color(display-p3 ...)`.
209
+ //
210
+ // This local wrapper extends the parser to cover those cases so that colors
211
+ // arriving from the canvas's computed-style bridge are always usable.
212
+
213
+ const MODERN_RGB_PATTERN =
214
+ /^rgba?\(\s*([0-9.]+)\s+([0-9.]+)\s+([0-9.]+)(?:\s*\/\s*([0-9.]+%?))?\s*\)$/i;
215
+
216
+ /** Canvas element reused across calls for DOM-based color resolution. */
217
+ let _resolverCanvas: HTMLCanvasElement | null = null;
218
+ let _resolverCtx: CanvasRenderingContext2D | null = null;
219
+
220
+ /**
221
+ * Parses a CSS color string into RgbaColor, extending the base parser with:
222
+ * - Modern space-separated `rgb(R G B)` / `rgb(R G B / A)` syntax
223
+ * - Opaque formats (oklch, color, etc.) resolved via a hidden canvas
224
+ *
225
+ * Falls back to null if the value is unparseable and the DOM is unavailable.
226
+ */
227
+ function parseCssColorExtended(value: string): RgbaColor | null {
228
+ // 1. Try the standard parser first (handles hex, comma rgb/rgba, hsl/hsla).
229
+ const standard = parseCssColor(value);
230
+ if (standard) return standard;
231
+
232
+ const trimmed = value.trim();
233
+ if (!trimmed || trimmed === "transparent" || trimmed === "none") return null;
234
+
235
+ // 2. Modern space-separated rgb/rgba — CSS Level 4.
236
+ const modernRgb = trimmed.match(MODERN_RGB_PATTERN);
237
+ if (modernRgb) {
238
+ const parseAlphaLocal = (v: string | undefined): number => {
239
+ if (!v) return 1;
240
+ if (v.endsWith("%"))
241
+ return Math.max(0, Math.min(1, Number(v.slice(0, -1)) / 100));
242
+ return Math.max(0, Math.min(1, Number(v)));
243
+ };
244
+ return {
245
+ r: Math.round(Math.max(0, Math.min(255, Number(modernRgb[1])))),
246
+ g: Math.round(Math.max(0, Math.min(255, Number(modernRgb[2])))),
247
+ b: Math.round(Math.max(0, Math.min(255, Number(modernRgb[3])))),
248
+ a: parseAlphaLocal(modernRgb[4]),
249
+ };
250
+ }
251
+
252
+ // 3. DOM-based resolver for oklch, color(display-p3 ...), hsl (modern), etc.
253
+ // Uses a hidden 1×1 canvas to resolve any valid CSS color to rgb().
254
+ if (typeof document === "undefined") return null;
255
+ try {
256
+ if (!_resolverCanvas) {
257
+ _resolverCanvas = document.createElement("canvas");
258
+ _resolverCanvas.width = 1;
259
+ _resolverCanvas.height = 1;
260
+ }
261
+ if (!_resolverCtx) {
262
+ _resolverCtx = _resolverCanvas.getContext("2d", {
263
+ willReadFrequently: true,
264
+ });
265
+ }
266
+ const ctx = _resolverCtx;
267
+ if (!ctx) return null;
268
+ // Detect invalid color values: save fillStyle before and after assignment.
269
+ // If the browser rejects the value, fillStyle won't change.
270
+ const prev = ctx.fillStyle;
271
+ ctx.fillStyle = trimmed;
272
+ const next = ctx.fillStyle; // browser normalises to rgb/hex on accept
273
+ // If the value was rejected, fillStyle stays at the previous value.
274
+ if (next === prev) return null;
275
+ ctx.clearRect(0, 0, 1, 1);
276
+ ctx.fillRect(0, 0, 1, 1);
277
+ const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
278
+ return { r, g, b, a: a / 255 };
279
+ } catch {
280
+ return null;
281
+ }
282
+ }
283
+
194
284
  const DEFAULT_LABELS: DesignColorPickerLabels = {
195
285
  trigger: "Open color picker", // i18n-ignore fallback component label
196
286
  hex: "Hex", // i18n-ignore fallback component label
@@ -568,6 +658,24 @@ const NOISE_FALLBACK_CSS =
568
658
  "repeating-conic-gradient(#0000 0% 25%, #00000010 0% 50%) 0 0 / 6px 6px, #8a8a8a";
569
659
  const PATTERN_FALLBACK_CSS =
570
660
  "repeating-linear-gradient(45deg, #00000014 0 6px, #ffffff14 6px 12px), #9aa0a6";
661
+ const BLEND_MODE_OPTIONS = [
662
+ { value: "normal", label: "Normal" },
663
+ { value: "multiply", label: "Multiply" },
664
+ { value: "screen", label: "Screen" },
665
+ { value: "overlay", label: "Overlay" },
666
+ { value: "darken", label: "Darken" },
667
+ { value: "lighten", label: "Lighten" },
668
+ { value: "color-dodge", label: "Color dodge" }, // i18n-ignore design blend mode label
669
+ { value: "color-burn", label: "Color burn" }, // i18n-ignore design blend mode label
670
+ { value: "hard-light", label: "Hard light" }, // i18n-ignore design blend mode label
671
+ { value: "soft-light", label: "Soft light" }, // i18n-ignore design blend mode label
672
+ { value: "difference", label: "Difference" },
673
+ { value: "exclusion", label: "Exclusion" },
674
+ { value: "hue", label: "Hue" },
675
+ { value: "saturation", label: "Saturation" },
676
+ { value: "color", label: "Color" },
677
+ { value: "luminosity", label: "Luminosity" },
678
+ ] as const;
571
679
 
572
680
  // ─── Main component ────────────────────────────────────────────────────────────
573
681
 
@@ -575,12 +683,13 @@ export function DesignColorPicker({
575
683
  value,
576
684
  onChange,
577
685
  onPaintValueChange,
686
+ onImageFillChange,
578
687
  label: _label,
579
688
  opacity,
580
689
  onOpacityChange,
581
- blendMode: _blendMode,
582
- onBlendModeChange: _onBlendModeChange,
583
- showBlendMode: _showBlendMode,
690
+ blendMode,
691
+ onBlendModeChange,
692
+ showBlendMode = false,
584
693
  fillRows: _fillRows,
585
694
  selectedFillId: _selectedFillId,
586
695
  onFillSelect: _onFillSelect,
@@ -605,10 +714,15 @@ export function DesignColorPicker({
605
714
  className,
606
715
  }: DesignColorPickerProps) {
607
716
  const copy = { ...DEFAULT_LABELS, ...labels };
608
- const color = parseCssColor(value) ?? FALLBACK_COLOR;
717
+ const color = parseCssColorExtended(value) ?? FALLBACK_COLOR;
609
718
  const hsv = rgbaToHsv(color);
610
719
  const hsl = rgbaToHsl(color);
611
720
  const effectiveOpacity = opacity ?? alphaToOpacity(color.a);
721
+ const blendModeValue = BLEND_MODE_OPTIONS.some(
722
+ (option) => option.value === blendMode,
723
+ )
724
+ ? blendMode
725
+ : "normal";
612
726
 
613
727
  const [mode, setMode] = useState<DesignColorMode>("hex");
614
728
  const [hexDraft, setHexDraft] = useState(() => toDisplayHex(color));
@@ -651,16 +765,24 @@ export function DesignColorPicker({
651
765
 
652
766
  // Resolve the active gradient: prefer EditPanel-driven props; otherwise parse
653
767
  // the live CSS value, falling back to local edit state.
654
- const parsedGradient = parseGradientCss(value, gradientType ?? "linear");
768
+ const parsedGradient = useMemo(
769
+ () => parseGradientCss(value, gradientType ?? "linear"),
770
+ [gradientType, value],
771
+ );
772
+ const fallbackGradient = useMemo(
773
+ () =>
774
+ GRADIENT_TYPES.has(effectivePaintType)
775
+ ? defaultGradient(
776
+ effectivePaintType as GradientKind,
777
+ toCssColor(color) || "#000000",
778
+ )
779
+ : null,
780
+ [color.r, color.g, color.b, color.a, effectivePaintType],
781
+ );
655
782
  const activeGradient: GradientValue | null = GRADIENT_TYPES.has(
656
783
  effectivePaintType,
657
784
  )
658
- ? (localGradient ??
659
- parsedGradient ??
660
- defaultGradient(
661
- effectivePaintType as GradientKind,
662
- toCssColor(color) || "#000000",
663
- ))
785
+ ? (localGradient ?? parsedGradient ?? fallbackGradient)
664
786
  : null;
665
787
 
666
788
  useEffect(() => {
@@ -754,7 +876,8 @@ export function DesignColorPicker({
754
876
 
755
877
  // The 2D field edits the selected gradient stop's color when in gradient mode.
756
878
  const fieldColor: RgbaColor = activeGradient
757
- ? (parseCssColor(selectedStop?.color ?? "#000000") ?? FALLBACK_COLOR)
879
+ ? (parseCssColorExtended(selectedStop?.color ?? "#000000") ??
880
+ FALLBACK_COLOR)
758
881
  : color;
759
882
  const rawFieldHsv = rgbaToHsv(fieldColor);
760
883
  // Preserve the last non-zero hue so dragging through gray doesn't lose it.
@@ -771,7 +894,7 @@ export function DesignColorPicker({
771
894
  const selectedStopColor = selectedStop?.color;
772
895
  useEffect(() => {
773
896
  if (!activeGradient || !selectedStopColor) return;
774
- const parsed = parseCssColor(selectedStopColor);
897
+ const parsed = parseCssColorExtended(selectedStopColor);
775
898
  if (parsed) setHexDraft(toDisplayHex(parsed));
776
899
  // eslint-disable-next-line react-hooks/exhaustive-deps
777
900
  }, [selectedStopColor, selectedStopId]);
@@ -807,6 +930,10 @@ export function DesignColorPicker({
807
930
 
808
931
  const emitImageFill = (next: ImageFillValue) => {
809
932
  setImageFill(next);
933
+ if (onImageFillChange) {
934
+ onImageFillChange(next);
935
+ return;
936
+ }
810
937
  emitPaintValue(imageFillToCss(next));
811
938
  };
812
939
 
@@ -860,6 +987,10 @@ export function DesignColorPicker({
860
987
  return;
861
988
  }
862
989
  if (nextType === "image") {
990
+ if (onImageFillChange && imageFill.url) {
991
+ onImageFillChange(imageFill);
992
+ return;
993
+ }
863
994
  emitPaintValue(imageFill.url ? imageFillToCss(imageFill) : "transparent");
864
995
  return;
865
996
  }
@@ -1060,8 +1191,18 @@ export function DesignColorPicker({
1060
1191
  align="start"
1061
1192
  sideOffset={8}
1062
1193
  className="z-[10000] w-[252px] p-0 shadow-xl"
1194
+ // Keep the picker open when the style change triggered by a paint-type
1195
+ // switch causes the canvas to re-project the element. Without this,
1196
+ // Radix treats the resulting focus shift as an "interact outside" event
1197
+ // and closes the popover before the type switch is visible.
1198
+ onInteractOutside={(e) => {
1199
+ // Allow closing only for genuine pointer clicks on the canvas area
1200
+ // (the user clicked somewhere else). Programmatic focus changes from
1201
+ // the canvas bridge (element re-projection) should not close the picker.
1202
+ if (e.type === "focusoutside") e.preventDefault();
1203
+ }}
1063
1204
  >
1064
- <div className="overflow-hidden rounded-md bg-popover text-popover-foreground">
1205
+ <div className="rounded-md bg-popover text-popover-foreground">
1065
1206
  {view === "shader" ? (
1066
1207
  <ShaderFillsPanel
1067
1208
  descriptor={shaderDescriptor ?? undefined}
@@ -1395,6 +1536,39 @@ export function DesignColorPicker({
1395
1536
  </div>
1396
1537
  )}
1397
1538
 
1539
+ {showBlendMode && onBlendModeChange && (
1540
+ <div className="border-t border-border/70 px-3 py-2.5">
1541
+ <div className="flex items-center gap-1.5">
1542
+ <span className="min-w-0 flex-1 text-[11px] text-muted-foreground">
1543
+ {copy.blendMode}
1544
+ </span>
1545
+ <Select
1546
+ value={blendModeValue}
1547
+ disabled={disabled}
1548
+ onValueChange={onBlendModeChange}
1549
+ >
1550
+ <SelectTrigger
1551
+ aria-label={copy.blendMode}
1552
+ className="h-6 min-w-0 flex-1 rounded-md border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] px-1.5 text-[11px] shadow-none focus:ring-1 focus:ring-[var(--design-editor-accent-color)]"
1553
+ >
1554
+ <SelectValue />
1555
+ </SelectTrigger>
1556
+ <SelectContent>
1557
+ {BLEND_MODE_OPTIONS.map((option) => (
1558
+ <SelectItem
1559
+ key={option.value}
1560
+ value={option.value}
1561
+ className="text-[11px]"
1562
+ >
1563
+ {option.label}
1564
+ </SelectItem>
1565
+ ))}
1566
+ </SelectContent>
1567
+ </Select>
1568
+ </div>
1569
+ </div>
1570
+ )}
1571
+
1398
1572
  {/* ── Document colors ──────────────────────────────────────── */}
1399
1573
  {/* Renders the palette of colors already used in the design.
1400
1574
  When `documentColors` is provided, those swatches are shown;
@@ -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]">
@@ -0,0 +1,145 @@
1
+ import { useT } from "@agent-native/core/client";
2
+ import {
3
+ IconClipboard,
4
+ IconChevronDown,
5
+ IconSparkles,
6
+ } from "@tabler/icons-react";
7
+ import { useState } from "react";
8
+
9
+ import { Button } from "@/components/ui/button";
10
+ import {
11
+ Collapsible,
12
+ CollapsibleContent,
13
+ CollapsibleTrigger,
14
+ } from "@/components/ui/collapsible";
15
+ import { Textarea } from "@/components/ui/textarea";
16
+ import { useAgentEditRequest } from "@/hooks/useAgentEditRequest";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ export interface InspectorAiActionsProps {
20
+ /** CSS selector for the currently-selected element, if any. */
21
+ selector?: string;
22
+ /** Source id (data-code-layer-id) of the selected element, if any. */
23
+ sourceId?: string;
24
+ /** Active file id. */
25
+ fileId?: string;
26
+ /** Active file name (e.g. "index.html"). */
27
+ filename?: string;
28
+ /** The design id. */
29
+ designId?: string;
30
+ /** When false, the controls are disabled. */
31
+ canEdit: boolean;
32
+ }
33
+
34
+ /**
35
+ * Compact inspector block that lets the user type a freeform AI edit request
36
+ * and either route it to the agent chat sidebar ("Apply with AI") or copy the
37
+ * prompt to the clipboard ("Copy prompt").
38
+ *
39
+ * Collapsed by default to keep the inspector clean.
40
+ */
41
+ export function InspectorAiActions({
42
+ selector,
43
+ sourceId,
44
+ fileId,
45
+ filename,
46
+ designId,
47
+ canEdit,
48
+ }: InspectorAiActionsProps) {
49
+ const t = useT();
50
+ const { sendEdit, copyPrompt } = useAgentEditRequest();
51
+ const [open, setOpen] = useState(false);
52
+ const [request, setRequest] = useState("");
53
+
54
+ const args = {
55
+ message: request,
56
+ selector,
57
+ sourceId,
58
+ fileId,
59
+ filename,
60
+ designId,
61
+ };
62
+ const disabled = !canEdit || !request.trim();
63
+
64
+ return (
65
+ <Collapsible open={open} onOpenChange={setOpen} className="w-full">
66
+ <CollapsibleTrigger asChild>
67
+ <button
68
+ type="button"
69
+ className={cn(
70
+ "flex w-full items-center justify-between gap-1 rounded px-2 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
71
+ )}
72
+ >
73
+ <span className="flex items-center gap-1.5">
74
+ <IconSparkles className="size-3.5 shrink-0" />
75
+ {t("designEditor.localSourceEdit.askAi")}
76
+ </span>
77
+ <IconChevronDown
78
+ className={cn(
79
+ "size-3.5 shrink-0 transition-transform duration-150",
80
+ open && "rotate-180",
81
+ )}
82
+ />
83
+ </button>
84
+ </CollapsibleTrigger>
85
+ <CollapsibleContent className="overflow-hidden data-[state=closed]:animate-none">
86
+ <div className="flex flex-col gap-2 px-1 pb-2 pt-1">
87
+ <Textarea
88
+ value={request}
89
+ onChange={(e) => setRequest(e.target.value)}
90
+ placeholder={
91
+ selector
92
+ ? t("designEditor.localSourceEdit.describeElementChange")
93
+ : t("designEditor.localSourceEdit.describeChange")
94
+ }
95
+ className="min-h-[64px] resize-none text-xs"
96
+ disabled={!canEdit}
97
+ onKeyDown={(e) => {
98
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey) && !disabled) {
99
+ e.preventDefault();
100
+ void sendEdit(args);
101
+ setRequest("");
102
+ setOpen(false);
103
+ }
104
+ }}
105
+ />
106
+ <div className="flex gap-1.5">
107
+ <Button
108
+ size="sm"
109
+ variant="default"
110
+ className="flex-1 gap-1.5 text-xs"
111
+ disabled={disabled}
112
+ onClick={() => {
113
+ void sendEdit(args);
114
+ setRequest("");
115
+ setOpen(false);
116
+ }}
117
+ >
118
+ <IconSparkles className="size-3.5 shrink-0" />
119
+ {t("designEditor.localSourceEdit.applyWithAi")}
120
+ </Button>
121
+ <Button
122
+ size="sm"
123
+ variant="outline"
124
+ className="gap-1.5 text-xs"
125
+ disabled={disabled}
126
+ onClick={() => {
127
+ void copyPrompt(args);
128
+ }}
129
+ title={t("designEditor.localSourceEdit.copyPromptTooltip")}
130
+ >
131
+ <IconClipboard className="size-3.5 shrink-0" />
132
+ {t("designEditor.localSourceEdit.copyPrompt")}
133
+ </Button>
134
+ </div>
135
+ {selector && (
136
+ <p className="text-[10px] leading-tight text-muted-foreground truncate">
137
+ {t("designEditor.localSourceEdit.targeting")}{" "}
138
+ <code className="font-mono">{selector}</code>
139
+ </p>
140
+ )}
141
+ </div>
142
+ </CollapsibleContent>
143
+ </Collapsible>
144
+ );
145
+ }
@@ -6,6 +6,30 @@ right spot plus copy-pasteable code to insert or replace.
6
6
 
7
7
  Do NOT rely on line numbers — they drift. Use the search strings instead.
8
8
 
9
+ ## Status: shader fills are user-reachable and applyable
10
+
11
+ The **Shader Fills** card in `DesignExtensionsPanel.tsx` (inspector slot
12
+ `design.editor.inspector`) is the live entry point: open it, **Browse Shaders**,
13
+ pick a preset, tune it with `ShaderControls`, and the iframe previews the fill as
14
+ a CSS gradient (`preview-shader-fill`). With an element selected on the canvas, the
15
+ card's **Apply fill** button persists that fill via the `apply-shader-fill` action.
16
+
17
+ `apply-shader-fill` is **no longer gated** — it is SAFETY-gated, not Builder-gated:
18
+
19
+ - It asserts **editor** access on the target design (`accessFilter` read +
20
+ `assertAccess("design", id, "editor")`) before any write.
21
+ - It only persists **HTML design-file** sources. localhost / fusion / inline-html
22
+ sources return the preview value and write nothing.
23
+ - It writes a single inline-style `background` onto the target node through the
24
+ deterministic HTML editor (`applyVisualEdit`, the same persist path as
25
+ `apply-visual-edit`), reusing the strict CSS-colour allowlist from
26
+ `shared/shader-fill.ts` so `descriptor.colors` can never inject CSS.
27
+
28
+ Sections (a), (b), (d), and (f) below remain optional ways to surface shaders in
29
+ _other_ inspector seams (the colour picker fill type, the effects panel, the
30
+ artboard WebGL bridge, design-system tokens) and are not required for the
31
+ card-based apply path that ships today.
32
+
9
33
  ---
10
34
 
11
35
  ## (a) DesignColorPicker.tsx — Add `"shader"` fill type
@@ -351,20 +375,17 @@ if (fill.type === "shader") {
351
375
 
352
376
  ---
353
377
 
354
- ## (e) Changelog entry (DEFERRED)
355
-
356
- The shader feature is not yet user-reachable — it still needs all seam files wired.
357
- Do NOT add a changelog entry yet.
378
+ ## (e) Changelog entry
358
379
 
359
- Once the seam files are integrated and the feature is accessible from the UI (a user
360
- can apply a shader fill from the fill picker or add a shader effect from the effects
361
- panel), run:
380
+ The shader-fills card is now user-reachable and the apply path persists, so a
381
+ user-facing changelog entry is warranted. From the `templates/design/` directory:
362
382
 
363
383
  ```bash
364
- agent-native changelog add "Add GPU shader fills and effects — 8 presets (MeshGradient, GrainGradient, Voronoi, Metaballs, Warp, GodRays, Dithering, PaperTexture) with live preview and agent-tunable params" --type added
384
+ agent-native changelog add "Add GPU shader fills — 8 presets (MeshGradient, GrainGradient, Voronoi, Metaballs, Warp, GodRays, Dithering, PaperTexture) with live preview and one-click apply to the selected element" --type added
365
385
  ```
366
386
 
367
- from the `templates/design/` directory.
387
+ (The effects-panel surface from section (b) is still optional; scope the changelog
388
+ line to what actually ships.)
368
389
 
369
390
  ---
370
391
 
@@ -407,14 +428,23 @@ shader token picker.
407
428
 
408
429
  ## Integration Checklist
409
430
 
431
+ Shipped (card-based preview + apply path):
432
+
433
+ - [x] `DesignExtensionsPanel.tsx` — Shader Fills card opens `ShaderFillsPanel`
434
+ - [x] `DesignExtensionsPanel.tsx` — "Apply fill" persists via `apply-shader-fill`
435
+ - [x] `actions/apply-shader-fill.ts` — persists fill as CSS background (editor-gated)
436
+ - [x] `actions/preview-shader-fill.ts` — preview-only CSS (unchanged)
437
+ - [x] `actions/apply-shader.ts` exists (planning/codegen snippet)
438
+ - [x] `actions/get-shader.ts` exists
439
+
440
+ Optional follow-ups (other inspector seams):
441
+
410
442
  - [ ] `DesignColorPicker.tsx` — `DesignFillType` includes `"shader"`
411
443
  - [ ] `DesignColorPicker.tsx` — `DesignPaintType` includes `"shader"`
412
444
  - [ ] `DesignColorPicker.tsx` — shader button renders in paint-type row
413
445
  - [ ] `DesignColorPicker.tsx` — `ShaderControls` renders when `paintType === "shader"`
414
446
  - [ ] `EditPanel.tsx` — `ShaderEffectRow` renders in `EffectsProperties`
415
447
  - [ ] `EditPanel.tsx` — "Add Shader" option in effects dropdown
416
- - [ ] `actions/apply-shader.ts` exists
417
- - [ ] `actions/get-shader.ts` exists
418
448
  - [ ] `DesignCanvas.tsx` — shader bridge script injected into artboard
419
449
  - [ ] `DesignCanvas.tsx` — `data-shader` attribute serialized for shader fills
420
- - [ ] Changelog entry added (after feature is user-reachable)
450
+ - [ ] Changelog entry added (see section (e))