@1agh/maude 0.28.1 → 0.30.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.
- package/README.md +3 -3
- package/{plugins/design/dev-server → apps/studio}/ai-banner.tsx +1 -2
- package/apps/studio/annotations-align.ts +149 -0
- package/apps/studio/annotations-bindings.ts +197 -0
- package/{plugins/design/dev-server → apps/studio}/annotations-context-toolbar.tsx +681 -151
- package/apps/studio/annotations-groups.ts +270 -0
- package/apps/studio/annotations-layer.tsx +4537 -0
- package/apps/studio/annotations-model.ts +2077 -0
- package/apps/studio/annotations-snap.ts +125 -0
- package/{plugins/design/dev-server → apps/studio}/api.ts +616 -70
- package/{plugins/design/dev-server → apps/studio}/artboard-activity-overlay.tsx +1 -1
- package/{plugins/design/dev-server → apps/studio}/artboard-marquee.tsx +1 -1
- package/apps/studio/bin/_motion-sample-playwright.mjs +129 -0
- package/{plugins/design/dev-server → apps/studio}/bin/_png-playwright.mjs +1 -1
- package/apps/studio/bin/annotate.mjs +732 -0
- package/apps/studio/bin/annotate.sh +17 -0
- package/{plugins/design/dev-server → apps/studio}/bin/canvas-edit.sh +1 -1
- package/{plugins/design/dev-server → apps/studio}/bin/draw-proof.sh +37 -2
- package/{plugins/design/dev-server → apps/studio}/bin/preflight.sh +1 -1
- package/apps/studio/bin/read-annotations.mjs +573 -0
- package/apps/studio/bin/read-annotations.sh +11 -0
- package/{plugins/design/dev-server → apps/studio}/bin/runtime-health.sh +1 -1
- package/{plugins/design/dev-server → apps/studio}/bin/screenshot.sh +62 -2
- package/{plugins/design/dev-server → apps/studio}/bin/server-up.sh +9 -3
- package/apps/studio/bin/to-lottie-verify.html +68 -0
- package/apps/studio/bin/to-lottie.sh +128 -0
- package/{plugins/design/dev-server → apps/studio}/build.ts +6 -4
- package/{plugins/design/dev-server → apps/studio}/canvas-arrowheads.ts +79 -10
- package/{plugins/design/dev-server → apps/studio}/canvas-comment-mount.tsx +1 -1
- package/apps/studio/canvas-create.ts +104 -0
- package/{plugins/design/dev-server → apps/studio}/canvas-cursors.ts +48 -12
- package/{plugins/design/dev-server → apps/studio}/canvas-edit.ts +257 -7
- package/{plugins/design/dev-server → apps/studio}/canvas-icons.tsx +165 -1
- package/{plugins/design/dev-server → apps/studio}/canvas-lib-inline.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/canvas-lib-resolver.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/canvas-lib.tsx +31 -12
- package/{plugins/design/dev-server → apps/studio}/canvas-shell.tsx +360 -48
- package/apps/studio/client/app.jsx +6742 -0
- package/apps/studio/client/canvas-url.js +81 -0
- package/{plugins/design/dev-server → apps/studio}/client/comments-overlay.css +41 -27
- package/apps/studio/client/index.html +16 -0
- package/apps/studio/client/styles/1-tokens-maude.css +296 -0
- package/apps/studio/client/styles/3-shell-maude.css +1161 -0
- package/{plugins/design/dev-server → apps/studio}/client/styles/3-shell.css +129 -0
- package/apps/studio/client/styles/4-components-maude.css +74 -0
- package/{plugins/design/dev-server → apps/studio}/client/styles/4-components.css +396 -34
- package/apps/studio/client/styles/5-maude-overrides.css +137 -0
- package/{plugins/design/dev-server → apps/studio}/client/styles/_index.css +9 -0
- package/{plugins/design/dev-server → apps/studio}/client/styles.css +1 -1
- package/apps/studio/client/tour/overlay.jsx +279 -0
- package/apps/studio/client/tour/usage-tour.js +48 -0
- package/apps/studio/client/whats-new-seen.js +52 -0
- package/apps/studio/client/whats-new.jsx +250 -0
- package/{plugins/design/dev-server → apps/studio}/commands/annotation-strokes-command.ts +2 -2
- package/{plugins/design/dev-server → apps/studio}/commands/equal-spacing-command.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/commands/move-artboards-command.ts +2 -2
- package/{plugins/design/dev-server → apps/studio}/comments-overlay.tsx +32 -11
- package/{plugins/design/dev-server → apps/studio}/context-menu.tsx +5 -4
- package/{plugins/design/dev-server → apps/studio}/contextual-toolbar.tsx +18 -7
- package/{plugins/design/dev-server → apps/studio}/cursors-overlay.tsx +21 -21
- package/apps/studio/dist/client.bundle.js +25545 -0
- package/apps/studio/dist/comment-mount.js +2046 -0
- package/apps/studio/dist/styles.css +8018 -0
- package/apps/studio/dom-selection.ts +342 -0
- package/apps/studio/draw/animate.ts +333 -0
- package/{plugins/design/dev-server → apps/studio}/draw/brush.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/draw/composition.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/draw/geometry.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/draw/index.ts +4 -1
- package/{plugins/design/dev-server → apps/studio}/draw/layout.ts +1 -1
- package/apps/studio/draw/morph.ts +204 -0
- package/{plugins/design/dev-server → apps/studio}/draw/optimize.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/draw/palette.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/draw/primitives.ts +1 -1
- package/apps/studio/draw/serialize-animate.ts +324 -0
- package/{plugins/design/dev-server → apps/studio}/draw/serialize.ts +9 -3
- package/apps/studio/draw/test/animate.test.ts +172 -0
- package/apps/studio/draw/test/morph.test.ts +107 -0
- package/apps/studio/draw/test/serialize-animate.test.ts +142 -0
- package/{plugins/design/dev-server → apps/studio}/equal-spacing-detector.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/equal-spacing-handles.tsx +7 -29
- package/{plugins/design/dev-server → apps/studio}/export-dialog.tsx +16 -4
- package/{plugins/design/dev-server → apps/studio}/history.ts +20 -3
- package/{plugins/design/dev-server → apps/studio}/http.ts +226 -6
- package/{plugins/design/dev-server → apps/studio}/input-router.tsx +15 -1
- package/{plugins/design/dev-server → apps/studio}/inspect.ts +50 -4
- package/{plugins/design/dev-server → apps/studio}/marquee-overlay.tsx +5 -2
- package/{plugins/design/dev-server → apps/studio}/participants-chrome.tsx +2 -8
- package/{plugins/design/dev-server → apps/studio}/paths.ts +15 -11
- package/{plugins/design/dev-server → apps/studio}/server.ts +23 -2
- package/{plugins/design/dev-server → apps/studio}/sync/agent.ts +231 -57
- package/{plugins/design/dev-server → apps/studio}/sync/codec.ts +45 -0
- package/apps/studio/sync/cold-start.ts +158 -0
- package/{plugins/design/dev-server → apps/studio}/sync/connection-state.ts +58 -2
- package/{plugins/design/dev-server → apps/studio}/sync/index.ts +563 -221
- package/apps/studio/sync/journal.ts +190 -0
- package/apps/studio/sync/migrate-seed.ts +321 -0
- package/{plugins/design/dev-server → apps/studio}/sync/projection.ts +22 -3
- package/{plugins/design/dev-server → apps/studio}/sync/status.ts +15 -4
- package/{plugins/design/dev-server → apps/studio}/test/activity.test.ts +1 -7
- package/apps/studio/test/annotate-write.test.ts +184 -0
- package/apps/studio/test/annotations-align.test.ts +88 -0
- package/apps/studio/test/annotations-bindings.test.ts +124 -0
- package/apps/studio/test/annotations-groups.test.ts +231 -0
- package/{plugins/design/dev-server → apps/studio}/test/annotations-layer.test.ts +63 -0
- package/{plugins/design/dev-server → apps/studio}/test/annotations-roundtrip.test.ts +97 -0
- package/apps/studio/test/annotations-snap.test.ts +79 -0
- package/apps/studio/test/annotations-text-format.test.ts +396 -0
- package/apps/studio/test/asset-api.test.ts +149 -0
- package/apps/studio/test/canvas-create-api.test.ts +361 -0
- package/{plugins/design/dev-server → apps/studio}/test/canvas-cursors.test.ts +2 -0
- package/apps/studio/test/canvas-edit.test.ts +319 -0
- package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-resolver.test.ts +1 -1
- package/apps/studio/test/canvas-media-drop.test.ts +158 -0
- package/{plugins/design/dev-server → apps/studio}/test/canvas-origin-gate.test.ts +25 -1
- package/apps/studio/test/canvas-url.test.ts +99 -0
- package/{plugins/design/dev-server → apps/studio}/test/collab-bridge.test.ts +0 -2
- package/{plugins/design/dev-server → apps/studio}/test/collab-room.test.ts +2 -7
- package/{plugins/design/dev-server → apps/studio}/test/csp-canvas-shell.test.ts +5 -0
- package/apps/studio/test/csrf-write-guard.test.ts +52 -0
- package/apps/studio/test/figjam-v3-model.test.ts +342 -0
- package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +1 -0
- package/apps/studio/test/index-data-canvas-ds.test.ts +97 -0
- package/apps/studio/test/motion-sample.test.ts +35 -0
- package/{plugins/design/dev-server → apps/studio}/test/perf-harness.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/test/phase-3.6-smoke.test.ts +3 -1
- package/apps/studio/test/read-annotations.test.ts +409 -0
- package/{plugins/design/dev-server → apps/studio}/test/sanitize-annotation-svg.test.ts +108 -2
- package/{plugins/design/dev-server → apps/studio}/test/shared-doc-convergence.test.ts +1 -1
- package/apps/studio/test/shared-doc-migrate.test.ts +369 -0
- package/apps/studio/test/sync-agent.test.ts +575 -0
- package/{plugins/design/dev-server → apps/studio}/test/sync-codec.test.ts +65 -0
- package/apps/studio/test/sync-cold-start.test.ts +244 -0
- package/{plugins/design/dev-server → apps/studio}/test/sync-connection-state.test.ts +68 -0
- package/{plugins/design/dev-server → apps/studio}/test/sync-hardening.test.ts +0 -8
- package/{plugins/design/dev-server → apps/studio}/test/sync-hubs-config.test.ts +0 -1
- package/apps/studio/test/sync-incident-replay.test.ts +211 -0
- package/apps/studio/test/sync-journal.test.ts +176 -0
- package/{plugins/design/dev-server → apps/studio}/test/sync-runtime.test.ts +360 -5
- package/{plugins/design/dev-server → apps/studio}/test/sync-status.test.ts +66 -0
- package/apps/studio/test/tour-overlay.test.tsx +56 -0
- package/apps/studio/test/use-annotation-resize.test.ts +402 -0
- package/{plugins/design/dev-server → apps/studio}/test/use-artboard-drag.test.ts +0 -1
- package/{plugins/design/dev-server → apps/studio}/test/use-collab.test.ts +0 -0
- package/{plugins/design/dev-server → apps/studio}/test/use-tool-mode.test.tsx +8 -2
- package/apps/studio/test/whats-new.test.ts +101 -0
- package/apps/studio/text-imports.d.ts +9 -0
- package/{plugins/design/dev-server → apps/studio}/tool-palette.tsx +15 -70
- package/{plugins/design/dev-server → apps/studio}/undo-hud.tsx +1 -2
- package/{plugins/design/dev-server → apps/studio}/undo-stack.ts +1 -1
- package/{plugins/design/dev-server → apps/studio}/use-agent-presence.tsx +5 -3
- package/apps/studio/use-annotation-resize.tsx +912 -0
- package/{plugins/design/dev-server → apps/studio}/use-annotation-selection.tsx +17 -5
- package/{plugins/design/dev-server → apps/studio}/use-annotations-visibility.tsx +1 -1
- package/{plugins/design/dev-server → apps/studio}/use-artboard-drag.tsx +1 -1
- package/{plugins/design/dev-server → apps/studio}/use-canvas-activity.tsx +3 -3
- package/apps/studio/use-canvas-media-drop.tsx +343 -0
- package/{plugins/design/dev-server → apps/studio}/use-collab.tsx +21 -16
- package/{plugins/design/dev-server → apps/studio}/use-cursor-modifiers.tsx +1 -1
- package/{plugins/design/dev-server → apps/studio}/use-keyboard-discipline.tsx +5 -2
- package/{plugins/design/dev-server → apps/studio}/use-selection-set.tsx +18 -1
- package/{plugins/design/dev-server → apps/studio}/use-snap-guides.tsx +1 -1
- package/{plugins/design/dev-server → apps/studio}/use-tool-mode.tsx +8 -2
- package/{plugins/design/dev-server → apps/studio}/use-undo-stack.tsx +1 -1
- package/apps/studio/whats-new.json +264 -0
- package/apps/studio/whats-new.schema.json +86 -0
- package/apps/studio/whats-new.ts +87 -0
- package/cli/bin/maude.mjs +10 -0
- package/cli/commands/design-link.test.mjs +84 -0
- package/cli/commands/design.mjs +16 -7
- package/cli/commands/design.test.mjs +40 -0
- package/cli/commands/help.mjs +8 -2
- package/cli/commands/hub.mjs +3 -3
- package/cli/commands/hub.test.mjs +1 -1
- package/cli/commands/scenario-report.mjs +2 -9
- package/cli/lib/design-link.mjs +51 -1
- package/cli/lib/flow-design-integration.test.mjs +1 -1
- package/cli/lib/gitignore-block.mjs +1 -0
- package/cli/lib/plugin-cli-reachability.test.mjs +8 -7
- package/cli/lib/preflight.mjs +1 -1
- package/package.json +15 -15
- package/plugins/design/templates/_shell.html +28 -4
- package/plugins/design/templates/brief-board.tsx.template +61 -0
- package/plugins/design/templates/canvas.tsx.template +1 -1
- package/plugins/design/templates/design-system-inspiration/core/config.json.tpl +1 -1
- package/plugins/design/templates/design-system-inspiration/core/preview/_motion-readme.md.tpl +1 -1
- package/plugins/flow/.claude-plugin/config.schema.json +16 -0
- package/plugins/design/dev-server/annotations-layer.tsx +0 -3402
- package/plugins/design/dev-server/client/app.jsx +0 -2985
- package/plugins/design/dev-server/client/index.html +0 -15
- package/plugins/design/dev-server/dist/client.bundle.js +0 -20692
- package/plugins/design/dev-server/dist/comment-mount.js +0 -1924
- package/plugins/design/dev-server/dist/styles.css +0 -2710
- package/plugins/design/dev-server/dom-selection.ts +0 -156
- package/plugins/design/dev-server/sync/migrate-seed.ts +0 -163
- package/plugins/design/dev-server/test/canvas-edit.test.ts +0 -139
- package/plugins/design/dev-server/test/shared-doc-migrate.test.ts +0 -159
- package/plugins/design/dev-server/test/sync-agent.test.ts +0 -305
- package/plugins/design/dev-server/test/use-annotation-resize.test.ts +0 -200
- package/plugins/design/dev-server/use-annotation-resize.tsx +0 -449
- /package/{plugins/design/dev-server → apps/studio}/activity.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_enumerate-artboards-playwright.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_html-playwright.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_pdf-playwright.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_pptx-playwright.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_pw-launch.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_screenshot-playwright.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_svg-optimize.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/_svg-playwright.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/asset-sweep.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/bootstrap-check.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/check-runtime-bundles.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/draw-build.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/handoff.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/prep.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/scenario-report.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/slug.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/smoke.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/svg-optimize.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/bin/visual-sanity.sh +0 -0
- /package/{plugins/design/dev-server → apps/studio}/boot-self-heal.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/canvas-build.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/canvas-header.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/canvas-meta.schema.json +0 -0
- /package/{plugins/design/dev-server → apps/studio}/canvas-pipeline.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/client/hmr.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/client/iframe-lazy.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/client/styles/0-reset.css +0 -0
- /package/{plugins/design/dev-server → apps/studio}/client/styles/1-tokens.css +0 -0
- /package/{plugins/design/dev-server → apps/studio}/client/styles/2-layout.css +0 -0
- /package/{plugins/design/dev-server → apps/studio}/client/styles/5-utilities.css +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/ai-activity.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/awareness-bridge.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/git-lifecycle.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/index.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/persistence.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/protocol.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/registry.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/collab/room.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/config.schema.json +0 -0
- /package/{plugins/design/dev-server → apps/studio}/context.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/.min-sizes.json +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/lib0_decoding.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/lib0_encoding.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/motion.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/motion_react.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/pixi-js.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react-dom.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react-dom_client.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react_jsx-dev-runtime.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/react_jsx-runtime.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/y-protocols_awareness.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/y-protocols_sync.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/dist/runtime/yjs.js +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/brush.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/composition.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/geometry.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/gradient.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/layout.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/optimize.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/palette.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/primitives.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/draw/test/serialize.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/examples/README.md +0 -0
- /package/{plugins/design/dev-server → apps/studio}/examples/perf-100-artboards.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/_browser-bundles.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/canva-handoff-prompt.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/canva.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/html.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/index.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/pdf.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/png.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/pptx.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/scope.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/svg.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/exporters/zip.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/fs-watch.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/handoff.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/hmr-broadcast.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/locator.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/mem.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/runtime-bundle.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/server.mjs +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/atomic-write.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/echo-guard.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/fs-mirror.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/hubs-config.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/materialize.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/origins.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/sync/untrusted.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/_helpers.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/active-state.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/ai-activity.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/annotation-strokes-command.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/annotations-api.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/annotations-draw-modifiers.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/artboard-activity-overlay.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/binary-smoke.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/boot-self-heal.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/bundle-smoke.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-build.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-header.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-hmr-runtime.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-inline.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-lib-motion.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-meta-api.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-pipeline.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/canvas-route.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/collab-annotations-bridge.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/collab-awareness-bridge.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/collab-loopback.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/collab-protocol.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/collab-reseed-guard.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/collab-stress.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/comment-mount.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/comments-api.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/compile-entry.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/context-resolve-tokens.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/equal-spacing-detector.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/canva.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/endpoint.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/history.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/html.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/pdf.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/png.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx-deck.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/pptx.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/pw-launch.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/scope.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/svg.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/exporters/zip.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-20-annotations.svg +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/fixtures/phase-21-annotations.svg +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/fs-watch.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/git-lifecycle.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/handoff-static-frames.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/handoff.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/history-rollback.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/hmr-broadcast.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/hmr-classify.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/input-router.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/locator.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/marquee-overlay.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/move-artboards-command.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/participants-chrome.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/paths.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle-error-mapping.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/runtime-bundle.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/server-lifecycle.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/shared-doc-foundation.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/shared-doc-projection.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/snap-distance-pill.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/sync-atomic-write.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/sync-echo-guard.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/sync-fs-mirror.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/sync-meta-codec.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/sync-untrusted.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/system-endpoint.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/tool-palette.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/undo-stack.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-agent-presence.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-annotation-selection.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-canvas-activity.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-cursor-modifiers.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-keyboard-discipline.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-selection-set.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-snap-guides.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/use-undo-stack.test.tsx +0 -0
- /package/{plugins/design/dev-server → apps/studio}/test/ws-handshake.test.ts +0 -0
- /package/{plugins/design/dev-server → apps/studio}/tsconfig.json +0 -0
- /package/{plugins/design/dev-server → apps/studio}/ws.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file canvas-cursors.ts — Phase 24 custom tool cursors (Kenney CC0)
|
|
3
|
-
* @scope
|
|
3
|
+
* @scope apps/studio/canvas-cursors.ts
|
|
4
4
|
* @purpose FigJam/Figma-style custom cursors for EVERY canvas tool. The
|
|
5
5
|
* native crosshair / text / arrow cursors are tiny + thin and
|
|
6
6
|
* vanish on busy canvases; these are 32×32 SVG cursors that read on
|
|
@@ -46,16 +46,29 @@ const HALO = "stroke='#ffffff' stroke-linejoin='round' stroke-linecap='round'";
|
|
|
46
46
|
// Kenney's outline band (`b`) is painted WHITE (the halo) and its inner fill
|
|
47
47
|
// (`w`) is painted dark INK. Reads crisply on a LIGHT canvas (solid dark glyph)
|
|
48
48
|
// AND a dark one (white halo edge).
|
|
49
|
-
function kenney(b: string, w: string): string {
|
|
50
|
-
|
|
49
|
+
function kenney(b: string, w: string, transform?: string): string {
|
|
50
|
+
// Optional `<g transform>` for the drawing tools whose Kenney glyph needs
|
|
51
|
+
// re-orienting so the writing tip lands at the hotspot (user steer
|
|
52
|
+
// 2026-06-04: pen / highlighter "kreslí pod koncem, ne na špičce" → flipped so
|
|
53
|
+
// the nib points down-LEFT, top-right→bottom-left).
|
|
54
|
+
const open = transform ? `<g transform='${transform}'>` : '';
|
|
55
|
+
const close = transform ? '</g>' : '';
|
|
56
|
+
return `<svg ${W}>${open}<path fill='#ffffff' d='${b}'/><path fill='${INK}' d='${w}'/>${close}</svg>`;
|
|
51
57
|
}
|
|
52
58
|
|
|
59
|
+
// Vertical mirror about the 32-viewBox horizontal centre: (x,y) → (x, 32−y).
|
|
60
|
+
// Applied to pen/highlighter so the glyph lies along the top-right→bottom-left
|
|
61
|
+
// diagonal with the nib at bottom-left.
|
|
62
|
+
const FLIP_V = 'translate(0,32) scale(1,-1)';
|
|
63
|
+
|
|
64
|
+
// move → Kenney `pointer_b` (user steer 2026-06-04 — the plain variant, not the
|
|
65
|
+
// shaded one). Hotspot at the arrow tip (top).
|
|
53
66
|
const MOVE = svgCursor(
|
|
54
67
|
kenney(
|
|
55
|
-
'
|
|
56
|
-
'
|
|
68
|
+
'M10.25 8.25 L10.05 8.65 10 9 10 23.1 10.05 23.4 10.25 23.75 10.8 24 11.45 23.85 11.6 23.7 11.75 23.45 14.65 19.8 14.85 19.65 14.95 19.5 15.4 19.2 15.95 19.1 21.05 19.1 21.2 19.1 21.35 19.05 21.65 18.9 21.9 18.6 22 18.3 22 17.9 21.9 17.65 21.75 17.35 21.65 17.3 21.55 17.15 11.5 8.25 11.25 8.05 10.95 8 10.6 8.05 10.25 8.25 M9.15 6.6 L9.7 6.25 10 6.15 10.95 6 11.9 6.15 13 6.9 22.9 15.65 23 15.8 23.2 15.95 23.75 16.75 24 17.9 24 18.3 23.9 18.95 23.8 19.25 23.6 19.7 23.1 20.35 22.75 20.6 22.1 20.9 22.05 20.95 22 20.95 21.2 21.1 21.05 21.1 16.2 21.1 16.1 21.25 16.05 21.25 13.4 24.6 13.05 25.15 12.9 25.3 12.55 25.55 Q11.6 26.15 10.55 26 L10.5 26 Q9.65 25.85 9 25.3 L8.45 24.65 8.4 24.5 8.15 24.05 8 23.1 8 9 Q8 8.45 8.15 8.05 L8.25 7.75 8.45 7.35 9.15 6.6',
|
|
69
|
+
'M10.25 8.25 L10.6 8.05 10.95 8 11.25 8.05 11.5 8.25 21.55 17.15 21.65 17.3 21.75 17.35 21.9 17.65 22 17.9 22 18.3 21.9 18.6 21.65 18.9 21.35 19.05 21.2 19.1 21.05 19.1 15.95 19.1 15.4 19.2 14.95 19.5 14.85 19.65 14.65 19.8 11.75 23.45 11.6 23.7 11.45 23.85 10.8 24 10.25 23.75 10.05 23.4 10 23.1 10 9 10.05 8.65 10.25 8.25'
|
|
57
70
|
),
|
|
58
|
-
|
|
71
|
+
8,
|
|
59
72
|
5,
|
|
60
73
|
'default'
|
|
61
74
|
);
|
|
@@ -68,22 +81,40 @@ const HAND = svgCursor(
|
|
|
68
81
|
12,
|
|
69
82
|
'grab'
|
|
70
83
|
);
|
|
84
|
+
// comment → Kenney `message_round` (user steer 2026-06-04). Hotspot at the
|
|
85
|
+
// tail tip (bottom-centre), where the comment pin is dropped.
|
|
71
86
|
const COMMENT = svgCursor(
|
|
72
87
|
kenney(
|
|
73
|
-
'
|
|
74
|
-
'
|
|
88
|
+
'M28 14 Q28 9.85 24.45 6.9 20.95 4 16 4 11.05 4 7.5 6.9 L7.45 7 Q4 9.9 4 14 4 18.15 7.55 21.05 L7.5 21.05 Q9.2 22.45 11.2 23.2 L15.3 27.3 16 27.6 16.7 27.3 20.85 23.2 Q22.7 22.45 24.3 21.15 L24.45 21.05 Q28 18.15 28 14 M25.75 5.35 Q30.05 8.95 30 14 30.05 19.05 25.75 22.6 L25.4 22.85 Q23.8 24.1 22 24.9 L18.1 28.75 18.15 28.75 Q17.2 29.6 16 29.6 14.8 29.6 13.85 28.75 L13.9 28.75 10 24.9 6.6 22.85 6.25 22.6 Q1.95 19.05 2 14 1.95 8.95 6.25 5.35 10.3 2 16 2 21.7 2 25.75 5.35',
|
|
89
|
+
'M28 14 Q28 18.15 24.45 21.05 L24.3 21.15 Q22.7 22.45 20.85 23.2 L16.7 27.3 16 27.6 15.3 27.3 11.2 23.2 Q9.2 22.45 7.5 21.05 L7.55 21.05 Q4 18.15 4 14 4 9.9 7.45 7 L7.5 6.9 Q11.05 4 16 4 20.95 4 24.45 6.9 28 9.85 28 14'
|
|
75
90
|
),
|
|
76
91
|
12,
|
|
77
|
-
|
|
92
|
+
21,
|
|
78
93
|
'crosshair'
|
|
79
94
|
);
|
|
95
|
+
// pen → Kenney `drawing_pen`, mirrored vertically (FLIP_V) so the nib points
|
|
96
|
+
// down-LEFT (top-right→bottom-left diagonal). Source gradient-shade path dropped.
|
|
97
|
+
// Hotspot at the nib, bottom-left.
|
|
80
98
|
const PEN = svgCursor(
|
|
99
|
+
kenney(
|
|
100
|
+
'M4 13.1 L4 6 Q4 5.15 4.6 4.6 5.15 4 6 4 L13.1 4 Q13.95 4 14.55 4.6 L28.65 18.75 Q29.8 19.9 29.75 21.45 L29.75 21.6 29.75 21.7 Q29.75 23.2 28.7 24.35 L24.45 28.65 24.35 28.75 Q23.15 29.85 21.65 29.8 L21.55 29.8 21.4 29.8 Q20.2 29.8 19.25 29.15 L18 29.35 Q16.6 29.4 15.25 28 L15.2 27.95 8.2 20.95 Q7.6 20.35 7.6 19.55 7.6 18.7 8.2 18.1 L4.6 14.5 Q4 13.9 4 13.1 M19.5 26.65 L20.1 27.25 Q20.7 27.85 21.5 27.8 22.35 27.85 23 27.25 L27.25 22.95 Q27.8 22.35 27.75 21.55 27.8 20.75 27.2 20.15 L13.1 6 6 6 6 13.1 12.35 19.45 9.6 19.5 16.65 26.55 Q18.05 28.05 19.5 26.65 M8.05 12.3 L8 8 12.25 8.05 13.8 9.6 9.6 13.85 8.05 12.3 M15.25 11.05 L23 18.8 18.8 23.05 11.05 15.3 15.25 11.05',
|
|
101
|
+
'M15.25 11.05 L11.05 15.3 18.8 23.05 23 18.8 15.25 11.05 M12.35 19.45 L6 13.1 6 6 13.1 6 27.2 20.15 Q27.8 20.75 27.75 21.55 27.8 22.35 27.25 22.95 L23 27.25 Q22.35 27.85 21.5 27.8 20.7 27.85 20.1 27.25 L19.5 26.65 12.35 19.45 M8.05 12.3 L9.6 13.85 13.8 9.6 12.25 8.05 8 8 8.05 12.3',
|
|
102
|
+
FLIP_V
|
|
103
|
+
),
|
|
104
|
+
6,
|
|
105
|
+
18,
|
|
106
|
+
'crosshair'
|
|
107
|
+
);
|
|
108
|
+
// highlighter → Kenney `drawing_pencil`, also mirrored vertically (distinct from
|
|
109
|
+
// the pen glyph). Hotspot at the lead tip, bottom-left.
|
|
110
|
+
const HIGHLIGHTER = svgCursor(
|
|
81
111
|
kenney(
|
|
82
112
|
'M5.15 10.85 Q4 9.65 4 8.1 L4 7.95 4 7.85 Q3.95 6.2 5.1 5.15 6.25 4 7.85 4 L7.95 4 8.1 4 Q9.65 4 10.85 5.15 L11 5.3 14.3 5.25 Q15.15 5.25 15.75 5.85 L29.9 20 Q31 21.15 31 22.75 L31 22.85 31 23 Q31.05 24.5 29.9 25.7 L29.55 25.95 25.65 29.9 25.65 29.95 Q24.45 31.1 22.75 31.1 21.2 31.15 20 29.95 L5.85 15.8 Q5.25 15.2 5.25 14.35 L5.25 10.95 5.15 10.85 M19.95 24.2 L18.55 22.8 22.8 18.55 24.2 19.95 19.95 24.2 M28.45 21.4 L14.3 7.25 10.15 7.3 9.4 6.55 Q8.8 5.95 7.95 6 7.1 5.95 6.5 6.55 5.95 7.1 6 7.95 5.95 8.8 6.55 9.4 L7.25 10.1 7.25 14.35 21.4 28.5 Q22 29.1 22.75 29.1 23.6 29.1 24.2 28.5 L28.45 24.25 Q29.05 23.65 29 22.85 29.05 22 28.45 21.4 M9.25 13.5 L9.25 9.3 13.5 9.25 14.3 10.05 10.05 14.3 9.25 13.5 M17.15 21.4 L11.5 15.75 15.75 11.5 21.4 17.15 17.15 21.4',
|
|
83
|
-
'M17.15 21.4 L21.4 17.15 15.75 11.5 11.5 15.75 17.15 21.4 M28.45 21.4 Q29.05 22 29 22.85 29.05 23.65 28.45 24.25 L24.2 28.5 Q23.6 29.1 22.75 29.1 22 29.1 21.4 28.5 L7.25 14.35 7.25 10.1 6.55 9.4 Q5.95 8.8 6 7.95 5.95 7.1 6.5 6.55 7.1 5.95 7.95 6 8.8 5.95 9.4 6.55 L10.15 7.3 14.3 7.25 28.45 21.4 M19.95 24.2 L24.2 19.95 22.8 18.55 18.55 22.8 19.95 24.2 M9.25 13.5 L10.05 14.3 14.3 10.05 13.5 9.25 9.25 9.3 9.25 13.5'
|
|
113
|
+
'M17.15 21.4 L21.4 17.15 15.75 11.5 11.5 15.75 17.15 21.4 M28.45 21.4 Q29.05 22 29 22.85 29.05 23.65 28.45 24.25 L24.2 28.5 Q23.6 29.1 22.75 29.1 22 29.1 21.4 28.5 L7.25 14.35 7.25 10.1 6.55 9.4 Q5.95 8.8 6 7.95 5.95 7.1 6.5 6.55 7.1 5.95 7.95 6 8.8 5.95 9.4 6.55 L10.15 7.3 14.3 7.25 28.45 21.4 M19.95 24.2 L24.2 19.95 22.8 18.55 18.55 22.8 19.95 24.2 M9.25 13.5 L10.05 14.3 14.3 10.05 13.5 9.25 9.25 9.3 9.25 13.5',
|
|
114
|
+
FLIP_V
|
|
84
115
|
),
|
|
85
|
-
|
|
86
|
-
|
|
116
|
+
6,
|
|
117
|
+
18,
|
|
87
118
|
'crosshair'
|
|
88
119
|
);
|
|
89
120
|
const CROSSHAIR = svgCursor(
|
|
@@ -140,6 +171,11 @@ export const TOOL_CURSORS: Record<Tool, string> = Object.freeze({
|
|
|
140
171
|
hand: HAND,
|
|
141
172
|
comment: COMMENT,
|
|
142
173
|
pen: PEN,
|
|
174
|
+
// FigJam v3 — the section container draws like a shape (crosshair glyph).
|
|
175
|
+
section: CROSSHAIR,
|
|
176
|
+
// Highlighter = Kenney `drawing_pencil` rot180; pen = `drawing_pen` rot180 —
|
|
177
|
+
// distinct glyphs, both from the Kenney pack (user steer 2026-06-04).
|
|
178
|
+
highlighter: HIGHLIGHTER,
|
|
143
179
|
shape: CROSSHAIR,
|
|
144
180
|
rect: CROSSHAIR,
|
|
145
181
|
ellipse: CROSSHAIR,
|
|
@@ -68,6 +68,8 @@ function computeId(componentName: string, idx: number): string {
|
|
|
68
68
|
|
|
69
69
|
interface OpeningHit {
|
|
70
70
|
opening: AnyNode;
|
|
71
|
+
/** The full JSXElement node — `editText` needs `.children` (JSXText), not just the opening tag. */
|
|
72
|
+
element: AnyNode;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
/**
|
|
@@ -108,7 +110,7 @@ function findOpening(program: AnyNode, targetId: string): OpeningHit | null {
|
|
|
108
110
|
frame.jsxIndex += 1;
|
|
109
111
|
const id = computeId(frame.componentName, idx);
|
|
110
112
|
if (id === targetId) {
|
|
111
|
-
hit = { opening: node.openingElement };
|
|
113
|
+
hit = { opening: node.openingElement, element: node };
|
|
112
114
|
}
|
|
113
115
|
if (!hit) {
|
|
114
116
|
if (node.openingElement) visit(node.openingElement.attributes);
|
|
@@ -200,6 +202,111 @@ export async function editAttribute(
|
|
|
200
202
|
});
|
|
201
203
|
}
|
|
202
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Remove an attribute (or one inline-style property) from the element with the
|
|
207
|
+
* given `data-cd-id` — the "reset to original" path (Phase 12.3). `attr` follows
|
|
208
|
+
* the same shape as `editAttribute`: `style.<camelOrKebab>` removes one inline
|
|
209
|
+
* style key (dropping the whole `style={{}}` when it was the last key); any other
|
|
210
|
+
* name removes that plain JSX attribute. A missing key/attribute is a no-op
|
|
211
|
+
* (delta 0), never an error. Same atomic write + per-file lock as `editAttribute`.
|
|
212
|
+
*/
|
|
213
|
+
export async function removeAttribute(
|
|
214
|
+
canvasAbsPath: string,
|
|
215
|
+
id: string,
|
|
216
|
+
attr: string
|
|
217
|
+
): Promise<EditResult> {
|
|
218
|
+
return withLock(canvasAbsPath, async () => {
|
|
219
|
+
const file = Bun.file(canvasAbsPath);
|
|
220
|
+
if (!(await file.exists())) {
|
|
221
|
+
throw new CanvasEditError(`Canvas not found: ${canvasAbsPath}`, {
|
|
222
|
+
canvas: canvasAbsPath,
|
|
223
|
+
id,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const source = await file.text();
|
|
227
|
+
const next = applyRemove(canvasAbsPath, source, id, attr);
|
|
228
|
+
if (next.source === source) return { source, delta: 0 };
|
|
229
|
+
const tmp = `${canvasAbsPath}.tmp.${Math.random().toString(36).slice(2, 10)}`;
|
|
230
|
+
await Bun.write(tmp, next.source);
|
|
231
|
+
const { rename } = await import('node:fs/promises');
|
|
232
|
+
await rename(tmp, canvasAbsPath);
|
|
233
|
+
return next;
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Pure variant of `removeAttribute` — exposed for tests. */
|
|
238
|
+
export function applyRemove(
|
|
239
|
+
canvasAbsPath: string,
|
|
240
|
+
source: string,
|
|
241
|
+
id: string,
|
|
242
|
+
attr: string
|
|
243
|
+
): EditResult {
|
|
244
|
+
const parsed = parseSync(canvasAbsPath, source, { sourceType: 'module' });
|
|
245
|
+
if (parsed.errors && parsed.errors.length > 0) {
|
|
246
|
+
const first = parsed.errors[0];
|
|
247
|
+
throw new CanvasEditError(
|
|
248
|
+
`oxc-parser failed on ${canvasAbsPath}: ${first?.message ?? 'unknown'}`,
|
|
249
|
+
{
|
|
250
|
+
canvas: canvasAbsPath,
|
|
251
|
+
id,
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
const hit = findOpening(parsed.program, id);
|
|
256
|
+
if (!hit) {
|
|
257
|
+
throw new CanvasEditError(`data-cd-id "${id}" not found in ${canvasAbsPath}`, {
|
|
258
|
+
canvas: canvasAbsPath,
|
|
259
|
+
id,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
const s = new MagicString(source);
|
|
263
|
+
if (attr.startsWith('style.')) {
|
|
264
|
+
removeStyleProp(s, hit.opening, attr.slice('style.'.length), source);
|
|
265
|
+
} else if (attr === 'data-cd-id') {
|
|
266
|
+
throw new CanvasEditError('data-cd-id is owned by the pipeline; cannot be removed', {
|
|
267
|
+
canvas: canvasAbsPath,
|
|
268
|
+
id,
|
|
269
|
+
});
|
|
270
|
+
} else {
|
|
271
|
+
removeStringAttr(s, hit.opening, attr, source);
|
|
272
|
+
}
|
|
273
|
+
const out = s.toString();
|
|
274
|
+
return { source: out, delta: out.length - source.length };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Apply an inline TEXT-content edit to the JSX element with the given
|
|
279
|
+
* `data-cd-id`. Leaf-text only: the element's children must be exactly one
|
|
280
|
+
* `JSXText` node (whitespace-only siblings are ignored). Mixed/expression
|
|
281
|
+
* children (`<b>x</b>`, `{count}`) throw `CanvasEditError` — the caller should
|
|
282
|
+
* surface a "use /design:edit" refusal rather than guess. The text is
|
|
283
|
+
* JSX-escaped before it touches source. Same atomic write + per-file lock as
|
|
284
|
+
* `editAttribute`. See DDR-103.
|
|
285
|
+
*/
|
|
286
|
+
export async function editText(
|
|
287
|
+
canvasAbsPath: string,
|
|
288
|
+
id: string,
|
|
289
|
+
text: string
|
|
290
|
+
): Promise<EditResult> {
|
|
291
|
+
return withLock(canvasAbsPath, async () => {
|
|
292
|
+
const file = Bun.file(canvasAbsPath);
|
|
293
|
+
if (!(await file.exists())) {
|
|
294
|
+
throw new CanvasEditError(`Canvas not found: ${canvasAbsPath}`, {
|
|
295
|
+
canvas: canvasAbsPath,
|
|
296
|
+
id,
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
const source = await file.text();
|
|
300
|
+
const next = applyTextEdit(canvasAbsPath, source, id, text);
|
|
301
|
+
if (next.source === source) return { source, delta: 0 };
|
|
302
|
+
const tmp = `${canvasAbsPath}.tmp.${Math.random().toString(36).slice(2, 10)}`;
|
|
303
|
+
await Bun.write(tmp, next.source);
|
|
304
|
+
const { rename } = await import('node:fs/promises');
|
|
305
|
+
await rename(tmp, canvasAbsPath);
|
|
306
|
+
return next;
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
203
310
|
/**
|
|
204
311
|
* Pure variant — exposed for tests + in-memory pipelines. Caller owns
|
|
205
312
|
* persistence. Throws CanvasEditError if the ID isn't found or the edit shape
|
|
@@ -245,6 +352,68 @@ export function applyEdit(
|
|
|
245
352
|
return { source: out, delta: out.length - source.length };
|
|
246
353
|
}
|
|
247
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Pure variant of `editText` — parse, locate the JSXText child, overwrite its
|
|
357
|
+
* source span (preserving the original leading/trailing whitespace so JSX
|
|
358
|
+
* indentation survives), escaping the new text. Throws `CanvasEditError` for a
|
|
359
|
+
* missing id, no text content, or mixed/expression children.
|
|
360
|
+
*/
|
|
361
|
+
export function applyTextEdit(
|
|
362
|
+
canvasAbsPath: string,
|
|
363
|
+
source: string,
|
|
364
|
+
id: string,
|
|
365
|
+
text: string
|
|
366
|
+
): EditResult {
|
|
367
|
+
const parsed = parseSync(canvasAbsPath, source, { sourceType: 'module' });
|
|
368
|
+
if (parsed.errors && parsed.errors.length > 0) {
|
|
369
|
+
const first = parsed.errors[0];
|
|
370
|
+
throw new CanvasEditError(
|
|
371
|
+
`oxc-parser failed on ${canvasAbsPath}: ${first?.message ?? 'unknown'}`,
|
|
372
|
+
{ canvas: canvasAbsPath, id }
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const hit = findOpening(parsed.program, id);
|
|
377
|
+
if (!hit) {
|
|
378
|
+
throw new CanvasEditError(`data-cd-id "${id}" not found in ${canvasAbsPath}`, {
|
|
379
|
+
canvas: canvasAbsPath,
|
|
380
|
+
id,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const children: AnyNode[] = Array.isArray(hit.element?.children) ? hit.element.children : [];
|
|
385
|
+
// Ignore whitespace-only JSXText siblings (`<button>\n Save\n</button>` parses
|
|
386
|
+
// as one JSXText; `<a>\n <b/>\n</a>` parses as ws + element + ws — the ws is
|
|
387
|
+
// noise). What's left is the "real" content.
|
|
388
|
+
const meaningful = children.filter(
|
|
389
|
+
(c) => !(c?.type === 'JSXText' && typeof c.value === 'string' && c.value.trim() === '')
|
|
390
|
+
);
|
|
391
|
+
if (meaningful.length === 0) {
|
|
392
|
+
throw new CanvasEditError(`element "${id}" has no editable text content`, {
|
|
393
|
+
canvas: canvasAbsPath,
|
|
394
|
+
id,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
const only = meaningful[0];
|
|
398
|
+
if (meaningful.length > 1 || only?.type !== 'JSXText') {
|
|
399
|
+
throw new CanvasEditError(
|
|
400
|
+
`element "${id}" has mixed or expression content — edit it via /design:edit`,
|
|
401
|
+
{ canvas: canvasAbsPath, id }
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const start = only.start as number;
|
|
406
|
+
const end = only.end as number;
|
|
407
|
+
const raw = source.slice(start, end);
|
|
408
|
+
// Preserve the original indentation/newline framing; swap only the visible text.
|
|
409
|
+
const lead = /^\s*/.exec(raw)?.[0] ?? '';
|
|
410
|
+
const trail = /\s*$/.exec(raw)?.[0] ?? '';
|
|
411
|
+
const s = new MagicString(source);
|
|
412
|
+
s.overwrite(start, end, `${lead}${escapeJsxText(text)}${trail}`);
|
|
413
|
+
const out = s.toString();
|
|
414
|
+
return { source: out, delta: out.length - source.length };
|
|
415
|
+
}
|
|
416
|
+
|
|
248
417
|
// ---------------------------------------------------------------------------
|
|
249
418
|
// Edit shapes.
|
|
250
419
|
|
|
@@ -263,14 +432,20 @@ function editStringAttr(s: MagicString, opening: AnyNode, name: string, value: s
|
|
|
263
432
|
return;
|
|
264
433
|
}
|
|
265
434
|
if (v.type === 'Literal' || v.type === 'StringLiteral') {
|
|
266
|
-
// Replace
|
|
267
|
-
|
|
435
|
+
// Replace the whole `"value"` (quotes included) so we control the escaping.
|
|
436
|
+
// The value lands in a JSX *attribute*, where `"` must become `"` and
|
|
437
|
+
// `<`/`>` their entities — NOT JS backslash escaping. `JSON.stringify` would
|
|
438
|
+
// emit `\"`, which is invalid in a JSX attribute and corrupts the source on
|
|
439
|
+
// any value containing a double quote. Use the same `escapeAttr` as the two
|
|
440
|
+
// insert branches so all four paths agree. See DDR-103 / DDR-105.
|
|
441
|
+
s.overwrite(v.start, v.end, `"${escapeAttr(value)}"`);
|
|
268
442
|
return;
|
|
269
443
|
}
|
|
270
444
|
if (v.type === 'JSXExpressionContainer') {
|
|
271
445
|
// Replace the whole `{...}` with a plain quoted literal — keeps the
|
|
272
|
-
// resulting JSX readable
|
|
273
|
-
|
|
446
|
+
// resulting JSX readable. Same JSX-attribute escaping as above (NOT
|
|
447
|
+
// `JSON.stringify`, which would JS-escape a `"` and corrupt the source).
|
|
448
|
+
s.overwrite(v.start, v.end, `"${escapeAttr(value)}"`);
|
|
274
449
|
return;
|
|
275
450
|
}
|
|
276
451
|
// Unknown shape — refuse rather than corrupt.
|
|
@@ -289,6 +464,24 @@ function escapeAttr(value: string): string {
|
|
|
289
464
|
return value.replace(/"/g, '"').replace(/[<>]/g, (c) => (c === '<' ? '<' : '>'));
|
|
290
465
|
}
|
|
291
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Escape JSX-significant characters so user-typed text lands in source `.tsx`
|
|
469
|
+
* as inert TEXT, never as markup or an expression. The text is written between
|
|
470
|
+
* an element's tags (`<button>HERE</button>`), where `<`/`>` would start a tag
|
|
471
|
+
* and `{`/`}` would open a JSX expression — so all four (plus a bare `&`, which
|
|
472
|
+
* begins an entity) are encoded. This is the load-bearing guard that keeps the
|
|
473
|
+
* inline text editor (Phase 12) from being a source-injection vector. See
|
|
474
|
+
* DDR-103.
|
|
475
|
+
*/
|
|
476
|
+
function escapeJsxText(value: string): string {
|
|
477
|
+
return value
|
|
478
|
+
.replace(/&/g, '&')
|
|
479
|
+
.replace(/</g, '<')
|
|
480
|
+
.replace(/>/g, '>')
|
|
481
|
+
.replace(/\{/g, '{')
|
|
482
|
+
.replace(/\}/g, '}');
|
|
483
|
+
}
|
|
484
|
+
|
|
292
485
|
function editStyleProp(
|
|
293
486
|
s: MagicString,
|
|
294
487
|
opening: AnyNode,
|
|
@@ -308,14 +501,14 @@ function editStyleProp(
|
|
|
308
501
|
return;
|
|
309
502
|
}
|
|
310
503
|
const v = attr.value;
|
|
311
|
-
if (
|
|
504
|
+
if (v?.type !== 'JSXExpressionContainer') {
|
|
312
505
|
throw new CanvasEditError(
|
|
313
506
|
`style attribute on ${id} is not a {{...}} expression — refusing to edit`,
|
|
314
507
|
{ canvas: canvasAbsPath, id }
|
|
315
508
|
);
|
|
316
509
|
}
|
|
317
510
|
const obj = v.expression;
|
|
318
|
-
if (
|
|
511
|
+
if (obj?.type !== 'ObjectExpression') {
|
|
319
512
|
throw new CanvasEditError(
|
|
320
513
|
`style={...} on ${id} is not an inline ObjectExpression — refusing to edit`,
|
|
321
514
|
{ canvas: canvasAbsPath, id }
|
|
@@ -349,6 +542,63 @@ function editStyleProp(
|
|
|
349
542
|
void tail;
|
|
350
543
|
}
|
|
351
544
|
|
|
545
|
+
/**
|
|
546
|
+
* Remove a single inline-style property (the "reset to original" path — DDR-104
|
|
547
|
+
* Phase 12.3). No-op when the style attribute or the key is absent. When the key
|
|
548
|
+
* was the object's ONLY property, the whole `style={{…}}` attribute is removed so
|
|
549
|
+
* we don't leave an empty `style={{}}` behind.
|
|
550
|
+
*/
|
|
551
|
+
function removeStyleProp(s: MagicString, opening: AnyNode, prop: string, source: string): boolean {
|
|
552
|
+
const attr = findAttribute(opening, 'style');
|
|
553
|
+
if (!attr) return false;
|
|
554
|
+
const v = attr.value;
|
|
555
|
+
if (v?.type !== 'JSXExpressionContainer') return false;
|
|
556
|
+
const obj = v.expression;
|
|
557
|
+
if (obj?.type !== 'ObjectExpression') return false;
|
|
558
|
+
const props = (obj.properties as AnyNode[]).filter(
|
|
559
|
+
(p) => p?.type === 'Property' || p?.type === 'ObjectProperty'
|
|
560
|
+
);
|
|
561
|
+
const propCamel = prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
562
|
+
const idx = props.findIndex((p) => {
|
|
563
|
+
const k = p.key;
|
|
564
|
+
const kname =
|
|
565
|
+
k?.type === 'Identifier' ? k.name : k?.type === 'Literal' ? String(k.value) : null;
|
|
566
|
+
return kname === prop || kname === propCamel;
|
|
567
|
+
});
|
|
568
|
+
if (idx === -1) return false;
|
|
569
|
+
|
|
570
|
+
// Only property → drop the whole `style={{…}}` attribute (plus the leading space).
|
|
571
|
+
if (props.length === 1) {
|
|
572
|
+
const start = source[attr.start - 1] === ' ' ? attr.start - 1 : attr.start;
|
|
573
|
+
s.remove(start, attr.end);
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
// Otherwise remove the one property + one adjacent comma/whitespace run so the
|
|
577
|
+
// remaining object stays well-formed: consume forward to the next prop's start
|
|
578
|
+
// (eats the trailing `, `), or — for the last prop — backward from the previous
|
|
579
|
+
// prop's end (eats the leading `, `).
|
|
580
|
+
const target = props[idx];
|
|
581
|
+
if (idx < props.length - 1) {
|
|
582
|
+
s.remove(target.start as number, props[idx + 1].start as number);
|
|
583
|
+
} else {
|
|
584
|
+
s.remove(props[idx - 1].end as number, target.end as number);
|
|
585
|
+
}
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Remove a plain JSX attribute (the custom-attribute "reset" path). No-op when
|
|
591
|
+
* absent. Refuses `data-cd-id` / `style` (pipeline-owned / wrong endpoint).
|
|
592
|
+
*/
|
|
593
|
+
function removeStringAttr(s: MagicString, opening: AnyNode, name: string, source: string): boolean {
|
|
594
|
+
if (name === 'data-cd-id' || name === 'style') return false;
|
|
595
|
+
const attr = findAttribute(opening, name);
|
|
596
|
+
if (!attr) return false;
|
|
597
|
+
const start = source[attr.start - 1] === ' ' ? attr.start - 1 : attr.start;
|
|
598
|
+
s.remove(start, attr.end);
|
|
599
|
+
return true;
|
|
600
|
+
}
|
|
601
|
+
|
|
352
602
|
/**
|
|
353
603
|
* Render a JS object key — bare identifier when the prop is camelCase + valid
|
|
354
604
|
* JS id, quoted otherwise. Mirrors how authors write JSX styles.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file canvas-icons.tsx — Phase 5.1 inline-SVG icon set
|
|
3
|
-
* @scope
|
|
3
|
+
* @scope apps/studio/canvas-icons.tsx
|
|
4
4
|
* @purpose Tiny dependency-free Lucide-style icon set for the canvas
|
|
5
5
|
* chrome (tool palette, context toolbar). Each icon is a single
|
|
6
6
|
* `<svg>` with `currentColor` stroke so it inherits the button
|
|
@@ -122,6 +122,18 @@ export function IconText(props: IconProps) {
|
|
|
122
122
|
);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
// Phase 23 — link (chain) glyph, used by the annotation context toolbar's
|
|
126
|
+
// "Open link" button. (Media is paste/drop-only — no toolbar buttons — so the
|
|
127
|
+
// picture-frame image icon was dropped.)
|
|
128
|
+
export function IconLink(props: IconProps) {
|
|
129
|
+
return (
|
|
130
|
+
<Svg {...props}>
|
|
131
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
|
|
132
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
|
|
133
|
+
</Svg>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
125
137
|
export function IconPresentation(props: IconProps) {
|
|
126
138
|
return (
|
|
127
139
|
<Svg {...props}>
|
|
@@ -404,16 +416,65 @@ export function IconAlignRight(props: IconProps) {
|
|
|
404
416
|
);
|
|
405
417
|
}
|
|
406
418
|
|
|
419
|
+
// ── Annotation polish text-style icons (italic / underline / lists) ──────────
|
|
420
|
+
export function IconItalic(props: IconProps) {
|
|
421
|
+
return (
|
|
422
|
+
<Svg {...props}>
|
|
423
|
+
<path d="M10 5h8M6 19h8M14 5l-4 14" />
|
|
424
|
+
</Svg>
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
export function IconUnderline(props: IconProps) {
|
|
428
|
+
return (
|
|
429
|
+
<Svg {...props}>
|
|
430
|
+
<path d="M7 4v7a5 5 0 0010 0V4M5 20h14" />
|
|
431
|
+
</Svg>
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
export function IconListBullet(props: IconProps) {
|
|
435
|
+
return (
|
|
436
|
+
<Svg {...props}>
|
|
437
|
+
<path d="M9 6h11M9 12h11M9 18h11" />
|
|
438
|
+
<circle cx="4.5" cy="6" r="1.1" fill="currentColor" stroke="none" />
|
|
439
|
+
<circle cx="4.5" cy="12" r="1.1" fill="currentColor" stroke="none" />
|
|
440
|
+
<circle cx="4.5" cy="18" r="1.1" fill="currentColor" stroke="none" />
|
|
441
|
+
</Svg>
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
export function IconListOrdered(props: IconProps) {
|
|
445
|
+
return (
|
|
446
|
+
<Svg {...props}>
|
|
447
|
+
<path d="M10 6h10M10 12h10M10 18h10" />
|
|
448
|
+
<path d="M3 5l1.4-.5V9M3 9h2.8" strokeWidth={1.4} />
|
|
449
|
+
<path d="M3.2 14.2a1 1 0 011.7.7c0 .9-1.7 1.4-1.7 2.6h2" strokeWidth={1.4} />
|
|
450
|
+
</Svg>
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// ── Annotation polish — highlighter (chisel-tip marker) ──────────────────────
|
|
455
|
+
export function IconHighlighter(props: IconProps) {
|
|
456
|
+
return (
|
|
457
|
+
<Svg {...props}>
|
|
458
|
+
<path d="M14 4l6 6-8.5 8.5H6v-5.5z" />
|
|
459
|
+
<path d="M11 7l6 6" />
|
|
460
|
+
<path d="M4 21h7" strokeWidth={2.5} />
|
|
461
|
+
</Svg>
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
407
465
|
export const TOOL_ICONS: Record<string, (p: IconProps) => JSX.Element> = {
|
|
408
466
|
move: IconMove,
|
|
409
467
|
hand: IconHand,
|
|
410
468
|
comment: IconComment,
|
|
411
469
|
pen: IconPen,
|
|
470
|
+
highlighter: IconHighlighter,
|
|
412
471
|
// Phase 24 — single Shape tool. rect/ellipse kept for any legacy lookups.
|
|
413
472
|
shape: IconShape,
|
|
414
473
|
rect: IconRect,
|
|
415
474
|
ellipse: IconEllipse,
|
|
416
475
|
sticky: IconSticky,
|
|
476
|
+
// FigJam v3 — labelled organizing container.
|
|
477
|
+
section: IconSection,
|
|
417
478
|
arrow: IconArrow,
|
|
418
479
|
text: IconText,
|
|
419
480
|
eraser: IconEraser,
|
|
@@ -428,3 +489,106 @@ export const SHAPE_KIND_ICONS: Record<string, (p: IconProps) => JSX.Element> = {
|
|
|
428
489
|
triangle: IconTriangle,
|
|
429
490
|
'triangle-down': IconTriangleDown,
|
|
430
491
|
};
|
|
492
|
+
|
|
493
|
+
// ── FigJam v3 — multi-select manipulation icons ──────────────────────────────
|
|
494
|
+
// Object align (an edge line + two boxes), distribute (rails + a box), and
|
|
495
|
+
// group/ungroup. Same 24×24 stroke language as the rest of the set.
|
|
496
|
+
|
|
497
|
+
export function IconObjAlignLeft(props: IconProps) {
|
|
498
|
+
return (
|
|
499
|
+
<Svg {...props}>
|
|
500
|
+
<path d="M4 3v18" />
|
|
501
|
+
<rect x="7" y="6" width="11" height="4" rx="1" />
|
|
502
|
+
<rect x="7" y="14" width="6" height="4" rx="1" />
|
|
503
|
+
</Svg>
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
export function IconObjAlignHCenter(props: IconProps) {
|
|
507
|
+
return (
|
|
508
|
+
<Svg {...props}>
|
|
509
|
+
<path d="M12 3v2M12 19v2" />
|
|
510
|
+
<rect x="6" y="6" width="12" height="4" rx="1" />
|
|
511
|
+
<rect x="8" y="14" width="8" height="4" rx="1" />
|
|
512
|
+
</Svg>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
export function IconObjAlignRight(props: IconProps) {
|
|
516
|
+
return (
|
|
517
|
+
<Svg {...props}>
|
|
518
|
+
<path d="M20 3v18" />
|
|
519
|
+
<rect x="6" y="6" width="11" height="4" rx="1" />
|
|
520
|
+
<rect x="11" y="14" width="6" height="4" rx="1" />
|
|
521
|
+
</Svg>
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
export function IconObjAlignTop(props: IconProps) {
|
|
525
|
+
return (
|
|
526
|
+
<Svg {...props}>
|
|
527
|
+
<path d="M3 4h18" />
|
|
528
|
+
<rect x="6" y="7" width="4" height="11" rx="1" />
|
|
529
|
+
<rect x="14" y="7" width="4" height="6" rx="1" />
|
|
530
|
+
</Svg>
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
export function IconObjAlignVCenter(props: IconProps) {
|
|
534
|
+
return (
|
|
535
|
+
<Svg {...props}>
|
|
536
|
+
<path d="M3 12h2M19 12h2" />
|
|
537
|
+
<rect x="6" y="6" width="4" height="12" rx="1" />
|
|
538
|
+
<rect x="14" y="8" width="4" height="8" rx="1" />
|
|
539
|
+
</Svg>
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
export function IconObjAlignBottom(props: IconProps) {
|
|
543
|
+
return (
|
|
544
|
+
<Svg {...props}>
|
|
545
|
+
<path d="M3 20h18" />
|
|
546
|
+
<rect x="6" y="6" width="4" height="11" rx="1" />
|
|
547
|
+
<rect x="14" y="11" width="4" height="6" rx="1" />
|
|
548
|
+
</Svg>
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
export function IconDistributeH(props: IconProps) {
|
|
552
|
+
return (
|
|
553
|
+
<Svg {...props}>
|
|
554
|
+
<path d="M4 3v18M20 3v18" />
|
|
555
|
+
<rect x="9" y="8" width="6" height="8" rx="1" />
|
|
556
|
+
</Svg>
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
export function IconDistributeV(props: IconProps) {
|
|
560
|
+
return (
|
|
561
|
+
<Svg {...props}>
|
|
562
|
+
<path d="M3 4h18M3 20h18" />
|
|
563
|
+
<rect x="8" y="9" width="8" height="6" rx="1" />
|
|
564
|
+
</Svg>
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
export function IconGroup(props: IconProps) {
|
|
568
|
+
return (
|
|
569
|
+
<Svg {...props}>
|
|
570
|
+
<path d="M3 7V4a1 1 0 011-1h3M17 3h3a1 1 0 011 1v3M21 17v3a1 1 0 01-1 1h-3M7 21H4a1 1 0 01-1-1v-3" />
|
|
571
|
+
<rect x="7" y="7" width="6" height="6" rx="1" />
|
|
572
|
+
<rect x="11" y="11" width="6" height="6" rx="1" />
|
|
573
|
+
</Svg>
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
export function IconUngroup(props: IconProps) {
|
|
577
|
+
return (
|
|
578
|
+
<Svg {...props}>
|
|
579
|
+
<rect x="4" y="4" width="7" height="7" rx="1" />
|
|
580
|
+
<rect x="13" y="13" width="7" height="7" rx="1" />
|
|
581
|
+
<path d="M15 6l3 3M6 15l3 3" />
|
|
582
|
+
</Svg>
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/** FigJam v3 — section tool: a region with its name chip docked top-left. */
|
|
587
|
+
export function IconSection(props: IconProps) {
|
|
588
|
+
return (
|
|
589
|
+
<Svg {...props}>
|
|
590
|
+
<rect x="4" y="8" width="16" height="12" rx="2" />
|
|
591
|
+
<path d="M4 4h7" />
|
|
592
|
+
</Svg>
|
|
593
|
+
);
|
|
594
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
// `/design:handoff` emits a self-contained shadcn registry-item.json. Canvases
|
|
5
5
|
// import their envelope + helpers from `@maude/canvas-lib`, which the dev-server
|
|
6
|
-
// resolves to its bundled `
|
|
6
|
+
// resolves to its bundled `apps/studio/canvas-lib.tsx`. The
|
|
7
7
|
// handoff drop must inline every used export so the consumer never sees the
|
|
8
8
|
// `@maude/canvas-lib` specifier — it's a dev-time virtual module, not a real
|
|
9
9
|
// npm dep.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Canvases import the shared canvas library via the specifier `@maude/canvas-lib`.
|
|
4
4
|
// At build time we redirect that to the dev-server-bundled source at
|
|
5
|
-
// `
|
|
5
|
+
// `apps/studio/canvas-lib.tsx` so:
|
|
6
6
|
//
|
|
7
7
|
// - the lib ships with the dev-server install (single source of truth — see
|
|
8
8
|
// DDR-025; reverses DDR-022's "project-owned source under <designRoot>/_lib/"),
|