@agent-native/core 0.92.10 → 0.92.12
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +29 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +214 -17
- package/corpus/core/src/agent/run-manager.ts +72 -14
- package/corpus/core/src/agent/run-store.ts +152 -27
- package/corpus/core/src/cli/design-connect.ts +433 -151
- package/corpus/core/src/cli/skills.ts +14 -0
- package/corpus/core/src/client/AssistantChat.tsx +25 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +40 -6
- package/corpus/core/src/client/agent-chat-adapter.ts +56 -12
- package/corpus/core/src/client/agent-chat.ts +165 -1
- package/corpus/core/src/client/chat/index.ts +9 -1
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +38 -2
- package/corpus/core/src/client/index.ts +5 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +18 -7
- package/corpus/core/src/collab/awareness-store.ts +23 -12
- package/corpus/core/src/collab/client.ts +16 -5
- package/corpus/core/src/collab/index.ts +4 -0
- package/corpus/core/src/collab/recent-edits.ts +65 -2
- package/corpus/core/src/index.browser.ts +1 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +98 -11
- package/corpus/core/src/server/builder-design-systems.ts +30 -4
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +12 -6
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/create-recording.ts +2 -0
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +5 -3
- package/corpus/templates/clips/actions/request-transcript.ts +102 -33
- package/corpus/templates/clips/app/components/library/library-grid.tsx +1 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +59 -19
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +75 -9
- package/corpus/templates/clips/app/components/player/video-player.tsx +17 -12
- package/corpus/templates/clips/app/hooks/use-player-shortcuts.ts +1 -0
- package/corpus/templates/clips/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -37
- package/corpus/templates/clips/app/routes/record.tsx +17 -4
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-popover-sits-closer-to-the-menu-bar.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-recording-optimization-progress-stays-visible-until-the-clip-opens.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-large-video-file-uploads-failing-before-their-resumabl.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-new-video-uploads-defaulting-to-private.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-long-recordings-now-get-enough-time-to-download-their-media-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-meeting-notes-no-longer-lowers-your-microphone-volume-for-ot.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-on-mobile-tapping-a-playing-clip-reveals-playback-controls-w.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-regenerate-any-clip-transcript-from-its-saved-recording-or-r.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-slack-previews-now-show-the-clip-length-alongside-its-descri.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-fixed-copying-agent-responses-and-transcript-text-from-recor.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +12 -2
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +8 -1
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -5
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +5 -5
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +3 -0
- package/corpus/templates/clips/desktop/src/styles.css +6 -3
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +29 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +103 -21
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +117 -39
- package/corpus/templates/clips/server/lib/slack-unfurls.ts +20 -1
- package/corpus/templates/clips/server/lib/streaming-upload-mode.ts +10 -4
- package/corpus/templates/clips/shared/recording-core.ts +12 -0
- package/corpus/templates/content/AGENTS.md +7 -6
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +82 -7
- package/corpus/templates/content/actions/_database-source-utils.ts +149 -30
- package/corpus/templates/content/actions/_document-flush.ts +132 -17
- package/corpus/templates/content/actions/_notion-action-utils.ts +15 -0
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +4 -7
- package/corpus/templates/content/actions/attach-content-database-source.ts +41 -17
- package/corpus/templates/content/actions/change-content-database-source-role.ts +46 -8
- package/corpus/templates/content/actions/create-and-link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/pull-document.ts +5 -7
- package/corpus/templates/content/actions/pull-notion-page.ts +2 -0
- package/corpus/templates/content/actions/push-notion-page.ts +10 -0
- package/corpus/templates/content/actions/resolve-notion-sync-conflict.ts +2 -0
- package/corpus/templates/content/actions/suggest-source-join-key.ts +8 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +88 -23
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +32 -2
- package/corpus/templates/content/app/hooks/use-notion.ts +6 -6
- package/corpus/templates/content/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/content/app/i18n-data.ts +18 -0
- package/corpus/templates/content/changelog/2026-07-09-builder-source-refreshes-now-keep-mapped-fields-such-as-topi.md +6 -0
- package/corpus/templates/content/changelog/2026-07-09-notion-conflict-choices-and-version-restores-preserve-docume.md +6 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +80 -64
- package/corpus/templates/content/shared/api.ts +1 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +29 -2
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +86 -0
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +57 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +11 -0
- package/corpus/templates/design/AGENTS.md +45 -10
- package/corpus/templates/design/actions/add-localhost-screens.ts +66 -13
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +45 -36
- package/corpus/templates/design/actions/apply-motion-edit.ts +25 -31
- package/corpus/templates/design/actions/apply-shader-fill.ts +29 -42
- package/corpus/templates/design/actions/detach-component-instance.ts +337 -0
- package/corpus/templates/design/actions/export-design-as-figma-svg.ts +219 -0
- package/corpus/templates/design/actions/generate-design.ts +79 -12
- package/corpus/templates/design/actions/generate-screens.ts +57 -12
- package/corpus/templates/design/actions/get-figma-styles.ts +115 -0
- package/corpus/templates/design/actions/go-to-main-component.ts +254 -0
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +4 -3
- package/corpus/templates/design/actions/import-design-source.ts +4 -31
- package/corpus/templates/design/actions/import-figma-clipboard.ts +134 -0
- package/corpus/templates/design/actions/import-figma-frame.ts +95 -0
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/design/actions/list-design-components.ts +104 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +1 -24
- package/corpus/templates/design/actions/open-component-source.ts +2 -4
- package/corpus/templates/design/actions/present-design-variants.ts +412 -16
- package/corpus/templates/design/actions/preview-source-edit.ts +14 -1
- package/corpus/templates/design/actions/run-design-audit.ts +25 -3
- package/corpus/templates/design/actions/show-design-questions.ts +10 -0
- package/corpus/templates/design/actions/swap-component-instance.ts +544 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +45 -60
- package/corpus/templates/design/actions/write-local-file.ts +25 -1
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +152 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1077 -58
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +5 -5
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +73 -21
- package/corpus/templates/design/app/components/design/EditPanel.tsx +16 -11
- package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +364 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +180 -53
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +0 -2
- package/corpus/templates/design/app/components/design/MotionDock.tsx +144 -21
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1152 -167
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +27 -5
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +23 -2
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +63 -49
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +1293 -54
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +6 -1
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +23 -6
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +5 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +14 -2
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +37 -2
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open-guard.ts +25 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +19 -1
- package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +43 -5
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +27 -2
- package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +10 -1
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +19 -2
- package/corpus/templates/design/app/components/design/design-canvas/annotation-snapshot.ts +265 -0
- package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +16 -5
- package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +16 -2
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +7 -2
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +3 -1
- package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +78 -8
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +451 -73
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +12 -4
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +398 -272
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +41 -7
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +16 -3
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +24 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +222 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +171 -78
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +45 -5
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +299 -28
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +120 -150
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +53 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +284 -117
- package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +81 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +19 -14
- package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +7 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +155 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +268 -46
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +350 -31
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +233 -23
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +72 -2
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +51 -11
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +84 -11
- package/corpus/templates/design/app/components/design/inspector/index.ts +3 -0
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +552 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +157 -0
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +53 -0
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +184 -0
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +403 -26
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +20 -1
- package/corpus/templates/design/app/components/design/types.ts +33 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +59 -7
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +119 -17
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +275 -63
- package/corpus/templates/design/app/hooks/use-question-flow.ts +14 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +67 -10
- package/corpus/templates/design/app/i18n/zh-TW.ts +91 -1
- package/corpus/templates/design/app/i18n-data.ts +1217 -10
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +577 -0
- package/corpus/templates/design/app/lib/agent-chat.ts +23 -0
- package/corpus/templates/design/app/lib/design-import.ts +24 -0
- package/corpus/templates/design/app/lib/figma-clipboard.ts +157 -0
- package/corpus/templates/design/app/lib/figma-svg-copy.ts +221 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +143 -30
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +15 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +33 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +38 -0
- package/corpus/templates/design/app/pages/design-editor/overview-annotation-context.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +62 -6
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +245 -0
- package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +586 -0
- package/corpus/templates/design/app/pages/design-editor/screen-auto-layout.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +201 -1
- package/corpus/templates/design/changelog/2026-07-09-added-underline-strikethrough-and-text-case-uppercase-lowerc.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-annotate-now-draws-across-the-all-screens-canvas-without-swi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-auto-layout-children-can-now-be-dragged-into-freeform-screen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-board-shapes-now-stay-visible-and-nest-correctly-across-the-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-component-source-navigation-now-opens-reliably-from-the-insp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-local-react-layer-moves-now-hand-off-exact-sour.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-moves-undo-and-redo-now-keep-both-screens-stabl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-detach-a-component-instance-into-plain-editable-eleme.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-dragging-layers-into-auto-layout-now-respects-ignore-auto-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-drawing-annotations-sent-to-the-agent-now-include-a-rendered.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-editor-sidebars-now-use-figma-matched-default-widths-for-a-r.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-empty-frames-and-rectangles-now-expose-full-auto-layout-cont.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-export-any-design-screen-as-a-real-vector-svg-for-figma-with.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-grid-auto-layout-now-uses-true-responsive-rows-and-columns-w.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-hidden-and-locked-screens-now-behave-consistently-between-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-image-fills-now-preserve-valid-urls-and-layered-fit-settings.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-import-figma-frames-as-pixel-accurate-design-screens-via-a-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspect-code-now-hides-internal-styling-metadata-and-wraps-l.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspector-blur-and-shadow-effects-now-preserve-other-effects.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-jump-to-a-components-other-instances-from-the-inspecto.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-keyboard-shortcuts-are-now-discoverable-in-a-figma-style-bot.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layer-selection-now-keeps-cmd-or-ctrl-toggles-and-shift-rang.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layers-dropped-into-auto-layout-now-participate-correctly-in.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-live-edit-screens-now-enter-and-leave-full-view-withou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-preview-urls-now-live-in-the-inspector-instead-of-taki.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-can-now-be-hidden-and-locked-from-layers-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-now-keep-exact-source-provenance-and-supp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-visual-editing-now-loads-reliably-and-shows-live.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-paste-from-figma-cmd-v-now-imports-exact-editable-nodes-when.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-pressing-escape-after-selecting-a-screen-now-reveals-page-pr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-right-click-overlapping-or-nested-objects-to-choose-the-exac.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-scale-edge-stretch-and-center-constraints-now-preserve-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-rows-can-now-be-reordered-in-layers-with-matching-can.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-selection-stays-responsive-in-designs-with-hundreds-o.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-shift-a-now-enables-auto-layout-on-a-selected-screen-with-fl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-swap-a-component-instance-for-another-from-the-libra.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-drawing-annotations-now-stay-available-to-retry-when-the.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +3 -6
- package/corpus/templates/design/e2e/helpers.ts +27 -6
- package/corpus/templates/design/server/lib/design-to-figma-svg.ts +1412 -0
- package/corpus/templates/design/server/lib/figma-clipboard-match.ts +196 -0
- package/corpus/templates/design/server/lib/figma-node-import.ts +311 -0
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +1334 -0
- package/corpus/templates/design/server/lib/figma-paste-fallback.ts +64 -0
- package/corpus/templates/design/server/lib/playwright-runtime.ts +78 -0
- package/corpus/templates/design/server/plugins/db.ts +41 -0
- package/corpus/templates/design/server/source-workspace.ts +64 -0
- package/corpus/templates/design/shared/board-file.ts +13 -2
- package/corpus/templates/design/shared/canvas-math.ts +231 -33
- package/corpus/templates/design/shared/code-layer.ts +122 -8
- package/corpus/templates/design/shared/component-library.ts +161 -0
- package/corpus/templates/design/shared/db-conflict.ts +27 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +2 -1
- package/corpus/templates/design/shared/figma-url.ts +149 -0
- package/corpus/templates/design/shared/pen-path.ts +16 -7
- package/corpus/templates/design/shared/source-mode.ts +1 -0
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +7 -19
- package/corpus/templates/plan/changelog/2026-07-09-canvas-panning-now-keeps-zoom-fixed-even-at-the-edges.md +6 -0
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +311 -70
- package/corpus/templates/slides/changelog/2026-07-09-fixed-the-slide-rail-going-permanently-stale-during-a-long-a.md +6 -0
- package/dist/agent/production-agent.d.ts +82 -7
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +180 -17
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +63 -14
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +46 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +129 -22
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/design-connect.d.ts +6 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +336 -139
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +14 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +19 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +38 -18
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +48 -12
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.d.ts +60 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +122 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts +12 -0
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +36 -2
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +18 -6
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/collab/awareness-store.d.ts +5 -0
- package/dist/collab/awareness-store.d.ts.map +1 -1
- package/dist/collab/awareness-store.js +19 -12
- package/dist/collab/awareness-store.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +13 -5
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +1 -0
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +1 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +3 -1
- package/dist/collab/recent-edits.d.ts.map +1 -1
- package/dist/collab/recent-edits.js +57 -2
- package/dist/collab/recent-edits.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +87 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/builder-design-systems.d.ts +15 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +9 -4
- package/dist/server/builder-design-systems.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useActionMutation,
|
|
3
|
+
useActionQuery,
|
|
4
|
+
useT,
|
|
5
|
+
} from "@agent-native/core/client";
|
|
2
6
|
import { propNameToDataAttribute } from "@shared/component-model";
|
|
3
7
|
import {
|
|
4
8
|
IconArrowRight,
|
|
9
|
+
IconArrowsLeftRight,
|
|
5
10
|
IconCode,
|
|
11
|
+
IconComponents,
|
|
6
12
|
IconExternalLink,
|
|
7
13
|
IconLoader2,
|
|
14
|
+
IconUnlink,
|
|
8
15
|
} from "@tabler/icons-react";
|
|
9
16
|
import { useQueryClient } from "@tanstack/react-query";
|
|
10
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
17
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
18
|
import { toast } from "sonner";
|
|
12
19
|
|
|
13
20
|
import { Button } from "@/components/ui/button";
|
|
14
21
|
import { Input } from "@/components/ui/input";
|
|
15
22
|
import { Label } from "@/components/ui/label";
|
|
23
|
+
import {
|
|
24
|
+
Popover,
|
|
25
|
+
PopoverContent,
|
|
26
|
+
PopoverTrigger,
|
|
27
|
+
} from "@/components/ui/popover";
|
|
16
28
|
import {
|
|
17
29
|
Select,
|
|
18
30
|
SelectContent,
|
|
@@ -91,6 +103,7 @@ function MakeItRealCard({
|
|
|
91
103
|
*/
|
|
92
104
|
featureLabel: string;
|
|
93
105
|
}) {
|
|
106
|
+
const t = useT();
|
|
94
107
|
const { data, isLoading } = useActionQuery<ConnectBuilderAppResult>(
|
|
95
108
|
"connect-builder-app",
|
|
96
109
|
{ designId },
|
|
@@ -160,7 +173,7 @@ function MakeItRealCard({
|
|
|
160
173
|
rel="noopener noreferrer"
|
|
161
174
|
className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md px-1.5 text-[10px] font-semibold text-[var(--design-editor-accent-color)] hover:bg-[var(--design-editor-panel-raised-bg)]"
|
|
162
175
|
>
|
|
163
|
-
{"
|
|
176
|
+
{t("designEditor.makeItRealCard.open")}
|
|
164
177
|
<IconExternalLink className="size-2.5" />
|
|
165
178
|
</a>
|
|
166
179
|
</div>
|
|
@@ -173,8 +186,8 @@ function MakeItRealCard({
|
|
|
173
186
|
: `Connect Builder to enable ${featureLabel}.`;
|
|
174
187
|
const primaryLabel =
|
|
175
188
|
cta.kind === "configure-project"
|
|
176
|
-
? "
|
|
177
|
-
: "
|
|
189
|
+
? t("designEditor.makeItRealCard.choose")
|
|
190
|
+
: t("designEditor.makeItRealCard.connect");
|
|
178
191
|
|
|
179
192
|
return (
|
|
180
193
|
<div className="space-y-1">
|
|
@@ -213,10 +226,10 @@ function MakeItRealCard({
|
|
|
213
226
|
{isPending ? (
|
|
214
227
|
<>
|
|
215
228
|
<IconLoader2 className="size-2.5 animate-spin" />
|
|
216
|
-
{"
|
|
229
|
+
{t("designEditor.makeItRealCard.generating")}
|
|
217
230
|
</>
|
|
218
231
|
) : (
|
|
219
|
-
<>{"
|
|
232
|
+
<>{t("designEditor.makeItRealCard.generate")}</>
|
|
220
233
|
)}
|
|
221
234
|
</Button>
|
|
222
235
|
)}
|
|
@@ -225,7 +238,7 @@ function MakeItRealCard({
|
|
|
225
238
|
<p className="px-2 text-[10px] text-destructive">
|
|
226
239
|
{migrateError instanceof Error
|
|
227
240
|
? migrateError.message
|
|
228
|
-
:
|
|
241
|
+
: t("designEditor.makeItRealCard.migrationFailed")}
|
|
229
242
|
</p>
|
|
230
243
|
) : null}
|
|
231
244
|
</div>
|
|
@@ -260,6 +273,150 @@ interface ComponentDetailsResult {
|
|
|
260
273
|
};
|
|
261
274
|
}
|
|
262
275
|
|
|
276
|
+
/** Shape returned by `go-to-main-component`. */
|
|
277
|
+
interface GoToMainComponentResult {
|
|
278
|
+
isMain?: boolean;
|
|
279
|
+
ctaRequired?: boolean;
|
|
280
|
+
ctaMessage?: string;
|
|
281
|
+
note?: string;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Shape returned by `swap-component-instance`. */
|
|
285
|
+
interface SwapComponentInstanceResult {
|
|
286
|
+
swapped?: boolean;
|
|
287
|
+
conflict?: boolean;
|
|
288
|
+
ctaRequired?: boolean;
|
|
289
|
+
ctaMessage?: string;
|
|
290
|
+
error?: string;
|
|
291
|
+
note?: string;
|
|
292
|
+
fromComponent?: string;
|
|
293
|
+
toComponent?: string;
|
|
294
|
+
fileId?: string;
|
|
295
|
+
content?: string;
|
|
296
|
+
updatedAt?: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** Shape returned by `detach-component-instance`. */
|
|
300
|
+
interface DetachComponentInstanceResult {
|
|
301
|
+
detached?: boolean;
|
|
302
|
+
conflict?: boolean;
|
|
303
|
+
ctaRequired?: boolean;
|
|
304
|
+
ctaMessage?: string;
|
|
305
|
+
error?: string;
|
|
306
|
+
note?: string;
|
|
307
|
+
fileId?: string;
|
|
308
|
+
content?: string;
|
|
309
|
+
updatedAt?: string;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** Each editable row: name + current value + how it persists + its options. */
|
|
313
|
+
export type PropRow = {
|
|
314
|
+
name: string;
|
|
315
|
+
value: string;
|
|
316
|
+
/** Variant/enum options when the prop is a known group. */
|
|
317
|
+
options?: string[];
|
|
318
|
+
/** Persist surface for this prop. */
|
|
319
|
+
surface: "alpineData" | "attribute";
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Build the editable prop rows for a component instance from
|
|
324
|
+
* `get-component-details`'s response: Alpine `x-data` keys first (they drive
|
|
325
|
+
* the live variant/state), then observed `data-agent-native-prop-*`
|
|
326
|
+
* attributes not already covered by x-data, then any persisted variant group
|
|
327
|
+
* that has never been observed on this instance at all (seeded to its first
|
|
328
|
+
* option).
|
|
329
|
+
*
|
|
330
|
+
* Pure — exported for tests.
|
|
331
|
+
*/
|
|
332
|
+
export function buildComponentPropRows(data: {
|
|
333
|
+
instance?: { alpineData?: string | null } | null;
|
|
334
|
+
observedProps: Array<{ name: string; value: string }>;
|
|
335
|
+
persistedVariants: Record<string, string[]>;
|
|
336
|
+
}): PropRow[] {
|
|
337
|
+
const { observedProps, persistedVariants, instance } = data;
|
|
338
|
+
const alpineData = parseAlpineDataObject(instance?.alpineData);
|
|
339
|
+
|
|
340
|
+
const rows: PropRow[] = [];
|
|
341
|
+
const seen = new Set<string>();
|
|
342
|
+
|
|
343
|
+
// 1) Alpine x-data keys come first — they drive the live variant/state.
|
|
344
|
+
if (alpineData) {
|
|
345
|
+
for (const [key, value] of Object.entries(alpineData)) {
|
|
346
|
+
rows.push({
|
|
347
|
+
name: key,
|
|
348
|
+
value,
|
|
349
|
+
options: persistedVariants[key],
|
|
350
|
+
surface: "alpineData",
|
|
351
|
+
});
|
|
352
|
+
seen.add(key);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 2) data-agent-native-prop-* attributes not already covered by x-data.
|
|
357
|
+
for (const prop of observedProps) {
|
|
358
|
+
if (seen.has(prop.name)) continue;
|
|
359
|
+
rows.push({
|
|
360
|
+
name: prop.name,
|
|
361
|
+
value: prop.value,
|
|
362
|
+
options: persistedVariants[prop.name],
|
|
363
|
+
surface: "attribute",
|
|
364
|
+
});
|
|
365
|
+
seen.add(prop.name);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 3) persistedVariant groups with no observed value yet (default to first).
|
|
369
|
+
// Surface is always "attribute" here, NOT "alpineData" even when this
|
|
370
|
+
// instance's x-data happens to be non-empty for other keys: x-data blocks
|
|
371
|
+
// for a real component instance are written with every prop the component
|
|
372
|
+
// declares initialized up front (e.g. `{ variant: 'solid', size: 'md' }`),
|
|
373
|
+
// so a group that never showed up in step 1 was never a x-data key on this
|
|
374
|
+
// instance in the first place — it is attribute-driven. Guessing
|
|
375
|
+
// "alpineData" from unrelated sibling keys used to route the very first
|
|
376
|
+
// edit of such a prop into a surgical/rebuild x-data write that either
|
|
377
|
+
// silently wrote a key nothing in the template reads, or hit the "can't
|
|
378
|
+
// safely edit this prop inline" bail-out when the sibling x-data content
|
|
379
|
+
// was too complex to rebuild — even though the plain attribute write would
|
|
380
|
+
// have worked fine.
|
|
381
|
+
for (const [group, options] of Object.entries(persistedVariants)) {
|
|
382
|
+
if (seen.has(group)) continue;
|
|
383
|
+
rows.push({
|
|
384
|
+
name: group,
|
|
385
|
+
value: options[0] ?? "",
|
|
386
|
+
options,
|
|
387
|
+
surface: "attribute",
|
|
388
|
+
});
|
|
389
|
+
seen.add(group);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return rows;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* True when a "message" event's source window matches one of this document's
|
|
397
|
+
* own embedded design-preview iframes.
|
|
398
|
+
*
|
|
399
|
+
* `postMessage` has no origin/source check built in, so without this any
|
|
400
|
+
* window — including a spoofed one from a compromised/unrelated frame — could
|
|
401
|
+
* post `{ type: "element-select" }` at the parent and force this section to
|
|
402
|
+
* refetch. Mirrors the DOM-identity check DesignCanvas's
|
|
403
|
+
* `isTrustedCanvasBridgeMessage` and MultiScreenCanvas's cross-screen-drag
|
|
404
|
+
* handler use: trust comes from matching `iframe.contentWindow` against
|
|
405
|
+
* `event.source`, not from anything in the message payload.
|
|
406
|
+
*
|
|
407
|
+
* Exported for tests.
|
|
408
|
+
*/
|
|
409
|
+
export function isMessageFromOwnPreviewIframe(
|
|
410
|
+
source: MessageEventSource | null,
|
|
411
|
+
): boolean {
|
|
412
|
+
if (typeof document === "undefined" || !source) return false;
|
|
413
|
+
return Array.from(
|
|
414
|
+
document.querySelectorAll<HTMLIFrameElement>(
|
|
415
|
+
"iframe[data-design-preview-iframe]",
|
|
416
|
+
),
|
|
417
|
+
).some((iframe) => iframe.contentWindow === source);
|
|
418
|
+
}
|
|
419
|
+
|
|
263
420
|
/**
|
|
264
421
|
* Contextual COMPONENT section rendered inside the Design tab when the
|
|
265
422
|
* selected element is a component instance (carries
|
|
@@ -279,6 +436,7 @@ export function ComponentSection({
|
|
|
279
436
|
activeContent,
|
|
280
437
|
activeFileUpdatedAt,
|
|
281
438
|
nodeId,
|
|
439
|
+
swapPickerRequest = 0,
|
|
282
440
|
onComponentPropApplied,
|
|
283
441
|
sourceCapabilities = [],
|
|
284
442
|
}: {
|
|
@@ -287,6 +445,8 @@ export function ComponentSection({
|
|
|
287
445
|
activeContent?: string;
|
|
288
446
|
activeFileUpdatedAt?: string | null;
|
|
289
447
|
nodeId: string;
|
|
448
|
+
/** Increment to open the Swap instance picker from another UI entry point. */
|
|
449
|
+
swapPickerRequest?: number;
|
|
290
450
|
onComponentPropApplied?: (
|
|
291
451
|
fileId: string,
|
|
292
452
|
content: string,
|
|
@@ -295,6 +455,7 @@ export function ComponentSection({
|
|
|
295
455
|
/** Capability names advertised by the current source. */
|
|
296
456
|
sourceCapabilities?: string[];
|
|
297
457
|
}) {
|
|
458
|
+
const t = useT();
|
|
298
459
|
const queryClient = useQueryClient();
|
|
299
460
|
const detailsParams = { designId, nodeId, ...(fileId ? { fileId } : {}) };
|
|
300
461
|
const detailsKey = ["action", "get-component-details", detailsParams];
|
|
@@ -322,6 +483,153 @@ export function ComponentSection({
|
|
|
322
483
|
|
|
323
484
|
const openSourceMutation = useActionMutation("open-component-source");
|
|
324
485
|
const applyPropMutation = useActionMutation("apply-component-prop-edit");
|
|
486
|
+
const goToMainMutation = useActionMutation("go-to-main-component");
|
|
487
|
+
const detachMutation = useActionMutation("detach-component-instance");
|
|
488
|
+
const swapMutation = useActionMutation("swap-component-instance");
|
|
489
|
+
|
|
490
|
+
// ── Swap instance picker (searchable popover) ─────────────────────────────
|
|
491
|
+
const [swapPickerOpen, setSwapPickerOpen] = useState(false);
|
|
492
|
+
const [swapQuery, setSwapQuery] = useState("");
|
|
493
|
+
useEffect(() => {
|
|
494
|
+
if (swapPickerRequest > 0) setSwapPickerOpen(true);
|
|
495
|
+
}, [swapPickerRequest]);
|
|
496
|
+
const componentName = data?.name;
|
|
497
|
+
const { data: swapCatalog, isLoading: swapCatalogLoading } = useActionQuery(
|
|
498
|
+
"list-design-components",
|
|
499
|
+
{ designId, excludeName: componentName },
|
|
500
|
+
{ enabled: swapPickerOpen && Boolean(componentName) },
|
|
501
|
+
);
|
|
502
|
+
const swapCandidates = (swapCatalog?.components ?? []).filter((c) =>
|
|
503
|
+
c.name.toLowerCase().includes(swapQuery.trim().toLowerCase()),
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
// Refresh the component section + design canvas after a detach/swap
|
|
507
|
+
// mutates the design file, mirroring persistPropEdit's onSettled below.
|
|
508
|
+
// Plain function (not memoized) — matches this file's existing
|
|
509
|
+
// persistPropEdit/commitProp convention of re-creating handlers per render
|
|
510
|
+
// rather than threading useCallback dependency arrays through them.
|
|
511
|
+
const refreshAfterInstanceMutation = (result: {
|
|
512
|
+
fileId?: string;
|
|
513
|
+
content?: string;
|
|
514
|
+
updatedAt?: string;
|
|
515
|
+
}) => {
|
|
516
|
+
if (
|
|
517
|
+
typeof result.fileId === "string" &&
|
|
518
|
+
typeof result.content === "string"
|
|
519
|
+
) {
|
|
520
|
+
latestSourceRef.current = {
|
|
521
|
+
content: result.content,
|
|
522
|
+
revision: result.updatedAt ?? latestSourceRef.current.revision,
|
|
523
|
+
};
|
|
524
|
+
onComponentPropApplied?.(result.fileId, result.content, result.updatedAt);
|
|
525
|
+
}
|
|
526
|
+
void queryClient.invalidateQueries({ queryKey: ["action", "get-design"] });
|
|
527
|
+
void queryClient.invalidateQueries({ queryKey: detailsKey });
|
|
528
|
+
void refetch();
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
const sourceForMutation = () => {
|
|
532
|
+
const latestSource = latestSourceRef.current;
|
|
533
|
+
return latestSource.content
|
|
534
|
+
? {
|
|
535
|
+
currentContent: latestSource.content,
|
|
536
|
+
...(latestSource.revision ? { revision: latestSource.revision } : {}),
|
|
537
|
+
}
|
|
538
|
+
: undefined;
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
const handleGoToMainComponent = () => {
|
|
542
|
+
goToMainMutation.mutate(
|
|
543
|
+
{ designId, nodeId, ...(fileId ? { fileId } : {}) },
|
|
544
|
+
{
|
|
545
|
+
onSuccess: (result: GoToMainComponentResult) => {
|
|
546
|
+
if (result.ctaRequired) {
|
|
547
|
+
toast.error(
|
|
548
|
+
result.ctaMessage ??
|
|
549
|
+
t("designEditor.componentInstances.goToMainUnavailable"),
|
|
550
|
+
);
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (result.isMain) {
|
|
554
|
+
toast(
|
|
555
|
+
result.note ??
|
|
556
|
+
t("designEditor.componentInstances.onlyKnownInstance"),
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
onError: () =>
|
|
561
|
+
toast.error(t("designEditor.componentInstances.resolveMainFailed")),
|
|
562
|
+
},
|
|
563
|
+
);
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
const handleDetachInstance = () => {
|
|
567
|
+
const source = sourceForMutation();
|
|
568
|
+
detachMutation.mutate(
|
|
569
|
+
{
|
|
570
|
+
designId,
|
|
571
|
+
nodeId,
|
|
572
|
+
...(fileId ? { fileId } : {}),
|
|
573
|
+
...(source ? { source } : {}),
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
onSuccess: (result: DetachComponentInstanceResult) => {
|
|
577
|
+
if (result.conflict || result.ctaRequired) {
|
|
578
|
+
toast.error(
|
|
579
|
+
result.error ??
|
|
580
|
+
result.ctaMessage ??
|
|
581
|
+
t("designEditor.componentInstances.detachFailed"),
|
|
582
|
+
);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
if (result.detached) {
|
|
586
|
+
toast(result.note ?? t("designEditor.componentInstances.detached"));
|
|
587
|
+
refreshAfterInstanceMutation(result);
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
onError: () =>
|
|
591
|
+
toast.error(t("designEditor.componentInstances.detachFailed")),
|
|
592
|
+
},
|
|
593
|
+
);
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const handleSwapInstance = (targetComponentName: string) => {
|
|
597
|
+
const source = sourceForMutation();
|
|
598
|
+
swapMutation.mutate(
|
|
599
|
+
{
|
|
600
|
+
designId,
|
|
601
|
+
nodeId,
|
|
602
|
+
...(fileId ? { fileId } : {}),
|
|
603
|
+
targetComponentName,
|
|
604
|
+
...(source ? { source } : {}),
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
onSuccess: (result: SwapComponentInstanceResult) => {
|
|
608
|
+
if (result.conflict || result.ctaRequired) {
|
|
609
|
+
toast.error(
|
|
610
|
+
result.error ??
|
|
611
|
+
result.ctaMessage ??
|
|
612
|
+
t("designEditor.componentInstances.swapFailed"),
|
|
613
|
+
);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
if (result.swapped) {
|
|
617
|
+
toast(
|
|
618
|
+
result.note ??
|
|
619
|
+
t("designEditor.componentInstances.swappedFor", {
|
|
620
|
+
name: targetComponentName,
|
|
621
|
+
}),
|
|
622
|
+
);
|
|
623
|
+
setSwapPickerOpen(false);
|
|
624
|
+
setSwapQuery("");
|
|
625
|
+
refreshAfterInstanceMutation(result);
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
onError: () =>
|
|
629
|
+
toast.error(t("designEditor.componentInstances.swapFailed")),
|
|
630
|
+
},
|
|
631
|
+
);
|
|
632
|
+
};
|
|
325
633
|
|
|
326
634
|
const postComponentPropPreview = useCallback(
|
|
327
635
|
(attribute: string, value: string) => {
|
|
@@ -428,10 +736,12 @@ export function ComponentSection({
|
|
|
428
736
|
|
|
429
737
|
const handleMessage = (event: MessageEvent) => {
|
|
430
738
|
if (
|
|
431
|
-
(event.data as { type?: unknown } | null)?.type
|
|
739
|
+
(event.data as { type?: unknown } | null)?.type !== "element-select"
|
|
432
740
|
) {
|
|
433
|
-
|
|
741
|
+
return;
|
|
434
742
|
}
|
|
743
|
+
if (!isMessageFromOwnPreviewIframe(event.source)) return;
|
|
744
|
+
void refetch();
|
|
435
745
|
};
|
|
436
746
|
window.addEventListener("message", handleMessage);
|
|
437
747
|
return () => {
|
|
@@ -479,55 +789,11 @@ export function ComponentSection({
|
|
|
479
789
|
const editingEnabled = isInline && capabilities.canEditProps; // gated; real-app stays read-only for now
|
|
480
790
|
const alpineData = parseAlpineDataObject(instance?.alpineData);
|
|
481
791
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
options?: string[];
|
|
488
|
-
/** Persist surface for this prop. */
|
|
489
|
-
surface: "alpineData" | "attribute";
|
|
490
|
-
};
|
|
491
|
-
|
|
492
|
-
const rows: PropRow[] = [];
|
|
493
|
-
const seen = new Set<string>();
|
|
494
|
-
|
|
495
|
-
// 1) Alpine x-data keys come first — they drive the live variant/state.
|
|
496
|
-
if (alpineData) {
|
|
497
|
-
for (const [key, value] of Object.entries(alpineData)) {
|
|
498
|
-
rows.push({
|
|
499
|
-
name: key,
|
|
500
|
-
value,
|
|
501
|
-
options: persistedVariants[key],
|
|
502
|
-
surface: "alpineData",
|
|
503
|
-
});
|
|
504
|
-
seen.add(key);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// 2) data-agent-native-prop-* attributes not already covered by x-data.
|
|
509
|
-
for (const prop of observedProps) {
|
|
510
|
-
if (seen.has(prop.name)) continue;
|
|
511
|
-
rows.push({
|
|
512
|
-
name: prop.name,
|
|
513
|
-
value: prop.value,
|
|
514
|
-
options: persistedVariants[prop.name],
|
|
515
|
-
surface: "attribute",
|
|
516
|
-
});
|
|
517
|
-
seen.add(prop.name);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// 3) persistedVariant groups with no observed value yet (default to first).
|
|
521
|
-
for (const [group, options] of Object.entries(persistedVariants)) {
|
|
522
|
-
if (seen.has(group)) continue;
|
|
523
|
-
rows.push({
|
|
524
|
-
name: group,
|
|
525
|
-
value: options[0] ?? "",
|
|
526
|
-
options,
|
|
527
|
-
surface: alpineData ? "alpineData" : "attribute",
|
|
528
|
-
});
|
|
529
|
-
seen.add(group);
|
|
530
|
-
}
|
|
792
|
+
const rows: PropRow[] = buildComponentPropRows({
|
|
793
|
+
instance,
|
|
794
|
+
observedProps,
|
|
795
|
+
persistedVariants,
|
|
796
|
+
});
|
|
531
797
|
|
|
532
798
|
const hasRows = rows.length > 0;
|
|
533
799
|
|
|
@@ -559,10 +825,7 @@ export function ComponentSection({
|
|
|
559
825
|
// can't rewrite for this key without dropping it. Fail safe: skip the
|
|
560
826
|
// edit rather than persist a lossy rewrite, and tell the user why so
|
|
561
827
|
// the change doesn't silently vanish.
|
|
562
|
-
toast.error(
|
|
563
|
-
// i18n-ignore
|
|
564
|
-
"Can’t safely edit this prop inline — this component’s Alpine state is too complex. Edit the source instead.",
|
|
565
|
-
);
|
|
828
|
+
toast.error(t("designEditor.componentProps.alpineTooComplexToEdit"));
|
|
566
829
|
return;
|
|
567
830
|
}
|
|
568
831
|
|
|
@@ -625,6 +888,125 @@ export function ComponentSection({
|
|
|
625
888
|
<h3 className="min-w-0 flex-1 truncate !text-[11px] font-semibold text-foreground">
|
|
626
889
|
{name}
|
|
627
890
|
</h3>
|
|
891
|
+
{/* Instance operations: Go to main component / Swap instance /
|
|
892
|
+
Detach instance (Figma's instance-only affordances). Inline/Alpine
|
|
893
|
+
designs only — the underlying actions fail closed for real-app
|
|
894
|
+
sources, so hide them entirely there rather than show a
|
|
895
|
+
perpetually-disabled button. */}
|
|
896
|
+
{isInline && (
|
|
897
|
+
<>
|
|
898
|
+
<Tooltip>
|
|
899
|
+
<TooltipTrigger asChild>
|
|
900
|
+
<Button
|
|
901
|
+
type="button"
|
|
902
|
+
variant="ghost"
|
|
903
|
+
size="icon"
|
|
904
|
+
className="size-6 rounded-md text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40"
|
|
905
|
+
disabled={goToMainMutation.isPending}
|
|
906
|
+
aria-label={t("designEditor.componentInstances.goToMain")}
|
|
907
|
+
onClick={handleGoToMainComponent}
|
|
908
|
+
>
|
|
909
|
+
<IconComponents className="size-3.5" />
|
|
910
|
+
</Button>
|
|
911
|
+
</TooltipTrigger>
|
|
912
|
+
<TooltipContent>
|
|
913
|
+
{t("designEditor.componentInstances.goToMain")}
|
|
914
|
+
</TooltipContent>
|
|
915
|
+
</Tooltip>
|
|
916
|
+
|
|
917
|
+
<Popover
|
|
918
|
+
open={swapPickerOpen}
|
|
919
|
+
onOpenChange={(open) => {
|
|
920
|
+
setSwapPickerOpen(open);
|
|
921
|
+
if (!open) setSwapQuery("");
|
|
922
|
+
}}
|
|
923
|
+
>
|
|
924
|
+
<Tooltip>
|
|
925
|
+
<TooltipTrigger asChild>
|
|
926
|
+
<PopoverTrigger asChild>
|
|
927
|
+
<Button
|
|
928
|
+
type="button"
|
|
929
|
+
variant="ghost"
|
|
930
|
+
size="icon"
|
|
931
|
+
className="size-6 rounded-md text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40"
|
|
932
|
+
disabled={!editingEnabled || swapMutation.isPending}
|
|
933
|
+
aria-label={t("designEditor.componentInstances.swap")}
|
|
934
|
+
>
|
|
935
|
+
<IconArrowsLeftRight className="size-3.5" />
|
|
936
|
+
</Button>
|
|
937
|
+
</PopoverTrigger>
|
|
938
|
+
</TooltipTrigger>
|
|
939
|
+
<TooltipContent>
|
|
940
|
+
{t("designEditor.componentInstances.swap")}
|
|
941
|
+
</TooltipContent>
|
|
942
|
+
</Tooltip>
|
|
943
|
+
<PopoverContent
|
|
944
|
+
align="end"
|
|
945
|
+
className="w-56 rounded-md border-[var(--design-editor-control-border)] bg-[var(--design-editor-panel-bg)] p-1.5 text-[11px]"
|
|
946
|
+
>
|
|
947
|
+
<Input
|
|
948
|
+
autoFocus
|
|
949
|
+
value={swapQuery}
|
|
950
|
+
onChange={(e) => setSwapQuery(e.target.value)}
|
|
951
|
+
placeholder={t(
|
|
952
|
+
"designEditor.componentInstances.searchComponents",
|
|
953
|
+
)}
|
|
954
|
+
className="mb-1.5 h-7 !text-[11px]"
|
|
955
|
+
/>
|
|
956
|
+
<div className="max-h-52 overflow-y-auto">
|
|
957
|
+
{swapCatalogLoading ? (
|
|
958
|
+
<div className="px-2 py-1.5 text-muted-foreground">
|
|
959
|
+
{t("designEditor.componentInstances.loading")}
|
|
960
|
+
</div>
|
|
961
|
+
) : swapCandidates.length === 0 ? (
|
|
962
|
+
<div className="px-2 py-1.5 text-muted-foreground">
|
|
963
|
+
{t("designEditor.componentInstances.noOtherComponents")}
|
|
964
|
+
</div>
|
|
965
|
+
) : (
|
|
966
|
+
swapCandidates.map((candidate) => (
|
|
967
|
+
<button
|
|
968
|
+
key={candidate.name}
|
|
969
|
+
type="button"
|
|
970
|
+
disabled={swapMutation.isPending}
|
|
971
|
+
onClick={() => handleSwapInstance(candidate.name)}
|
|
972
|
+
className="flex w-full items-center justify-between gap-2 rounded-[4px] px-2 py-1.5 text-left hover:bg-[var(--design-editor-selection-color)] hover:text-white disabled:cursor-wait disabled:opacity-60"
|
|
973
|
+
>
|
|
974
|
+
<span className="min-w-0 flex-1 truncate">
|
|
975
|
+
{candidate.name}
|
|
976
|
+
</span>
|
|
977
|
+
<span className="shrink-0 text-[10px] text-muted-foreground">
|
|
978
|
+
{candidate.instanceCount}
|
|
979
|
+
</span>
|
|
980
|
+
</button>
|
|
981
|
+
))
|
|
982
|
+
)}
|
|
983
|
+
</div>
|
|
984
|
+
</PopoverContent>
|
|
985
|
+
</Popover>
|
|
986
|
+
|
|
987
|
+
<Tooltip>
|
|
988
|
+
<TooltipTrigger asChild>
|
|
989
|
+
<Button
|
|
990
|
+
type="button"
|
|
991
|
+
variant="ghost"
|
|
992
|
+
size="icon"
|
|
993
|
+
className="size-6 rounded-md text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40"
|
|
994
|
+
disabled={!editingEnabled || detachMutation.isPending}
|
|
995
|
+
aria-label={t("designEditor.componentInstances.detach")}
|
|
996
|
+
onClick={handleDetachInstance}
|
|
997
|
+
>
|
|
998
|
+
<IconUnlink className="size-3.5" />
|
|
999
|
+
</Button>
|
|
1000
|
+
</TooltipTrigger>
|
|
1001
|
+
<TooltipContent>
|
|
1002
|
+
{t("designEditor.componentInstances.detach")}
|
|
1003
|
+
<span className="ms-1.5 text-muted-foreground/70">
|
|
1004
|
+
{"⌥⌘B" /* i18n-ignore keyboard shortcut */}
|
|
1005
|
+
</span>
|
|
1006
|
+
</TooltipContent>
|
|
1007
|
+
</Tooltip>
|
|
1008
|
+
</>
|
|
1009
|
+
)}
|
|
628
1010
|
{/* Jump-to-source action */}
|
|
629
1011
|
<Tooltip>
|
|
630
1012
|
<TooltipTrigger asChild>
|
|
@@ -634,9 +1016,7 @@ export function ComponentSection({
|
|
|
634
1016
|
size="icon"
|
|
635
1017
|
className="size-6 rounded-md text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-40"
|
|
636
1018
|
disabled={!canJumpToSource}
|
|
637
|
-
aria-label={
|
|
638
|
-
"Edit component source" /* i18n-ignore design inspector action */
|
|
639
|
-
}
|
|
1019
|
+
aria-label={t("designEditor.componentSource.editSource")}
|
|
640
1020
|
onClick={() => {
|
|
641
1021
|
openSourceMutation.mutate({
|
|
642
1022
|
designId,
|
|
@@ -649,12 +1029,10 @@ export function ComponentSection({
|
|
|
649
1029
|
</Button>
|
|
650
1030
|
</TooltipTrigger>
|
|
651
1031
|
<TooltipContent>
|
|
652
|
-
{
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
"Source jump needs a connected app") /* i18n-ignore design inspector tooltip */
|
|
657
|
-
}
|
|
1032
|
+
{canJumpToSource
|
|
1033
|
+
? t("designEditor.componentSource.editSource")
|
|
1034
|
+
: (capabilities.ctaMessage ??
|
|
1035
|
+
t("designEditor.componentSource.needsConnectedApp"))}
|
|
658
1036
|
</TooltipContent>
|
|
659
1037
|
</Tooltip>
|
|
660
1038
|
</div>
|
|
@@ -680,7 +1058,7 @@ export function ComponentSection({
|
|
|
680
1058
|
{hasRows && (
|
|
681
1059
|
<div className="space-y-1">
|
|
682
1060
|
<p className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground/70">
|
|
683
|
-
{"
|
|
1061
|
+
{t("designEditor.componentProps.label")}
|
|
684
1062
|
</p>
|
|
685
1063
|
{rows.map((row) => {
|
|
686
1064
|
const hasOptions = (row.options?.length ?? 0) > 0;
|
|
@@ -74,10 +74,18 @@ export function selectionColorValues(
|
|
|
74
74
|
return rawValues
|
|
75
75
|
.map((color) => ({ ...color, value: color.value?.trim() }))
|
|
76
76
|
.filter((color): color is SelectionColorValue => Boolean(color.value))
|
|
77
|
-
.filter(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
.filter((color) => {
|
|
78
|
+
// Skip fully transparent colors — not a meaningful "selection color"
|
|
79
|
+
// swatch (matches extractDocumentColorPalette's same alpha check
|
|
80
|
+
// below). Parsed via parseCssColor rather than compared against the
|
|
81
|
+
// two literal spellings "transparent"/"rgba(0, 0, 0, 0)" — a border/
|
|
82
|
+
// outline color can be zero-alpha in many other forms (e.g.
|
|
83
|
+
// "rgba(255, 0, 0, 0)", "hsla(0, 0%, 0%, 0)", no-space formatting)
|
|
84
|
+
// and those previously slipped through as a bogus opaque-looking
|
|
85
|
+
// swatch instead of being hidden like every other invisible color.
|
|
86
|
+
const parsed = parseCssColor(color.value);
|
|
87
|
+
return !parsed || parsed.a > 0;
|
|
88
|
+
})
|
|
81
89
|
.filter((color) => {
|
|
82
90
|
const key = color.value.toLowerCase();
|
|
83
91
|
if (seen.has(key)) return false;
|