@1agh/maude 0.28.0 → 0.29.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 (361) hide show
  1. package/README.md +2 -2
  2. package/{plugins/design/dev-server → apps/studio}/ai-banner.tsx +1 -1
  3. package/{plugins/design/dev-server → apps/studio}/annotations-context-toolbar.tsx +286 -6
  4. package/{plugins/design/dev-server → apps/studio}/annotations-layer.tsx +1209 -122
  5. package/{plugins/design/dev-server → apps/studio}/api.ts +486 -32
  6. package/{plugins/design/dev-server → apps/studio}/artboard-activity-overlay.tsx +1 -1
  7. package/{plugins/design/dev-server → apps/studio}/artboard-marquee.tsx +1 -1
  8. package/apps/studio/bin/_motion-sample-playwright.mjs +129 -0
  9. package/{plugins/design/dev-server → apps/studio}/bin/canvas-edit.sh +1 -1
  10. package/{plugins/design/dev-server → apps/studio}/bin/draw-proof.sh +37 -2
  11. package/{plugins/design/dev-server → apps/studio}/bin/preflight.sh +1 -1
  12. package/apps/studio/bin/read-annotations.mjs +438 -0
  13. package/apps/studio/bin/read-annotations.sh +11 -0
  14. package/{plugins/design/dev-server → apps/studio}/bin/runtime-health.sh +1 -1
  15. package/{plugins/design/dev-server → apps/studio}/bin/scenario-report.mjs +1 -1
  16. package/{plugins/design/dev-server → apps/studio}/bin/screenshot.sh +62 -2
  17. package/apps/studio/bin/server-up.sh +234 -0
  18. package/apps/studio/bin/to-lottie-verify.html +68 -0
  19. package/apps/studio/bin/to-lottie.sh +128 -0
  20. package/{plugins/design/dev-server → apps/studio}/bin/visual-sanity.sh +19 -3
  21. package/{plugins/design/dev-server → apps/studio}/build.ts +5 -3
  22. package/{plugins/design/dev-server → apps/studio}/canvas-arrowheads.ts +1 -1
  23. package/{plugins/design/dev-server → apps/studio}/canvas-comment-mount.tsx +2 -2
  24. package/apps/studio/canvas-create.ts +104 -0
  25. package/{plugins/design/dev-server → apps/studio}/canvas-cursors.ts +47 -13
  26. package/{plugins/design/dev-server → apps/studio}/canvas-icons.tsx +60 -1
  27. package/{plugins/design/dev-server → apps/studio}/canvas-lib-inline.ts +1 -1
  28. package/{plugins/design/dev-server → apps/studio}/canvas-lib-resolver.ts +1 -1
  29. package/{plugins/design/dev-server → apps/studio}/canvas-lib.tsx +41 -33
  30. package/{plugins/design/dev-server → apps/studio}/canvas-shell.tsx +57 -42
  31. package/{plugins/design/dev-server → apps/studio}/client/app.jsx +1713 -530
  32. package/apps/studio/client/canvas-url.js +81 -0
  33. package/{plugins/design/dev-server → apps/studio}/client/comments-overlay.css +41 -27
  34. package/{plugins/design/dev-server → apps/studio}/client/index.html +2 -1
  35. package/apps/studio/client/styles/1-tokens-maude.css +296 -0
  36. package/apps/studio/client/styles/3-shell-maude.css +459 -0
  37. package/{plugins/design/dev-server → apps/studio}/client/styles/3-shell.css +129 -0
  38. package/apps/studio/client/styles/4-components-maude.css +74 -0
  39. package/{plugins/design/dev-server → apps/studio}/client/styles/4-components.css +357 -34
  40. package/apps/studio/client/styles/5-maude-overrides.css +123 -0
  41. package/{plugins/design/dev-server → apps/studio}/client/styles/_index.css +9 -0
  42. package/{plugins/design/dev-server → apps/studio}/client/styles.css +1 -1
  43. package/apps/studio/client/tour/overlay.jsx +191 -0
  44. package/apps/studio/client/tour/usage-tour.js +35 -0
  45. package/apps/studio/client/whats-new-seen.js +52 -0
  46. package/apps/studio/client/whats-new.jsx +250 -0
  47. package/{plugins/design/dev-server → apps/studio}/collab/index.ts +4 -4
  48. package/{plugins/design/dev-server → apps/studio}/collab/persistence.ts +1 -1
  49. package/{plugins/design/dev-server → apps/studio}/commands/annotation-strokes-command.ts +1 -1
  50. package/{plugins/design/dev-server → apps/studio}/commands/equal-spacing-command.ts +1 -1
  51. package/{plugins/design/dev-server → apps/studio}/commands/move-artboards-command.ts +1 -1
  52. package/{plugins/design/dev-server → apps/studio}/comments-overlay.tsx +25 -6
  53. package/{plugins/design/dev-server → apps/studio}/context-menu.tsx +2 -2
  54. package/{plugins/design/dev-server → apps/studio}/contextual-toolbar.tsx +4 -7
  55. package/{plugins/design/dev-server → apps/studio}/cursors-overlay.tsx +1 -1
  56. package/apps/studio/dist/client.bundle.js +22825 -0
  57. package/apps/studio/dist/comment-mount.js +1960 -0
  58. package/apps/studio/dist/runtime/lib0_decoding.js +1 -0
  59. package/apps/studio/dist/runtime/lib0_encoding.js +1 -0
  60. package/apps/studio/dist/runtime/motion.js +4 -0
  61. package/apps/studio/dist/runtime/motion_react.js +12 -0
  62. package/apps/studio/dist/runtime/pixi-js.js +3397 -0
  63. package/apps/studio/dist/runtime/react-dom.js +1 -0
  64. package/apps/studio/dist/runtime/react-dom_client.js +9 -0
  65. package/apps/studio/dist/runtime/react.js +1 -0
  66. package/apps/studio/dist/runtime/react_jsx-dev-runtime.js +1 -0
  67. package/apps/studio/dist/runtime/react_jsx-runtime.js +1 -0
  68. package/apps/studio/dist/runtime/y-protocols_awareness.js +1 -0
  69. package/apps/studio/dist/runtime/y-protocols_sync.js +1 -0
  70. package/apps/studio/dist/runtime/yjs.js +5 -0
  71. package/apps/studio/dist/styles.css +5695 -0
  72. package/{plugins/design/dev-server → apps/studio}/dom-selection.ts +75 -4
  73. package/apps/studio/draw/animate.ts +333 -0
  74. package/{plugins/design/dev-server → apps/studio}/draw/brush.ts +4 -4
  75. package/{plugins/design/dev-server → apps/studio}/draw/composition.ts +1 -1
  76. package/{plugins/design/dev-server → apps/studio}/draw/geometry.ts +1 -1
  77. package/{plugins/design/dev-server → apps/studio}/draw/index.ts +9 -6
  78. package/{plugins/design/dev-server → apps/studio}/draw/layout.ts +2 -2
  79. package/apps/studio/draw/morph.ts +204 -0
  80. package/{plugins/design/dev-server → apps/studio}/draw/optimize.ts +1 -1
  81. package/{plugins/design/dev-server → apps/studio}/draw/palette.ts +1 -1
  82. package/{plugins/design/dev-server → apps/studio}/draw/primitives.ts +1 -1
  83. package/apps/studio/draw/serialize-animate.ts +324 -0
  84. package/{plugins/design/dev-server → apps/studio}/draw/serialize.ts +9 -3
  85. package/apps/studio/draw/test/animate.test.ts +172 -0
  86. package/{plugins/design/dev-server → apps/studio}/draw/test/layout.test.ts +1 -1
  87. package/apps/studio/draw/test/morph.test.ts +107 -0
  88. package/apps/studio/draw/test/serialize-animate.test.ts +142 -0
  89. package/{plugins/design/dev-server → apps/studio}/draw/test/serialize.test.ts +1 -1
  90. package/{plugins/design/dev-server → apps/studio}/equal-spacing-detector.ts +1 -1
  91. package/{plugins/design/dev-server → apps/studio}/equal-spacing-handles.tsx +7 -29
  92. package/{plugins/design/dev-server → apps/studio}/examples/perf-100-artboards.tsx +1 -2
  93. package/{plugins/design/dev-server → apps/studio}/export-dialog.tsx +14 -2
  94. package/{plugins/design/dev-server → apps/studio}/exporters/index.ts +2 -2
  95. package/{plugins/design/dev-server → apps/studio}/http.ts +103 -2
  96. package/{plugins/design/dev-server → apps/studio}/input-router.tsx +8 -1
  97. package/{plugins/design/dev-server → apps/studio}/inspect.ts +20 -3
  98. package/{plugins/design/dev-server → apps/studio}/marquee-overlay.tsx +6 -3
  99. package/{plugins/design/dev-server → apps/studio}/participants-chrome.tsx +1 -1
  100. package/{plugins/design/dev-server → apps/studio}/paths.ts +15 -11
  101. package/{plugins/design/dev-server → apps/studio}/server.ts +19 -1
  102. package/{plugins/design/dev-server → apps/studio}/sync/index.ts +6 -6
  103. package/{plugins/design/dev-server → apps/studio}/sync/materialize.ts +2 -2
  104. package/{plugins/design/dev-server → apps/studio}/test/ai-activity.test.ts +1 -1
  105. package/{plugins/design/dev-server → apps/studio}/test/annotations-api.test.ts +1 -2
  106. package/{plugins/design/dev-server → apps/studio}/test/annotations-layer.test.ts +69 -6
  107. package/{plugins/design/dev-server → apps/studio}/test/annotations-roundtrip.test.ts +98 -1
  108. package/apps/studio/test/annotations-text-format.test.ts +396 -0
  109. package/apps/studio/test/asset-api.test.ts +149 -0
  110. package/{plugins/design/dev-server → apps/studio}/test/boot-self-heal.test.ts +1 -1
  111. package/apps/studio/test/canvas-create-api.test.ts +361 -0
  112. package/{plugins/design/dev-server → apps/studio}/test/canvas-cursors.test.ts +3 -1
  113. package/{plugins/design/dev-server → apps/studio}/test/canvas-edit.test.ts +1 -1
  114. package/{plugins/design/dev-server → apps/studio}/test/canvas-hmr-runtime.test.tsx +1 -1
  115. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-inline.test.ts +1 -1
  116. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-resolver.test.ts +2 -3
  117. package/apps/studio/test/canvas-media-drop.test.ts +158 -0
  118. package/{plugins/design/dev-server → apps/studio}/test/canvas-meta-api.test.ts +1 -2
  119. package/{plugins/design/dev-server → apps/studio}/test/canvas-origin-gate.test.ts +18 -3
  120. package/apps/studio/test/canvas-url.test.ts +99 -0
  121. package/{plugins/design/dev-server → apps/studio}/test/collab-annotations-bridge.test.ts +1 -1
  122. package/{plugins/design/dev-server → apps/studio}/test/collab-bridge.test.ts +1 -1
  123. package/{plugins/design/dev-server → apps/studio}/test/collab-room.test.ts +1 -1
  124. package/{plugins/design/dev-server → apps/studio}/test/collab-stress.test.ts +1 -1
  125. package/{plugins/design/dev-server → apps/studio}/test/comments-api.test.ts +1 -2
  126. package/{plugins/design/dev-server → apps/studio}/test/compile-entry.test.ts +1 -2
  127. package/{plugins/design/dev-server → apps/studio}/test/exporters/canva.test.ts +1 -2
  128. package/{plugins/design/dev-server → apps/studio}/test/exporters/history.test.ts +1 -2
  129. package/{plugins/design/dev-server → apps/studio}/test/exporters/pw-launch.test.ts +1 -1
  130. package/{plugins/design/dev-server → apps/studio}/test/exporters/scope.test.ts +1 -2
  131. package/{plugins/design/dev-server → apps/studio}/test/exporters/zip.test.ts +1 -2
  132. package/{plugins/design/dev-server → apps/studio}/test/git-lifecycle.test.ts +1 -2
  133. package/{plugins/design/dev-server → apps/studio}/test/handoff-static-frames.test.ts +1 -1
  134. package/{plugins/design/dev-server → apps/studio}/test/hmr-broadcast.test.ts +1 -1
  135. package/apps/studio/test/index-data-canvas-ds.test.ts +97 -0
  136. package/apps/studio/test/motion-sample.test.ts +35 -0
  137. package/{plugins/design/dev-server → apps/studio}/test/perf-harness.ts +1 -1
  138. package/{plugins/design/dev-server → apps/studio}/test/phase-3.6-smoke.test.ts +3 -1
  139. package/apps/studio/test/read-annotations.test.ts +409 -0
  140. package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle.test.ts +1 -1
  141. package/{plugins/design/dev-server → apps/studio}/test/sanitize-annotation-svg.test.ts +108 -2
  142. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-convergence.test.ts +2 -2
  143. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-migrate.test.ts +2 -3
  144. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-projection.test.ts +1 -1
  145. package/{plugins/design/dev-server → apps/studio}/test/snap-distance-pill.test.ts +1 -1
  146. package/{plugins/design/dev-server → apps/studio}/test/sync-agent.test.ts +2 -3
  147. package/{plugins/design/dev-server → apps/studio}/test/sync-atomic-write.test.ts +2 -3
  148. package/{plugins/design/dev-server → apps/studio}/test/sync-connection-state.test.ts +1 -1
  149. package/{plugins/design/dev-server → apps/studio}/test/sync-echo-guard.test.ts +1 -1
  150. package/{plugins/design/dev-server → apps/studio}/test/sync-fs-mirror.test.ts +1 -2
  151. package/{plugins/design/dev-server → apps/studio}/test/sync-hardening.test.ts +4 -5
  152. package/{plugins/design/dev-server → apps/studio}/test/sync-hubs-config.test.ts +1 -2
  153. package/{plugins/design/dev-server → apps/studio}/test/sync-runtime.test.ts +3 -8
  154. package/{plugins/design/dev-server → apps/studio}/test/sync-status.test.ts +1 -1
  155. package/{plugins/design/dev-server → apps/studio}/test/sync-untrusted.test.ts +1 -2
  156. package/apps/studio/test/tour-overlay.test.tsx +56 -0
  157. package/{plugins/design/dev-server → apps/studio}/test/use-agent-presence.test.tsx +4 -1
  158. package/{plugins/design/dev-server → apps/studio}/test/use-annotation-resize.test.ts +43 -0
  159. package/{plugins/design/dev-server → apps/studio}/test/use-snap-guides.test.ts +1 -1
  160. package/{plugins/design/dev-server → apps/studio}/test/use-tool-mode.test.tsx +4 -1
  161. package/apps/studio/test/whats-new.test.ts +101 -0
  162. package/apps/studio/text-imports.d.ts +9 -0
  163. package/{plugins/design/dev-server → apps/studio}/tool-palette.tsx +4 -69
  164. package/{plugins/design/dev-server → apps/studio}/undo-hud.tsx +1 -1
  165. package/{plugins/design/dev-server → apps/studio}/undo-stack.ts +1 -1
  166. package/{plugins/design/dev-server → apps/studio}/use-agent-presence.tsx +2 -2
  167. package/{plugins/design/dev-server → apps/studio}/use-annotation-resize.tsx +41 -12
  168. package/{plugins/design/dev-server → apps/studio}/use-annotation-selection.tsx +3 -7
  169. package/{plugins/design/dev-server → apps/studio}/use-annotations-visibility.tsx +2 -2
  170. package/{plugins/design/dev-server → apps/studio}/use-artboard-drag.tsx +2 -2
  171. package/{plugins/design/dev-server → apps/studio}/use-canvas-activity.tsx +2 -2
  172. package/apps/studio/use-canvas-media-drop.tsx +343 -0
  173. package/{plugins/design/dev-server → apps/studio}/use-collab.tsx +4 -5
  174. package/{plugins/design/dev-server → apps/studio}/use-cursor-modifiers.tsx +1 -1
  175. package/{plugins/design/dev-server → apps/studio}/use-keyboard-discipline.tsx +5 -2
  176. package/{plugins/design/dev-server → apps/studio}/use-selection-set.tsx +10 -2
  177. package/{plugins/design/dev-server → apps/studio}/use-snap-guides.tsx +1 -1
  178. package/{plugins/design/dev-server → apps/studio}/use-tool-mode.tsx +4 -2
  179. package/{plugins/design/dev-server → apps/studio}/use-undo-stack.tsx +5 -6
  180. package/apps/studio/whats-new.json +139 -0
  181. package/apps/studio/whats-new.schema.json +70 -0
  182. package/apps/studio/whats-new.ts +87 -0
  183. package/cli/bin/maude.mjs +10 -0
  184. package/cli/commands/design.mjs +84 -10
  185. package/cli/commands/design.test.mjs +133 -1
  186. package/cli/commands/help.mjs +8 -2
  187. package/cli/commands/hub.mjs +3 -3
  188. package/cli/commands/hub.test.mjs +1 -1
  189. package/cli/commands/scenario-report.mjs +2 -9
  190. package/cli/lib/cache.mjs +1 -1
  191. package/cli/lib/config-lint.mjs +1 -1
  192. package/cli/lib/copy-tree.mjs +1 -1
  193. package/cli/lib/design-link.mjs +1 -1
  194. package/cli/lib/flow-design-integration.test.mjs +2 -2
  195. package/cli/lib/gitignore-block.mjs +1 -0
  196. package/cli/lib/gitignore-block.test.mjs +2 -2
  197. package/cli/lib/plugin-cli-reachability.test.mjs +8 -7
  198. package/cli/lib/preflight.mjs +1 -1
  199. package/cli/lib/stack-detect.mjs +1 -1
  200. package/package.json +16 -16
  201. package/plugins/design/templates/_shell.html +3 -3
  202. package/plugins/design/templates/brief-board.tsx.template +61 -0
  203. package/plugins/design/templates/canvas.tsx.template +1 -1
  204. package/plugins/design/templates/design-system-inspiration/SUB-AGENT-PROMPTS.md +18 -3
  205. package/plugins/design/templates/design-system-inspiration/core/config.json.tpl +1 -1
  206. package/plugins/design/templates/design-system-inspiration/core/preview/_motion-readme.md.tpl +1 -1
  207. package/plugins/flow/.claude-plugin/config.schema.json +16 -0
  208. package/plugins/design/dev-server/bin/server-up.sh +0 -135
  209. package/plugins/design/dev-server/dist/client.bundle.js +0 -20692
  210. package/plugins/design/dev-server/dist/comment-mount.js +0 -1924
  211. package/plugins/design/dev-server/dist/runtime/lib0_decoding.js +0 -620
  212. package/plugins/design/dev-server/dist/runtime/lib0_encoding.js +0 -604
  213. package/plugins/design/dev-server/dist/runtime/motion.js +0 -4944
  214. package/plugins/design/dev-server/dist/runtime/motion_react.js +0 -10056
  215. package/plugins/design/dev-server/dist/runtime/pixi-js.js +0 -53104
  216. package/plugins/design/dev-server/dist/runtime/react-dom.js +0 -231
  217. package/plugins/design/dev-server/dist/runtime/react-dom_client.js +0 -10357
  218. package/plugins/design/dev-server/dist/runtime/react.js +0 -535
  219. package/plugins/design/dev-server/dist/runtime/react_jsx-dev-runtime.js +0 -60
  220. package/plugins/design/dev-server/dist/runtime/react_jsx-runtime.js +0 -85
  221. package/plugins/design/dev-server/dist/runtime/y-protocols_awareness.js +0 -376
  222. package/plugins/design/dev-server/dist/runtime/y-protocols_sync.js +0 -100
  223. package/plugins/design/dev-server/dist/runtime/yjs.js +0 -6687
  224. package/plugins/design/dev-server/dist/styles.css +0 -2710
  225. package/{plugins/design/dev-server → apps/studio}/activity.ts +0 -0
  226. package/{plugins/design/dev-server → apps/studio}/bin/_enumerate-artboards-playwright.mjs +0 -0
  227. package/{plugins/design/dev-server → apps/studio}/bin/_html-playwright.mjs +0 -0
  228. package/{plugins/design/dev-server → apps/studio}/bin/_pdf-playwright.mjs +0 -0
  229. package/{plugins/design/dev-server → apps/studio}/bin/_png-playwright.mjs +0 -0
  230. package/{plugins/design/dev-server → apps/studio}/bin/_pptx-playwright.mjs +0 -0
  231. package/{plugins/design/dev-server → apps/studio}/bin/_pw-launch.mjs +0 -0
  232. package/{plugins/design/dev-server → apps/studio}/bin/_screenshot-playwright.mjs +0 -0
  233. package/{plugins/design/dev-server → apps/studio}/bin/_svg-optimize.mjs +0 -0
  234. package/{plugins/design/dev-server → apps/studio}/bin/_svg-playwright.mjs +0 -0
  235. package/{plugins/design/dev-server → apps/studio}/bin/asset-sweep.sh +0 -0
  236. package/{plugins/design/dev-server → apps/studio}/bin/bootstrap-check.sh +0 -0
  237. package/{plugins/design/dev-server → apps/studio}/bin/check-runtime-bundles.sh +0 -0
  238. package/{plugins/design/dev-server → apps/studio}/bin/draw-build.sh +0 -0
  239. package/{plugins/design/dev-server → apps/studio}/bin/handoff.sh +0 -0
  240. package/{plugins/design/dev-server → apps/studio}/bin/prep.sh +0 -0
  241. package/{plugins/design/dev-server → apps/studio}/bin/slug.sh +0 -0
  242. package/{plugins/design/dev-server → apps/studio}/bin/smoke.sh +0 -0
  243. package/{plugins/design/dev-server → apps/studio}/bin/svg-optimize.sh +0 -0
  244. package/{plugins/design/dev-server → apps/studio}/boot-self-heal.ts +0 -0
  245. package/{plugins/design/dev-server → apps/studio}/canvas-build.ts +0 -0
  246. package/{plugins/design/dev-server → apps/studio}/canvas-edit.ts +0 -0
  247. package/{plugins/design/dev-server → apps/studio}/canvas-header.ts +0 -0
  248. package/{plugins/design/dev-server → apps/studio}/canvas-meta.schema.json +0 -0
  249. package/{plugins/design/dev-server → apps/studio}/canvas-pipeline.ts +0 -0
  250. package/{plugins/design/dev-server → apps/studio}/client/hmr.mjs +0 -0
  251. package/{plugins/design/dev-server → apps/studio}/client/iframe-lazy.mjs +0 -0
  252. package/{plugins/design/dev-server → apps/studio}/client/styles/0-reset.css +0 -0
  253. package/{plugins/design/dev-server → apps/studio}/client/styles/1-tokens.css +0 -0
  254. package/{plugins/design/dev-server → apps/studio}/client/styles/2-layout.css +0 -0
  255. package/{plugins/design/dev-server → apps/studio}/client/styles/5-utilities.css +0 -0
  256. package/{plugins/design/dev-server → apps/studio}/collab/ai-activity.ts +0 -0
  257. package/{plugins/design/dev-server → apps/studio}/collab/awareness-bridge.ts +1 -1
  258. package/{plugins/design/dev-server → apps/studio}/collab/git-lifecycle.ts +0 -0
  259. package/{plugins/design/dev-server → apps/studio}/collab/protocol.ts +0 -0
  260. package/{plugins/design/dev-server → apps/studio}/collab/registry.ts +0 -0
  261. package/{plugins/design/dev-server → apps/studio}/collab/room.ts +0 -0
  262. package/{plugins/design/dev-server → apps/studio}/config.schema.json +0 -0
  263. package/{plugins/design/dev-server → apps/studio}/context.ts +0 -0
  264. package/{plugins/design/dev-server → apps/studio}/dist/runtime/.min-sizes.json +0 -0
  265. package/{plugins/design/dev-server → apps/studio}/draw/test/brush.test.ts +0 -0
  266. package/{plugins/design/dev-server → apps/studio}/draw/test/composition.test.ts +0 -0
  267. package/{plugins/design/dev-server → apps/studio}/draw/test/geometry.test.ts +1 -1
  268. package/{plugins/design/dev-server → apps/studio}/draw/test/gradient.test.ts +0 -0
  269. package/{plugins/design/dev-server → apps/studio}/draw/test/optimize.test.ts +0 -0
  270. package/{plugins/design/dev-server → apps/studio}/draw/test/palette.test.ts +0 -0
  271. package/{plugins/design/dev-server → apps/studio}/draw/test/primitives.test.ts +1 -1
  272. package/{plugins/design/dev-server → apps/studio}/examples/README.md +0 -0
  273. package/{plugins/design/dev-server → apps/studio}/exporters/_browser-bundles.ts +0 -0
  274. package/{plugins/design/dev-server → apps/studio}/exporters/canva-handoff-prompt.ts +0 -0
  275. package/{plugins/design/dev-server → apps/studio}/exporters/canva.ts +0 -0
  276. package/{plugins/design/dev-server → apps/studio}/exporters/html.ts +1 -1
  277. package/{plugins/design/dev-server → apps/studio}/exporters/pdf.ts +1 -1
  278. package/{plugins/design/dev-server → apps/studio}/exporters/png.ts +1 -1
  279. package/{plugins/design/dev-server → apps/studio}/exporters/pptx.ts +1 -1
  280. package/{plugins/design/dev-server → apps/studio}/exporters/scope.ts +0 -0
  281. package/{plugins/design/dev-server → apps/studio}/exporters/svg.ts +1 -1
  282. package/{plugins/design/dev-server → apps/studio}/exporters/zip.ts +0 -0
  283. package/{plugins/design/dev-server → apps/studio}/fs-watch.ts +0 -0
  284. package/{plugins/design/dev-server → apps/studio}/handoff.ts +0 -0
  285. package/{plugins/design/dev-server → apps/studio}/history.ts +0 -0
  286. package/{plugins/design/dev-server → apps/studio}/hmr-broadcast.ts +0 -0
  287. package/{plugins/design/dev-server → apps/studio}/locator.ts +0 -0
  288. package/{plugins/design/dev-server → apps/studio}/mem.ts +0 -0
  289. package/{plugins/design/dev-server → apps/studio}/runtime-bundle.ts +0 -0
  290. package/{plugins/design/dev-server → apps/studio}/server.mjs +0 -0
  291. package/{plugins/design/dev-server → apps/studio}/sync/agent.ts +1 -1
  292. package/{plugins/design/dev-server → apps/studio}/sync/atomic-write.ts +0 -0
  293. package/{plugins/design/dev-server → apps/studio}/sync/codec.ts +0 -0
  294. package/{plugins/design/dev-server → apps/studio}/sync/connection-state.ts +0 -0
  295. package/{plugins/design/dev-server → apps/studio}/sync/echo-guard.ts +0 -0
  296. package/{plugins/design/dev-server → apps/studio}/sync/fs-mirror.ts +0 -0
  297. package/{plugins/design/dev-server → apps/studio}/sync/hubs-config.ts +0 -0
  298. package/{plugins/design/dev-server → apps/studio}/sync/migrate-seed.ts +1 -1
  299. package/{plugins/design/dev-server → apps/studio}/sync/origins.ts +0 -0
  300. package/{plugins/design/dev-server → apps/studio}/sync/projection.ts +3 -3
  301. package/{plugins/design/dev-server → apps/studio}/sync/status.ts +0 -0
  302. package/{plugins/design/dev-server → apps/studio}/sync/untrusted.ts +0 -0
  303. package/{plugins/design/dev-server → apps/studio}/test/_helpers.ts +0 -0
  304. package/{plugins/design/dev-server → apps/studio}/test/active-state.test.ts +0 -0
  305. package/{plugins/design/dev-server → apps/studio}/test/activity.test.ts +0 -0
  306. package/{plugins/design/dev-server → apps/studio}/test/annotation-strokes-command.test.ts +0 -0
  307. package/{plugins/design/dev-server → apps/studio}/test/annotations-draw-modifiers.test.ts +2 -2
  308. package/{plugins/design/dev-server → apps/studio}/test/artboard-activity-overlay.test.tsx +0 -0
  309. package/{plugins/design/dev-server → apps/studio}/test/binary-smoke.test.ts +0 -0
  310. package/{plugins/design/dev-server → apps/studio}/test/bundle-smoke.test.ts +0 -0
  311. package/{plugins/design/dev-server → apps/studio}/test/canvas-build.test.ts +0 -0
  312. package/{plugins/design/dev-server → apps/studio}/test/canvas-header.test.ts +1 -1
  313. package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-motion.test.ts +0 -0
  314. package/{plugins/design/dev-server → apps/studio}/test/canvas-pipeline.test.ts +0 -0
  315. package/{plugins/design/dev-server → apps/studio}/test/canvas-route.test.ts +0 -0
  316. package/{plugins/design/dev-server → apps/studio}/test/collab-awareness-bridge.test.ts +0 -0
  317. package/{plugins/design/dev-server → apps/studio}/test/collab-loopback.test.ts +0 -0
  318. package/{plugins/design/dev-server → apps/studio}/test/collab-protocol.test.ts +2 -2
  319. package/{plugins/design/dev-server → apps/studio}/test/collab-reseed-guard.test.ts +0 -0
  320. package/{plugins/design/dev-server → apps/studio}/test/comment-mount.test.ts +0 -0
  321. package/{plugins/design/dev-server → apps/studio}/test/context-resolve-tokens.test.ts +0 -0
  322. package/{plugins/design/dev-server → apps/studio}/test/csp-canvas-shell.test.ts +0 -0
  323. package/{plugins/design/dev-server → apps/studio}/test/equal-spacing-detector.test.ts +0 -0
  324. package/{plugins/design/dev-server → apps/studio}/test/exporters/endpoint.test.ts +0 -0
  325. package/{plugins/design/dev-server → apps/studio}/test/exporters/html.test.ts +0 -0
  326. package/{plugins/design/dev-server → apps/studio}/test/exporters/pdf.test.ts +0 -0
  327. package/{plugins/design/dev-server → apps/studio}/test/exporters/png.test.ts +0 -0
  328. package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx-deck.test.ts +0 -0
  329. package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx.test.ts +0 -0
  330. package/{plugins/design/dev-server → apps/studio}/test/exporters/svg.test.ts +0 -0
  331. package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-20-annotations.svg +0 -0
  332. package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-21-annotations.svg +0 -0
  333. package/{plugins/design/dev-server → apps/studio}/test/fs-watch.test.ts +0 -0
  334. package/{plugins/design/dev-server → apps/studio}/test/handoff.test.ts +1 -1
  335. package/{plugins/design/dev-server → apps/studio}/test/history-rollback.test.ts +0 -0
  336. package/{plugins/design/dev-server → apps/studio}/test/hmr-classify.test.ts +0 -0
  337. package/{plugins/design/dev-server → apps/studio}/test/input-router.test.ts +2 -2
  338. package/{plugins/design/dev-server → apps/studio}/test/locator.test.ts +1 -1
  339. package/{plugins/design/dev-server → apps/studio}/test/marquee-overlay.test.ts +0 -0
  340. package/{plugins/design/dev-server → apps/studio}/test/move-artboards-command.test.ts +0 -0
  341. package/{plugins/design/dev-server → apps/studio}/test/participants-chrome.test.ts +0 -0
  342. package/{plugins/design/dev-server → apps/studio}/test/paths.test.ts +0 -0
  343. package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle-error-mapping.test.ts +0 -0
  344. package/{plugins/design/dev-server → apps/studio}/test/server-lifecycle.test.ts +0 -0
  345. package/{plugins/design/dev-server → apps/studio}/test/shared-doc-foundation.test.ts +0 -0
  346. package/{plugins/design/dev-server → apps/studio}/test/sync-codec.test.ts +1 -1
  347. package/{plugins/design/dev-server → apps/studio}/test/sync-meta-codec.test.ts +1 -1
  348. package/{plugins/design/dev-server → apps/studio}/test/system-endpoint.test.ts +0 -0
  349. package/{plugins/design/dev-server → apps/studio}/test/tool-palette.test.tsx +0 -0
  350. package/{plugins/design/dev-server → apps/studio}/test/undo-stack.test.ts +2 -2
  351. package/{plugins/design/dev-server → apps/studio}/test/use-annotation-selection.test.tsx +0 -0
  352. package/{plugins/design/dev-server → apps/studio}/test/use-artboard-drag.test.ts +3 -3
  353. package/{plugins/design/dev-server → apps/studio}/test/use-canvas-activity.test.tsx +2 -2
  354. package/{plugins/design/dev-server → apps/studio}/test/use-collab.test.ts +0 -0
  355. package/{plugins/design/dev-server → apps/studio}/test/use-cursor-modifiers.test.ts +0 -0
  356. package/{plugins/design/dev-server → apps/studio}/test/use-keyboard-discipline.test.ts +0 -0
  357. package/{plugins/design/dev-server → apps/studio}/test/use-selection-set.test.tsx +1 -1
  358. package/{plugins/design/dev-server → apps/studio}/test/use-undo-stack.test.tsx +2 -2
  359. /package/{plugins/design/dev-server → apps/studio}/test/ws-handshake.test.ts +0 -0
  360. /package/{plugins/design/dev-server → apps/studio}/tsconfig.json +0 -0
  361. /package/{plugins/design/dev-server → apps/studio}/ws.ts +0 -0
@@ -0,0 +1,104 @@
1
+ // canvas-create.ts — Phase 22 UI add-on. Pure helpers behind POST /_api/canvas
2
+ // (api.ts createCanvas), which lets the browser file-tree create a blank brief
3
+ // board directly — no slash command, no model cost. Generation (ingesting a
4
+ // board's notes into artboards) stays with Claude via `/design:new`; this only
5
+ // stamps out the empty annotation surface.
6
+ //
7
+ // SINGLE SOURCE — the board envelope is the SAME `brief-board.tsx.template`
8
+ // `/design:new --blank` substitutes. We text-import it so Bun.build inlines the
9
+ // content into the `bun --compile` standalone binary (verified: works at dev
10
+ // runtime AND embeds at build time), sidestepping DDR-045 — no runtime disk read
11
+ // of a file that lives outside `apps/studio/`. The template stayed under the
12
+ // design plugin (plugins/design/templates) when the studio moved (DDR-095).
13
+
14
+ import briefBoardTemplate from '../../plugins/design/templates/brief-board.tsx.template' with {
15
+ type: 'text',
16
+ };
17
+
18
+ export const BRIEF_BOARD_TEMPLATE: string = briefBoardTemplate;
19
+
20
+ /**
21
+ * The ONE security boundary for the create endpoint. A canvas name is the only
22
+ * user-controlled value, and it is interpolated into BOTH a real nested
23
+ * filesystem path (`<group>/<name>.tsx`) AND the generated `.tsx` (JSX text) +
24
+ * `.meta.json` (JSON string). This strict allowlist does triple duty:
25
+ * • path safety — no `/`, `\`, `..`, or leading dot ⇒ no traversal;
26
+ * • template safety — no `<`, `>`, `{`, `}` ⇒ can't break out of JSX text;
27
+ * • JSON safety — no `"` or `\` ⇒ can't break out of a meta string.
28
+ * Unicode letters/numbers are allowed (so "Onboarding Brief" / accented names
29
+ * work); the first char must be a letter/number (excludes leading space/dash/dot).
30
+ */
31
+ const NAME_RE = /^[\p{L}\p{N}][\p{L}\p{N} _-]{0,59}$/u;
32
+
33
+ export interface NameValidation {
34
+ ok: boolean;
35
+ name?: string;
36
+ componentName?: string;
37
+ error?: string;
38
+ }
39
+
40
+ export function validateCanvasName(raw: unknown): NameValidation {
41
+ if (typeof raw !== 'string') return { ok: false, error: 'name must be a string' };
42
+ // NFC-normalize so a decomposed (NFD) name and its composed sibling can't hash
43
+ // to two JS strings that collide to ONE on-disk path on a normalizing filesystem
44
+ // (APFS/HFS+) — which would let the 409 existence guard be bypassed and an
45
+ // existing board silently overwritten (Phase 22 security review, low). Collapse
46
+ // runs of SPACES (the one allowed whitespace) to a single space so the JS slug
47
+ // (`/\s+/→_`) and slug.sh (`tr ' ' '_'`) can't diverge on a double-spaced name
48
+ // (review #4); tabs/newlines stay un-collapsed and are rejected by NAME_RE.
49
+ const name = raw.normalize('NFC').trim().replace(/ +/g, ' ');
50
+ if (!name) return { ok: false, error: 'name is required' };
51
+ if (name.length > 60) return { ok: false, error: 'name must be 60 characters or fewer' };
52
+ if (!NAME_RE.test(name)) {
53
+ return {
54
+ ok: false,
55
+ error: 'name may contain only letters, numbers, spaces, hyphens and underscores',
56
+ };
57
+ }
58
+ // Defense in depth — the regex already forbids these, but assert no path bits
59
+ // survive (a regex edit must never silently re-open traversal).
60
+ if (name.includes('..') || name.includes('/') || name.includes('\\') || name.startsWith('.')) {
61
+ return { ok: false, error: 'name may not contain path separators or leading dots' };
62
+ }
63
+ return { ok: true, name, componentName: componentNameFrom(name) };
64
+ }
65
+
66
+ /** PascalCase a name into a valid JS identifier for the component default export.
67
+ * Non-identifier characters split words; an empty / digit-leading result gets a
68
+ * `Board` prefix so the emitted `export default function <id>()` always parses. */
69
+ export function componentNameFrom(name: string): string {
70
+ // Split on NON-(letter|number) so Unicode letters survive (the validator
71
+ // accepts them) — `Přihlášení` → `Přihlášení`, a valid JS identifier (verified
72
+ // it parses), not the ASCII-mangled `PIhlEn` (review #1). Empty (all-symbol) →
73
+ // `BriefBoard`; a digit-leading result (incl. Unicode digits) → `Board…` so the
74
+ // emitted `export default function <id>()` always parses.
75
+ const pascal = name
76
+ .split(/[^\p{L}\p{N}]+/u)
77
+ .filter(Boolean)
78
+ .map((w) => w[0].toUpperCase() + w.slice(1))
79
+ .join('');
80
+ if (!pascal) return 'BriefBoard';
81
+ if (/^\p{Nd}/u.test(pascal)) return `Board${pascal}`;
82
+ return pascal;
83
+ }
84
+
85
+ export interface BriefBoardOpts {
86
+ name: string;
87
+ componentName: string;
88
+ dsName: string;
89
+ platform: string;
90
+ seedHint: string;
91
+ historyDir: string;
92
+ }
93
+
94
+ /** Substitute the brief-board template placeholders. Safe because `name`
95
+ * (the only user value reaching here) is validated by `validateCanvasName`,
96
+ * and every other field is server-derived (config / fixed strings). */
97
+ export function renderBriefBoard(opts: BriefBoardOpts): string {
98
+ return BRIEF_BOARD_TEMPLATE.replaceAll('{{NAME}}', opts.name)
99
+ .replaceAll('{{COMPONENT_NAME}}', opts.componentName)
100
+ .replaceAll('{{DS_NAME}}', opts.dsName)
101
+ .replaceAll('{{PLATFORM}}', opts.platform)
102
+ .replaceAll('{{SEED_HINT}}', opts.seedHint)
103
+ .replaceAll('{{HISTORY_DIR}}', opts.historyDir);
104
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file canvas-cursors.ts — Phase 24 custom tool cursors (Kenney CC0)
3
- * @scope plugins/design/dev-server/canvas-cursors.ts
3
+ * @scope apps/studio/canvas-cursors.ts
4
4
  * @purpose FigJam/Figma-style custom cursors for EVERY canvas tool. The
5
5
  * native crosshair / text / arrow cursors are tiny + thin and
6
6
  * vanish on busy canvases; these are 32×32 SVG cursors that read on
@@ -46,16 +46,29 @@ const HALO = "stroke='#ffffff' stroke-linejoin='round' stroke-linecap='round'";
46
46
  // Kenney's outline band (`b`) is painted WHITE (the halo) and its inner fill
47
47
  // (`w`) is painted dark INK. Reads crisply on a LIGHT canvas (solid dark glyph)
48
48
  // AND a dark one (white halo edge).
49
- function kenney(b: string, w: string): string {
50
- return `<svg ${W}><path fill='#ffffff' d='${b}'/><path fill='${INK}' d='${w}'/></svg>`;
49
+ function kenney(b: string, w: string, transform?: string): string {
50
+ // Optional `<g transform>` for the drawing tools whose Kenney glyph needs
51
+ // re-orienting so the writing tip lands at the hotspot (user steer
52
+ // 2026-06-04: pen / highlighter "kreslí pod koncem, ne na špičce" → flipped so
53
+ // the nib points down-LEFT, top-right→bottom-left).
54
+ const open = transform ? `<g transform='${transform}'>` : '';
55
+ const close = transform ? '</g>' : '';
56
+ return `<svg ${W}>${open}<path fill='#ffffff' d='${b}'/><path fill='${INK}' d='${w}'/>${close}</svg>`;
51
57
  }
52
58
 
59
+ // Vertical mirror about the 32-viewBox horizontal centre: (x,y) → (x, 32−y).
60
+ // Applied to pen/highlighter so the glyph lies along the top-right→bottom-left
61
+ // diagonal with the nib at bottom-left.
62
+ const FLIP_V = 'translate(0,32) scale(1,-1)';
63
+
64
+ // move → Kenney `pointer_b` (user steer 2026-06-04 — the plain variant, not the
65
+ // shaded one). Hotspot at the arrow tip (top).
53
66
  const MOVE = svgCursor(
54
67
  kenney(
55
- 'M16.75 23.9 L20 22.55 20.5 22.15 20.35 21.55 18.4 17.75 21.25 17.25 21.75 17 22 16.45 Q22 16.1 21.6 15.9 L11.45 8.2 11.4 8.2 10.85 8 10.2 8.25 10 8.8 10 20.75 Q10 21.55 10.85 21.55 L11.4 21.35 13.6 19.8 15.6 23.5 16.05 23.95 16.75 23.9 M8 8.8 Q7.95 8.05 8.55 7.15 L8.95 6.75 Q9.8 6 10.85 6 11.55 6 12.2 6.35 L12.65 6.6 22.65 14.15 Q24.15 15 24 16.45 24.05 17.55 23.2 18.45 L23.05 18.55 Q22.1 19.3 21.45 19.3 L22.1 20.55 Q22.5 21.2 22.5 22.15 L22.05 23.4 20.9 24.35 20.8 24.4 17.55 25.75 15.25 25.8 Q14.15 25.4 13.75 24.25 L12.95 22.75 12.65 22.9 12.55 23 Q11.75 23.55 10.85 23.55 7.95 23.55 8 20.75 L8 8.8',
56
- 'M16.75 23.9 L16.05 23.95 15.6 23.5 13.6 19.8 11.4 21.35 10.85 21.55 Q10 21.55 10 20.75 L10 8.8 10.2 8.25 10.85 8 11.4 8.2 11.45 8.2 21.6 15.9 Q22 16.1 22 16.45 L21.75 17 21.25 17.25 18.4 17.75 20.35 21.55 20.5 22.15 20 22.55 16.75 23.9'
68
+ 'M10.25 8.25 L10.05 8.65 10 9 10 23.1 10.05 23.4 10.25 23.75 10.8 24 11.45 23.85 11.6 23.7 11.75 23.45 14.65 19.8 14.85 19.65 14.95 19.5 15.4 19.2 15.95 19.1 21.05 19.1 21.2 19.1 21.35 19.05 21.65 18.9 21.9 18.6 22 18.3 22 17.9 21.9 17.65 21.75 17.35 21.65 17.3 21.55 17.15 11.5 8.25 11.25 8.05 10.95 8 10.6 8.05 10.25 8.25 M9.15 6.6 L9.7 6.25 10 6.15 10.95 6 11.9 6.15 13 6.9 22.9 15.65 23 15.8 23.2 15.95 23.75 16.75 24 17.9 24 18.3 23.9 18.95 23.8 19.25 23.6 19.7 23.1 20.35 22.75 20.6 22.1 20.9 22.05 20.95 22 20.95 21.2 21.1 21.05 21.1 16.2 21.1 16.1 21.25 16.05 21.25 13.4 24.6 13.05 25.15 12.9 25.3 12.55 25.55 Q11.6 26.15 10.55 26 L10.5 26 Q9.65 25.85 9 25.3 L8.45 24.65 8.4 24.5 8.15 24.05 8 23.1 8 9 Q8 8.45 8.15 8.05 L8.25 7.75 8.45 7.35 9.15 6.6',
69
+ 'M10.25 8.25 L10.6 8.05 10.95 8 11.25 8.05 11.5 8.25 21.55 17.15 21.65 17.3 21.75 17.35 21.9 17.65 22 17.9 22 18.3 21.9 18.6 21.65 18.9 21.35 19.05 21.2 19.1 21.05 19.1 15.95 19.1 15.4 19.2 14.95 19.5 14.85 19.65 14.65 19.8 11.75 23.45 11.6 23.7 11.45 23.85 10.8 24 10.25 23.75 10.05 23.4 10 23.1 10 9 10.05 8.65 10.25 8.25'
57
70
  ),
58
- 6,
71
+ 8,
59
72
  5,
60
73
  'default'
61
74
  );
@@ -68,22 +81,40 @@ const HAND = svgCursor(
68
81
  12,
69
82
  'grab'
70
83
  );
84
+ // comment → Kenney `message_round` (user steer 2026-06-04). Hotspot at the
85
+ // tail tip (bottom-centre), where the comment pin is dropped.
71
86
  const COMMENT = svgCursor(
72
87
  kenney(
73
- 'M8 4 Q4 4 4 8 L4 20 Q4 24 8 24 L12 24 15.3 27.3 16 27.6 16.7 27.3 20 24 24 24 Q28 24 28 20 L28 8 Q28 4 24 4 L8 4 M24 2 Q30 2 30 8 L30 20 Q30 26 24 26 L20.85 26 18.15 28.75 Q17.2 29.6 16 29.6 14.8 29.6 13.9 28.75 L11.15 26 8 26 Q2 26 2 20 L2 8 Q2 2 8 2 L24 2 M24 14 Q24 14.85 23.4 15.4 22.85 16 22 16 21.15 16 20.55 15.4 20 14.85 20 14 20 13.15 20.55 12.55 21.15 12 22 12 22.85 12 23.4 12.55 24 13.15 24 14 M12 14 Q12 14.85 11.4 15.4 10.85 16 10 16 9.15 16 8.55 15.4 8 14.85 8 14 8 13.15 8.55 12.55 9.15 12 10 12 10.85 12 11.4 12.55 12 13.15 12 14 M18 14 Q18 14.85 17.4 15.4 16.85 16 16 16 15.15 16 14.55 15.4 14 14.85 14 14 14 13.15 14.55 12.55 15.15 12 16 12 16.85 12 17.4 12.55 18 13.15 18 14',
74
- 'M18 14 Q18 13.15 17.4 12.55 16.85 12 16 12 15.15 12 14.55 12.55 14 13.15 14 14 14 14.85 14.55 15.4 15.15 16 16 16 16.85 16 17.4 15.4 18 14.85 18 14 M8 4 L24 4 Q28 4 28 8 L28 20 Q28 24 24 24 L20 24 16.7 27.3 16 27.6 15.3 27.3 12 24 8 24 Q4 24 4 20 L4 8 Q4 4 8 4 M12 14 Q12 13.15 11.4 12.55 10.85 12 10 12 9.15 12 8.55 12.55 8 13.15 8 14 8 14.85 8.55 15.4 9.15 16 10 16 10.85 16 11.4 15.4 12 14.85 12 14 M24 14 Q24 13.15 23.4 12.55 22.85 12 22 12 21.15 12 20.55 12.55 20 13.15 20 14 20 14.85 20.55 15.4 21.15 16 22 16 22.85 16 23.4 15.4 24 14.85 24 14'
88
+ 'M28 14 Q28 9.85 24.45 6.9 20.95 4 16 4 11.05 4 7.5 6.9 L7.45 7 Q4 9.9 4 14 4 18.15 7.55 21.05 L7.5 21.05 Q9.2 22.45 11.2 23.2 L15.3 27.3 16 27.6 16.7 27.3 20.85 23.2 Q22.7 22.45 24.3 21.15 L24.45 21.05 Q28 18.15 28 14 M25.75 5.35 Q30.05 8.95 30 14 30.05 19.05 25.75 22.6 L25.4 22.85 Q23.8 24.1 22 24.9 L18.1 28.75 18.15 28.75 Q17.2 29.6 16 29.6 14.8 29.6 13.85 28.75 L13.9 28.75 10 24.9 6.6 22.85 6.25 22.6 Q1.95 19.05 2 14 1.95 8.95 6.25 5.35 10.3 2 16 2 21.7 2 25.75 5.35',
89
+ 'M28 14 Q28 18.15 24.45 21.05 L24.3 21.15 Q22.7 22.45 20.85 23.2 L16.7 27.3 16 27.6 15.3 27.3 11.2 23.2 Q9.2 22.45 7.5 21.05 L7.55 21.05 Q4 18.15 4 14 4 9.9 7.45 7 L7.5 6.9 Q11.05 4 16 4 20.95 4 24.45 6.9 28 9.85 28 14'
75
90
  ),
76
91
  12,
77
- 22,
92
+ 21,
78
93
  'crosshair'
79
94
  );
95
+ // pen → Kenney `drawing_pen`, mirrored vertically (FLIP_V) so the nib points
96
+ // down-LEFT (top-right→bottom-left diagonal). Source gradient-shade path dropped.
97
+ // Hotspot at the nib, bottom-left.
80
98
  const PEN = svgCursor(
99
+ kenney(
100
+ 'M4 13.1 L4 6 Q4 5.15 4.6 4.6 5.15 4 6 4 L13.1 4 Q13.95 4 14.55 4.6 L28.65 18.75 Q29.8 19.9 29.75 21.45 L29.75 21.6 29.75 21.7 Q29.75 23.2 28.7 24.35 L24.45 28.65 24.35 28.75 Q23.15 29.85 21.65 29.8 L21.55 29.8 21.4 29.8 Q20.2 29.8 19.25 29.15 L18 29.35 Q16.6 29.4 15.25 28 L15.2 27.95 8.2 20.95 Q7.6 20.35 7.6 19.55 7.6 18.7 8.2 18.1 L4.6 14.5 Q4 13.9 4 13.1 M19.5 26.65 L20.1 27.25 Q20.7 27.85 21.5 27.8 22.35 27.85 23 27.25 L27.25 22.95 Q27.8 22.35 27.75 21.55 27.8 20.75 27.2 20.15 L13.1 6 6 6 6 13.1 12.35 19.45 9.6 19.5 16.65 26.55 Q18.05 28.05 19.5 26.65 M8.05 12.3 L8 8 12.25 8.05 13.8 9.6 9.6 13.85 8.05 12.3 M15.25 11.05 L23 18.8 18.8 23.05 11.05 15.3 15.25 11.05',
101
+ 'M15.25 11.05 L11.05 15.3 18.8 23.05 23 18.8 15.25 11.05 M12.35 19.45 L6 13.1 6 6 13.1 6 27.2 20.15 Q27.8 20.75 27.75 21.55 27.8 22.35 27.25 22.95 L23 27.25 Q22.35 27.85 21.5 27.8 20.7 27.85 20.1 27.25 L19.5 26.65 12.35 19.45 M8.05 12.3 L9.6 13.85 13.8 9.6 12.25 8.05 8 8 8.05 12.3',
102
+ FLIP_V
103
+ ),
104
+ 6,
105
+ 18,
106
+ 'crosshair'
107
+ );
108
+ // highlighter → Kenney `drawing_pencil`, also mirrored vertically (distinct from
109
+ // the pen glyph). Hotspot at the lead tip, bottom-left.
110
+ const HIGHLIGHTER = svgCursor(
81
111
  kenney(
82
112
  'M5.15 10.85 Q4 9.65 4 8.1 L4 7.95 4 7.85 Q3.95 6.2 5.1 5.15 6.25 4 7.85 4 L7.95 4 8.1 4 Q9.65 4 10.85 5.15 L11 5.3 14.3 5.25 Q15.15 5.25 15.75 5.85 L29.9 20 Q31 21.15 31 22.75 L31 22.85 31 23 Q31.05 24.5 29.9 25.7 L29.55 25.95 25.65 29.9 25.65 29.95 Q24.45 31.1 22.75 31.1 21.2 31.15 20 29.95 L5.85 15.8 Q5.25 15.2 5.25 14.35 L5.25 10.95 5.15 10.85 M19.95 24.2 L18.55 22.8 22.8 18.55 24.2 19.95 19.95 24.2 M28.45 21.4 L14.3 7.25 10.15 7.3 9.4 6.55 Q8.8 5.95 7.95 6 7.1 5.95 6.5 6.55 5.95 7.1 6 7.95 5.95 8.8 6.55 9.4 L7.25 10.1 7.25 14.35 21.4 28.5 Q22 29.1 22.75 29.1 23.6 29.1 24.2 28.5 L28.45 24.25 Q29.05 23.65 29 22.85 29.05 22 28.45 21.4 M9.25 13.5 L9.25 9.3 13.5 9.25 14.3 10.05 10.05 14.3 9.25 13.5 M17.15 21.4 L11.5 15.75 15.75 11.5 21.4 17.15 17.15 21.4',
83
- 'M17.15 21.4 L21.4 17.15 15.75 11.5 11.5 15.75 17.15 21.4 M28.45 21.4 Q29.05 22 29 22.85 29.05 23.65 28.45 24.25 L24.2 28.5 Q23.6 29.1 22.75 29.1 22 29.1 21.4 28.5 L7.25 14.35 7.25 10.1 6.55 9.4 Q5.95 8.8 6 7.95 5.95 7.1 6.5 6.55 7.1 5.95 7.95 6 8.8 5.95 9.4 6.55 L10.15 7.3 14.3 7.25 28.45 21.4 M19.95 24.2 L24.2 19.95 22.8 18.55 18.55 22.8 19.95 24.2 M9.25 13.5 L10.05 14.3 14.3 10.05 13.5 9.25 9.25 9.3 9.25 13.5'
113
+ 'M17.15 21.4 L21.4 17.15 15.75 11.5 11.5 15.75 17.15 21.4 M28.45 21.4 Q29.05 22 29 22.85 29.05 23.65 28.45 24.25 L24.2 28.5 Q23.6 29.1 22.75 29.1 22 29.1 21.4 28.5 L7.25 14.35 7.25 10.1 6.55 9.4 Q5.95 8.8 6 7.95 5.95 7.1 6.5 6.55 7.1 5.95 7.95 6 8.8 5.95 9.4 6.55 L10.15 7.3 14.3 7.25 28.45 21.4 M19.95 24.2 L24.2 19.95 22.8 18.55 18.55 22.8 19.95 24.2 M9.25 13.5 L10.05 14.3 14.3 10.05 13.5 9.25 9.25 9.3 9.25 13.5',
114
+ FLIP_V
84
115
  ),
85
- 20,
86
- 20,
116
+ 6,
117
+ 18,
87
118
  'crosshair'
88
119
  );
89
120
  const CROSSHAIR = svgCursor(
@@ -140,6 +171,9 @@ export const TOOL_CURSORS: Record<Tool, string> = Object.freeze({
140
171
  hand: HAND,
141
172
  comment: COMMENT,
142
173
  pen: PEN,
174
+ // Highlighter = Kenney `drawing_pencil` rot180; pen = `drawing_pen` rot180 —
175
+ // distinct glyphs, both from the Kenney pack (user steer 2026-06-04).
176
+ highlighter: HIGHLIGHTER,
143
177
  shape: CROSSHAIR,
144
178
  rect: CROSSHAIR,
145
179
  ellipse: CROSSHAIR,
@@ -168,6 +202,6 @@ export const TOOL_CURSORS: Record<Tool, string> = Object.freeze({
168
202
  */
169
203
  export function resolveToolCursor(token: unknown): string | null {
170
204
  if (typeof token !== 'string' || !/^[a-z-]+$/.test(token)) return null;
171
- if (!Object.prototype.hasOwnProperty.call(TOOL_CURSORS, token)) return null;
205
+ if (!Object.hasOwn(TOOL_CURSORS, token)) return null;
172
206
  return TOOL_CURSORS[token as Tool];
173
207
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file canvas-icons.tsx — Phase 5.1 inline-SVG icon set
3
- * @scope plugins/design/dev-server/canvas-icons.tsx
3
+ * @scope apps/studio/canvas-icons.tsx
4
4
  * @purpose Tiny dependency-free Lucide-style icon set for the canvas
5
5
  * chrome (tool palette, context toolbar). Each icon is a single
6
6
  * `<svg>` with `currentColor` stroke so it inherits the button
@@ -122,6 +122,18 @@ export function IconText(props: IconProps) {
122
122
  );
123
123
  }
124
124
 
125
+ // Phase 23 — link (chain) glyph, used by the annotation context toolbar's
126
+ // "Open link" button. (Media is paste/drop-only — no toolbar buttons — so the
127
+ // picture-frame image icon was dropped.)
128
+ export function IconLink(props: IconProps) {
129
+ return (
130
+ <Svg {...props}>
131
+ <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
132
+ <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
133
+ </Svg>
134
+ );
135
+ }
136
+
125
137
  export function IconPresentation(props: IconProps) {
126
138
  return (
127
139
  <Svg {...props}>
@@ -404,11 +416,58 @@ export function IconAlignRight(props: IconProps) {
404
416
  );
405
417
  }
406
418
 
419
+ // ── Annotation polish text-style icons (italic / underline / lists) ──────────
420
+ export function IconItalic(props: IconProps) {
421
+ return (
422
+ <Svg {...props}>
423
+ <path d="M10 5h8M6 19h8M14 5l-4 14" />
424
+ </Svg>
425
+ );
426
+ }
427
+ export function IconUnderline(props: IconProps) {
428
+ return (
429
+ <Svg {...props}>
430
+ <path d="M7 4v7a5 5 0 0010 0V4M5 20h14" />
431
+ </Svg>
432
+ );
433
+ }
434
+ export function IconListBullet(props: IconProps) {
435
+ return (
436
+ <Svg {...props}>
437
+ <path d="M9 6h11M9 12h11M9 18h11" />
438
+ <circle cx="4.5" cy="6" r="1.1" fill="currentColor" stroke="none" />
439
+ <circle cx="4.5" cy="12" r="1.1" fill="currentColor" stroke="none" />
440
+ <circle cx="4.5" cy="18" r="1.1" fill="currentColor" stroke="none" />
441
+ </Svg>
442
+ );
443
+ }
444
+ export function IconListOrdered(props: IconProps) {
445
+ return (
446
+ <Svg {...props}>
447
+ <path d="M10 6h10M10 12h10M10 18h10" />
448
+ <path d="M3 5l1.4-.5V9M3 9h2.8" strokeWidth={1.4} />
449
+ <path d="M3.2 14.2a1 1 0 011.7.7c0 .9-1.7 1.4-1.7 2.6h2" strokeWidth={1.4} />
450
+ </Svg>
451
+ );
452
+ }
453
+
454
+ // ── Annotation polish — highlighter (chisel-tip marker) ──────────────────────
455
+ export function IconHighlighter(props: IconProps) {
456
+ return (
457
+ <Svg {...props}>
458
+ <path d="M14 4l6 6-8.5 8.5H6v-5.5z" />
459
+ <path d="M11 7l6 6" />
460
+ <path d="M4 21h7" strokeWidth={2.5} />
461
+ </Svg>
462
+ );
463
+ }
464
+
407
465
  export const TOOL_ICONS: Record<string, (p: IconProps) => JSX.Element> = {
408
466
  move: IconMove,
409
467
  hand: IconHand,
410
468
  comment: IconComment,
411
469
  pen: IconPen,
470
+ highlighter: IconHighlighter,
412
471
  // Phase 24 — single Shape tool. rect/ellipse kept for any legacy lookups.
413
472
  shape: IconShape,
414
473
  rect: IconRect,
@@ -3,7 +3,7 @@
3
3
  //
4
4
  // `/design:handoff` emits a self-contained shadcn registry-item.json. Canvases
5
5
  // import their envelope + helpers from `@maude/canvas-lib`, which the dev-server
6
- // resolves to its bundled `plugins/design/dev-server/canvas-lib.tsx`. The
6
+ // resolves to its bundled `apps/studio/canvas-lib.tsx`. The
7
7
  // handoff drop must inline every used export so the consumer never sees the
8
8
  // `@maude/canvas-lib` specifier — it's a dev-time virtual module, not a real
9
9
  // npm dep.
@@ -2,7 +2,7 @@
2
2
  //
3
3
  // Canvases import the shared canvas library via the specifier `@maude/canvas-lib`.
4
4
  // At build time we redirect that to the dev-server-bundled source at
5
- // `plugins/design/dev-server/canvas-lib.tsx` so:
5
+ // `apps/studio/canvas-lib.tsx` so:
6
6
  //
7
7
  // - the lib ships with the dev-server install (single source of truth — see
8
8
  // DDR-025; reverses DDR-022's "project-owned source under <designRoot>/_lib/"),
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file canvas-lib.tsx — dev-server-bundled canvas library
3
- * @scope plugins/design/dev-server/canvas-lib.tsx
3
+ * @scope apps/studio/canvas-lib.tsx
4
4
  * Ships with the dev-server install; resolved at canvas build time
5
5
  * via the `@maude/canvas-lib` virtual specifier. Per DDR-025, this
6
6
  * is the single source of truth — no project-side copy.
@@ -67,14 +67,19 @@
67
67
  * deprecation log at dev-server boot.
68
68
  */
69
69
 
70
+ import {
71
+ AnimatePresence as _MotionAnimatePresence,
72
+ motion as _motionImpl,
73
+ useReducedMotion as _useReducedMotion,
74
+ } from 'motion/react';
70
75
  import {
71
76
  type CSSProperties,
77
+ createContext,
72
78
  Fragment,
79
+ isValidElement,
73
80
  type ReactNode,
74
81
  type PointerEvent as ReactPointerEvent,
75
82
  type RefObject,
76
- createContext,
77
- isValidElement,
78
83
  useCallback,
79
84
  useContext,
80
85
  useEffect,
@@ -84,12 +89,6 @@ import {
84
89
  useState,
85
90
  } from 'react';
86
91
 
87
- import {
88
- AnimatePresence as _MotionAnimatePresence,
89
- motion as _motionImpl,
90
- useReducedMotion as _useReducedMotion,
91
- } from 'motion/react';
92
-
93
92
  import { ArtboardActivityOverlay } from './artboard-activity-overlay.tsx';
94
93
  import { CanvasShell } from './canvas-shell.tsx';
95
94
  import {
@@ -138,10 +137,9 @@ const ENGINE_CSS = `
138
137
  /* Canvas-shell chrome — the workspace plane + dotted grid follow the Maude
139
138
  chrome theme (--maude-chrome-*), NOT the DS palette. See canvas-shell.tsx
140
139
  HUD_TOKENS_CSS. Artboards (.dc-artboard) keep the DS theme. */
141
- background-color: var(--maude-chrome-bg-1, #f4f1ea);
140
+ background-color: var(--maude-chrome-bg-0, #f4f1ea);
142
141
  background-image:
143
- linear-gradient(var(--maude-chrome-border, rgba(0,0,0,0.08)) 1px, transparent 1px),
144
- linear-gradient(90deg, var(--maude-chrome-border, rgba(0,0,0,0.08)) 1px, transparent 1px);
142
+ radial-gradient(var(--maude-chrome-dot, rgba(0,0,0,0.12)) 1.1px, transparent 1.2px);
145
143
  background-size: 24px 24px;
146
144
  }
147
145
  /* DDR-046 — Snap guides. Sibling kind = confident magenta + glow + distance
@@ -200,6 +198,17 @@ const ENGINE_CSS = `
200
198
  irrelevant under zoom (zoom anchors top-left of the box). will-change
201
199
  hints to the compositor that this layer changes often. */
202
200
  will-change: transform;
201
+ /* Marquee / multi-select drags over artboards must not trigger native text
202
+ selection (it highlighted the canvas content). Editable surfaces re-enable
203
+ it below. */
204
+ user-select: none;
205
+ -webkit-user-select: none;
206
+ }
207
+ .dc-world input,
208
+ .dc-world textarea,
209
+ .dc-world [contenteditable="true"] {
210
+ user-select: text;
211
+ -webkit-user-select: text;
203
212
  }
204
213
  .dc-section-collapsed { display: contents; }
205
214
 
@@ -1163,7 +1172,7 @@ export function useDragStateContext(): DragStateBus | null {
1163
1172
  interface DesignCanvasProps {
1164
1173
  children: ReactNode;
1165
1174
  /** Per-overlay opt-out. `false` hides it; omit or `true` shows it. */
1166
- controls?: { minimap?: boolean; toolbar?: boolean };
1175
+ controls?: { minimap?: boolean; toolbar?: boolean; zoom?: boolean };
1167
1176
  }
1168
1177
 
1169
1178
  /**
@@ -1375,6 +1384,7 @@ function DesignCanvasInner({ children, controls }: DesignCanvasProps) {
1375
1384
  );
1376
1385
 
1377
1386
  const showMiniMap = controls?.minimap !== false;
1387
+ const showZoom = controls?.zoom !== false;
1378
1388
 
1379
1389
  // Drag-state bus (Phase 4.2). Single source of truth: only one artboard
1380
1390
  // drag is active at a time. DCArtboards write here when their local drag
@@ -1446,10 +1456,12 @@ function DesignCanvasInner({ children, controls }: DesignCanvasProps) {
1446
1456
  {children}
1447
1457
  </div>
1448
1458
  {showMiniMap ? <DCMiniMap /> : null}
1449
- {/* DCZoomToolbar is intentionally not rendered here. The Phase 5.1
1450
- ToolPalette absorbs its 4 actions into the unified canvas chrome.
1451
- The component stays exported for back-compat with any consumer that
1452
- still imports it directly. */}
1459
+ {/* Plan C F6 separate bottom-left zoom pill (the design's ZoomHud).
1460
+ Phase 5.1 had folded zoom into the ToolPalette; user feedback wants
1461
+ the design's standalone pill, so DCZoomToolbar renders here again (the
1462
+ ToolPalette's inline zoom is removed in tool-palette.tsx). It carries
1463
+ MORE than the mock — fit + actual-size — so no capability is lost. */}
1464
+ {showZoom ? <DCZoomToolbar /> : null}
1453
1465
  </div>
1454
1466
  );
1455
1467
 
@@ -1901,6 +1913,9 @@ const OVERLAY_CSS = `
1901
1913
  overflow: hidden;
1902
1914
  }
1903
1915
  .dc-mm-hd {
1916
+ display: flex;
1917
+ align-items: center;
1918
+ justify-content: space-between;
1904
1919
  padding: 5px 8px 4px;
1905
1920
  border-bottom: 1px solid var(--maude-chrome-border, rgba(0,0,0,0.08));
1906
1921
  letter-spacing: 0.05em;
@@ -1908,6 +1923,7 @@ const OVERLAY_CSS = `
1908
1923
  font-size: 9px;
1909
1924
  background: var(--maude-chrome-bg-1, #f4f1ea);
1910
1925
  }
1926
+ .dc-mm-count { font-variant-numeric: tabular-nums; color: var(--maude-chrome-fg-2, rgba(40,30,20,0.55)); }
1911
1927
  .dc-mm-body {
1912
1928
  position: relative;
1913
1929
  width: 100%;
@@ -1933,9 +1949,8 @@ const OVERLAY_CSS = `
1933
1949
  }
1934
1950
  .dc-zoom-tb {
1935
1951
  position: absolute;
1936
- left: 50%;
1952
+ left: 16px;
1937
1953
  bottom: 16px;
1938
- transform: translateX(-50%);
1939
1954
  display: flex;
1940
1955
  align-items: stretch;
1941
1956
  background: var(--maude-chrome-bg-0, #ffffff);
@@ -2106,7 +2121,10 @@ export function DCMiniMap() {
2106
2121
  return (
2107
2122
  <div className="dc-mm" aria-hidden="true">
2108
2123
  <div className="dc-mm-hd">
2109
- WORLD MAP · {world.artboards.length}/{world.artboards.length}
2124
+ <span>World</span>
2125
+ <span className="dc-mm-count">
2126
+ {world.artboards.length} / {world.artboards.length}
2127
+ </span>
2110
2128
  </div>
2111
2129
  <div
2112
2130
  className="dc-mm-body"
@@ -2204,11 +2222,7 @@ export function SpecimenHeader({
2204
2222
  }
2205
2223
 
2206
2224
  /** `<dl class="specimen-meta">` ladder. */
2207
- export function SpecimenMeta({
2208
- entries,
2209
- }: {
2210
- entries: Array<{ label: string; value: ReactNode }>;
2211
- }) {
2225
+ export function SpecimenMeta({ entries }: { entries: Array<{ label: string; value: ReactNode }> }) {
2212
2226
  return (
2213
2227
  <dl className="specimen-meta">
2214
2228
  {entries.map(({ label, value }) => (
@@ -2227,13 +2241,7 @@ export function KbdHint({ children }: { children: ReactNode }) {
2227
2241
  }
2228
2242
 
2229
2243
  /** Inline `var(--name)` value visualiser — small chip + token name. */
2230
- export function TokenChip({
2231
- name,
2232
- swatch,
2233
- }: {
2234
- name: string;
2235
- swatch?: boolean;
2236
- }) {
2244
+ export function TokenChip({ name, swatch }: { name: string; swatch?: boolean }) {
2237
2245
  return (
2238
2246
  <span className="token-chip" data-token={name}>
2239
2247
  {swatch ? (
@@ -2763,7 +2771,7 @@ export function ReducedMotionToggle() {
2763
2771
  }
2764
2772
 
2765
2773
  export {
2774
+ _MotionAnimatePresence as AnimatePresence,
2766
2775
  _motionImpl as motion,
2767
2776
  _useReducedMotion as useReducedMotion,
2768
- _MotionAnimatePresence as AnimatePresence,
2769
2777
  };