@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
package/README.md CHANGED
@@ -129,8 +129,8 @@ The repo is a **pnpm workspace monorepo** with one published npm package (`@1agh
129
129
  | --------- | ------- |
130
130
  | `.` (root) | The single npm publisher — CLI, dev-server entry, plugin templates that ship to npm. |
131
131
  | `site/` | Docs site — Fumadocs + Next.js, deployed to Vercel ([DDR-005](.ai/decisions/DDR-005-docs-site-stack-and-hosting.md)). |
132
- | `plugins/design/dev-server/` | Zero-dep Node dev server + browser client. Bundled output (`dist/`) is the only thing in the npm tarball. |
133
- | `plugins/design/hub/` | Reserved for the v1.1 federated hub (Phase 9). |
132
+ | `apps/studio/` | Zero-dep Node dev server + browser client. Bundled output (`dist/`) is the only thing in the npm tarball. |
133
+ | `apps/hub/` | Reserved for the v1.1 federated hub (Phase 9). |
134
134
 
135
135
  Common scripts at the root:
136
136
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file ai-banner.tsx — yellow "Claude is editing this canvas" banner
3
- * @scope plugins/design/dev-server/ai-banner.tsx
3
+ * @scope apps/studio/ai-banner.tsx
4
4
  * @purpose Mounted by canvas-shell. Subscribes to the inspector WS
5
5
  * `ai-activity` event for the canvas's own file path; shows a
6
6
  * non-modal yellow banner while AI work is in progress and clears
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file annotations-context-toolbar.tsx — Phase 5.1 per-selection toolbar
3
- * @scope plugins/design/dev-server/annotations-context-toolbar.tsx
3
+ * @scope apps/studio/annotations-context-toolbar.tsx
4
4
  * @purpose FigJam-style floating chrome anchored above the currently
5
5
  * selected annotation strokes. Reads `useAnnotationSelection` +
6
6
  * `useStrokesStore`; mutations dispatch through the store so the
@@ -26,6 +26,7 @@ import {
26
26
  type ArrowHead,
27
27
  type ArrowLineType,
28
28
  FILL_PALETTE,
29
+ type ListType,
29
30
  STICKY_PALETTE,
30
31
  STROKE_PALETTE,
31
32
  type Stroke,
@@ -36,27 +37,33 @@ import {
36
37
  IconAlignCenter,
37
38
  IconAlignLeft,
38
39
  IconAlignRight,
39
- IconArrowNone,
40
40
  IconArrowheadCircle,
41
41
  IconArrowheadDiamond,
42
42
  IconArrowheadLine,
43
43
  IconArrowheadTriangle,
44
44
  IconArrowheadTriangleOutline,
45
+ IconArrowNone,
45
46
  IconBold,
46
47
  IconChevronDown,
47
48
  IconCornerPill,
48
49
  IconCornerSoft,
49
50
  IconCornerSquare,
50
51
  IconDash,
52
+ IconItalic,
51
53
  IconLineCurved,
52
54
  IconLineElbow,
53
55
  IconLineStraight,
54
56
  IconLineThick,
55
57
  IconLineThin,
58
+ IconLink,
59
+ IconListBullet,
60
+ IconListOrdered,
56
61
  IconStrike,
57
62
  IconTrash,
63
+ IconUnderline,
58
64
  } from './canvas-icons.tsx';
59
65
  import { useAnnotationSelectionOptional } from './use-annotation-selection.tsx';
66
+ import { isHttpUrl, linkDomain } from './use-canvas-media-drop.tsx';
60
67
 
61
68
  // Phase 24 — arrowhead + line-type option metadata (icon + label per value),
62
69
  // driving the per-end head dropdowns + the line-type dropdown.
@@ -253,6 +260,28 @@ const TOOLBAR_CSS = `
253
260
  background: color-mix(in oklab, #ff5a4d 26%, transparent);
254
261
  color: #ffffff;
255
262
  }
263
+ /* Phase 23 — media (image alt / link url) inline text field inside the dark
264
+ property bar. */
265
+ .dc-annot-ctx-field {
266
+ display: inline-flex;
267
+ align-items: center;
268
+ gap: 6px;
269
+ padding: 0 2px;
270
+ }
271
+ .dc-annot-ctx-field label { color: rgba(255,255,255,0.6); font-size: 11px; }
272
+ .dc-annot-ctx-input {
273
+ width: 220px;
274
+ max-width: 44vw;
275
+ padding: 4px 7px;
276
+ border: 1px solid rgba(255,255,255,0.18);
277
+ border-radius: 6px;
278
+ background: rgba(255,255,255,0.06);
279
+ color: #fff;
280
+ font: inherit;
281
+ font-size: 12px;
282
+ }
283
+ .dc-annot-ctx-input::placeholder { color: rgba(255,255,255,0.4); }
284
+ .dc-annot-ctx-input:focus-visible { outline: 2px solid #ffffff; outline-offset: -1px; }
256
285
  /* Phase 24 — icon dropdown (arrowhead / line-type / text-align). The wrapper
257
286
  anchors the menu directly above the trigger. */
258
287
  .dc-annot-ctx-dd { position: relative; display: inline-flex; }
@@ -422,6 +451,11 @@ export function AnnotationContextToolbar() {
422
451
  // separately below.
423
452
  const allRect = selectedStrokes.every((s) => s.tool === 'rect');
424
453
  const allArrow = selectedStrokes.every((s) => s.tool === 'arrow');
454
+ // Dash now applies to arrows AND every outlined shape (rect / ellipse /
455
+ // polygon) — item 7. Heads + line-type (arrowDir) stay arrow-only.
456
+ const allDashable = selectedStrokes.every(
457
+ (s) => s.tool === 'arrow' || s.tool === 'rect' || s.tool === 'ellipse' || s.tool === 'polygon'
458
+ );
425
459
  return {
426
460
  color: true,
427
461
  fill: allFillable,
@@ -429,7 +463,7 @@ export function AnnotationContextToolbar() {
429
463
  fontSize: fontSizeApplicable,
430
464
  cornerRadius: allRect,
431
465
  arrowDir: allArrow,
432
- dash: allArrow,
466
+ dash: allDashable,
433
467
  };
434
468
  }, [selectedStrokes]);
435
469
 
@@ -545,6 +579,40 @@ export function AnnotationContextToolbar() {
545
579
  },
546
580
  [store, selectedStrokes]
547
581
  );
582
+ // Italic / underline / list (items 4b + 4c) — same text + sticky fan-out.
583
+ const setItalic = useCallback(
584
+ (italic: boolean) => {
585
+ if (!store) return;
586
+ for (const s of selectedStrokes) {
587
+ if (s.tool === 'text' || s.tool === 'sticky') {
588
+ store.updateStroke(s.id, { italic } as Partial<Stroke>);
589
+ }
590
+ }
591
+ },
592
+ [store, selectedStrokes]
593
+ );
594
+ const setUnderline = useCallback(
595
+ (underline: boolean) => {
596
+ if (!store) return;
597
+ for (const s of selectedStrokes) {
598
+ if (s.tool === 'text' || s.tool === 'sticky') {
599
+ store.updateStroke(s.id, { underline } as Partial<Stroke>);
600
+ }
601
+ }
602
+ },
603
+ [store, selectedStrokes]
604
+ );
605
+ const setListType = useCallback(
606
+ (listType: ListType | undefined) => {
607
+ if (!store) return;
608
+ for (const s of selectedStrokes) {
609
+ if (s.tool === 'text' || s.tool === 'sticky') {
610
+ store.updateStroke(s.id, { listType } as Partial<Stroke>);
611
+ }
612
+ }
613
+ },
614
+ [store, selectedStrokes]
615
+ );
548
616
  const setAlign = useCallback(
549
617
  (align: TextAlign) => {
550
618
  if (!store) return;
@@ -597,12 +665,17 @@ export function AnnotationContextToolbar() {
597
665
  },
598
666
  [store, selectedStrokes]
599
667
  );
600
- // Phase 21 — arrow dash toggle.
668
+ // Dash toggle — arrow + rect / ellipse / polygon (item 7).
601
669
  const setDashed = useCallback(
602
670
  (dashed: boolean) => {
603
671
  if (!store) return;
604
672
  for (const s of selectedStrokes) {
605
- if (s.tool === 'arrow') {
673
+ if (
674
+ s.tool === 'arrow' ||
675
+ s.tool === 'rect' ||
676
+ s.tool === 'ellipse' ||
677
+ s.tool === 'polygon'
678
+ ) {
606
679
  store.updateStroke(s.id, { dashed } as Partial<Stroke>);
607
680
  }
608
681
  }
@@ -617,6 +690,145 @@ export function AnnotationContextToolbar() {
617
690
 
618
691
  if (!annotSel || !store || selectedStrokes.length === 0) return null;
619
692
 
693
+ // ── Phase 23 — dedicated panel for a single image / link selection. ─────────
694
+ // Image / link carry no color / fill / thickness, so the generic swatch bar is
695
+ // meaningless for them; render a focused panel instead (image alt for a11y;
696
+ // link url/title + Open). Uncontrolled fields keyed by id commit ONCE on
697
+ // blur/Enter (no per-keystroke undo spam). Multi-select / mixed selections
698
+ // fall through to the generic bar below.
699
+ const soleMedia =
700
+ selectedStrokes.length === 1 &&
701
+ (selectedStrokes[0]?.tool === 'image' || selectedStrokes[0]?.tool === 'link')
702
+ ? selectedStrokes[0]
703
+ : null;
704
+ if (soleMedia?.tool === 'image') {
705
+ const img = soleMedia;
706
+ const commitAlt = (value: string) => {
707
+ const next = value.trim();
708
+ if ((img.alt ?? '') !== next) {
709
+ store.updateStroke(img.id, { alt: next || undefined } as Partial<Stroke>);
710
+ }
711
+ };
712
+ return (
713
+ <div
714
+ ref={ref}
715
+ className="dc-annot-ctx"
716
+ role="toolbar"
717
+ aria-label="Image properties"
718
+ style={{ display: 'flex', top: -9999, left: -9999 }}
719
+ >
720
+ <div className="dc-annot-ctx-field">
721
+ <label htmlFor="dc-img-alt">Alt</label>
722
+ <input
723
+ id="dc-img-alt"
724
+ key={img.id}
725
+ className="dc-annot-ctx-input"
726
+ type="text"
727
+ defaultValue={img.alt ?? ''}
728
+ placeholder="Describe this image (alt text)"
729
+ aria-label="Image alt text"
730
+ onBlur={(e) => commitAlt(e.currentTarget.value)}
731
+ onKeyDown={(e) => {
732
+ if (e.key === 'Enter') {
733
+ e.preventDefault();
734
+ e.currentTarget.blur();
735
+ }
736
+ }}
737
+ />
738
+ </div>
739
+ <div className="dc-annot-ctx-sep" />
740
+ <button
741
+ type="button"
742
+ className="dc-annot-ctx-ibtn dc-annot-ctx-ibtn--danger"
743
+ aria-label="Delete image"
744
+ title="Delete"
745
+ onClick={remove}
746
+ >
747
+ <IconTrash />
748
+ </button>
749
+ </div>
750
+ );
751
+ }
752
+ if (soleMedia?.tool === 'link') {
753
+ const link = soleMedia;
754
+ const commitUrl = (value: string) => {
755
+ const next = value.trim();
756
+ if (isHttpUrl(next) && next !== link.url) {
757
+ store.updateStroke(link.id, { url: next, domain: linkDomain(next) } as Partial<Stroke>);
758
+ }
759
+ };
760
+ const commitTitle = (value: string) => {
761
+ const next = value.trim();
762
+ if (next !== link.title) store.updateStroke(link.id, { title: next } as Partial<Stroke>);
763
+ };
764
+ const openLink = () => {
765
+ if (isHttpUrl(link.url)) window.open(link.url, '_blank', 'noopener,noreferrer');
766
+ };
767
+ return (
768
+ <div
769
+ ref={ref}
770
+ className="dc-annot-ctx"
771
+ role="toolbar"
772
+ aria-label="Link properties"
773
+ style={{ display: 'flex', top: -9999, left: -9999 }}
774
+ >
775
+ <button
776
+ type="button"
777
+ className="dc-annot-ctx-ibtn"
778
+ aria-label={`Open ${link.domain || 'link'} in a new tab`}
779
+ title="Open link"
780
+ onClick={openLink}
781
+ >
782
+ <IconLink />
783
+ </button>
784
+ <div className="dc-annot-ctx-sep" />
785
+ <div className="dc-annot-ctx-field">
786
+ <input
787
+ key={`${link.id}-url`}
788
+ className="dc-annot-ctx-input"
789
+ type="url"
790
+ inputMode="url"
791
+ defaultValue={link.url}
792
+ placeholder="https://…"
793
+ aria-label="Link URL"
794
+ onBlur={(e) => commitUrl(e.currentTarget.value)}
795
+ onKeyDown={(e) => {
796
+ if (e.key === 'Enter') {
797
+ e.preventDefault();
798
+ e.currentTarget.blur();
799
+ }
800
+ }}
801
+ />
802
+ <input
803
+ key={`${link.id}-title`}
804
+ className="dc-annot-ctx-input"
805
+ type="text"
806
+ defaultValue={link.title}
807
+ placeholder="Title"
808
+ aria-label="Link title"
809
+ onBlur={(e) => commitTitle(e.currentTarget.value)}
810
+ onKeyDown={(e) => {
811
+ if (e.key === 'Enter') {
812
+ e.preventDefault();
813
+ e.currentTarget.blur();
814
+ }
815
+ }}
816
+ />
817
+ </div>
818
+ <div className="dc-annot-ctx-sep" />
819
+ <button
820
+ type="button"
821
+ className="dc-annot-ctx-ibtn dc-annot-ctx-ibtn--danger"
822
+ aria-label="Delete link"
823
+ title="Delete"
824
+ onClick={remove}
825
+ >
826
+ <IconTrash />
827
+ </button>
828
+ </div>
829
+ );
830
+ }
831
+
620
832
  // Active values for swatch highlighting — when uniform across selection.
621
833
  const uniqColor = uniformValue(selectedStrokes.map((s) => s.color));
622
834
  const uniqFill = caps.fill
@@ -659,6 +871,29 @@ export function AnnotationContextToolbar() {
659
871
  )
660
872
  )
661
873
  : undefined;
874
+ const uniqItalic = caps.fontSize
875
+ ? uniformValue(
876
+ selectedStrokes.map((s) =>
877
+ s.tool === 'text' || s.tool === 'sticky' ? !!s.italic : undefined
878
+ )
879
+ )
880
+ : undefined;
881
+ const uniqUnderline = caps.fontSize
882
+ ? uniformValue(
883
+ selectedStrokes.map((s) =>
884
+ s.tool === 'text' || s.tool === 'sticky' ? !!s.underline : undefined
885
+ )
886
+ )
887
+ : undefined;
888
+ // List type — undefined when no list (the active-state for the two list
889
+ // toggles reads off this; both off ⇒ no list).
890
+ const uniqListType = caps.fontSize
891
+ ? uniformValue(
892
+ selectedStrokes.map((s) =>
893
+ s.tool === 'text' || s.tool === 'sticky' ? (s.listType ?? 'none') : undefined
894
+ )
895
+ )
896
+ : undefined;
662
897
  const uniqAlign = caps.fontSize
663
898
  ? uniformValue(
664
899
  selectedStrokes.map((s) => {
@@ -699,7 +934,11 @@ export function AnnotationContextToolbar() {
699
934
  : undefined;
700
935
  const uniqDashed = caps.dash
701
936
  ? uniformValue(
702
- selectedStrokes.map((s) => (s.tool === 'arrow' ? (s.dashed ?? false) : undefined))
937
+ selectedStrokes.map((s) =>
938
+ s.tool === 'arrow' || s.tool === 'rect' || s.tool === 'ellipse' || s.tool === 'polygon'
939
+ ? (s.dashed ?? false)
940
+ : undefined
941
+ )
703
942
  )
704
943
  : undefined;
705
944
 
@@ -817,6 +1056,16 @@ export function AnnotationContextToolbar() {
817
1056
  >
818
1057
  <IconBold />
819
1058
  </button>
1059
+ <button
1060
+ type="button"
1061
+ className="dc-annot-ctx-ibtn"
1062
+ aria-label="Italic"
1063
+ aria-pressed={uniqItalic === true}
1064
+ title="Italic"
1065
+ onClick={() => setItalic(!(uniqItalic === true))}
1066
+ >
1067
+ <IconItalic />
1068
+ </button>
820
1069
  <button
821
1070
  type="button"
822
1071
  className="dc-annot-ctx-ibtn"
@@ -827,6 +1076,16 @@ export function AnnotationContextToolbar() {
827
1076
  >
828
1077
  <IconStrike />
829
1078
  </button>
1079
+ <button
1080
+ type="button"
1081
+ className="dc-annot-ctx-ibtn"
1082
+ aria-label="Underline"
1083
+ aria-pressed={uniqUnderline === true}
1084
+ title="Underline"
1085
+ onClick={() => setUnderline(!(uniqUnderline === true))}
1086
+ >
1087
+ <IconUnderline />
1088
+ </button>
830
1089
  <IconDropdown
831
1090
  ariaLabel="Text alignment"
832
1091
  value={uniqAlign ?? 'left'}
@@ -837,6 +1096,27 @@ export function AnnotationContextToolbar() {
837
1096
  }}
838
1097
  onPick={(v) => setAlign(v as TextAlign)}
839
1098
  />
1099
+ {/* List style — two mutually-exclusive toggles; click-again clears. */}
1100
+ <button
1101
+ type="button"
1102
+ className="dc-annot-ctx-ibtn"
1103
+ aria-label="Bulleted list"
1104
+ aria-pressed={uniqListType === 'bullet'}
1105
+ title="Bulleted list"
1106
+ onClick={() => setListType(uniqListType === 'bullet' ? undefined : 'bullet')}
1107
+ >
1108
+ <IconListBullet />
1109
+ </button>
1110
+ <button
1111
+ type="button"
1112
+ className="dc-annot-ctx-ibtn"
1113
+ aria-label="Numbered list"
1114
+ aria-pressed={uniqListType === 'number'}
1115
+ title="Numbered list"
1116
+ onClick={() => setListType(uniqListType === 'number' ? undefined : 'number')}
1117
+ >
1118
+ <IconListOrdered />
1119
+ </button>
840
1120
  </>
841
1121
  ) : null}
842
1122
  {caps.cornerRadius ? (