@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,191 @@
1
+ // overlay.jsx — hand-rolled guided-tour engine (zero runtime dep, DDR-B).
2
+ //
3
+ // One <TourOverlay steps={[…]} open onClose onComplete/> drives both the
4
+ // per-feature spotlight tours (a What's New entry's `tour[]`) and the evergreen
5
+ // usage tour. A step = { target (CSS selector / [data-tour] anchor), title,
6
+ // body, placement? }. A step whose target can't be resolved still shows, just
7
+ // centered with no spotlight — the tour never dead-ends on a missing element.
8
+ //
9
+ // A11y: role="dialog" + aria-modal, focus moves to the primary button on each
10
+ // step and is trapped within the card, focus is restored on close, Esc skips,
11
+ // ←/→ navigate. prefers-reduced-motion disables the spotlight transition.
12
+
13
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
14
+
15
+ function getRect(target) {
16
+ if (typeof document === 'undefined' || !target) return null;
17
+ try {
18
+ const el = document.querySelector(target);
19
+ if (!el) return null;
20
+ const r = el.getBoundingClientRect();
21
+ if (r.width === 0 && r.height === 0) return null;
22
+ return r;
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ const CARD_W = 320;
29
+ const CARD_H_EST = 168;
30
+
31
+ function computeCardStyle(rect) {
32
+ if (typeof window === 'undefined' || !rect) {
33
+ return { top: '50%', left: '50%', transform: 'translate(-50%, -50%)', width: CARD_W };
34
+ }
35
+ const vw = window.innerWidth;
36
+ const vh = window.innerHeight;
37
+ const roomBelow = vh - rect.bottom;
38
+ const top =
39
+ roomBelow > CARD_H_EST + 24 ? rect.bottom + 12 : Math.max(12, rect.top - CARD_H_EST - 12);
40
+ const left = Math.min(Math.max(12, rect.left), vw - CARD_W - 12);
41
+ return { top, left, width: CARD_W };
42
+ }
43
+
44
+ export function TourOverlay({ steps, open, onClose, onComplete }) {
45
+ const [i, setI] = useState(0);
46
+ const [rect, setRect] = useState(null);
47
+ const cardRef = useRef(null);
48
+ const prevFocus = useRef(null);
49
+
50
+ const measure = useCallback(() => {
51
+ const step = steps[i];
52
+ setRect(step ? getRect(step.target) : null);
53
+ }, [steps, i]);
54
+
55
+ // Reset to the first step whenever a tour (re)opens.
56
+ useEffect(() => {
57
+ if (open) setI(0);
58
+ }, [open]);
59
+
60
+ useLayoutEffect(() => {
61
+ if (open) measure();
62
+ }, [open, measure]);
63
+
64
+ // Keep the spotlight glued to its target through scroll/resize; restore focus.
65
+ useEffect(() => {
66
+ if (!open) return;
67
+ prevFocus.current = document.activeElement;
68
+ const onMove = () => measure();
69
+ window.addEventListener('resize', onMove);
70
+ window.addEventListener('scroll', onMove, true);
71
+ return () => {
72
+ window.removeEventListener('resize', onMove);
73
+ window.removeEventListener('scroll', onMove, true);
74
+ try {
75
+ prevFocus.current?.focus?.();
76
+ } catch {}
77
+ };
78
+ }, [open, measure]);
79
+
80
+ const last = i >= steps.length - 1;
81
+ const next = useCallback(() => {
82
+ if (last) {
83
+ onComplete?.();
84
+ onClose?.();
85
+ } else {
86
+ setI((n) => Math.min(n + 1, steps.length - 1));
87
+ }
88
+ }, [last, onComplete, onClose, steps.length]);
89
+ const back = useCallback(() => setI((n) => Math.max(0, n - 1)), []);
90
+
91
+ // Keyboard: Esc skips, ←/→ navigate, Tab is trapped within the card buttons.
92
+ useEffect(() => {
93
+ if (!open) return;
94
+ function onKey(e) {
95
+ if (e.key === 'Escape') {
96
+ e.preventDefault();
97
+ onClose?.();
98
+ } else if (e.key === 'ArrowRight') {
99
+ e.preventDefault();
100
+ next();
101
+ } else if (e.key === 'ArrowLeft') {
102
+ e.preventDefault();
103
+ back();
104
+ } else if (e.key === 'Tab') {
105
+ const card = cardRef.current;
106
+ if (!card) return;
107
+ const f = card.querySelectorAll('button');
108
+ if (!f.length) return;
109
+ const first = f[0];
110
+ const lastEl = f[f.length - 1];
111
+ if (e.shiftKey && document.activeElement === first) {
112
+ e.preventDefault();
113
+ lastEl.focus();
114
+ } else if (!e.shiftKey && document.activeElement === lastEl) {
115
+ e.preventDefault();
116
+ first.focus();
117
+ }
118
+ }
119
+ }
120
+ window.addEventListener('keydown', onKey, true);
121
+ return () => window.removeEventListener('keydown', onKey, true);
122
+ }, [open, next, back, onClose]);
123
+
124
+ // Move focus to the primary action on each step (accessible dialog behavior).
125
+ useEffect(() => {
126
+ if (!open) return;
127
+ const t = setTimeout(() => {
128
+ const primary = cardRef.current?.querySelector('[data-tour-primary]');
129
+ try {
130
+ primary?.focus();
131
+ } catch {}
132
+ }, 0);
133
+ return () => clearTimeout(t);
134
+ }, [open, i]);
135
+
136
+ if (!open || !steps.length) return null;
137
+ const step = steps[i];
138
+ const pad = 6;
139
+ const spot = rect
140
+ ? {
141
+ top: rect.top - pad,
142
+ left: rect.left - pad,
143
+ width: rect.width + pad * 2,
144
+ height: rect.height + pad * 2,
145
+ }
146
+ : null;
147
+
148
+ return (
149
+ <div className="mdcc-tour" role="presentation">
150
+ {spot ? (
151
+ <div className="mdcc-tour__spot" style={spot} aria-hidden="true" />
152
+ ) : (
153
+ <div className="mdcc-tour__scrim" aria-hidden="true" />
154
+ )}
155
+ <div
156
+ className="mdcc-tour__card"
157
+ ref={cardRef}
158
+ role="dialog"
159
+ aria-modal="true"
160
+ aria-labelledby="mdcc-tour-title"
161
+ aria-describedby="mdcc-tour-body"
162
+ style={computeCardStyle(rect)}
163
+ >
164
+ <div className="mdcc-tour__step">
165
+ {i + 1} / {steps.length}
166
+ </div>
167
+ <div className="mdcc-tour__title" id="mdcc-tour-title">
168
+ {step.title}
169
+ </div>
170
+ <div className="mdcc-tour__body" id="mdcc-tour-body">
171
+ {step.body}
172
+ </div>
173
+ <div className="mdcc-tour__actions">
174
+ <button type="button" className="mdcc-tour__skip" onClick={onClose}>
175
+ Skip
176
+ </button>
177
+ <div className="mdcc-tour__nav">
178
+ {i > 0 && (
179
+ <button type="button" className="mdcc-tour__back" onClick={back}>
180
+ Back
181
+ </button>
182
+ )}
183
+ <button type="button" className="mdcc-tour__next" data-tour-primary onClick={next}>
184
+ {last ? 'Done' : 'Next'}
185
+ </button>
186
+ </div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ );
191
+ }
@@ -0,0 +1,35 @@
1
+ // usage-tour.js — the evergreen "how the Maude UI works" walkthrough.
2
+ //
3
+ // Targets stable elements that exist at first load (no canvas open required):
4
+ // the sidebar, the empty viewport, the menus, the What's New badge, and Help.
5
+ // Steps whose target is missing are shown centered by the overlay, so this is
6
+ // resilient to chrome changes. Reached from Help → "Take the tour" and offered
7
+ // once on first run.
8
+
9
+ export const USAGE_TOUR = [
10
+ {
11
+ target: '.sidebar',
12
+ title: 'Your canvases live here',
13
+ body: 'Every mock in the project shows up in this tree. Click one to open it in a tab — or use “+ board” to spin up a blank brief-board, no command needed.',
14
+ },
15
+ {
16
+ target: '.viewport',
17
+ title: 'The canvas',
18
+ body: 'Open a canvas, then ⌘-hover to preview the element under your cursor and ⌘-click to select it. Right-click for Copy CSS / Fit / Reset.',
19
+ },
20
+ {
21
+ target: '.mb-menus',
22
+ title: 'Menus & tools',
23
+ body: 'View toggles panels (tree, comments, annotations); Selection and Tools act on the active canvas. Press ? for every shortcut.',
24
+ },
25
+ {
26
+ target: "[data-tour='whatsnew']",
27
+ title: 'What’s new',
28
+ body: 'New features land here. Click the ✦ badge any time to catch up on what shipped.',
29
+ },
30
+ {
31
+ target: "[data-tour='help']",
32
+ title: 'Help is one key away',
33
+ body: 'Press ? for the full keyboard cheat-sheet — and you can restart this tour from the Help menu whenever you like.',
34
+ },
35
+ ];
@@ -0,0 +1,52 @@
1
+ // whats-new-seen.js — pure, browser-safe "what have I already seen?" logic.
2
+ //
3
+ // No React, no DOM, no node imports — so it's bundled into the client AND
4
+ // imported directly by bun:test (test/whats-new.test.ts). Keep it that way.
5
+
6
+ /** Parse a semver-ish string into a [major, minor, patch] triple, or null. */
7
+ export function parseVer(v) {
8
+ if (typeof v !== 'string') return null;
9
+ const m = v.match(/^(\d+)\.(\d+)\.(\d+)/);
10
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
11
+ }
12
+
13
+ /**
14
+ * Is version `a` strictly newer than `b`?
15
+ * - Unparseable `a` (e.g. "dev") → not newer (false).
16
+ * - Unparseable `b` but parseable `a` → newer (true): a real release outranks
17
+ * a non-version "seen" marker, so the entry surfaces.
18
+ */
19
+ export function verGt(a, b) {
20
+ const pa = parseVer(a);
21
+ const pb = parseVer(b);
22
+ if (!pa) return false;
23
+ if (!pb) return true;
24
+ for (let i = 0; i < 3; i++) {
25
+ if (pa[i] !== pb[i]) return pa[i] > pb[i];
26
+ }
27
+ return false;
28
+ }
29
+
30
+ /**
31
+ * Entries the user hasn't seen yet, given the version they last acknowledged.
32
+ * A pending entry (version == null) is always unseen until acknowledged.
33
+ */
34
+ export function computeUnseen(entries, seenVersion) {
35
+ if (!Array.isArray(entries)) return [];
36
+ return entries.filter((e) => e && (e.version == null || verGt(e.version, seenVersion)));
37
+ }
38
+
39
+ /**
40
+ * The version to persist as "seen" after the user reads the panel — the highest
41
+ * of the current feed version and every entry's version. Stamping this clears
42
+ * the unseen set (pending entries excepted — they have no version to outrank).
43
+ */
44
+ export function bestSeenVersion(entries, currentVersion) {
45
+ let best = currentVersion;
46
+ if (Array.isArray(entries)) {
47
+ for (const e of entries) {
48
+ if (e && e.version && verGt(e.version, best)) best = e.version;
49
+ }
50
+ }
51
+ return best;
52
+ }
@@ -0,0 +1,250 @@
1
+ // whats-new.jsx — Maude UI "What's New" surfaces.
2
+ //
3
+ // useWhatsNew(version) → headless handle (fetch + seen-state + open-state)
4
+ // <WhatsNewBadge> → menubar entry point (✦ + unseen-count dot)
5
+ // <WhatsNewToast> → first-run notice (bottom-left, mirrors ai-banner.tsx)
6
+ // <WhatsNewPanel> → list of entries (reuses the help-modal backdrop)
7
+ //
8
+ // Styling lives in client/styles/4-components.css (.mdcc-wn-*). Spotlight tours
9
+ // (entry.tour[]) land in Phase 3 — the panel/toast leave a hook for them.
10
+
11
+ import { useCallback, useEffect, useState } from 'react';
12
+ import { bestSeenVersion, computeUnseen } from './whats-new-seen.js';
13
+
14
+ const WN_SEEN = 'mdcc-whatsnew-seen';
15
+ const WN_TOAST = 'mdcc-whatsnew-toast-dismissed';
16
+
17
+ // learnMore renders as <a href> in the privileged main origin. Only bind an
18
+ // http(s) URL — belt-and-suspenders next to React's built-in URL sanitizer and
19
+ // the schema's pattern (security review, defense-in-depth).
20
+ function isSafeHref(url) {
21
+ return typeof url === 'string' && /^https?:\/\//i.test(url);
22
+ }
23
+
24
+ function readSeen(currentVersion) {
25
+ try {
26
+ const v = localStorage.getItem(WN_SEEN);
27
+ if (v) return v;
28
+ // First ever run: acknowledge the current version silently so a brand-new
29
+ // user isn't greeted with the entire backlog as "new". Only true upgrades
30
+ // (and pending dev entries) surface after this.
31
+ localStorage.setItem(WN_SEEN, currentVersion);
32
+ } catch {}
33
+ return currentVersion;
34
+ }
35
+
36
+ function readToastDismissed() {
37
+ try {
38
+ return localStorage.getItem(WN_TOAST);
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+
44
+ export function useWhatsNew(currentVersion) {
45
+ const [entries, setEntries] = useState([]);
46
+ const [feedVersion, setFeedVersion] = useState(currentVersion);
47
+ const [seenVersion, setSeenVersion] = useState(() => readSeen(currentVersion));
48
+ const [toastDismissed, setToastDismissed] = useState(() => readToastDismissed());
49
+ const [panelOpen, setPanelOpen] = useState(false);
50
+
51
+ useEffect(() => {
52
+ let cancelled = false;
53
+ fetch('/_api/whats-new')
54
+ .then((r) => r.json())
55
+ .then((j) => {
56
+ if (cancelled) return;
57
+ setEntries(Array.isArray(j?.entries) ? j.entries : []);
58
+ if (typeof j?.version === 'string') setFeedVersion(j.version);
59
+ })
60
+ .catch(() => {
61
+ /* offline / restart — no banner */
62
+ });
63
+ return () => {
64
+ cancelled = true;
65
+ };
66
+ }, []);
67
+
68
+ const unseen = computeUnseen(entries, seenVersion);
69
+ const showToast = unseen.length > 0 && toastDismissed !== feedVersion && !panelOpen;
70
+ const toastEntry = unseen[0] ?? null;
71
+
72
+ const markAllSeen = useCallback(() => {
73
+ const next = bestSeenVersion(entries, feedVersion);
74
+ setSeenVersion(next);
75
+ setToastDismissed(feedVersion);
76
+ try {
77
+ localStorage.setItem(WN_SEEN, next);
78
+ localStorage.setItem(WN_TOAST, feedVersion);
79
+ } catch {}
80
+ }, [entries, feedVersion]);
81
+
82
+ const dismissToast = useCallback(() => {
83
+ setToastDismissed(feedVersion);
84
+ try {
85
+ localStorage.setItem(WN_TOAST, feedVersion);
86
+ } catch {}
87
+ }, [feedVersion]);
88
+
89
+ const openPanel = useCallback(() => setPanelOpen(true), []);
90
+ const closePanel = useCallback(() => {
91
+ setPanelOpen(false);
92
+ markAllSeen();
93
+ }, [markAllSeen]);
94
+
95
+ return {
96
+ entries,
97
+ unseen,
98
+ feedVersion,
99
+ panelOpen,
100
+ openPanel,
101
+ closePanel,
102
+ showToast,
103
+ toastEntry,
104
+ dismissToast,
105
+ markAllSeen,
106
+ };
107
+ }
108
+
109
+ export function WhatsNewBadge({ count = 0, onOpen }) {
110
+ return (
111
+ <button
112
+ type="button"
113
+ className="mdcc-wn-badge"
114
+ data-tour="whatsnew"
115
+ onClick={onOpen}
116
+ title="What's new"
117
+ aria-label={count > 0 ? `What's new — ${count} new` : "What's new"}
118
+ >
119
+ <span aria-hidden="true">✦</span>
120
+ <span className="mdcc-wn-badge__label">New</span>
121
+ {count > 0 && (
122
+ <span className="mdcc-wn-badge__dot" aria-hidden="true">
123
+ {count}
124
+ </span>
125
+ )}
126
+ </button>
127
+ );
128
+ }
129
+
130
+ export function WhatsNewToast({ wn }) {
131
+ if (!wn.showToast || !wn.toastEntry) return null;
132
+ const e = wn.toastEntry;
133
+ const total = wn.unseen.length;
134
+ // Plan C P6 — restyled to the maude `.st-toast` family (was `mdcc-wn-toast`),
135
+ // matching `.design/ui/Studio.tsx` AB-D. Behavior unchanged.
136
+ return (
137
+ <div className="st-toast" role="status" aria-live="polite">
138
+ <button
139
+ type="button"
140
+ className="st-toast-close"
141
+ aria-label="Dismiss"
142
+ onClick={wn.dismissToast}
143
+ >
144
+ ×
145
+ </button>
146
+ <div className="st-toast-hd">
147
+ <span aria-hidden="true">✦</span>
148
+ What's new{e.version ? ` · v${e.version}` : ''}
149
+ </div>
150
+ <div className="st-toast-title">{e.title}</div>
151
+ <div className="st-toast-txt">{e.summary}</div>
152
+ <div className="st-toast-actions">
153
+ <button type="button" className="btn btn--primary btn--sm" onClick={wn.openPanel}>
154
+ {total > 1 ? `See all (${total})` : 'Details'}
155
+ </button>
156
+ <button type="button" className="btn btn--ghost btn--sm" onClick={wn.dismissToast}>
157
+ Dismiss
158
+ </button>
159
+ </div>
160
+ </div>
161
+ );
162
+ }
163
+
164
+ export function WhatsNewPanel({ wn, onStartTour }) {
165
+ const { panelOpen, closePanel } = wn;
166
+ useEffect(() => {
167
+ if (!panelOpen) return;
168
+ function onKey(e) {
169
+ if (e.key === 'Escape') closePanel();
170
+ }
171
+ window.addEventListener('keydown', onKey);
172
+ return () => window.removeEventListener('keydown', onKey);
173
+ }, [panelOpen, closePanel]);
174
+
175
+ if (!panelOpen) return null;
176
+ const unseenIds = new Set(wn.unseen.map((e) => e.id));
177
+ return (
178
+ <div
179
+ className="help-modal-backdrop"
180
+ role="presentation"
181
+ onMouseDown={(e) => {
182
+ if (e.target === e.currentTarget) closePanel();
183
+ }}
184
+ >
185
+ <div
186
+ className="mdcc-wn-panel"
187
+ role="dialog"
188
+ aria-modal="true"
189
+ aria-labelledby="mdcc-wn-title"
190
+ >
191
+ <header className="help-modal-hd">
192
+ <span className="title" id="mdcc-wn-title">
193
+ ✦ What’s new in maude
194
+ </span>
195
+ <button
196
+ type="button"
197
+ className="help-modal-close"
198
+ aria-label="Close (Esc)"
199
+ onClick={closePanel}
200
+ >
201
+ ×
202
+ </button>
203
+ </header>
204
+ <div className="mdcc-wn-panel__body">
205
+ {wn.entries.length === 0 ? (
206
+ <p className="mdcc-wn-empty">Nothing new yet.</p>
207
+ ) : (
208
+ <ul className="mdcc-wn-list">
209
+ {wn.entries.map((e) => (
210
+ <li
211
+ key={e.id}
212
+ className={'mdcc-wn-item' + (unseenIds.has(e.id) ? ' is-unseen' : '')}
213
+ >
214
+ <div className="mdcc-wn-item__hd">
215
+ <span className={'mdcc-wn-kind mdcc-wn-kind--' + e.kind}>{e.kind}</span>
216
+ <span className="mdcc-wn-item__title">{e.title}</span>
217
+ <span className="mdcc-wn-item__ver">{e.version ? `v${e.version}` : 'next'}</span>
218
+ </div>
219
+ <p className="mdcc-wn-item__summary">{e.summary}</p>
220
+ {isSafeHref(e.learnMore) && (
221
+ <a
222
+ className="mdcc-wn-item__more"
223
+ href={e.learnMore}
224
+ target="_blank"
225
+ rel="noreferrer"
226
+ >
227
+ Learn more →
228
+ </a>
229
+ )}
230
+ {onStartTour && Array.isArray(e.tour) && e.tour.length > 0 && (
231
+ <button
232
+ type="button"
233
+ className="mdcc-wn-item__tour"
234
+ onClick={() => {
235
+ closePanel();
236
+ onStartTour(e.tour);
237
+ }}
238
+ >
239
+ ▶ Take tour
240
+ </button>
241
+ )}
242
+ </li>
243
+ ))}
244
+ </ul>
245
+ )}
246
+ </div>
247
+ </div>
248
+ </div>
249
+ );
250
+ }
@@ -7,13 +7,13 @@ import path from 'node:path';
7
7
  import type { Api } from '../api.ts';
8
8
  import type { Context } from '../context.ts';
9
9
 
10
- import { Y_TYPES, createPersistence } from './persistence.ts';
11
- import { type Registry, createRegistry } from './registry.ts';
10
+ import { createPersistence, Y_TYPES } from './persistence.ts';
11
+ import { createRegistry, type Registry } from './registry.ts';
12
12
 
13
- export { Y_TYPES };
13
+ export type { CollabConn } from './protocol.ts';
14
14
  export type { Registry } from './registry.ts';
15
15
  export type { Room, RoomConn } from './room.ts';
16
- export type { CollabConn } from './protocol.ts';
16
+ export { Y_TYPES };
17
17
 
18
18
  export interface Collab {
19
19
  registry: Registry;
@@ -8,7 +8,7 @@ import * as Y from 'yjs';
8
8
 
9
9
  import type { Api } from '../api.ts';
10
10
  import type { Context } from '../context.ts';
11
- import { type RoomCallbacks, ensureStateDir } from './room.ts';
11
+ import { ensureStateDir, type RoomCallbacks } from './room.ts';
12
12
 
13
13
  /**
14
14
  * Y.Doc shared-type names. Frozen on Task 1 so client + server agree even
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file commands/annotation-strokes-command.ts — undo entry for annotation
3
3
  * stroke add / erase / batch-translate.
4
- * @scope plugins/design/dev-server/commands/annotation-strokes-command.ts
4
+ * @scope apps/studio/commands/annotation-strokes-command.ts
5
5
  * @purpose Records a `Stroke[]` pair (before/after) and routes both
6
6
  * directions through a single `putFn`. The server endpoint is
7
7
  * `PUT /_api/annotations` which replaces the entire SVG; we
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file commands/equal-spacing-command.ts — undo label helpers for
3
3
  * equal-spacing / align gestures.
4
- * @scope plugins/design/dev-server/commands/equal-spacing-command.ts
4
+ * @scope apps/studio/commands/equal-spacing-command.ts
5
5
  * @purpose Distribute + align both call `dragBus.commitPositions(moved)`,
6
6
  * which wraps the move in a generic MoveArtboardsCommand. Per
7
7
  * DDR-050 the underlying command type is shared (the inverse
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file commands/move-artboards-command.ts — undo entry for artboard moves
3
- * @scope plugins/design/dev-server/commands/move-artboards-command.ts
3
+ * @scope apps/studio/commands/move-artboards-command.ts
4
4
  * @purpose Reversible record of an artboard-layout PATCH. Pairs the full
5
5
  * `before` and `after` layout snapshots with an injected
6
6
  * `patchFn` (in production, `applyArtboardLayout`; in tests, a