@agent-native/core 0.80.7 → 0.80.9
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 +2 -2
- package/corpus/core/CHANGELOG.md +18 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +6 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +8 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +10 -2
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +10 -2
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +7 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +7 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +7 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +9 -2
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +6 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +6 -0
- package/corpus/core/docs/content/template-design.mdx +9 -2
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/mcp.ts +10 -0
- package/corpus/core/src/cli/skills.ts +58 -12
- package/corpus/core/src/client/AssistantChat.tsx +70 -27
- package/corpus/core/src/client/analytics.ts +3 -1
- package/corpus/core/src/client/error-format.ts +25 -0
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +13 -11
- package/corpus/core/src/client/guided-questions.tsx +32 -4
- package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +33 -1
- package/corpus/core/src/client/resources/BuiltinCapabilityDetail.tsx +8 -0
- package/corpus/core/src/client/resources/use-builtin-capabilities.ts +4 -2
- package/corpus/core/src/client/session-replay.ts +34 -0
- package/corpus/core/src/client/sharing/ShareButton.tsx +106 -21
- package/corpus/core/src/coding-tools/index.ts +1 -1
- package/corpus/core/src/mcp/index.ts +2 -0
- package/corpus/core/src/mcp/screen-memory-stdio.ts +290 -0
- package/corpus/core/src/mcp-client/builtin-capabilities.ts +13 -1
- package/corpus/core/src/mcp-client/index.ts +9 -0
- package/corpus/core/src/mcp-client/screen-memory-local.ts +461 -0
- package/corpus/core/src/onboarding/types.ts +7 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +25 -0
- package/corpus/core/src/server/agents-bundle.ts +35 -7
- package/corpus/core/src/styles/agent-native.css +5 -0
- package/corpus/core/src/templates/default/app/global.css +35 -35
- package/corpus/templates/analytics/AGENTS.md +6 -0
- package/corpus/templates/analytics/actions/github-repo-files.ts +9 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +4 -4
- package/corpus/templates/analytics/app/global.css +144 -40
- package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +4 -4
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -9
- package/corpus/templates/analytics/changelog/2026-06-29-agents-can-search-and-read-connected-github-repositories-whe.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-sessions-and-explorer-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
- package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +1 -1
- package/corpus/templates/assets/app/global.css +99 -35
- package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +4 -4
- package/corpus/templates/assets/app/routes/library.tsx +4 -4
- package/corpus/templates/assets/changelog/2026-06-29-asset-library-and-detail-layouts-adapt-when-the-agent-sidebar.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/brain/app/global.css +63 -35
- package/corpus/templates/brain/app/routes/search.tsx +1 -1
- package/corpus/templates/brain/app/routes/settings.tsx +1 -1
- package/corpus/templates/brain/app/routes/sources.tsx +2 -2
- package/corpus/templates/brain/changelog/2026-06-29-search-settings-and-source-layouts-adapt-when-the-agent-sidebar.md +6 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +4 -4
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +3 -2
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -2
- package/corpus/templates/calendar/app/global.css +69 -35
- package/corpus/templates/calendar/changelog/2026-06-29-event-and-find-time-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/global.css +35 -35
- package/corpus/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/clips/AGENTS.md +13 -0
- package/corpus/templates/clips/actions/get-screen-memory-status.ts +12 -0
- package/corpus/templates/clips/actions/query-screen-memory-context.ts +29 -0
- package/corpus/templates/clips/actions/view-screen.ts +2 -2
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
- package/corpus/templates/clips/app/global.css +47 -35
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +3 -3
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +45 -18
- package/corpus/templates/clips/changelog/2026-06-29-meeting-detail-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-29-screen-memory-keeps-a-local-rolling-screen-buffer-for-agent-context.md +5 -0
- package/corpus/templates/clips/changelog/2026-06-29-video-chat-is-easier-to-find-on-recording-pages-and-s3-setup.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/styles.css +39 -39
- package/corpus/templates/clips/desktop/src/app.tsx +290 -1
- package/corpus/templates/clips/desktop/src/shared/config.ts +83 -0
- package/corpus/templates/clips/desktop/src/styles.css +67 -52
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +50 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +17 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +13 -13
- package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +990 -0
- package/corpus/templates/clips/server/plugins/onboarding.ts +2 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +69 -16
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +3 -3
- package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/content/app/global.css +29 -15
- package/corpus/templates/content/changelog/2026-06-29-database-gallery-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/content/changelog/2026-06-29-read-only-pages-no-longer-try-to-autosave-or-open-editor-onl.md +6 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +25 -20
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +8 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +13 -0
- package/corpus/templates/design/AGENTS.md +24 -14
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1054 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +24 -4
- package/corpus/templates/design/actions/edit-design.ts +6 -3
- package/corpus/templates/design/actions/export-coding-handoff.ts +12 -4
- package/corpus/templates/design/actions/generate-design.ts +6 -21
- package/corpus/templates/design/actions/generate-screens.ts +48 -5
- package/corpus/templates/design/actions/get-design.ts +1 -0
- package/corpus/templates/design/actions/present-design-variants.ts +355 -30
- package/corpus/templates/design/actions/update-design.ts +47 -10
- package/corpus/templates/design/actions/update-file.ts +33 -8
- package/corpus/templates/design/actions/view-screen.ts +89 -31
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +389 -71
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
- package/corpus/templates/design/app/components/design/EditPanel.tsx +596 -95
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +428 -221
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1197 -228
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +94 -217
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +28 -14
- package/corpus/templates/design/app/components/design/index.ts +0 -1
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +228 -170
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +140 -13
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +39 -8
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +4 -2
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +75 -5
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +37 -12
- package/corpus/templates/design/app/components/design/inspector/index.ts +1 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +17 -4
- package/corpus/templates/design/app/components/design/types.ts +9 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +23 -5
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +448 -259
- package/corpus/templates/design/app/global.css +77 -49
- package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +8 -1
- package/corpus/templates/design/app/i18n/zh-TW.ts +4 -0
- package/corpus/templates/design/app/i18n-data.ts +55 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2783 -658
- package/corpus/templates/design/app/root.tsx +1 -1
- package/corpus/templates/design/changelog/2026-06-29-agent-edits-to-a-design-are-no-longer-occasionally-dropped-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-box-shadow-and-gradient-colors-keep-named-css-colors-like-re.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-containers-no-longer-block-selecting-nested-elements-and-nor.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-cut-cmd-ctrl-x-now-removes-the-selected-element-to-the-clipb.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-deleting-with-multiple-layers-selected-in-the-layers-panel-n.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-agents-now-generate-and-refine-variants-from-stronger.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-questions-now-appear-as-a-cleaner-canvas-intake-with-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-variant-directions-now-appear-as-board-screens-with-chat-buttons.md +5 -0
- package/corpus/templates/design/changelog/2026-06-29-duplicating-a-screen-now-gives-the-copy-its-own-layer-ids-so.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-element-selection-no-longer-snaps-back-to-the-previous-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-frame-resize-measurements-now-stay-beside-the-cursor-while-d.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-hiding-and-re-showing-a-gradient-fill-now-preserves-each-sto.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-inspector-number-fields-have-cleaner-tooltips-and-draggable-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layer-locking-layer-nesting-generated-question-intake-and-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layer-names-in-the-sidebar-can-scroll-horizontally-instead-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layer-nesting-in-the-sidebar-now-uses-tighter-spacing-so-nam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-layers-no-longer-repeat-document-wrapper-rows-when-a-screen-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-overview-previews-now-keep-element-hover-and-selection-tied-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-picking-a-design-direction-now-submits-to-the-agent-right-aw.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-pressing-escape-now-cancels-a-stuck-screen-drag-in-the-overv.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-only-highlights-screens-when-the-frame-or-ti.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-previews-now-resize-to-match-the-selected-de.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-now-uses-a-pointer-cursor-instead-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-outlines-now-stay-locked-to-the-se.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-zoom-now-reports-real-screen-scale-separatel.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-feels-smoother-and-selection-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-now-stays-on-the-overview-canvas-ins.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-selecting-a-nested-layer-from-all-screens-now-keeps-you-in-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-share-now-groups-link-sharing-exports-and-agent-handoff.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-style-changes-that-set-several-properties-at-once-fixed-size.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-design-editor-loading-skeleton-now-uses-a-softer-charcoa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-device-preview-menu-now-sits-next-to-the-preview-button-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-editor-no-longer-crashes-when-a-screen-ends-up-with-dupl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-inspector-stays-read-only-while-an-empty-design-is-still.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-missing-design-view-now-matches-the-rest-of-the-editor-c.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-icon-and-tool-option-menus-better-match-the-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-typography-controls-now-keep-the-font-name-visible-and-move-.md +6 -0
- package/corpus/templates/design/e2e/README.md +4 -3
- package/corpus/templates/design/e2e/global-setup.ts +24 -23
- package/corpus/templates/design/e2e/helpers.ts +122 -11
- package/corpus/templates/design/playwright.config.ts +19 -4
- package/corpus/templates/design/server/lib/coding-handoff.ts +126 -2
- package/corpus/templates/design/server/plugins/core-routes.ts +1 -2
- package/corpus/templates/design/server/routes/api/design-handoff/[id].zip.get.ts +86 -0
- package/corpus/templates/design/shared/code-layer.ts +125 -22
- package/corpus/templates/design/shared/color-utils.ts +159 -0
- package/corpus/templates/design/shared/generation-session.ts +42 -0
- package/corpus/templates/dispatch/app/global.css +79 -35
- package/corpus/templates/dispatch/app/routes/integrations.tsx +8 -7
- package/corpus/templates/dispatch/changelog/2026-06-29-integration-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -2
- package/corpus/templates/forms/app/global.css +64 -35
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +2 -2
- package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +3 -3
- package/corpus/templates/forms/changelog/2026-06-29-form-list-and-insight-layouts-adapt-when-the-agent-sidebar.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/macros/app/global.css +25 -9
- package/corpus/templates/macros/changelog/2026-06-29-macro-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -2
- package/corpus/templates/mail/app/global.css +42 -36
- package/corpus/templates/mail/app/pages/InboxPage.tsx +1 -1
- package/corpus/templates/mail/changelog/2026-06-29-the-contact-panel-now-adapts-to-the-available-mail-pane-width.md +6 -0
- package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +6 -7
- package/corpus/templates/plan/app/global.css +74 -42
- package/corpus/templates/plan/changelog/2026-06-29-plan-document-blocks-adapt-to-the-available-document-width.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-29-plan-titles-and-summaries-can-be-edited-inline-without-focus.md +6 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/slides/app/global.css +49 -33
- package/corpus/templates/slides/changelog/2026-06-29-slide-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/corpus/templates/videos/app/components/layout/Layout.tsx +3 -1
- package/corpus/templates/videos/app/global.css +35 -35
- package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +10 -0
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +58 -12
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +54 -24
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +2 -1
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +17 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +3 -4
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/guided-questions.d.ts +4 -0
- package/dist/client/guided-questions.d.ts.map +1 -1
- package/dist/client/guided-questions.js +16 -7
- package/dist/client/guided-questions.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +26 -1
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.js +1 -1
- package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -1
- package/dist/client/resources/use-builtin-capabilities.d.ts +1 -1
- package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -1
- package/dist/client/resources/use-builtin-capabilities.js +2 -1
- package/dist/client/resources/use-builtin-capabilities.js.map +1 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +31 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +14 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +36 -7
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/coding-tools/index.js +1 -1
- package/dist/coding-tools/index.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +6 -0
- package/dist/mcp/screen-memory-stdio.d.ts.map +1 -0
- package/dist/mcp/screen-memory-stdio.js +213 -0
- package/dist/mcp/screen-memory-stdio.js.map +1 -0
- package/dist/mcp-client/builtin-capabilities.d.ts +1 -1
- package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -1
- package/dist/mcp-client/builtin-capabilities.js +10 -0
- package/dist/mcp-client/builtin-capabilities.js.map +1 -1
- package/dist/mcp-client/index.d.ts +1 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +1 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/screen-memory-local.d.ts +61 -0
- package/dist/mcp-client/screen-memory-local.d.ts.map +1 -0
- package/dist/mcp-client/screen-memory-local.js +336 -0
- package/dist/mcp-client/screen-memory-local.js.map +1 -0
- package/dist/onboarding/types.d.ts +7 -0
- package/dist/onboarding/types.d.ts.map +1 -1
- package/dist/onboarding/types.js.map +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +26 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agents-bundle.d.ts.map +1 -1
- package/dist/server/agents-bundle.js +22 -7
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +5 -0
- package/dist/templates/default/app/global.css +35 -35
- package/docs/content/locales/ar-SA/template-design.mdx +6 -0
- package/docs/content/locales/de-DE/template-design.mdx +8 -0
- package/docs/content/locales/es-ES/template-design.mdx +10 -2
- package/docs/content/locales/fr-FR/template-design.mdx +10 -2
- package/docs/content/locales/hi-IN/template-design.mdx +7 -0
- package/docs/content/locales/ja-JP/template-design.mdx +7 -0
- package/docs/content/locales/ko-KR/template-design.mdx +7 -0
- package/docs/content/locales/pt-BR/template-design.mdx +9 -2
- package/docs/content/locales/zh-CN/template-design.mdx +6 -0
- package/docs/content/locales/zh-TW/template-design.mdx +6 -0
- package/docs/content/template-design.mdx +9 -2
- package/package.json +1 -1
- package/src/templates/default/app/global.css +35 -35
- package/corpus/templates/design/app/components/design/VariantGrid.tsx +0 -189
- package/corpus/templates/design/app/components/design/VariantHandoffCard.tsx +0 -115
- package/corpus/templates/design/app/hooks/use-variant-flow.ts +0 -258
|
@@ -247,8 +247,40 @@ function createEditorBridgeThemeScript(vars: Record<string, string>) {
|
|
|
247
247
|
const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
248
248
|
<script data-agent-native-editor-chrome-bridge>
|
|
249
249
|
(function() {
|
|
250
|
-
var
|
|
250
|
+
var readOnly = __READ_ONLY__;
|
|
251
|
+
var textEditingEnabled = !readOnly && __TEXT_EDITING_ENABLED__;
|
|
251
252
|
var scaleToolEnabled = false;
|
|
253
|
+
var editorChromeScaleX = Math.max(0.05, Number(__EDITOR_CHROME_SCALE_X__) || 1);
|
|
254
|
+
var editorChromeScaleY = Math.max(0.05, Number(__EDITOR_CHROME_SCALE_Y__) || editorChromeScaleX);
|
|
255
|
+
|
|
256
|
+
// Ease the constant-size selection chrome to its new size when overview zoom
|
|
257
|
+
// settles (parent posts set-editor-chrome-scale), matching the canvas chrome.
|
|
258
|
+
// Only chrome-scale-driven props animate; the overlay's live position is excluded.
|
|
259
|
+
(function () {
|
|
260
|
+
var chromeTransitionStyle = document.createElement('style');
|
|
261
|
+
chromeTransitionStyle.textContent =
|
|
262
|
+
'[data-agent-native-edit-overlay="selection"]{transition:border-width 150ms ease-out}' +
|
|
263
|
+
'[data-agent-native-edge-handle],[data-agent-native-edit-handle],[data-agent-native-rotate-handle]{transition:width 150ms ease-out,height 150ms ease-out,border-width 150ms ease-out,top 150ms ease-out,bottom 150ms ease-out,left 150ms ease-out,right 150ms ease-out}';
|
|
264
|
+
(document.head || document.documentElement).appendChild(chromeTransitionStyle);
|
|
265
|
+
})();
|
|
266
|
+
|
|
267
|
+
function chromeScaleX() {
|
|
268
|
+
return 1 / Math.max(0.05, editorChromeScaleX);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function chromeScaleY() {
|
|
272
|
+
return 1 / Math.max(0.05, editorChromeScaleY);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function chromeLineScale() {
|
|
276
|
+
return 1 / Math.max(0.05, Math.max(editorChromeScaleX, editorChromeScaleY));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function syncEditorChromeScaleVars() {
|
|
280
|
+
document.documentElement.style.setProperty('--agent-native-editor-chrome-scale-x', String(chromeScaleX()));
|
|
281
|
+
document.documentElement.style.setProperty('--agent-native-editor-chrome-scale-y', String(chromeScaleY()));
|
|
282
|
+
document.documentElement.style.setProperty('--agent-native-editor-chrome-line-scale', String(chromeLineScale()));
|
|
283
|
+
}
|
|
252
284
|
|
|
253
285
|
function escapeIdent(value) {
|
|
254
286
|
if (window.CSS && typeof window.CSS.escape === 'function') {
|
|
@@ -321,6 +353,32 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
321
353
|
);
|
|
322
354
|
}
|
|
323
355
|
|
|
356
|
+
function isDocumentRootElement(el) {
|
|
357
|
+
return el === document.body || el === document.documentElement;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function closestStableSourceElement(el) {
|
|
361
|
+
if (!el || !el.closest) return null;
|
|
362
|
+
var stable = el.closest('[data-agent-native-node-id],[data-code-layer-id],[data-layer-id],[data-builder-id],[data-loc]');
|
|
363
|
+
if (!stable || isDocumentRootElement(stable)) return null;
|
|
364
|
+
return stable;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function hasStableOwnSource(el) {
|
|
368
|
+
return !!(
|
|
369
|
+
el &&
|
|
370
|
+
!isDocumentRootElement(el) &&
|
|
371
|
+
getSourceId(el)
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function selectionTargetForHit(hit) {
|
|
376
|
+
if (!hit || isDocumentRootElement(hit)) return hit;
|
|
377
|
+
if (selectedEl && hit !== selectedEl && selectedEl.contains(hit)) return hit;
|
|
378
|
+
if (hasStableOwnSource(hit)) return hit;
|
|
379
|
+
return closestStableSourceElement(hit) || hit;
|
|
380
|
+
}
|
|
381
|
+
|
|
324
382
|
function freshRuntimeNodeId(prefix) {
|
|
325
383
|
var random = '';
|
|
326
384
|
try {
|
|
@@ -356,7 +414,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
356
414
|
if (stableOwnSelector) return stableOwnSelector;
|
|
357
415
|
|
|
358
416
|
if (el.id) return '#' + escapeIdent(el.id);
|
|
359
|
-
var stableAncestor = el
|
|
417
|
+
var stableAncestor = closestStableSourceElement(el);
|
|
360
418
|
if (stableAncestor && stableAncestor !== el) {
|
|
361
419
|
var stableAncestorSelector = selectorPart(stableAncestor);
|
|
362
420
|
if (stableAncestorSelector) {
|
|
@@ -379,7 +437,8 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
379
437
|
? window.getComputedStyle(el.parentElement)
|
|
380
438
|
: null;
|
|
381
439
|
var parentDisplay = parentStyles ? parentStyles.display : undefined;
|
|
382
|
-
var
|
|
440
|
+
var sourceBacked = hasStableOwnSource(el) || !!closestStableSourceElement(el);
|
|
441
|
+
var sourceId = sourceBacked ? (getSourceId(el) || getSelector(el)) : '';
|
|
383
442
|
var parentLayout = parentStyles
|
|
384
443
|
? {
|
|
385
444
|
display: parentStyles.display,
|
|
@@ -392,15 +451,24 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
392
451
|
position: parentStyles.position,
|
|
393
452
|
}
|
|
394
453
|
: undefined;
|
|
395
|
-
var capabilities =
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
454
|
+
var capabilities = sourceBacked
|
|
455
|
+
? [
|
|
456
|
+
{
|
|
457
|
+
kind: 'deterministic-style-edit',
|
|
458
|
+
label: 'deterministic-style-edit',
|
|
459
|
+
confidence: 0.92,
|
|
460
|
+
reason: 'Inline style can be patched and replayed through HMR/collab.',
|
|
461
|
+
},
|
|
462
|
+
]
|
|
463
|
+
: [
|
|
464
|
+
{
|
|
465
|
+
kind: 'unsupported',
|
|
466
|
+
label: 'runtime-only-element',
|
|
467
|
+
confidence: 0.3,
|
|
468
|
+
reason: 'This runtime node is not anchored to a source code layer.',
|
|
469
|
+
},
|
|
470
|
+
];
|
|
471
|
+
if (sourceBacked && el.classList && el.classList.length > 0) {
|
|
404
472
|
capabilities.push({
|
|
405
473
|
kind: 'deterministic-class-edit',
|
|
406
474
|
label: 'deterministic-class-edit',
|
|
@@ -408,7 +476,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
408
476
|
reason: 'Class tokens are visible on the selected element.',
|
|
409
477
|
});
|
|
410
478
|
}
|
|
411
|
-
if (parentDisplay === 'flex' || parentDisplay === 'inline-flex' || parentDisplay === 'grid' || parentDisplay === 'inline-grid') {
|
|
479
|
+
if (sourceBacked && (parentDisplay === 'flex' || parentDisplay === 'inline-flex' || parentDisplay === 'grid' || parentDisplay === 'inline-grid')) {
|
|
412
480
|
capabilities.push({
|
|
413
481
|
kind: 'agent-structural-edit',
|
|
414
482
|
label: 'agent-structural-edit',
|
|
@@ -433,9 +501,9 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
433
501
|
lineHeight: cs.lineHeight,
|
|
434
502
|
letterSpacing: cs.letterSpacing,
|
|
435
503
|
textAlign: cs.textAlign,
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
504
|
+
display: cs.display,
|
|
505
|
+
overflow: cs.overflow,
|
|
506
|
+
flexDirection: cs.flexDirection,
|
|
439
507
|
justifyContent: cs.justifyContent,
|
|
440
508
|
alignItems: cs.alignItems,
|
|
441
509
|
alignSelf: cs.alignSelf,
|
|
@@ -480,7 +548,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
480
548
|
mixBlendMode: cs.mixBlendMode,
|
|
481
549
|
zIndex: cs.zIndex,
|
|
482
550
|
},
|
|
483
|
-
boundingRect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
|
|
551
|
+
boundingRect: { x: rect.x + (window.scrollX || window.pageXOffset || 0), y: rect.y + (window.scrollY || window.pageYOffset || 0), width: rect.width, height: rect.height },
|
|
484
552
|
textContent: el.textContent ? el.textContent.slice(0, 200) : undefined,
|
|
485
553
|
htmlContent: el.innerHTML && el.innerHTML !== el.textContent ? el.innerHTML.slice(0, 4000) : undefined,
|
|
486
554
|
isFlexContainer: cs.display === 'flex' || cs.display === 'inline-flex',
|
|
@@ -501,12 +569,12 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
501
569
|
|
|
502
570
|
var highlightOverlay = document.createElement('div');
|
|
503
571
|
highlightOverlay.setAttribute('data-agent-native-edit-overlay', 'highlight');
|
|
504
|
-
highlightOverlay.style.cssText = 'position:fixed;pointer-events:none;z-index:
|
|
572
|
+
highlightOverlay.style.cssText = 'position:fixed;pointer-events:none;z-index:99997;border:1.5px solid var(--design-editor-accent-color);background:transparent;display:none;box-sizing:border-box;';
|
|
505
573
|
document.body.appendChild(highlightOverlay);
|
|
506
574
|
|
|
507
575
|
var selectionOverlay = document.createElement('div');
|
|
508
576
|
selectionOverlay.setAttribute('data-agent-native-edit-overlay', 'selection');
|
|
509
|
-
selectionOverlay.style.cssText = 'position:fixed;pointer-events:
|
|
577
|
+
selectionOverlay.style.cssText = 'position:fixed;pointer-events:none;z-index:99998;border:1.5px solid var(--design-editor-accent-color);background:transparent;display:none;box-sizing:border-box;cursor:default;';
|
|
510
578
|
['n','e','s','w'].forEach(function(pos) {
|
|
511
579
|
var edge = document.createElement('span');
|
|
512
580
|
edge.setAttribute('data-agent-native-edge-handle', pos);
|
|
@@ -542,7 +610,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
542
610
|
var handle = document.createElement('span');
|
|
543
611
|
handle.setAttribute('data-agent-native-edit-handle', pos);
|
|
544
612
|
var cursor = pos === 'n' || pos === 's' ? 'ns-resize' : pos === 'e' || pos === 'w' ? 'ew-resize' : pos === 'nw' || pos === 'se' ? 'nwse-resize' : 'nesw-resize';
|
|
545
|
-
handle.style.cssText = 'position:absolute;width:7px;height:7px;border:1px solid var(--design-editor-accent-color);background:var(--design-editor-accent-contrast-color);box-sizing:border-box;border-radius:1px;pointer-events:auto;cursor:' + cursor + ';';
|
|
613
|
+
handle.style.cssText = 'position:absolute;z-index:1;width:7px;height:7px;border:1px solid var(--design-editor-accent-color);background:var(--design-editor-accent-contrast-color);box-sizing:border-box;border-radius:1px;pointer-events:auto;cursor:' + cursor + ';';
|
|
546
614
|
if (pos.indexOf('n') !== -1) handle.style.top = '-4px';
|
|
547
615
|
if (pos.indexOf('s') !== -1) handle.style.bottom = '-4px';
|
|
548
616
|
if (pos.indexOf('w') !== -1) handle.style.left = '-4px';
|
|
@@ -596,6 +664,14 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
596
664
|
var lockedSelectors = [];
|
|
597
665
|
var hiddenSelectors = [];
|
|
598
666
|
|
|
667
|
+
function clearRuntimeSelection() {
|
|
668
|
+
selectedEl = null;
|
|
669
|
+
hoveredEl = null;
|
|
670
|
+
selectionOverlay.style.display = 'none';
|
|
671
|
+
highlightOverlay.style.display = 'none';
|
|
672
|
+
hideMeasurements();
|
|
673
|
+
}
|
|
674
|
+
|
|
599
675
|
function matchesSelectorList(el, selectors) {
|
|
600
676
|
if (!el || !selectors || selectors.length === 0) return false;
|
|
601
677
|
for (var i = 0; i < selectors.length; i += 1) {
|
|
@@ -752,7 +828,14 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
752
828
|
for (var i = 0; i < activeCandidates.length && !selectedEl; i += 1) {
|
|
753
829
|
try {
|
|
754
830
|
var match = document.querySelector(activeCandidates[i]);
|
|
755
|
-
|
|
831
|
+
// Skip the editor's own injected overlay chrome and re-anchor to a
|
|
832
|
+
// source-backed element. A stale positional candidate like
|
|
833
|
+
// body > div:nth-of-type(6) can otherwise re-match an overlay div
|
|
834
|
+
// (the only direct div children of body at runtime), which then has
|
|
835
|
+
// no code-layer node and fails every edit.
|
|
836
|
+
if (match && !isLayerInteractionBlocked(match) && !isOverlayElement(match)) {
|
|
837
|
+
selectedEl = selectionTargetForHit(match) || match;
|
|
838
|
+
}
|
|
756
839
|
} catch (_err) {}
|
|
757
840
|
}
|
|
758
841
|
if (selectedEl) {
|
|
@@ -784,22 +867,95 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
784
867
|
paddingOverlay.style.left = left + 'px';
|
|
785
868
|
}
|
|
786
869
|
|
|
870
|
+
function applyEditorChromeScale() {
|
|
871
|
+
syncEditorChromeScaleVars();
|
|
872
|
+
var sx = chromeScaleX();
|
|
873
|
+
var sy = chromeScaleY();
|
|
874
|
+
var line = chromeLineScale();
|
|
875
|
+
highlightOverlay.style.borderWidth = (1.5 * line) + 'px';
|
|
876
|
+
selectionOverlay.style.borderWidth = (1.5 * line) + 'px';
|
|
877
|
+
paddingOverlay.style.borderWidth = Math.max(1, 1 * line) + 'px';
|
|
878
|
+
|
|
879
|
+
selectionOverlay.querySelectorAll('[data-agent-native-edge-handle]').forEach(function(edge) {
|
|
880
|
+
var pos = edge.getAttribute('data-agent-native-edge-handle');
|
|
881
|
+
if (pos === 'n' || pos === 's') {
|
|
882
|
+
edge.style.height = (10 * sy) + 'px';
|
|
883
|
+
edge.style[pos === 'n' ? 'top' : 'bottom'] = (-5 * sy) + 'px';
|
|
884
|
+
}
|
|
885
|
+
if (pos === 'e' || pos === 'w') {
|
|
886
|
+
edge.style.width = (10 * sx) + 'px';
|
|
887
|
+
edge.style[pos === 'w' ? 'left' : 'right'] = (-5 * sx) + 'px';
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
selectionOverlay.querySelectorAll('[data-agent-native-edit-handle]').forEach(function(handle) {
|
|
892
|
+
var pos = handle.getAttribute('data-agent-native-edit-handle') || '';
|
|
893
|
+
handle.style.width = (7 * sx) + 'px';
|
|
894
|
+
handle.style.height = (7 * sy) + 'px';
|
|
895
|
+
handle.style.borderWidth = Math.max(1, 1 * line) + 'px';
|
|
896
|
+
if (pos.indexOf('n') !== -1) handle.style.top = (-4 * sy) + 'px';
|
|
897
|
+
if (pos.indexOf('s') !== -1) handle.style.bottom = (-4 * sy) + 'px';
|
|
898
|
+
if (pos.indexOf('w') !== -1) handle.style.left = (-4 * sx) + 'px';
|
|
899
|
+
if (pos.indexOf('e') !== -1) handle.style.right = (-4 * sx) + 'px';
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
selectionOverlay.querySelectorAll('[data-agent-native-rotate-handle]').forEach(function(handle) {
|
|
903
|
+
var pos = handle.getAttribute('data-agent-native-rotate-handle') || '';
|
|
904
|
+
handle.style.width = (18 * sx) + 'px';
|
|
905
|
+
handle.style.height = (18 * sy) + 'px';
|
|
906
|
+
if (pos.indexOf('n') !== -1) handle.style.top = (-26 * sy) + 'px';
|
|
907
|
+
if (pos.indexOf('s') !== -1) handle.style.bottom = (-26 * sy) + 'px';
|
|
908
|
+
if (pos.indexOf('w') !== -1) handle.style.left = (-26 * sx) + 'px';
|
|
909
|
+
if (pos.indexOf('e') !== -1) handle.style.right = (-26 * sx) + 'px';
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
|
|
787
913
|
function positionOverlay(overlay, el) {
|
|
788
914
|
if (!el || !document.documentElement.contains(el)) {
|
|
789
915
|
overlay.style.display = 'none';
|
|
790
916
|
return;
|
|
791
917
|
}
|
|
918
|
+
// For the selection overlay, prefer the CSS box + rotation transform so
|
|
919
|
+
// the handles hug the rotated element rather than its inflated AABB.
|
|
920
|
+
if (overlay === selectionOverlay) {
|
|
921
|
+
var elCs = window.getComputedStyle(el);
|
|
922
|
+
var elLeft = readFinitePx(el.style.left || elCs.left);
|
|
923
|
+
var elTop = readFinitePx(el.style.top || elCs.top);
|
|
924
|
+
var elW = readFinitePx(el.style.width || elCs.width);
|
|
925
|
+
var elH = readFinitePx(el.style.height || elCs.height);
|
|
926
|
+
var elRot = currentRotation(el);
|
|
927
|
+
var canUseLocalBox = Math.abs(elRot) > 0.01 && elLeft !== null && elTop !== null && elW !== null && elH !== null;
|
|
928
|
+
// Convert element-local left/top to viewport coords by walking to the
|
|
929
|
+
// nearest positioned ancestor (same reference frame as getBoundingClientRect).
|
|
930
|
+
if (canUseLocalBox) {
|
|
931
|
+
var parentRect = (el.offsetParent || document.documentElement).getBoundingClientRect();
|
|
932
|
+
overlay.style.display = 'block';
|
|
933
|
+
overlay.style.left = (parentRect.left + elLeft) + 'px';
|
|
934
|
+
overlay.style.top = (parentRect.top + elTop) + 'px';
|
|
935
|
+
overlay.style.width = elW + 'px';
|
|
936
|
+
overlay.style.height = elH + 'px';
|
|
937
|
+
overlay.style.transform = 'rotate(' + elRot + 'deg)';
|
|
938
|
+
overlay.style.transformOrigin = '0 0';
|
|
939
|
+
updatePaddingOverlay(el);
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
792
943
|
var rect = el.getBoundingClientRect();
|
|
793
944
|
overlay.style.display = 'block';
|
|
794
945
|
overlay.style.top = rect.top + 'px';
|
|
795
946
|
overlay.style.left = rect.left + 'px';
|
|
796
947
|
overlay.style.width = rect.width + 'px';
|
|
797
948
|
overlay.style.height = rect.height + 'px';
|
|
949
|
+
overlay.style.transform = '';
|
|
798
950
|
if (overlay === selectionOverlay) updatePaddingOverlay(el);
|
|
799
951
|
}
|
|
800
952
|
|
|
801
953
|
function refreshOverlays() {
|
|
802
|
-
if (hoveredEl
|
|
954
|
+
if (hoveredEl && hoveredEl !== selectedEl) {
|
|
955
|
+
positionOverlay(highlightOverlay, hoveredEl);
|
|
956
|
+
} else {
|
|
957
|
+
highlightOverlay.style.display = 'none';
|
|
958
|
+
}
|
|
803
959
|
if (selectedEl) positionOverlay(selectionOverlay, selectedEl);
|
|
804
960
|
}
|
|
805
961
|
|
|
@@ -1046,7 +1202,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1046
1202
|
window.parent.postMessage({ type: 'clear-selection' }, '*');
|
|
1047
1203
|
return;
|
|
1048
1204
|
}
|
|
1049
|
-
selectedEl = target;
|
|
1205
|
+
selectedEl = selectionTargetForHit(target);
|
|
1050
1206
|
var info = getElementInfo(selectedEl);
|
|
1051
1207
|
positionOverlay(selectionOverlay, selectedEl);
|
|
1052
1208
|
window.parent.postMessage({ type: 'element-select', payload: info }, '*');
|
|
@@ -1058,9 +1214,9 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1058
1214
|
var target = elementFromEditorPoint(e.clientX, e.clientY);
|
|
1059
1215
|
var info = null;
|
|
1060
1216
|
if (target) {
|
|
1061
|
-
selectedEl = target;
|
|
1062
|
-
info = getElementInfo(
|
|
1063
|
-
positionOverlay(selectionOverlay,
|
|
1217
|
+
selectedEl = selectionTargetForHit(target);
|
|
1218
|
+
info = getElementInfo(selectedEl);
|
|
1219
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
1064
1220
|
window.parent.postMessage({ type: 'element-select', payload: info }, '*');
|
|
1065
1221
|
}
|
|
1066
1222
|
window.parent.postMessage({
|
|
@@ -1117,6 +1273,12 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1117
1273
|
return Number.isFinite(num) ? num : 0;
|
|
1118
1274
|
}
|
|
1119
1275
|
|
|
1276
|
+
function readFinitePx(value) {
|
|
1277
|
+
if (!value || value === 'auto') return null;
|
|
1278
|
+
var num = parseFloat(value);
|
|
1279
|
+
return Number.isFinite(num) ? num : null;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1120
1282
|
function currentRotation(el) {
|
|
1121
1283
|
var transform = el.style.transform || window.getComputedStyle(el).transform || '';
|
|
1122
1284
|
var match = transform.match(/rotate\\((-?\\d+(?:\\.\\d+)?)deg\\)/);
|
|
@@ -1381,10 +1543,10 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1381
1543
|
}
|
|
1382
1544
|
}
|
|
1383
1545
|
|
|
1384
|
-
function postVisualStructureChange(el, target) {
|
|
1546
|
+
function postVisualStructureChange(el, target, origin) {
|
|
1385
1547
|
if (!el || !target || !target.anchor) return;
|
|
1386
1548
|
var requestId = 'move-' + Date.now() + '-' + Math.random().toString(16).slice(2);
|
|
1387
|
-
pendingStructureMove = { requestId: requestId, el: el, target: target };
|
|
1549
|
+
pendingStructureMove = { requestId: requestId, el: el, target: target, origin: origin || null };
|
|
1388
1550
|
window.parent.postMessage({
|
|
1389
1551
|
type: 'visual-structure-change',
|
|
1390
1552
|
requestId: requestId,
|
|
@@ -1458,11 +1620,15 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1458
1620
|
applyRuntimeReorder(reorderEl, currentTarget);
|
|
1459
1621
|
postVisualDuplicateChange(originalSelectedEl, reorderEl, currentTarget);
|
|
1460
1622
|
} else {
|
|
1623
|
+
// Capture the pre-drag DOM anchor so we can revert if the parent
|
|
1624
|
+
// reports applied===false on the structure-ack.
|
|
1625
|
+
var prevParent = reorderEl.parentElement;
|
|
1626
|
+
var prevNextSibling = reorderEl.nextSibling;
|
|
1461
1627
|
// Optimistically apply the reorder in the DOM for immediate
|
|
1462
1628
|
// visual feedback; the visual-structure-ack handler will confirm
|
|
1463
1629
|
// or revert once the parent processes the change.
|
|
1464
1630
|
applyRuntimeReorder(reorderEl, currentTarget);
|
|
1465
|
-
postVisualStructureChange(reorderEl, currentTarget);
|
|
1631
|
+
postVisualStructureChange(reorderEl, currentTarget, { prevParent: prevParent, prevNextSibling: prevNextSibling });
|
|
1466
1632
|
}
|
|
1467
1633
|
}
|
|
1468
1634
|
document.addEventListener('mousemove', onReorderMove, true);
|
|
@@ -1479,7 +1645,12 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1479
1645
|
// clear-selection postMessage cannot swap selectedEl mid-drag and cause
|
|
1480
1646
|
// mutations on the wrong element or a null-deref in onUp.
|
|
1481
1647
|
var dragEl = selectedEl;
|
|
1648
|
+
var moved = false;
|
|
1649
|
+
var DRAG_THRESHOLD = 3;
|
|
1482
1650
|
function onMove(ev) {
|
|
1651
|
+
if (!moved && Math.hypot(ev.clientX - startX, ev.clientY - startY) > DRAG_THRESHOLD) {
|
|
1652
|
+
moved = true;
|
|
1653
|
+
}
|
|
1483
1654
|
var nextLeft = originLeft + ev.clientX - startX;
|
|
1484
1655
|
var nextTop = originTop + ev.clientY - startY;
|
|
1485
1656
|
dragEl.style.left = Math.round(nextLeft) + 'px';
|
|
@@ -1492,6 +1663,14 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1492
1663
|
document.removeEventListener('mouseup', onUp, true);
|
|
1493
1664
|
hideTransformBadge();
|
|
1494
1665
|
if (!dragEl) return;
|
|
1666
|
+
if (duplicatedForDrag && !moved) {
|
|
1667
|
+
// Alt-click with no real drag — remove the premature clone and restore the original selection.
|
|
1668
|
+
if (dragEl.parentElement) dragEl.parentElement.removeChild(dragEl);
|
|
1669
|
+
selectedEl = originalSelectedEl;
|
|
1670
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
1671
|
+
window.parent.postMessage({ type: 'element-select', payload: getElementInfo(selectedEl) }, '*');
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1495
1674
|
if (duplicatedForDrag) {
|
|
1496
1675
|
postVisualDuplicateChange(originalSelectedEl, dragEl);
|
|
1497
1676
|
} else {
|
|
@@ -1535,9 +1714,19 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1535
1714
|
// Snapshot the element so a concurrent clear-selection postMessage cannot
|
|
1536
1715
|
// cause a null-deref in onMove/onUp.
|
|
1537
1716
|
var resizeEl = selectedEl;
|
|
1717
|
+
// Capture the element rotation once at drag-start so per-move projection is
|
|
1718
|
+
// cheap and consistent even if the transform changes during the drag.
|
|
1719
|
+
var resizeTheta = currentRotation(resizeEl) * Math.PI / 180;
|
|
1538
1720
|
function nextRect(ev) {
|
|
1539
|
-
var
|
|
1540
|
-
var
|
|
1721
|
+
var screenDx = ev.clientX - startX;
|
|
1722
|
+
var screenDy = ev.clientY - startY;
|
|
1723
|
+
// Project the screen-space pointer delta into the element's local
|
|
1724
|
+
// (un-rotated) coordinate frame so handles behave relative to the
|
|
1725
|
+
// visible rotated box rather than screen axes.
|
|
1726
|
+
var cosT = Math.cos(resizeTheta);
|
|
1727
|
+
var sinT = Math.sin(resizeTheta);
|
|
1728
|
+
var dx = screenDx * cosT + screenDy * sinT;
|
|
1729
|
+
var dy = -screenDx * sinT + screenDy * cosT;
|
|
1541
1730
|
var left = origin.left;
|
|
1542
1731
|
var top = origin.top;
|
|
1543
1732
|
var width = origin.width;
|
|
@@ -1554,9 +1743,16 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1554
1743
|
if (handle.indexOf('s') !== -1) height = origin.height + dy;
|
|
1555
1744
|
// Apply Shift / scaleToolEnabled aspect-ratio lock BEFORE the min-size
|
|
1556
1745
|
// clamp so the ratio is computed from unclamped values (bug fix).
|
|
1557
|
-
if (ev.shiftKey
|
|
1558
|
-
|
|
1559
|
-
|
|
1746
|
+
if (ev.shiftKey) {
|
|
1747
|
+
// Shift locks aspect ratio for ALL 8 handles (corners and edges).
|
|
1748
|
+
if (handle === 'e' || handle === 'w') {
|
|
1749
|
+
height = width / origin.ratio;
|
|
1750
|
+
} else if (handle === 'n' || handle === 's') {
|
|
1751
|
+
width = height * origin.ratio;
|
|
1752
|
+
} else if (handle.length === 2) {
|
|
1753
|
+
if (Math.abs(dx) > Math.abs(dy)) height = width / origin.ratio;
|
|
1754
|
+
else width = height * origin.ratio;
|
|
1755
|
+
}
|
|
1560
1756
|
}
|
|
1561
1757
|
if (scaleToolEnabled) {
|
|
1562
1758
|
// Scale tool: enforce aspect ratio on all 8 handles, not just corners.
|
|
@@ -1569,15 +1765,27 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1569
1765
|
else width = height * origin.ratio;
|
|
1570
1766
|
}
|
|
1571
1767
|
}
|
|
1572
|
-
// Clamp
|
|
1573
|
-
var
|
|
1574
|
-
var
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1768
|
+
// Clamp to minimum size.
|
|
1769
|
+
var clampedW = Math.max(8, width);
|
|
1770
|
+
var clampedH = Math.max(8, height);
|
|
1771
|
+
// After clamping, re-apply the ratio if Shift or scale tool is active so
|
|
1772
|
+
// the clamped dimension doesn't silently break the locked aspect ratio.
|
|
1773
|
+
if (ev.shiftKey || scaleToolEnabled) {
|
|
1774
|
+
if (clampedW !== width) {
|
|
1775
|
+
// Width was clamped; re-derive height from the clamped width.
|
|
1776
|
+
clampedH = Math.max(8, clampedW / origin.ratio);
|
|
1777
|
+
} else if (clampedH !== height) {
|
|
1778
|
+
// Height was clamped; re-derive width from the clamped height.
|
|
1779
|
+
clampedW = Math.max(8, clampedH * origin.ratio);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
width = clampedW;
|
|
1783
|
+
height = clampedH;
|
|
1784
|
+
// Re-anchor the pinned edge for w/n handles after aspect-ratio lock and
|
|
1785
|
+
// clamping so the opposite (e/s) edge stays fixed regardless of whether
|
|
1786
|
+
// the dimension change was driven by raw dx/dy or by the ratio lock.
|
|
1787
|
+
if (handle.indexOf('w') !== -1) left = origin.left + (origin.width - width);
|
|
1788
|
+
if (handle.indexOf('n') !== -1) top = origin.top + (origin.height - height);
|
|
1581
1789
|
if (ev.altKey) {
|
|
1582
1790
|
if (handle.indexOf('w') !== -1 || handle.indexOf('e') !== -1) left = origin.left - (width - origin.width) / 2;
|
|
1583
1791
|
if (handle.indexOf('n') !== -1 || handle.indexOf('s') !== -1) top = origin.top - (height - origin.height) / 2;
|
|
@@ -1688,6 +1896,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1688
1896
|
document.addEventListener('keydown', function(e) {
|
|
1689
1897
|
if (!shouldForwardDesignHotkey(e)) return;
|
|
1690
1898
|
stopNativeInteraction(e);
|
|
1899
|
+
if (e.key === 'Escape') clearRuntimeSelection();
|
|
1691
1900
|
window.parent.postMessage({
|
|
1692
1901
|
type: 'design-hotkey',
|
|
1693
1902
|
key: e.key,
|
|
@@ -1741,7 +1950,12 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1741
1950
|
stopNativeInteraction(e);
|
|
1742
1951
|
var target = findTextEditTarget(elementFromEditorPoint(e.clientX, e.clientY));
|
|
1743
1952
|
if (!target || target.nodeType !== 1) return;
|
|
1744
|
-
|
|
1953
|
+
// Anchor the selection identity to the nearest source-backed element. Text
|
|
1954
|
+
// editing still operates on the actual target text node, but a later
|
|
1955
|
+
// style edit posts from selectedEl, so it must point at a patchable
|
|
1956
|
+
// code-layer node rather than a runtime-only descendant (which would emit a
|
|
1957
|
+
// brittle body > div:nth-of-type(...) selector that never resolves).
|
|
1958
|
+
selectedEl = selectionTargetForHit(target) || target;
|
|
1745
1959
|
var originalText = target.textContent || '';
|
|
1746
1960
|
var originalHtml = target.innerHTML || '';
|
|
1747
1961
|
var committed = false;
|
|
@@ -1754,6 +1968,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1754
1968
|
setTextEditingPointerPassthrough(true);
|
|
1755
1969
|
positionOverlay(selectionOverlay, target);
|
|
1756
1970
|
window.parent.postMessage({ type: 'element-select', payload: getElementInfo(target) }, '*');
|
|
1971
|
+
window.parent.postMessage({ type: 'element-dblclick-text', payload: getElementInfo(target) }, '*');
|
|
1757
1972
|
postTextEditingState(target, true);
|
|
1758
1973
|
|
|
1759
1974
|
function finish(commit) {
|
|
@@ -1839,7 +2054,11 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1839
2054
|
return;
|
|
1840
2055
|
}
|
|
1841
2056
|
if (hoveredEl && hoveredEl.closest('[data-agent-native-text-editing]')) return;
|
|
1842
|
-
|
|
2057
|
+
if (hoveredEl === selectedEl) {
|
|
2058
|
+
highlightOverlay.style.display = 'none';
|
|
2059
|
+
} else {
|
|
2060
|
+
positionOverlay(highlightOverlay, hoveredEl);
|
|
2061
|
+
}
|
|
1843
2062
|
if (e.altKey && selectedEl && hoveredEl && selectedEl !== hoveredEl) {
|
|
1844
2063
|
showMeasurements(selectedEl, hoveredEl);
|
|
1845
2064
|
} else {
|
|
@@ -1854,6 +2073,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1854
2073
|
hoveredEl = null;
|
|
1855
2074
|
highlightOverlay.style.display = 'none';
|
|
1856
2075
|
hideMeasurements();
|
|
2076
|
+
window.parent.postMessage({ type: 'element-hover', payload: null }, '*');
|
|
1857
2077
|
}, true);
|
|
1858
2078
|
|
|
1859
2079
|
window.addEventListener('keyup', function(e) {
|
|
@@ -1863,16 +2083,21 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1863
2083
|
window.addEventListener('message', function(e) {
|
|
1864
2084
|
if (e.source !== window.parent) return;
|
|
1865
2085
|
if (!e.data) return;
|
|
2086
|
+
if (e.data.type === 'set-editor-chrome-scale') {
|
|
2087
|
+
// Live-update the constant-size chrome scale WITHOUT rebuilding srcdoc.
|
|
2088
|
+
// Rebuilding srcdoc reloads the iframe and flashes the content white.
|
|
2089
|
+
editorChromeScaleX = Math.max(0.05, Number(e.data.scaleX) || 1);
|
|
2090
|
+
editorChromeScaleY = Math.max(0.05, Number(e.data.scaleY) || editorChromeScaleX);
|
|
2091
|
+
applyEditorChromeScale();
|
|
2092
|
+
if (selectedEl || hoveredEl) refreshOverlays();
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
1866
2095
|
if (e.data.type === 'scale-tool-mode') {
|
|
1867
2096
|
scaleToolEnabled = !!e.data.enabled;
|
|
1868
2097
|
return;
|
|
1869
2098
|
}
|
|
1870
2099
|
if (e.data.type === 'clear-selection') {
|
|
1871
|
-
|
|
1872
|
-
hoveredEl = null;
|
|
1873
|
-
selectionOverlay.style.display = 'none';
|
|
1874
|
-
highlightOverlay.style.display = 'none';
|
|
1875
|
-
hideMeasurements();
|
|
2100
|
+
clearRuntimeSelection();
|
|
1876
2101
|
return;
|
|
1877
2102
|
}
|
|
1878
2103
|
if (e.data.type === 'select-element') {
|
|
@@ -1906,9 +2131,8 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1906
2131
|
}
|
|
1907
2132
|
if (!target) return;
|
|
1908
2133
|
selectedEl = target;
|
|
1909
|
-
var selectedInfo = getElementInfo(target);
|
|
1910
2134
|
positionOverlay(selectionOverlay, target);
|
|
1911
|
-
|
|
2135
|
+
if (hoveredEl === selectedEl) highlightOverlay.style.display = 'none';
|
|
1912
2136
|
return;
|
|
1913
2137
|
}
|
|
1914
2138
|
if (e.data.type === 'hover-element') {
|
|
@@ -1931,7 +2155,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1931
2155
|
}
|
|
1932
2156
|
var hoverTarget = findRuntimeTarget(String(e.data.selector || ''), hoverCandidates);
|
|
1933
2157
|
hoveredEl = hoverTarget;
|
|
1934
|
-
if (hoveredEl && !isLayerInteractionBlocked(hoveredEl)) {
|
|
2158
|
+
if (hoveredEl && !isLayerInteractionBlocked(hoveredEl) && hoveredEl !== selectedEl) {
|
|
1935
2159
|
positionOverlay(highlightOverlay, hoveredEl);
|
|
1936
2160
|
} else {
|
|
1937
2161
|
highlightOverlay.style.display = 'none';
|
|
@@ -1958,10 +2182,20 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1958
2182
|
var move = pendingStructureMove;
|
|
1959
2183
|
pendingStructureMove = null;
|
|
1960
2184
|
if (e.data.applied) {
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
2185
|
+
if (move.el && move.el.isConnected) {
|
|
2186
|
+
applyRuntimeReorder(move.el, move.target);
|
|
2187
|
+
selectedEl = move.el;
|
|
2188
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
2189
|
+
window.parent.postMessage({ type: 'element-select', payload: getElementInfo(selectedEl) }, '*');
|
|
2190
|
+
}
|
|
2191
|
+
} else {
|
|
2192
|
+
// Revert the optimistic reorder to its pre-drag position.
|
|
2193
|
+
if (move.el && move.el.isConnected && move.origin && move.origin.prevParent && move.origin.prevParent.isConnected) {
|
|
2194
|
+
move.origin.prevParent.insertBefore(move.el, move.origin.prevNextSibling);
|
|
2195
|
+
selectedEl = move.el;
|
|
2196
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
2197
|
+
window.parent.postMessage({ type: 'element-select', payload: getElementInfo(selectedEl) }, '*');
|
|
2198
|
+
}
|
|
1965
2199
|
}
|
|
1966
2200
|
return;
|
|
1967
2201
|
}
|
|
@@ -1988,6 +2222,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1988
2222
|
|
|
1989
2223
|
window.addEventListener('scroll', refreshOverlays, true);
|
|
1990
2224
|
window.addEventListener('resize', refreshOverlays);
|
|
2225
|
+
applyEditorChromeScale();
|
|
1991
2226
|
})();
|
|
1992
2227
|
</script>
|
|
1993
2228
|
`;
|
|
@@ -2003,12 +2238,17 @@ interface DesignCanvasProps {
|
|
|
2003
2238
|
viewportHeight: number;
|
|
2004
2239
|
displayWidth: number;
|
|
2005
2240
|
displayHeight: number;
|
|
2241
|
+
fluid?: boolean;
|
|
2006
2242
|
};
|
|
2243
|
+
editorChromeScaleX?: number;
|
|
2244
|
+
editorChromeScaleY?: number;
|
|
2007
2245
|
editMode: boolean;
|
|
2008
2246
|
interactMode: boolean;
|
|
2247
|
+
readOnly?: boolean;
|
|
2009
2248
|
scaleMode?: boolean;
|
|
2010
2249
|
onElementSelect: (info: ElementInfo) => void;
|
|
2011
|
-
onElementHover: (info: ElementInfo) => void;
|
|
2250
|
+
onElementHover: (info: ElementInfo | null) => void;
|
|
2251
|
+
onClearSelection?: () => void;
|
|
2012
2252
|
onVisualStyleChange?: (
|
|
2013
2253
|
selector: string,
|
|
2014
2254
|
styles: Record<string, string>,
|
|
@@ -2025,6 +2265,7 @@ interface DesignCanvasProps {
|
|
|
2025
2265
|
selector?: string;
|
|
2026
2266
|
hasRange?: boolean;
|
|
2027
2267
|
}) => void;
|
|
2268
|
+
onElementDblClickText?: (info: ElementInfo) => void;
|
|
2028
2269
|
onIframeHotkey?: (event: IframeHotkeyPayload) => void;
|
|
2029
2270
|
onIframeContextMenu?: (event: IframeContextMenuPayload) => void;
|
|
2030
2271
|
onVisualStructureChange?: (
|
|
@@ -2063,6 +2304,7 @@ interface DesignCanvasProps {
|
|
|
2063
2304
|
lockedSelectors?: string[];
|
|
2064
2305
|
hiddenSelectors?: string[];
|
|
2065
2306
|
clearSelectionRequest?: number;
|
|
2307
|
+
registerRuntimeBridge?: boolean;
|
|
2066
2308
|
/** Called when the user exits pin mode. */
|
|
2067
2309
|
onExitPinMode?: () => void;
|
|
2068
2310
|
/** Stable id of the open design (used for pin scoping + agent prompt). */
|
|
@@ -2119,15 +2361,20 @@ export function DesignCanvas({
|
|
|
2119
2361
|
onZoomChange,
|
|
2120
2362
|
deviceFrame,
|
|
2121
2363
|
embeddedFrame,
|
|
2364
|
+
editorChromeScaleX = 1,
|
|
2365
|
+
editorChromeScaleY = editorChromeScaleX,
|
|
2122
2366
|
editMode,
|
|
2123
2367
|
interactMode,
|
|
2368
|
+
readOnly = false,
|
|
2124
2369
|
scaleMode = false,
|
|
2125
2370
|
clearSelectionRequest,
|
|
2126
2371
|
onElementSelect,
|
|
2127
2372
|
onElementHover,
|
|
2373
|
+
onClearSelection,
|
|
2128
2374
|
onVisualStyleChange,
|
|
2129
2375
|
onTextContentChange,
|
|
2130
2376
|
onTextEditingStateChange,
|
|
2377
|
+
onElementDblClickText,
|
|
2131
2378
|
onIframeHotkey,
|
|
2132
2379
|
onIframeContextMenu,
|
|
2133
2380
|
onVisualStructureChange,
|
|
@@ -2143,6 +2390,7 @@ export function DesignCanvas({
|
|
|
2143
2390
|
lockedSelectors = [],
|
|
2144
2391
|
hiddenSelectors = [],
|
|
2145
2392
|
onExitPinMode,
|
|
2393
|
+
registerRuntimeBridge = true,
|
|
2146
2394
|
designId,
|
|
2147
2395
|
designTitle,
|
|
2148
2396
|
commentContextId,
|
|
@@ -2198,13 +2446,17 @@ export function DesignCanvas({
|
|
|
2198
2446
|
// outside Edit mode. The editor chrome bridge is omitted only for Interact.
|
|
2199
2447
|
const srcdoc = useMemo(() => {
|
|
2200
2448
|
if (externalPreviewUrl) return undefined;
|
|
2201
|
-
const editorChromeBridge =
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2449
|
+
const editorChromeBridge =
|
|
2450
|
+
interactMode || readOnly
|
|
2451
|
+
? ""
|
|
2452
|
+
: createEditorBridgeThemeScript(readEditorBridgeThemeVars()) +
|
|
2453
|
+
EDITOR_CHROME_BRIDGE_SCRIPT.replace(
|
|
2454
|
+
"__READ_ONLY__",
|
|
2455
|
+
readOnly ? "true" : "false",
|
|
2456
|
+
)
|
|
2457
|
+
.replace("__TEXT_EDITING_ENABLED__", editMode ? "true" : "false")
|
|
2458
|
+
.replace("__EDITOR_CHROME_SCALE_X__", String(editorChromeScaleX))
|
|
2459
|
+
.replace("__EDITOR_CHROME_SCALE_Y__", String(editorChromeScaleY));
|
|
2208
2460
|
const embeddedWheelBridge = EMBEDDED_WHEEL_BRIDGE_SCRIPT.replace(
|
|
2209
2461
|
"__EMBEDDED_WHEEL_FORWARDING_ENABLED__",
|
|
2210
2462
|
isEmbeddedFrame ? "true" : "false",
|
|
@@ -2223,11 +2475,17 @@ export function DesignCanvas({
|
|
|
2223
2475
|
}
|
|
2224
2476
|
// No body/html tags — wrap it
|
|
2225
2477
|
return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head><body>${renderedContent}${bridgeToInject}</body></html>`;
|
|
2478
|
+
// editorChromeScaleX/Y are intentionally NOT deps: they only seed the initial
|
|
2479
|
+
// baked chrome scale. Live zoom updates flow through the set-editor-chrome-scale
|
|
2480
|
+
// postMessage above. Including them here rebuilds srcdoc on every zoom commit,
|
|
2481
|
+
// which reloads the iframe and flashes the screen content white.
|
|
2482
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2226
2483
|
}, [
|
|
2227
2484
|
editMode,
|
|
2228
2485
|
externalPreviewUrl,
|
|
2229
2486
|
interactMode,
|
|
2230
2487
|
isEmbeddedFrame,
|
|
2488
|
+
readOnly,
|
|
2231
2489
|
renderedContent,
|
|
2232
2490
|
]);
|
|
2233
2491
|
|
|
@@ -2245,6 +2503,10 @@ export function DesignCanvas({
|
|
|
2245
2503
|
return;
|
|
2246
2504
|
}
|
|
2247
2505
|
if (!e.data || !e.data.type) return;
|
|
2506
|
+
if (e.data.type === "clear-selection") {
|
|
2507
|
+
onClearSelection?.();
|
|
2508
|
+
return;
|
|
2509
|
+
}
|
|
2248
2510
|
if (e.data.type === "element-select") {
|
|
2249
2511
|
onElementSelect(e.data.payload);
|
|
2250
2512
|
}
|
|
@@ -2352,6 +2614,10 @@ export function DesignCanvas({
|
|
|
2352
2614
|
});
|
|
2353
2615
|
return;
|
|
2354
2616
|
}
|
|
2617
|
+
if (e.data.type === "element-dblclick-text") {
|
|
2618
|
+
onElementDblClickText?.(e.data.payload);
|
|
2619
|
+
return;
|
|
2620
|
+
}
|
|
2355
2621
|
if (e.data.type === "design-hotkey") {
|
|
2356
2622
|
onIframeHotkey?.({
|
|
2357
2623
|
key: String(e.data.key || ""),
|
|
@@ -2470,9 +2736,11 @@ export function DesignCanvas({
|
|
|
2470
2736
|
}, [
|
|
2471
2737
|
onElementSelect,
|
|
2472
2738
|
onElementHover,
|
|
2739
|
+
onClearSelection,
|
|
2473
2740
|
onVisualStyleChange,
|
|
2474
2741
|
onTextContentChange,
|
|
2475
2742
|
onTextEditingStateChange,
|
|
2743
|
+
onElementDblClickText,
|
|
2476
2744
|
onIframeHotkey,
|
|
2477
2745
|
onIframeContextMenu,
|
|
2478
2746
|
onVisualStructureChange,
|
|
@@ -2548,6 +2816,21 @@ export function DesignCanvas({
|
|
|
2548
2816
|
);
|
|
2549
2817
|
}, [clearSelectionRequest]);
|
|
2550
2818
|
|
|
2819
|
+
// Push the constant-size chrome scale into the iframe LIVE (CSS vars only) when
|
|
2820
|
+
// overview zoom settles. This is intentionally separate from the srcdoc build so
|
|
2821
|
+
// a scale change never rebuilds srcdoc / reloads the iframe (which flashes the
|
|
2822
|
+
// content white). The baked __EDITOR_CHROME_SCALE__ values cover first paint.
|
|
2823
|
+
useEffect(() => {
|
|
2824
|
+
iframeRef.current?.contentWindow?.postMessage(
|
|
2825
|
+
{
|
|
2826
|
+
type: "set-editor-chrome-scale",
|
|
2827
|
+
scaleX: editorChromeScaleX,
|
|
2828
|
+
scaleY: editorChromeScaleY,
|
|
2829
|
+
},
|
|
2830
|
+
"*",
|
|
2831
|
+
);
|
|
2832
|
+
}, [editorChromeScaleX, editorChromeScaleY]);
|
|
2833
|
+
|
|
2551
2834
|
const sendStyleChange = useCallback(
|
|
2552
2835
|
(selector: string, property: string, value: string) => {
|
|
2553
2836
|
const iframe = iframeRef.current;
|
|
@@ -2597,15 +2880,31 @@ export function DesignCanvas({
|
|
|
2597
2880
|
|
|
2598
2881
|
// Expose iframe runtime mutations for the editor orchestrator.
|
|
2599
2882
|
useEffect(() => {
|
|
2883
|
+
if (!registerRuntimeBridge) return;
|
|
2600
2884
|
(window as any).__designCanvasSendStyle = sendStyleChange;
|
|
2601
2885
|
(window as any).__designCanvasReplaceContent = replacePreviewContent;
|
|
2602
2886
|
(window as any).__designCanvasDeleteElement = deleteRuntimeElement;
|
|
2603
2887
|
return () => {
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2888
|
+
if ((window as any).__designCanvasSendStyle === sendStyleChange) {
|
|
2889
|
+
delete (window as any).__designCanvasSendStyle;
|
|
2890
|
+
}
|
|
2891
|
+
if (
|
|
2892
|
+
(window as any).__designCanvasReplaceContent === replacePreviewContent
|
|
2893
|
+
) {
|
|
2894
|
+
delete (window as any).__designCanvasReplaceContent;
|
|
2895
|
+
}
|
|
2896
|
+
if (
|
|
2897
|
+
(window as any).__designCanvasDeleteElement === deleteRuntimeElement
|
|
2898
|
+
) {
|
|
2899
|
+
delete (window as any).__designCanvasDeleteElement;
|
|
2900
|
+
}
|
|
2607
2901
|
};
|
|
2608
|
-
}, [
|
|
2902
|
+
}, [
|
|
2903
|
+
deleteRuntimeElement,
|
|
2904
|
+
registerRuntimeBridge,
|
|
2905
|
+
replacePreviewContent,
|
|
2906
|
+
sendStyleChange,
|
|
2907
|
+
]);
|
|
2609
2908
|
|
|
2610
2909
|
// Device dimensions match real-world devices. iframes are replaced elements
|
|
2611
2910
|
// with an intrinsic 300×150 size, so `aspect-ratio` + `height: auto` doesn't
|
|
@@ -2622,6 +2921,7 @@ export function DesignCanvas({
|
|
|
2622
2921
|
|
|
2623
2922
|
const { width: iframeWidth, height: iframeHeight } =
|
|
2624
2923
|
deviceDimensions[deviceFrame];
|
|
2924
|
+
const embeddedFrameFluid = embeddedFrame?.fluid === true;
|
|
2625
2925
|
|
|
2626
2926
|
// Wrap the iframe in a positioned container so DrawOverlay /
|
|
2627
2927
|
// CanvasCommentPins can absolutely-position themselves on top of the
|
|
@@ -2634,9 +2934,15 @@ export function DesignCanvas({
|
|
|
2634
2934
|
<div
|
|
2635
2935
|
className="design-canvas-iframe-wrapper relative inline-block ring-1 ring-border/60 shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_8px_24px_-12px_rgba(0,0,0,0.45)]"
|
|
2636
2936
|
style={{
|
|
2637
|
-
width: embeddedFrame
|
|
2937
|
+
width: embeddedFrame
|
|
2938
|
+
? embeddedFrameFluid
|
|
2939
|
+
? "100%"
|
|
2940
|
+
: embeddedFrame.viewportWidth
|
|
2941
|
+
: iframeWidth,
|
|
2638
2942
|
height: embeddedFrame
|
|
2639
|
-
?
|
|
2943
|
+
? embeddedFrameFluid
|
|
2944
|
+
? "100%"
|
|
2945
|
+
: embeddedFrame.viewportHeight
|
|
2640
2946
|
: deviceFrame === "none"
|
|
2641
2947
|
? "100%"
|
|
2642
2948
|
: (iframeHeight ?? undefined),
|
|
@@ -2660,6 +2966,7 @@ export function DesignCanvas({
|
|
|
2660
2966
|
visible={!!drawMode}
|
|
2661
2967
|
canvasInteractive={!pinMode}
|
|
2662
2968
|
queuedAnnotationCount={queuedAnnotationPins.length}
|
|
2969
|
+
zoom={zoom}
|
|
2663
2970
|
onClose={() => onExitDrawMode?.()}
|
|
2664
2971
|
onSend={(annotations, instruction, canvasSize) => {
|
|
2665
2972
|
const summary = annotations
|
|
@@ -2713,6 +3020,17 @@ export function DesignCanvas({
|
|
|
2713
3020
|
);
|
|
2714
3021
|
|
|
2715
3022
|
if (embeddedFrame) {
|
|
3023
|
+
if (embeddedFrameFluid) {
|
|
3024
|
+
return (
|
|
3025
|
+
<div
|
|
3026
|
+
ref={scrollContainerRef}
|
|
3027
|
+
className="relative h-full w-full overflow-hidden"
|
|
3028
|
+
>
|
|
3029
|
+
{iframeElement}
|
|
3030
|
+
</div>
|
|
3031
|
+
);
|
|
3032
|
+
}
|
|
3033
|
+
|
|
2716
3034
|
const scaleX =
|
|
2717
3035
|
embeddedFrame.displayWidth / Math.max(1, embeddedFrame.viewportWidth);
|
|
2718
3036
|
const scaleY =
|