@agent-native/core 0.79.27 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +26 -0
  3. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +41 -0
  4. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +51 -0
  5. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +50 -0
  6. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +49 -0
  7. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +44 -0
  8. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +46 -0
  9. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +44 -0
  10. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +48 -0
  11. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +36 -0
  12. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +38 -0
  13. package/corpus/core/docs/content/template-design.mdx +45 -0
  14. package/corpus/core/package.json +2 -1
  15. package/corpus/core/src/agent/engine/index.ts +1 -0
  16. package/corpus/core/src/agent/engine/registry.ts +40 -0
  17. package/corpus/core/src/agent/production-agent.ts +6 -2
  18. package/corpus/core/src/cli/design-connect.ts +490 -0
  19. package/corpus/core/src/cli/index.ts +16 -0
  20. package/corpus/core/src/cli/skills.ts +126 -3
  21. package/corpus/core/src/client/AssistantChat.tsx +43 -7
  22. package/corpus/core/src/client/agent-chat.ts +27 -3
  23. package/corpus/core/src/client/blocks/library/MermaidBlock.tsx +1 -1
  24. package/corpus/core/src/client/blocks/library/diagram.tsx +2 -2
  25. package/corpus/core/src/client/blocks/library/wireframe.tsx +1 -1
  26. package/corpus/core/src/client/chat/message-components.tsx +1 -1
  27. package/corpus/core/src/client/chat-model-groups.ts +1 -2
  28. package/corpus/core/src/client/components/LiveCursorOverlay.tsx +33 -66
  29. package/corpus/core/src/client/composer/TiptapComposer.tsx +99 -24
  30. package/corpus/core/src/client/composer/useVoiceDictation.ts +429 -260
  31. package/corpus/core/src/client/frame-protocol.ts +17 -2
  32. package/corpus/core/src/client/rich-markdown-editor/RegistryBlockNode.tsx +2 -2
  33. package/corpus/core/src/client/sharing/ShareButton.tsx +20 -15
  34. package/corpus/core/src/client/use-agent-engine-configured.ts +80 -28
  35. package/corpus/core/src/server/transcribe-voice.ts +57 -22
  36. package/corpus/core/src/shared/mcp-embed-headers.ts +23 -1
  37. package/corpus/core/src/styles/agent-native.css +56 -7
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  39. package/corpus/core/src/vite/client.ts +2 -0
  40. package/corpus/core/src/voice/index.ts +18 -0
  41. package/corpus/core/src/voice/voice-cleanup-prompt.ts +38 -0
  42. package/corpus/core/src/voice/voice-context.ts +217 -0
  43. package/corpus/core/src/voice/voice-replacements.ts +75 -0
  44. package/corpus/templates/analytics/AGENTS.md +4 -3
  45. package/corpus/templates/analytics/actions/list-session-recordings.ts +6 -1
  46. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +557 -400
  47. package/corpus/templates/analytics/app/global.css +0 -4
  48. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  49. package/corpus/templates/analytics/app/i18n-data.ts +20 -0
  50. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +33 -8
  51. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +7 -0
  52. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +7 -0
  53. package/corpus/templates/analytics/changelog/2026-06-28-ask-tab-now-matches-the-darker-app-background.md +6 -0
  54. package/corpus/templates/analytics/changelog/2026-06-28-dashboard-email-reports-now-use-cleaner-light-mode-snapshots.md +6 -0
  55. package/corpus/templates/analytics/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  56. package/corpus/templates/analytics/changelog/2026-06-28-sessions-now-show-only-signed-in-recordings-with-playable-re.md +6 -0
  57. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +3 -3
  58. package/corpus/templates/analytics/server/lib/dashboard-report.ts +29 -7
  59. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +5 -2
  60. package/corpus/templates/analytics/server/lib/session-replay.ts +24 -4
  61. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +4 -4
  62. package/corpus/templates/assets/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  63. package/corpus/templates/brain/app/components/layout/Layout.tsx +29 -2
  64. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +131 -42
  65. package/corpus/templates/brain/app/i18n/zh-TW.ts +2 -0
  66. package/corpus/templates/brain/app/i18n-data.ts +20 -0
  67. package/corpus/templates/brain/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  68. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +29 -1
  69. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +417 -299
  70. package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
  71. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  72. package/corpus/templates/calendar/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  73. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +6 -19
  74. package/corpus/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  75. package/corpus/templates/clips/AGENTS.md +4 -0
  76. package/corpus/templates/clips/actions/cleanup-transcript.ts +39 -9
  77. package/corpus/templates/clips/actions/finalize-meeting.ts +81 -12
  78. package/corpus/templates/clips/actions/lib/agents-md-context.ts +4 -1
  79. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -3
  80. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +1 -1
  81. package/corpus/templates/clips/app/components/player/share-dialog.tsx +2 -2
  82. package/corpus/templates/clips/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  83. package/corpus/templates/clips/desktop/src/lib/personal-vocabulary.ts +13 -8
  84. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +60 -1
  85. package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +1 -1
  86. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -1
  87. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +5 -5
  88. package/corpus/templates/content/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  89. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +137 -0
  90. package/corpus/templates/design/AGENTS.md +95 -5
  91. package/corpus/templates/design/DESIGN.md +82 -0
  92. package/corpus/templates/design/DEVELOPING.md +43 -0
  93. package/corpus/templates/design/actions/add-localhost-screens.ts +426 -0
  94. package/corpus/templates/design/actions/apply-shader.ts +277 -0
  95. package/corpus/templates/design/actions/apply-visual-edit.ts +303 -0
  96. package/corpus/templates/design/actions/connect-localhost.ts +183 -0
  97. package/corpus/templates/design/actions/edit-design.ts +195 -42
  98. package/corpus/templates/design/actions/generate-design.ts +71 -1
  99. package/corpus/templates/design/actions/generate-screens.ts +193 -0
  100. package/corpus/templates/design/actions/get-code-layer-projection.ts +191 -0
  101. package/corpus/templates/design/actions/get-shader.ts +119 -0
  102. package/corpus/templates/design/actions/list-localhost-connections.ts +95 -0
  103. package/corpus/templates/design/actions/navigate.ts +55 -2
  104. package/corpus/templates/design/actions/view-screen.ts +68 -1
  105. package/corpus/templates/design/agent-native.app-skill.json +10 -0
  106. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +761 -0
  107. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +2057 -103
  108. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +74 -38
  109. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +399 -0
  110. package/corpus/templates/design/app/components/design/EditPanel.tsx +3185 -439
  111. package/corpus/templates/design/app/components/design/LayersPanel.tsx +1124 -0
  112. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +3116 -147
  113. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +700 -13
  114. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +107 -63
  115. package/corpus/templates/design/app/components/design/index.ts +0 -5
  116. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +286 -0
  117. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +699 -0
  118. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +461 -0
  119. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +166 -0
  120. package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +1420 -0
  121. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +420 -0
  122. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +215 -0
  123. package/corpus/templates/design/app/components/design/inspector/ShaderControls.stories.tsx +71 -0
  124. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +518 -0
  125. package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +106 -0
  126. package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +361 -0
  127. package/corpus/templates/design/app/components/design/inspector/index.ts +60 -0
  128. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +201 -0
  129. package/corpus/templates/design/app/components/design/types.ts +23 -0
  130. package/corpus/templates/design/app/components/layout/Layout.tsx +24 -13
  131. package/corpus/templates/design/app/components/layout/Sidebar.tsx +4 -4
  132. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +474 -36
  133. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +22 -5
  134. package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +24 -11
  135. package/corpus/templates/design/app/global.css +121 -3
  136. package/corpus/templates/design/app/hooks/use-agent-generating.ts +4 -0
  137. package/corpus/templates/design/app/hooks/use-navigation-state.ts +130 -8
  138. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +329 -0
  139. package/corpus/templates/design/app/i18n/zh-TW.ts +264 -0
  140. package/corpus/templates/design/app/i18n-data.ts +2790 -1
  141. package/corpus/templates/design/app/pages/DesignEditor.tsx +5108 -851
  142. package/corpus/templates/design/changelog/2026-06-28-annotate-mode-now-combines-drawing-and-comment-pins-in-one-c.md +6 -0
  143. package/corpus/templates/design/changelog/2026-06-28-design-editor-panel-borders-are-cleaner-so-the-canvas-edge-s.md +6 -0
  144. package/corpus/templates/design/changelog/2026-06-28-drawing-prompts-now-reliably-open-and-submit-to-the-design-a.md +6 -0
  145. package/corpus/templates/design/changelog/2026-06-28-editor-app-menus-now-use-an-outline-agent-native-mark-with-b.md +6 -0
  146. package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +6 -0
  147. package/corpus/templates/design/changelog/2026-06-28-layer-selection-now-updates-chat-context-without-opening-the.md +6 -0
  148. package/corpus/templates/design/changelog/2026-06-28-layer-selections-now-preserve-hidden-and-locked-canvas-state.md +6 -0
  149. package/corpus/templates/design/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  150. package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +6 -0
  151. package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +6 -0
  152. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-handles-zooming-drawing-opening-and-dele.md +6 -0
  153. package/corpus/templates/design/changelog/2026-06-28-screen-overview-now-selects-screens-on-click-and-opens-them-.md +6 -0
  154. package/corpus/templates/design/changelog/2026-06-28-screen-overview-zooms-into-the-active-screen-with-smoother-e.md +6 -0
  155. package/corpus/templates/design/changelog/2026-06-28-selected-element-chips-in-chat-are-shorter-and-easier-to-sca.md +6 -0
  156. package/corpus/templates/design/changelog/2026-06-28-the-design-editor-toolbar-is-more-compact-and-the-app-menu-m.md +6 -0
  157. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-at-the-top-of-the-design-sidebar-instead-of-.md +6 -0
  158. package/corpus/templates/design/changelog/2026-06-28-tweaks-now-live-in-the-right-inspector-beside-the-design-tab.md +6 -0
  159. package/corpus/templates/design/changelog/2026-06-29-active-sidebar-rows-use-soft-highlights.md +6 -0
  160. package/corpus/templates/design/changelog/2026-06-29-agents-can-now-open-screen-overview-focus-screens-and-add.md +6 -0
  161. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-edit-broad-copy-changes-more-reliably.md +6 -0
  162. package/corpus/templates/design/changelog/2026-06-29-design-editor-extensions-now-run-inline-beside-the-artboard.md +6 -0
  163. package/corpus/templates/design/changelog/2026-06-29-sidebars-use-darker-chrome-and-chat-warns-immediately.md +6 -0
  164. package/corpus/templates/design/changelog/2026-06-29-visual-edit-can-open-localhost-routes-as-url-backed-screens.md +6 -0
  165. package/corpus/templates/design/package.json +1 -0
  166. package/corpus/templates/design/server/db/schema.ts +26 -0
  167. package/corpus/templates/design/server/lib/design-snapshot.ts +1 -1
  168. package/corpus/templates/design/server/plugins/agent-chat.ts +3 -0
  169. package/corpus/templates/design/shared/api.ts +27 -0
  170. package/corpus/templates/design/shared/canvas-frames.ts +103 -0
  171. package/corpus/templates/design/shared/canvas-math.ts +1058 -0
  172. package/corpus/templates/design/shared/code-layer.ts +2212 -0
  173. package/corpus/templates/design/shared/color-utils.ts +180 -0
  174. package/corpus/templates/design/shared/generation-session.ts +61 -0
  175. package/corpus/templates/design/shared/shader-presets.ts +782 -0
  176. package/corpus/templates/design/shared/shader-safety.ts +137 -0
  177. package/corpus/templates/design/shared/source-mode.ts +237 -0
  178. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +149 -6
  179. package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
  180. package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
  181. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  182. package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
  183. package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
  184. package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
  185. package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
  186. package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
  187. package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
  188. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  189. package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
  190. package/corpus/templates/forms/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  191. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
  192. package/corpus/templates/macros/changelog/2026-06-28-left-sidebar-footer-controls-use-less-divider-chrome.md +6 -0
  193. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +408 -247
  194. package/corpus/templates/mail/app/i18n/ar-SA.ts +4 -0
  195. package/corpus/templates/mail/app/i18n/de-DE.ts +4 -0
  196. package/corpus/templates/mail/app/i18n/en-US.ts +4 -0
  197. package/corpus/templates/mail/app/i18n/es-ES.ts +4 -0
  198. package/corpus/templates/mail/app/i18n/fr-FR.ts +4 -0
  199. package/corpus/templates/mail/app/i18n/hi-IN.ts +4 -0
  200. package/corpus/templates/mail/app/i18n/ja-JP.ts +4 -0
  201. package/corpus/templates/mail/app/i18n/ko-KR.ts +4 -0
  202. package/corpus/templates/mail/app/i18n/pt-BR.ts +4 -0
  203. package/corpus/templates/mail/app/i18n/zh-CN.ts +4 -0
  204. package/corpus/templates/mail/app/i18n/zh-TW.ts +4 -0
  205. package/corpus/templates/mail/changelog/2026-06-28-pinned-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  206. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +6 -8
  207. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +1 -1
  208. package/corpus/templates/plan/app/global.css +61 -78
  209. package/corpus/templates/plan/app/pages/PlansPage.tsx +8 -0
  210. package/corpus/templates/plan/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  211. package/corpus/templates/plan/changelog/2026-06-28-plans-use-the-shared-neutral-light-and-dark-theme.md +6 -0
  212. package/corpus/templates/plan/changelog/2026-06-28-sending-open-feedback-from-a-plan-now-opens-the-inline-plan-.md +6 -0
  213. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +5 -5
  214. package/corpus/templates/slides/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  215. package/corpus/templates/videos/app/components/Sidebar.tsx +2 -2
  216. package/corpus/templates/videos/app/components/layout/Layout.tsx +29 -2
  217. package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +113 -30
  218. package/corpus/templates/videos/app/i18n/ar-SA.ts +2 -0
  219. package/corpus/templates/videos/app/i18n/de-DE.ts +2 -0
  220. package/corpus/templates/videos/app/i18n/en-US.ts +2 -0
  221. package/corpus/templates/videos/app/i18n/es-ES.ts +2 -0
  222. package/corpus/templates/videos/app/i18n/fr-FR.ts +2 -0
  223. package/corpus/templates/videos/app/i18n/hi-IN.ts +2 -0
  224. package/corpus/templates/videos/app/i18n/ja-JP.ts +2 -0
  225. package/corpus/templates/videos/app/i18n/ko-KR.ts +2 -0
  226. package/corpus/templates/videos/app/i18n/pt-BR.ts +2 -0
  227. package/corpus/templates/videos/app/i18n/zh-CN.ts +2 -0
  228. package/corpus/templates/videos/app/i18n/zh-TW.ts +2 -0
  229. package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +6 -0
  230. package/dist/agent/engine/index.d.ts +1 -1
  231. package/dist/agent/engine/index.d.ts.map +1 -1
  232. package/dist/agent/engine/index.js +1 -1
  233. package/dist/agent/engine/index.js.map +1 -1
  234. package/dist/agent/engine/registry.d.ts +9 -0
  235. package/dist/agent/engine/registry.d.ts.map +1 -1
  236. package/dist/agent/engine/registry.js +37 -0
  237. package/dist/agent/engine/registry.js.map +1 -1
  238. package/dist/agent/production-agent.d.ts.map +1 -1
  239. package/dist/agent/production-agent.js +4 -3
  240. package/dist/agent/production-agent.js.map +1 -1
  241. package/dist/cli/design-connect.d.ts +52 -0
  242. package/dist/cli/design-connect.d.ts.map +1 -0
  243. package/dist/cli/design-connect.js +409 -0
  244. package/dist/cli/design-connect.js.map +1 -0
  245. package/dist/cli/index.js +15 -0
  246. package/dist/cli/index.js.map +1 -1
  247. package/dist/cli/skills.d.ts +3 -0
  248. package/dist/cli/skills.d.ts.map +1 -1
  249. package/dist/cli/skills.js +121 -3
  250. package/dist/cli/skills.js.map +1 -1
  251. package/dist/client/AssistantChat.d.ts.map +1 -1
  252. package/dist/client/AssistantChat.js +38 -8
  253. package/dist/client/AssistantChat.js.map +1 -1
  254. package/dist/client/agent-chat.d.ts +6 -0
  255. package/dist/client/agent-chat.d.ts.map +1 -1
  256. package/dist/client/agent-chat.js +17 -3
  257. package/dist/client/agent-chat.js.map +1 -1
  258. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  259. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  260. package/dist/client/blocks/library/diagram.js +1 -1
  261. package/dist/client/blocks/library/diagram.js.map +1 -1
  262. package/dist/client/blocks/library/wireframe.js +1 -1
  263. package/dist/client/blocks/library/wireframe.js.map +1 -1
  264. package/dist/client/chat/message-components.js +1 -1
  265. package/dist/client/chat/message-components.js.map +1 -1
  266. package/dist/client/chat-model-groups.d.ts.map +1 -1
  267. package/dist/client/chat-model-groups.js +1 -2
  268. package/dist/client/chat-model-groups.js.map +1 -1
  269. package/dist/client/components/LiveCursorOverlay.d.ts +1 -2
  270. package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
  271. package/dist/client/components/LiveCursorOverlay.js +19 -40
  272. package/dist/client/components/LiveCursorOverlay.js.map +1 -1
  273. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  274. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  275. package/dist/client/composer/TiptapComposer.js +86 -24
  276. package/dist/client/composer/TiptapComposer.js.map +1 -1
  277. package/dist/client/composer/useVoiceDictation.d.ts +9 -0
  278. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  279. package/dist/client/composer/useVoiceDictation.js +154 -32
  280. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  281. package/dist/client/frame-protocol.d.ts +17 -2
  282. package/dist/client/frame-protocol.d.ts.map +1 -1
  283. package/dist/client/frame-protocol.js.map +1 -1
  284. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +2 -2
  285. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  286. package/dist/client/sharing/ShareButton.d.ts +2 -0
  287. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  288. package/dist/client/sharing/ShareButton.js +7 -6
  289. package/dist/client/sharing/ShareButton.js.map +1 -1
  290. package/dist/client/use-agent-engine-configured.d.ts +5 -0
  291. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  292. package/dist/client/use-agent-engine-configured.js +51 -25
  293. package/dist/client/use-agent-engine-configured.js.map +1 -1
  294. package/dist/collab/awareness.d.ts +2 -2
  295. package/dist/collab/awareness.d.ts.map +1 -1
  296. package/dist/collab/routes.d.ts +1 -1
  297. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  298. package/dist/notifications/routes.d.ts +3 -3
  299. package/dist/observability/routes.d.ts +8 -8
  300. package/dist/progress/routes.d.ts +1 -1
  301. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  302. package/dist/server/transcribe-voice.d.ts.map +1 -1
  303. package/dist/server/transcribe-voice.js +40 -24
  304. package/dist/server/transcribe-voice.js.map +1 -1
  305. package/dist/shared/mcp-embed-headers.d.ts +1 -0
  306. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  307. package/dist/shared/mcp-embed-headers.js +20 -1
  308. package/dist/shared/mcp-embed-headers.js.map +1 -1
  309. package/dist/styles/agent-native.css +56 -7
  310. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  311. package/dist/vite/client.d.ts.map +1 -1
  312. package/dist/vite/client.js +2 -0
  313. package/dist/vite/client.js.map +1 -1
  314. package/dist/voice/index.d.ts +5 -0
  315. package/dist/voice/index.d.ts.map +1 -0
  316. package/dist/voice/index.js +4 -0
  317. package/dist/voice/index.js.map +1 -0
  318. package/dist/voice/voice-cleanup-prompt.d.ts +6 -0
  319. package/dist/voice/voice-cleanup-prompt.d.ts.map +1 -0
  320. package/dist/voice/voice-cleanup-prompt.js +26 -0
  321. package/dist/voice/voice-cleanup-prompt.js.map +1 -0
  322. package/dist/voice/voice-context.d.ts +25 -0
  323. package/dist/voice/voice-context.d.ts.map +1 -0
  324. package/dist/voice/voice-context.js +156 -0
  325. package/dist/voice/voice-context.js.map +1 -0
  326. package/dist/voice/voice-replacements.d.ts +4 -0
  327. package/dist/voice/voice-replacements.d.ts.map +1 -0
  328. package/dist/voice/voice-replacements.js +52 -0
  329. package/dist/voice/voice-replacements.js.map +1 -0
  330. package/docs/content/locales/ar-SA/template-design.mdx +41 -0
  331. package/docs/content/locales/de-DE/template-design.mdx +51 -0
  332. package/docs/content/locales/es-ES/template-design.mdx +50 -0
  333. package/docs/content/locales/fr-FR/template-design.mdx +49 -0
  334. package/docs/content/locales/hi-IN/template-design.mdx +44 -0
  335. package/docs/content/locales/ja-JP/template-design.mdx +46 -0
  336. package/docs/content/locales/ko-KR/template-design.mdx +44 -0
  337. package/docs/content/locales/pt-BR/template-design.mdx +48 -0
  338. package/docs/content/locales/zh-CN/template-design.mdx +36 -0
  339. package/docs/content/locales/zh-TW/template-design.mdx +38 -0
  340. package/docs/content/template-design.mdx +45 -0
  341. package/package.json +2 -1
  342. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +10 -0
  343. package/corpus/templates/design/app/components/design/DesignToolbar.tsx +0 -339
  344. package/corpus/templates/design/app/components/design/PresentMode.tsx +0 -68
  345. package/corpus/templates/design/app/components/design/ViewportTabs.tsx +0 -149
  346. package/corpus/templates/design/app/components/design/ZoomControls.tsx +0 -157
@@ -1,6 +1,11 @@
1
1
  import { useT } from "@agent-native/core/client";
2
2
  import type { TweakDefinition } from "@shared/api";
3
- import { IconX, IconGripHorizontal, IconPlus } from "@tabler/icons-react";
3
+ import {
4
+ IconX,
5
+ IconGripHorizontal,
6
+ IconPlus,
7
+ IconAdjustmentsHorizontal,
8
+ } from "@tabler/icons-react";
4
9
  import { useState, useRef, useCallback } from "react";
5
10
 
6
11
  import { Button } from "@/components/ui/button";
@@ -22,6 +27,60 @@ interface TweaksPanelProps {
22
27
  visible: boolean;
23
28
  }
24
29
 
30
+ interface TweaksPanelContentProps {
31
+ tweaks: TweakDefinition[];
32
+ values: Record<string, string | number | boolean>;
33
+ onChange: (id: string, value: string | number | boolean) => void;
34
+ onRequestTweaks?: (anchor: HTMLElement) => void;
35
+ className?: string;
36
+ }
37
+
38
+ export function TweaksPanelContent({
39
+ tweaks,
40
+ values,
41
+ onChange,
42
+ onRequestTweaks,
43
+ className,
44
+ }: TweaksPanelContentProps) {
45
+ const t = useT();
46
+
47
+ return (
48
+ <div className={cn("space-y-1.5", className)}>
49
+ {tweaks.length > 0 ? (
50
+ tweaks.map((tweak) => (
51
+ <TweakControl
52
+ key={tweak.id}
53
+ tweak={tweak}
54
+ value={values[tweak.id] ?? tweak.defaultValue}
55
+ onChange={(v) => onChange(tweak.id, v)}
56
+ />
57
+ ))
58
+ ) : (
59
+ <div className="flex flex-col items-center gap-2 py-4 text-center">
60
+ <div className="flex size-8 items-center justify-center rounded-lg bg-muted/60">
61
+ <IconAdjustmentsHorizontal className="size-4 text-muted-foreground/70" />
62
+ </div>
63
+ <p className="text-[11px] leading-snug text-muted-foreground">
64
+ {t("designEditor.noTweakControls")}
65
+ </p>
66
+ {onRequestTweaks && (
67
+ <Button
68
+ type="button"
69
+ variant="outline"
70
+ size="sm"
71
+ className="h-6 cursor-pointer px-2.5 text-[11px]"
72
+ onClick={(e) => onRequestTweaks(e.currentTarget)}
73
+ >
74
+ <IconPlus className="size-3" />
75
+ {t("designEditor.addTweakControls")}
76
+ </Button>
77
+ )}
78
+ </div>
79
+ )}
80
+ </div>
81
+ );
82
+ }
83
+
25
84
  export function TweaksPanel({
26
85
  tweaks,
27
86
  values,
@@ -85,18 +144,18 @@ export function TweaksPanel({
85
144
  className="fixed z-[70] w-60 rounded-xl border border-border bg-card shadow-2xl backdrop-blur-sm"
86
145
  style={{ right: position.x, bottom: position.y }}
87
146
  >
88
- {/* Header — drag handle + collapse toggle */}
147
+ {/* Header — drag handle + collapse toggle + actions */}
89
148
  <div
90
- className="flex cursor-grab select-none items-center justify-between px-3 pt-2.5 pb-1.5 active:cursor-grabbing"
149
+ className="flex min-h-8 cursor-grab select-none items-center justify-between px-3 active:cursor-grabbing"
91
150
  onMouseDown={handleMouseDown}
92
151
  >
93
152
  <div className="flex items-center gap-1.5">
94
- <IconGripHorizontal className="h-3 w-3 text-muted-foreground/60" />
153
+ <IconGripHorizontal className="size-3 text-muted-foreground/40" />
95
154
  <button
96
155
  type="button"
97
156
  onMouseDown={(e) => e.stopPropagation()}
98
157
  onClick={() => setCollapsed((c) => !c)}
99
- className="cursor-pointer text-[11px] font-semibold uppercase tracking-wider text-muted-foreground hover:text-muted-foreground"
158
+ className="cursor-pointer text-[11px] font-semibold uppercase tracking-wider text-muted-foreground hover:text-foreground"
100
159
  >
101
160
  {t("designEditor.tweaks")}
102
161
  </button>
@@ -114,10 +173,10 @@ export function TweaksPanel({
114
173
  e.stopPropagation();
115
174
  onRequestTweaks(e.currentTarget);
116
175
  }}
117
- className="size-6 cursor-pointer text-muted-foreground/70 hover:text-foreground"
176
+ className="size-6 cursor-pointer text-muted-foreground/60 hover:text-foreground"
118
177
  aria-label={t("designEditor.addTweaks")}
119
178
  >
120
- <IconPlus className="h-3.5 w-3.5" />
179
+ <IconPlus className="size-3" />
121
180
  </Button>
122
181
  </TooltipTrigger>
123
182
  <TooltipContent>{t("designEditor.addTweaks")}</TooltipContent>
@@ -130,46 +189,26 @@ export function TweaksPanel({
130
189
  e.stopPropagation();
131
190
  onClose();
132
191
  }}
133
- className="flex size-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-muted-foreground"
192
+ className="flex size-6 cursor-pointer items-center justify-center rounded text-muted-foreground/60 hover:bg-accent hover:text-foreground"
134
193
  aria-label={t("designEditor.closeTweaks")}
135
194
  >
136
- <IconX className="h-3 w-3" />
195
+ <IconX className="size-3" />
137
196
  </button>
138
197
  </div>
139
198
  </div>
140
199
 
141
200
  {/* Body */}
142
201
  {!collapsed && (
143
- <div className="space-y-3.5 px-3 pb-3.5">
144
- {tweaks.length > 0 ? (
145
- tweaks.map((tweak) => (
146
- <TweakControl
147
- key={tweak.id}
148
- tweak={tweak}
149
- value={values[tweak.id] ?? tweak.defaultValue}
150
- onChange={(v) => onChange(tweak.id, v)}
151
- />
152
- ))
153
- ) : (
154
- <div className="space-y-2 rounded-lg border border-dashed border-border/80 bg-muted/20 p-3">
155
- <p className="text-xs leading-relaxed text-muted-foreground">
156
- {t("designEditor.noTweakControls")}
157
- </p>
158
- {onRequestTweaks && (
159
- <Button
160
- type="button"
161
- variant="outline"
162
- size="sm"
163
- className="h-8 w-full cursor-pointer text-xs"
164
- onClick={(e) => onRequestTweaks(e.currentTarget)}
165
- >
166
- <IconPlus className="h-3.5 w-3.5" />
167
- {t("designEditor.addTweakControls")}
168
- </Button>
169
- )}
170
- </div>
171
- )}
172
- </div>
202
+ <>
203
+ <div className="mx-3 border-t border-border/60" />
204
+ <TweaksPanelContent
205
+ tweaks={tweaks}
206
+ values={values}
207
+ onChange={onChange}
208
+ onRequestTweaks={onRequestTweaks}
209
+ className="px-3 py-2"
210
+ />
211
+ </>
173
212
  )}
174
213
  </div>
175
214
  );
@@ -184,15 +223,27 @@ function TweakControl({
184
223
  value: string | number | boolean;
185
224
  onChange: (v: string | number | boolean) => void;
186
225
  }) {
187
- return (
188
- <div>
189
- <div className="mb-1.5 text-[11px] text-muted-foreground">
190
- {tweak.label}
226
+ // Toggle gets an inline row; other types get a label above
227
+ if (tweak.type === "toggle") {
228
+ return (
229
+ <div className="flex h-6 items-center justify-between gap-1.5">
230
+ <span className="text-[11px] text-muted-foreground">{tweak.label}</span>
231
+ <Switch
232
+ checked={!!value}
233
+ onCheckedChange={(checked) => onChange(checked)}
234
+ className="scale-75 origin-right"
235
+ />
191
236
  </div>
237
+ );
238
+ }
239
+
240
+ return (
241
+ <div className="space-y-1">
242
+ <span className="text-[11px] text-muted-foreground">{tweak.label}</span>
192
243
 
193
- {(tweak.type as string) === "color-swatch" ||
194
- (tweak.type as string) === "color-swatches" ? (
195
- <div className="flex gap-2">
244
+ {((tweak.type as string) === "color-swatch" ||
245
+ (tweak.type as string) === "color-swatches") && (
246
+ <div className="flex gap-1.5">
196
247
  {tweak.options?.map((opt) => (
197
248
  <Tooltip key={opt.value}>
198
249
  <TooltipTrigger asChild>
@@ -200,32 +251,32 @@ function TweakControl({
200
251
  type="button"
201
252
  onClick={() => onChange(opt.value)}
202
253
  className={cn(
203
- "h-6 w-6 cursor-pointer rounded-full",
254
+ "size-5 cursor-pointer rounded-full transition-all",
204
255
  value === opt.value
205
- ? "ring-2 ring-white ring-offset-2 ring-offset-[hsl(240,5%,8%)]"
206
- : "ring-1 ring-white/10 hover:ring-white/30",
256
+ ? "ring-2 ring-foreground/80 ring-offset-1 ring-offset-card"
257
+ : "ring-1 ring-border/60 hover:ring-border",
207
258
  )}
208
- style={{ backgroundColor: opt.color || opt.value }}
259
+ style={{ backgroundColor: opt.color ?? opt.value }}
209
260
  />
210
261
  </TooltipTrigger>
211
262
  <TooltipContent>{opt.label}</TooltipContent>
212
263
  </Tooltip>
213
264
  ))}
214
265
  </div>
215
- ) : null}
266
+ )}
216
267
 
217
268
  {tweak.type === "segment" && (
218
- <div className="flex overflow-hidden rounded-lg border border-border">
269
+ <div className="flex h-6 overflow-hidden rounded border border-border">
219
270
  {tweak.options?.map((opt) => (
220
271
  <button
221
272
  type="button"
222
273
  key={opt.value}
223
274
  onClick={() => onChange(opt.value)}
224
275
  className={cn(
225
- "flex-1 cursor-pointer px-2.5 py-1 text-[11px] font-medium",
276
+ "flex flex-1 cursor-pointer items-center justify-center px-2 text-[11px] font-medium transition-colors",
226
277
  value === opt.value
227
278
  ? "bg-accent text-foreground"
228
- : "text-muted-foreground/70 hover:text-muted-foreground",
279
+ : "text-muted-foreground/70 hover:bg-accent/50 hover:text-foreground",
229
280
  )}
230
281
  >
231
282
  {opt.label}
@@ -235,7 +286,7 @@ function TweakControl({
235
286
  )}
236
287
 
237
288
  {tweak.type === "slider" && (
238
- <div className="flex items-center gap-2">
289
+ <div className="flex h-6 items-center gap-2">
239
290
  <Slider
240
291
  min={tweak.min ?? 0}
241
292
  max={tweak.max ?? 100}
@@ -244,19 +295,12 @@ function TweakControl({
244
295
  onValueChange={([v]) => onChange(v)}
245
296
  className="flex-1"
246
297
  />
247
- <span className="min-w-[2rem] text-right text-[11px] text-muted-foreground">
298
+ <span className="min-w-[2ch] text-right text-[11px] tabular-nums text-muted-foreground">
248
299
  {typeof value === "number" ? value : 50}
249
300
  {tweak.cssVar?.includes("radius") ? "px" : ""}
250
301
  </span>
251
302
  </div>
252
303
  )}
253
-
254
- {tweak.type === "toggle" && (
255
- <Switch
256
- checked={!!value}
257
- onCheckedChange={(checked) => onChange(checked)}
258
- />
259
- )}
260
304
  </div>
261
305
  );
262
306
  }
@@ -1,15 +1,10 @@
1
1
  export { DesignCanvas } from "./DesignCanvas";
2
- export { DesignToolbar } from "./DesignToolbar";
3
- export type { EditorMode } from "./DesignToolbar";
4
2
  export { DeviceFrame } from "./DeviceFrame";
5
3
  export { DrawOverlay } from "./DrawOverlay";
6
4
  export { EditPanel } from "./EditPanel";
7
5
  export { QuestionFlow } from "./QuestionFlow";
8
6
  export { TweaksPanel } from "./TweaksPanel";
9
7
  export { VariantGrid } from "./VariantGrid";
10
- export { ViewportTabs } from "./ViewportTabs";
11
- export { ZoomControls } from "./ZoomControls";
12
- export { PresentMode } from "./PresentMode";
13
8
  export type {
14
9
  DrawAnnotation,
15
10
  ElementInfo,
@@ -0,0 +1,286 @@
1
+ import type { ComponentType } from "react";
2
+
3
+ import {
4
+ Tooltip,
5
+ TooltipContent,
6
+ TooltipProvider,
7
+ TooltipTrigger,
8
+ } from "@/components/ui/tooltip";
9
+ import { cn } from "@/lib/utils";
10
+
11
+ export type AlignmentHorizontal = "left" | "center" | "right";
12
+ export type AlignmentVertical = "top" | "middle" | "bottom";
13
+ export type DistributionAxis = "horizontal" | "vertical";
14
+
15
+ export interface AlignmentMatrixValue {
16
+ horizontal: AlignmentHorizontal;
17
+ vertical: AlignmentVertical;
18
+ }
19
+
20
+ export interface AlignmentMatrixLabels {
21
+ title: string;
22
+ alignTopLeft: string;
23
+ alignTopCenter: string;
24
+ alignTopRight: string;
25
+ alignMiddleLeft: string;
26
+ alignCenter: string;
27
+ alignMiddleRight: string;
28
+ alignBottomLeft: string;
29
+ alignBottomCenter: string;
30
+ alignBottomRight: string;
31
+ distributeHorizontal: string;
32
+ distributeVertical: string;
33
+ }
34
+
35
+ export interface AlignmentMatrixProps {
36
+ value: AlignmentMatrixValue;
37
+ onChange: (value: AlignmentMatrixValue) => void;
38
+ onDistribute?: (axis: DistributionAxis) => void;
39
+ labels?: Partial<AlignmentMatrixLabels>;
40
+ disabled?: boolean;
41
+ className?: string;
42
+ }
43
+
44
+ type MatrixIcon = ComponentType<{ className?: string }>;
45
+
46
+ const DEFAULT_LABELS: AlignmentMatrixLabels = {
47
+ title: "Align", // i18n-ignore fallback component label
48
+ alignTopLeft: "Align top left", // i18n-ignore fallback component label
49
+ alignTopCenter: "Align top center", // i18n-ignore fallback component label
50
+ alignTopRight: "Align top right", // i18n-ignore fallback component label
51
+ alignMiddleLeft: "Align middle left", // i18n-ignore fallback component label
52
+ alignCenter: "Align center", // i18n-ignore fallback component label
53
+ alignMiddleRight: "Align middle right", // i18n-ignore fallback component label
54
+ alignBottomLeft: "Align bottom left", // i18n-ignore fallback component label
55
+ alignBottomCenter: "Align bottom center", // i18n-ignore fallback component label
56
+ alignBottomRight: "Align bottom right", // i18n-ignore fallback component label
57
+ distributeHorizontal: "Distribute horizontal spacing", // i18n-ignore fallback component label
58
+ distributeVertical: "Distribute vertical spacing", // i18n-ignore fallback component label
59
+ };
60
+
61
+ const MATRIX_OPTIONS: Array<{
62
+ horizontal: AlignmentHorizontal;
63
+ vertical: AlignmentVertical;
64
+ labelKey: keyof AlignmentMatrixLabels;
65
+ }> = [
66
+ { horizontal: "left", vertical: "top", labelKey: "alignTopLeft" },
67
+ { horizontal: "center", vertical: "top", labelKey: "alignTopCenter" },
68
+ { horizontal: "right", vertical: "top", labelKey: "alignTopRight" },
69
+ { horizontal: "left", vertical: "middle", labelKey: "alignMiddleLeft" },
70
+ { horizontal: "center", vertical: "middle", labelKey: "alignCenter" },
71
+ { horizontal: "right", vertical: "middle", labelKey: "alignMiddleRight" },
72
+ { horizontal: "left", vertical: "bottom", labelKey: "alignBottomLeft" },
73
+ { horizontal: "center", vertical: "bottom", labelKey: "alignBottomCenter" },
74
+ { horizontal: "right", vertical: "bottom", labelKey: "alignBottomRight" },
75
+ ];
76
+
77
+ /** Figma-style alignment cell: blue bars when active, faint dot when inactive. */
78
+ function AlignmentCell({
79
+ horizontal,
80
+ vertical,
81
+ active,
82
+ label,
83
+ disabled,
84
+ onClick,
85
+ }: {
86
+ horizontal: AlignmentHorizontal;
87
+ vertical: AlignmentVertical;
88
+ active: boolean;
89
+ label: string;
90
+ disabled: boolean;
91
+ onClick: () => void;
92
+ }) {
93
+ // The active cell shows blue bars representing the alignment direction.
94
+ // Inactive cells show a small faint dot.
95
+ return (
96
+ <Tooltip>
97
+ <TooltipTrigger asChild>
98
+ <button
99
+ type="button"
100
+ aria-label={label}
101
+ aria-pressed={active}
102
+ disabled={disabled}
103
+ onClick={onClick}
104
+ className={cn(
105
+ "flex size-[26px] items-center justify-center rounded-sm transition-colors",
106
+ "hover:bg-[var(--design-editor-control-bg)]",
107
+ disabled && "pointer-events-none opacity-40",
108
+ )}
109
+ >
110
+ {active ? (
111
+ <AlignmentBars horizontal={horizontal} vertical={vertical} />
112
+ ) : (
113
+ <span
114
+ className="block size-1 rounded-full bg-current opacity-25"
115
+ aria-hidden="true"
116
+ />
117
+ )}
118
+ </button>
119
+ </TooltipTrigger>
120
+ <TooltipContent className="text-xs">{label}</TooltipContent>
121
+ </Tooltip>
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Renders the Figma-style blue bars for the active alignment cell.
127
+ * The bars are drawn as short lines showing the items packed
128
+ * against the given horizontal + vertical edge.
129
+ */
130
+ function AlignmentBars({
131
+ horizontal,
132
+ vertical,
133
+ }: {
134
+ horizontal: AlignmentHorizontal;
135
+ vertical: AlignmentVertical;
136
+ }) {
137
+ // We draw 2-3 small bars inside a tiny box to indicate alignment direction.
138
+ // The bars are positioned based on which corner/edge is active.
139
+ const accent = "var(--design-editor-accent-color, #18a0fb)";
140
+
141
+ // Determine the transform for the inner bars container
142
+ // based on alignment position within the 16×16 drawing area
143
+ const justifyClass =
144
+ horizontal === "left"
145
+ ? "justify-start"
146
+ : horizontal === "right"
147
+ ? "justify-end"
148
+ : "justify-center";
149
+
150
+ const alignClass =
151
+ vertical === "top"
152
+ ? "items-start"
153
+ : vertical === "bottom"
154
+ ? "items-end"
155
+ : "items-center";
156
+
157
+ return (
158
+ <svg
159
+ viewBox="0 0 14 14"
160
+ width={14}
161
+ height={14}
162
+ fill="none"
163
+ aria-hidden="true"
164
+ >
165
+ {/* Outer frame (faint) */}
166
+ <rect
167
+ x="0.5"
168
+ y="0.5"
169
+ width="13"
170
+ height="13"
171
+ rx="1"
172
+ stroke={accent}
173
+ strokeWidth="1"
174
+ opacity="0.35"
175
+ />
176
+ {/* Inner content bars — positioned by alignment */}
177
+ <AlignmentBarsContent
178
+ horizontal={horizontal}
179
+ vertical={vertical}
180
+ accent={accent}
181
+ />
182
+ </svg>
183
+ );
184
+ }
185
+
186
+ function AlignmentBarsContent({
187
+ horizontal,
188
+ vertical,
189
+ accent,
190
+ }: {
191
+ horizontal: AlignmentHorizontal;
192
+ vertical: AlignmentVertical;
193
+ accent: string;
194
+ }) {
195
+ // Draw 2 bars (representing child items) packed toward the alignment edge.
196
+ // The bars are thin rectangles with rounded caps.
197
+ const barH = 2; // bar height in px
198
+ const barW = [4, 3]; // varying widths for visual interest
199
+ const gap = 1.5; // gap between bars
200
+ const totalH = barH * 2 + gap;
201
+ const totalW = Math.max(...barW);
202
+
203
+ // Y position based on vertical alignment
204
+ const yStart =
205
+ vertical === "top"
206
+ ? 2.5
207
+ : vertical === "bottom"
208
+ ? 14 - 2.5 - totalH
209
+ : (14 - totalH) / 2;
210
+
211
+ // X positions for the bars based on horizontal alignment
212
+ const getBarX = (w: number) => {
213
+ if (horizontal === "left") return 2.5;
214
+ if (horizontal === "right") return 14 - 2.5 - w;
215
+ return (14 - w) / 2;
216
+ };
217
+
218
+ return (
219
+ <>
220
+ <rect
221
+ x={getBarX(barW[0]!)}
222
+ y={yStart}
223
+ width={barW[0]}
224
+ height={barH}
225
+ rx={0.5}
226
+ fill={accent}
227
+ />
228
+ <rect
229
+ x={getBarX(barW[1]!)}
230
+ y={yStart + barH + gap}
231
+ width={barW[1]}
232
+ height={barH}
233
+ rx={0.5}
234
+ fill={accent}
235
+ />
236
+ </>
237
+ );
238
+ }
239
+
240
+ export function AlignmentMatrix({
241
+ value,
242
+ onChange,
243
+ onDistribute,
244
+ labels,
245
+ disabled = false,
246
+ className,
247
+ }: AlignmentMatrixProps) {
248
+ const copy = { ...DEFAULT_LABELS, ...labels };
249
+
250
+ return (
251
+ <TooltipProvider delayDuration={250}>
252
+ <div className={cn("space-y-0", className)}>
253
+ {/* 3×3 dot grid — Figma style */}
254
+ <div
255
+ className={cn(
256
+ "grid grid-cols-3 rounded-md border border-[var(--design-editor-control-border,hsl(var(--border)))]",
257
+ "bg-[var(--design-editor-control-bg)] p-0.5",
258
+ )}
259
+ style={{ width: 84 }}
260
+ >
261
+ {MATRIX_OPTIONS.map((option) => {
262
+ const active =
263
+ option.horizontal === value.horizontal &&
264
+ option.vertical === value.vertical;
265
+ return (
266
+ <AlignmentCell
267
+ key={`${option.horizontal}-${option.vertical}`}
268
+ horizontal={option.horizontal}
269
+ vertical={option.vertical}
270
+ active={active}
271
+ label={copy[option.labelKey]}
272
+ disabled={disabled}
273
+ onClick={() =>
274
+ onChange({
275
+ horizontal: option.horizontal,
276
+ vertical: option.vertical,
277
+ })
278
+ }
279
+ />
280
+ );
281
+ })}
282
+ </div>
283
+ </div>
284
+ </TooltipProvider>
285
+ );
286
+ }