@agent-native/core 0.80.8 → 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 +12 -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/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/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/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 +20 -12
- 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/export-coding-handoff.ts +12 -4
- package/corpus/templates/design/actions/generate-design.ts +6 -21
- package/corpus/templates/design/actions/generate-screens.ts +43 -2
- 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/view-screen.ts +75 -31
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +329 -69
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
- package/corpus/templates/design/app/components/design/EditPanel.tsx +479 -77
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +380 -216
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1050 -196
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +83 -206
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +1 -1
- package/corpus/templates/design/app/components/design/index.ts +0 -1
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +225 -133
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +122 -11
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +24 -5
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -1
- 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 +12 -5
- 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/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 +3 -0
- package/corpus/templates/design/app/i18n-data.ts +45 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2602 -657
- package/corpus/templates/design/app/root.tsx +1 -1
- 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-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-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-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-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-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-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 +3 -3
- package/corpus/templates/design/e2e/global-setup.ts +11 -22
- package/corpus/templates/design/e2e/helpers.ts +122 -11
- package/corpus/templates/design/playwright.config.ts +9 -3
- 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/generation-session.ts +41 -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/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/file-upload/actions/upload-image.d.ts +2 -2
- 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/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +8 -8
- 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/agent-engine-api-key-route.d.ts +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 -342
|
@@ -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,
|
|
@@ -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,6 +867,49 @@ 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';
|
|
@@ -793,23 +919,26 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
793
919
|
// the handles hug the rotated element rather than its inflated AABB.
|
|
794
920
|
if (overlay === selectionOverlay) {
|
|
795
921
|
var elCs = window.getComputedStyle(el);
|
|
796
|
-
var elLeft =
|
|
797
|
-
var elTop =
|
|
798
|
-
var elW =
|
|
799
|
-
var elH =
|
|
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);
|
|
800
926
|
var elRot = currentRotation(el);
|
|
927
|
+
var canUseLocalBox = Math.abs(elRot) > 0.01 && elLeft !== null && elTop !== null && elW !== null && elH !== null;
|
|
801
928
|
// Convert element-local left/top to viewport coords by walking to the
|
|
802
929
|
// nearest positioned ancestor (same reference frame as getBoundingClientRect).
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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
|
+
}
|
|
813
942
|
}
|
|
814
943
|
var rect = el.getBoundingClientRect();
|
|
815
944
|
overlay.style.display = 'block';
|
|
@@ -817,10 +946,16 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
817
946
|
overlay.style.left = rect.left + 'px';
|
|
818
947
|
overlay.style.width = rect.width + 'px';
|
|
819
948
|
overlay.style.height = rect.height + 'px';
|
|
949
|
+
overlay.style.transform = '';
|
|
950
|
+
if (overlay === selectionOverlay) updatePaddingOverlay(el);
|
|
820
951
|
}
|
|
821
952
|
|
|
822
953
|
function refreshOverlays() {
|
|
823
|
-
if (hoveredEl
|
|
954
|
+
if (hoveredEl && hoveredEl !== selectedEl) {
|
|
955
|
+
positionOverlay(highlightOverlay, hoveredEl);
|
|
956
|
+
} else {
|
|
957
|
+
highlightOverlay.style.display = 'none';
|
|
958
|
+
}
|
|
824
959
|
if (selectedEl) positionOverlay(selectionOverlay, selectedEl);
|
|
825
960
|
}
|
|
826
961
|
|
|
@@ -1067,7 +1202,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1067
1202
|
window.parent.postMessage({ type: 'clear-selection' }, '*');
|
|
1068
1203
|
return;
|
|
1069
1204
|
}
|
|
1070
|
-
selectedEl = target;
|
|
1205
|
+
selectedEl = selectionTargetForHit(target);
|
|
1071
1206
|
var info = getElementInfo(selectedEl);
|
|
1072
1207
|
positionOverlay(selectionOverlay, selectedEl);
|
|
1073
1208
|
window.parent.postMessage({ type: 'element-select', payload: info }, '*');
|
|
@@ -1079,9 +1214,9 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1079
1214
|
var target = elementFromEditorPoint(e.clientX, e.clientY);
|
|
1080
1215
|
var info = null;
|
|
1081
1216
|
if (target) {
|
|
1082
|
-
selectedEl = target;
|
|
1083
|
-
info = getElementInfo(
|
|
1084
|
-
positionOverlay(selectionOverlay,
|
|
1217
|
+
selectedEl = selectionTargetForHit(target);
|
|
1218
|
+
info = getElementInfo(selectedEl);
|
|
1219
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
1085
1220
|
window.parent.postMessage({ type: 'element-select', payload: info }, '*');
|
|
1086
1221
|
}
|
|
1087
1222
|
window.parent.postMessage({
|
|
@@ -1138,6 +1273,12 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1138
1273
|
return Number.isFinite(num) ? num : 0;
|
|
1139
1274
|
}
|
|
1140
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
|
+
|
|
1141
1282
|
function currentRotation(el) {
|
|
1142
1283
|
var transform = el.style.transform || window.getComputedStyle(el).transform || '';
|
|
1143
1284
|
var match = transform.match(/rotate\\((-?\\d+(?:\\.\\d+)?)deg\\)/);
|
|
@@ -1602,9 +1743,16 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1602
1743
|
if (handle.indexOf('s') !== -1) height = origin.height + dy;
|
|
1603
1744
|
// Apply Shift / scaleToolEnabled aspect-ratio lock BEFORE the min-size
|
|
1604
1745
|
// clamp so the ratio is computed from unclamped values (bug fix).
|
|
1605
|
-
if (ev.shiftKey
|
|
1606
|
-
|
|
1607
|
-
|
|
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
|
+
}
|
|
1608
1756
|
}
|
|
1609
1757
|
if (scaleToolEnabled) {
|
|
1610
1758
|
// Scale tool: enforce aspect ratio on all 8 handles, not just corners.
|
|
@@ -1617,9 +1765,22 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1617
1765
|
else width = height * origin.ratio;
|
|
1618
1766
|
}
|
|
1619
1767
|
}
|
|
1620
|
-
// Clamp
|
|
1621
|
-
|
|
1622
|
-
|
|
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;
|
|
1623
1784
|
// Re-anchor the pinned edge for w/n handles after aspect-ratio lock and
|
|
1624
1785
|
// clamping so the opposite (e/s) edge stays fixed regardless of whether
|
|
1625
1786
|
// the dimension change was driven by raw dx/dy or by the ratio lock.
|
|
@@ -1735,6 +1896,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1735
1896
|
document.addEventListener('keydown', function(e) {
|
|
1736
1897
|
if (!shouldForwardDesignHotkey(e)) return;
|
|
1737
1898
|
stopNativeInteraction(e);
|
|
1899
|
+
if (e.key === 'Escape') clearRuntimeSelection();
|
|
1738
1900
|
window.parent.postMessage({
|
|
1739
1901
|
type: 'design-hotkey',
|
|
1740
1902
|
key: e.key,
|
|
@@ -1788,7 +1950,12 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1788
1950
|
stopNativeInteraction(e);
|
|
1789
1951
|
var target = findTextEditTarget(elementFromEditorPoint(e.clientX, e.clientY));
|
|
1790
1952
|
if (!target || target.nodeType !== 1) return;
|
|
1791
|
-
|
|
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;
|
|
1792
1959
|
var originalText = target.textContent || '';
|
|
1793
1960
|
var originalHtml = target.innerHTML || '';
|
|
1794
1961
|
var committed = false;
|
|
@@ -1801,6 +1968,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1801
1968
|
setTextEditingPointerPassthrough(true);
|
|
1802
1969
|
positionOverlay(selectionOverlay, target);
|
|
1803
1970
|
window.parent.postMessage({ type: 'element-select', payload: getElementInfo(target) }, '*');
|
|
1971
|
+
window.parent.postMessage({ type: 'element-dblclick-text', payload: getElementInfo(target) }, '*');
|
|
1804
1972
|
postTextEditingState(target, true);
|
|
1805
1973
|
|
|
1806
1974
|
function finish(commit) {
|
|
@@ -1886,7 +2054,11 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1886
2054
|
return;
|
|
1887
2055
|
}
|
|
1888
2056
|
if (hoveredEl && hoveredEl.closest('[data-agent-native-text-editing]')) return;
|
|
1889
|
-
|
|
2057
|
+
if (hoveredEl === selectedEl) {
|
|
2058
|
+
highlightOverlay.style.display = 'none';
|
|
2059
|
+
} else {
|
|
2060
|
+
positionOverlay(highlightOverlay, hoveredEl);
|
|
2061
|
+
}
|
|
1890
2062
|
if (e.altKey && selectedEl && hoveredEl && selectedEl !== hoveredEl) {
|
|
1891
2063
|
showMeasurements(selectedEl, hoveredEl);
|
|
1892
2064
|
} else {
|
|
@@ -1901,6 +2073,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1901
2073
|
hoveredEl = null;
|
|
1902
2074
|
highlightOverlay.style.display = 'none';
|
|
1903
2075
|
hideMeasurements();
|
|
2076
|
+
window.parent.postMessage({ type: 'element-hover', payload: null }, '*');
|
|
1904
2077
|
}, true);
|
|
1905
2078
|
|
|
1906
2079
|
window.addEventListener('keyup', function(e) {
|
|
@@ -1910,16 +2083,21 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1910
2083
|
window.addEventListener('message', function(e) {
|
|
1911
2084
|
if (e.source !== window.parent) return;
|
|
1912
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
|
+
}
|
|
1913
2095
|
if (e.data.type === 'scale-tool-mode') {
|
|
1914
2096
|
scaleToolEnabled = !!e.data.enabled;
|
|
1915
2097
|
return;
|
|
1916
2098
|
}
|
|
1917
2099
|
if (e.data.type === 'clear-selection') {
|
|
1918
|
-
|
|
1919
|
-
hoveredEl = null;
|
|
1920
|
-
selectionOverlay.style.display = 'none';
|
|
1921
|
-
highlightOverlay.style.display = 'none';
|
|
1922
|
-
hideMeasurements();
|
|
2100
|
+
clearRuntimeSelection();
|
|
1923
2101
|
return;
|
|
1924
2102
|
}
|
|
1925
2103
|
if (e.data.type === 'select-element') {
|
|
@@ -1953,9 +2131,8 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1953
2131
|
}
|
|
1954
2132
|
if (!target) return;
|
|
1955
2133
|
selectedEl = target;
|
|
1956
|
-
var selectedInfo = getElementInfo(target);
|
|
1957
2134
|
positionOverlay(selectionOverlay, target);
|
|
1958
|
-
|
|
2135
|
+
if (hoveredEl === selectedEl) highlightOverlay.style.display = 'none';
|
|
1959
2136
|
return;
|
|
1960
2137
|
}
|
|
1961
2138
|
if (e.data.type === 'hover-element') {
|
|
@@ -1978,7 +2155,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
1978
2155
|
}
|
|
1979
2156
|
var hoverTarget = findRuntimeTarget(String(e.data.selector || ''), hoverCandidates);
|
|
1980
2157
|
hoveredEl = hoverTarget;
|
|
1981
|
-
if (hoveredEl && !isLayerInteractionBlocked(hoveredEl)) {
|
|
2158
|
+
if (hoveredEl && !isLayerInteractionBlocked(hoveredEl) && hoveredEl !== selectedEl) {
|
|
1982
2159
|
positionOverlay(highlightOverlay, hoveredEl);
|
|
1983
2160
|
} else {
|
|
1984
2161
|
highlightOverlay.style.display = 'none';
|
|
@@ -2045,6 +2222,7 @@ const EDITOR_CHROME_BRIDGE_SCRIPT = `
|
|
|
2045
2222
|
|
|
2046
2223
|
window.addEventListener('scroll', refreshOverlays, true);
|
|
2047
2224
|
window.addEventListener('resize', refreshOverlays);
|
|
2225
|
+
applyEditorChromeScale();
|
|
2048
2226
|
})();
|
|
2049
2227
|
</script>
|
|
2050
2228
|
`;
|
|
@@ -2060,12 +2238,17 @@ interface DesignCanvasProps {
|
|
|
2060
2238
|
viewportHeight: number;
|
|
2061
2239
|
displayWidth: number;
|
|
2062
2240
|
displayHeight: number;
|
|
2241
|
+
fluid?: boolean;
|
|
2063
2242
|
};
|
|
2243
|
+
editorChromeScaleX?: number;
|
|
2244
|
+
editorChromeScaleY?: number;
|
|
2064
2245
|
editMode: boolean;
|
|
2065
2246
|
interactMode: boolean;
|
|
2247
|
+
readOnly?: boolean;
|
|
2066
2248
|
scaleMode?: boolean;
|
|
2067
2249
|
onElementSelect: (info: ElementInfo) => void;
|
|
2068
|
-
onElementHover: (info: ElementInfo) => void;
|
|
2250
|
+
onElementHover: (info: ElementInfo | null) => void;
|
|
2251
|
+
onClearSelection?: () => void;
|
|
2069
2252
|
onVisualStyleChange?: (
|
|
2070
2253
|
selector: string,
|
|
2071
2254
|
styles: Record<string, string>,
|
|
@@ -2082,6 +2265,7 @@ interface DesignCanvasProps {
|
|
|
2082
2265
|
selector?: string;
|
|
2083
2266
|
hasRange?: boolean;
|
|
2084
2267
|
}) => void;
|
|
2268
|
+
onElementDblClickText?: (info: ElementInfo) => void;
|
|
2085
2269
|
onIframeHotkey?: (event: IframeHotkeyPayload) => void;
|
|
2086
2270
|
onIframeContextMenu?: (event: IframeContextMenuPayload) => void;
|
|
2087
2271
|
onVisualStructureChange?: (
|
|
@@ -2120,6 +2304,7 @@ interface DesignCanvasProps {
|
|
|
2120
2304
|
lockedSelectors?: string[];
|
|
2121
2305
|
hiddenSelectors?: string[];
|
|
2122
2306
|
clearSelectionRequest?: number;
|
|
2307
|
+
registerRuntimeBridge?: boolean;
|
|
2123
2308
|
/** Called when the user exits pin mode. */
|
|
2124
2309
|
onExitPinMode?: () => void;
|
|
2125
2310
|
/** Stable id of the open design (used for pin scoping + agent prompt). */
|
|
@@ -2176,15 +2361,20 @@ export function DesignCanvas({
|
|
|
2176
2361
|
onZoomChange,
|
|
2177
2362
|
deviceFrame,
|
|
2178
2363
|
embeddedFrame,
|
|
2364
|
+
editorChromeScaleX = 1,
|
|
2365
|
+
editorChromeScaleY = editorChromeScaleX,
|
|
2179
2366
|
editMode,
|
|
2180
2367
|
interactMode,
|
|
2368
|
+
readOnly = false,
|
|
2181
2369
|
scaleMode = false,
|
|
2182
2370
|
clearSelectionRequest,
|
|
2183
2371
|
onElementSelect,
|
|
2184
2372
|
onElementHover,
|
|
2373
|
+
onClearSelection,
|
|
2185
2374
|
onVisualStyleChange,
|
|
2186
2375
|
onTextContentChange,
|
|
2187
2376
|
onTextEditingStateChange,
|
|
2377
|
+
onElementDblClickText,
|
|
2188
2378
|
onIframeHotkey,
|
|
2189
2379
|
onIframeContextMenu,
|
|
2190
2380
|
onVisualStructureChange,
|
|
@@ -2200,6 +2390,7 @@ export function DesignCanvas({
|
|
|
2200
2390
|
lockedSelectors = [],
|
|
2201
2391
|
hiddenSelectors = [],
|
|
2202
2392
|
onExitPinMode,
|
|
2393
|
+
registerRuntimeBridge = true,
|
|
2203
2394
|
designId,
|
|
2204
2395
|
designTitle,
|
|
2205
2396
|
commentContextId,
|
|
@@ -2255,13 +2446,17 @@ export function DesignCanvas({
|
|
|
2255
2446
|
// outside Edit mode. The editor chrome bridge is omitted only for Interact.
|
|
2256
2447
|
const srcdoc = useMemo(() => {
|
|
2257
2448
|
if (externalPreviewUrl) return undefined;
|
|
2258
|
-
const editorChromeBridge =
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
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));
|
|
2265
2460
|
const embeddedWheelBridge = EMBEDDED_WHEEL_BRIDGE_SCRIPT.replace(
|
|
2266
2461
|
"__EMBEDDED_WHEEL_FORWARDING_ENABLED__",
|
|
2267
2462
|
isEmbeddedFrame ? "true" : "false",
|
|
@@ -2280,11 +2475,17 @@ export function DesignCanvas({
|
|
|
2280
2475
|
}
|
|
2281
2476
|
// No body/html tags — wrap it
|
|
2282
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
|
|
2283
2483
|
}, [
|
|
2284
2484
|
editMode,
|
|
2285
2485
|
externalPreviewUrl,
|
|
2286
2486
|
interactMode,
|
|
2287
2487
|
isEmbeddedFrame,
|
|
2488
|
+
readOnly,
|
|
2288
2489
|
renderedContent,
|
|
2289
2490
|
]);
|
|
2290
2491
|
|
|
@@ -2302,6 +2503,10 @@ export function DesignCanvas({
|
|
|
2302
2503
|
return;
|
|
2303
2504
|
}
|
|
2304
2505
|
if (!e.data || !e.data.type) return;
|
|
2506
|
+
if (e.data.type === "clear-selection") {
|
|
2507
|
+
onClearSelection?.();
|
|
2508
|
+
return;
|
|
2509
|
+
}
|
|
2305
2510
|
if (e.data.type === "element-select") {
|
|
2306
2511
|
onElementSelect(e.data.payload);
|
|
2307
2512
|
}
|
|
@@ -2409,6 +2614,10 @@ export function DesignCanvas({
|
|
|
2409
2614
|
});
|
|
2410
2615
|
return;
|
|
2411
2616
|
}
|
|
2617
|
+
if (e.data.type === "element-dblclick-text") {
|
|
2618
|
+
onElementDblClickText?.(e.data.payload);
|
|
2619
|
+
return;
|
|
2620
|
+
}
|
|
2412
2621
|
if (e.data.type === "design-hotkey") {
|
|
2413
2622
|
onIframeHotkey?.({
|
|
2414
2623
|
key: String(e.data.key || ""),
|
|
@@ -2527,9 +2736,11 @@ export function DesignCanvas({
|
|
|
2527
2736
|
}, [
|
|
2528
2737
|
onElementSelect,
|
|
2529
2738
|
onElementHover,
|
|
2739
|
+
onClearSelection,
|
|
2530
2740
|
onVisualStyleChange,
|
|
2531
2741
|
onTextContentChange,
|
|
2532
2742
|
onTextEditingStateChange,
|
|
2743
|
+
onElementDblClickText,
|
|
2533
2744
|
onIframeHotkey,
|
|
2534
2745
|
onIframeContextMenu,
|
|
2535
2746
|
onVisualStructureChange,
|
|
@@ -2605,6 +2816,21 @@ export function DesignCanvas({
|
|
|
2605
2816
|
);
|
|
2606
2817
|
}, [clearSelectionRequest]);
|
|
2607
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
|
+
|
|
2608
2834
|
const sendStyleChange = useCallback(
|
|
2609
2835
|
(selector: string, property: string, value: string) => {
|
|
2610
2836
|
const iframe = iframeRef.current;
|
|
@@ -2654,15 +2880,31 @@ export function DesignCanvas({
|
|
|
2654
2880
|
|
|
2655
2881
|
// Expose iframe runtime mutations for the editor orchestrator.
|
|
2656
2882
|
useEffect(() => {
|
|
2883
|
+
if (!registerRuntimeBridge) return;
|
|
2657
2884
|
(window as any).__designCanvasSendStyle = sendStyleChange;
|
|
2658
2885
|
(window as any).__designCanvasReplaceContent = replacePreviewContent;
|
|
2659
2886
|
(window as any).__designCanvasDeleteElement = deleteRuntimeElement;
|
|
2660
2887
|
return () => {
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
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
|
+
}
|
|
2664
2901
|
};
|
|
2665
|
-
}, [
|
|
2902
|
+
}, [
|
|
2903
|
+
deleteRuntimeElement,
|
|
2904
|
+
registerRuntimeBridge,
|
|
2905
|
+
replacePreviewContent,
|
|
2906
|
+
sendStyleChange,
|
|
2907
|
+
]);
|
|
2666
2908
|
|
|
2667
2909
|
// Device dimensions match real-world devices. iframes are replaced elements
|
|
2668
2910
|
// with an intrinsic 300×150 size, so `aspect-ratio` + `height: auto` doesn't
|
|
@@ -2679,6 +2921,7 @@ export function DesignCanvas({
|
|
|
2679
2921
|
|
|
2680
2922
|
const { width: iframeWidth, height: iframeHeight } =
|
|
2681
2923
|
deviceDimensions[deviceFrame];
|
|
2924
|
+
const embeddedFrameFluid = embeddedFrame?.fluid === true;
|
|
2682
2925
|
|
|
2683
2926
|
// Wrap the iframe in a positioned container so DrawOverlay /
|
|
2684
2927
|
// CanvasCommentPins can absolutely-position themselves on top of the
|
|
@@ -2691,9 +2934,15 @@ export function DesignCanvas({
|
|
|
2691
2934
|
<div
|
|
2692
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)]"
|
|
2693
2936
|
style={{
|
|
2694
|
-
width: embeddedFrame
|
|
2937
|
+
width: embeddedFrame
|
|
2938
|
+
? embeddedFrameFluid
|
|
2939
|
+
? "100%"
|
|
2940
|
+
: embeddedFrame.viewportWidth
|
|
2941
|
+
: iframeWidth,
|
|
2695
2942
|
height: embeddedFrame
|
|
2696
|
-
?
|
|
2943
|
+
? embeddedFrameFluid
|
|
2944
|
+
? "100%"
|
|
2945
|
+
: embeddedFrame.viewportHeight
|
|
2697
2946
|
: deviceFrame === "none"
|
|
2698
2947
|
? "100%"
|
|
2699
2948
|
: (iframeHeight ?? undefined),
|
|
@@ -2771,6 +3020,17 @@ export function DesignCanvas({
|
|
|
2771
3020
|
);
|
|
2772
3021
|
|
|
2773
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
|
+
|
|
2774
3034
|
const scaleX =
|
|
2775
3035
|
embeddedFrame.displayWidth / Math.max(1, embeddedFrame.viewportWidth);
|
|
2776
3036
|
const scaleY =
|