@agent-native/core 0.92.6 → 0.92.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +18 -0
- package/corpus/core/docs/content/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
- package/corpus/core/docs/content/pr-visual-recap.mdx +3 -3
- package/corpus/core/docs/content/pure-agent-apps.mdx +22 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/engine/builtin.ts +1 -1
- package/corpus/core/src/agent/model-config.ts +30 -30
- package/corpus/core/src/agent/production-agent.ts +129 -7
- package/corpus/core/src/cli/design-connect.ts +438 -83
- package/corpus/core/src/cli/recap.ts +2 -2
- package/corpus/core/src/cli/sync-builder-starter-manifest.ts +1 -1
- package/corpus/core/src/client/AgentPanel.tsx +8 -1
- package/corpus/core/src/client/agent-chat-adapter.ts +12 -7
- package/corpus/core/src/client/composer/TiptapComposer.tsx +1 -1
- package/corpus/core/src/client/index.ts +4 -0
- package/corpus/core/src/client/org/TeamPage.tsx +41 -26
- package/corpus/core/src/client/use-action.ts +113 -1
- package/corpus/core/src/db/client.ts +12 -2
- package/corpus/core/src/db/create-get-db.ts +4 -1
- package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +1 -1
- package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +1 -1
- package/corpus/core/src/server/transcribe-voice.ts +1 -1
- package/corpus/core/src/usage/store.ts +13 -4
- package/corpus/core/src/vite/client.ts +38 -1
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/get-data-program.ts +78 -0
- package/corpus/templates/analytics/actions/list-data-programs.ts +49 -0
- package/corpus/templates/analytics/app/global.css +11 -0
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +163 -17
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/analytics/app/i18n-data.ts +20 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +96 -3
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +61 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +40 -2
- package/corpus/templates/analytics/changelog/2026-07-09-analytics-no-longer-forgets-successful-data-queries-when-a-l.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-keep-consistent-spacing-when-they-stack-ver.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-tables-and-extensions-can-be-selected-and-d.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-09-long-running-analytics-requests-now-recover-automatically-wh.md +6 -0
- package/corpus/templates/analytics/server/db/index.ts +6 -0
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +1 -7
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +102 -15
- package/corpus/templates/content/app/hooks/use-content-database.ts +52 -0
- package/corpus/templates/content/app/hooks/use-document-properties.ts +50 -6
- package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/content/app/i18n-data.ts +28 -0
- package/corpus/templates/content/changelog/2026-07-09-notion-conflict-warnings-no-longer-flash-during-normal-synce.md +6 -0
- package/corpus/templates/content/changelog/2026-07-09-property-menus-and-delete-confirmations-now-open-visibly-and.md +6 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +130 -28
- package/corpus/templates/design/actions/add-breakpoint.ts +48 -68
- package/corpus/templates/design/actions/add-localhost-screens.ts +496 -61
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +2 -18
- package/corpus/templates/design/actions/apply-design-token-edit.ts +51 -82
- package/corpus/templates/design/actions/apply-tweaks.ts +63 -41
- package/corpus/templates/design/actions/capture-design-state.ts +2 -2
- package/corpus/templates/design/actions/connect-localhost.ts +58 -12
- package/corpus/templates/design/actions/create-component.ts +2 -18
- package/corpus/templates/design/actions/create-design-branch.ts +38 -18
- package/corpus/templates/design/actions/create-fusion-app.ts +15 -11
- package/corpus/templates/design/actions/delete-file.ts +19 -34
- package/corpus/templates/design/actions/deploy-design-preview.ts +59 -27
- package/corpus/templates/design/actions/deploy-fusion-app.ts +22 -15
- package/corpus/templates/design/actions/export-pdf.ts +2 -1
- package/corpus/templates/design/actions/export-zip.ts +9 -3
- package/corpus/templates/design/actions/generate-design.ts +107 -70
- package/corpus/templates/design/actions/get-component-details.ts +2 -18
- package/corpus/templates/design/actions/get-design-branch-diff.ts +2 -3
- package/corpus/templates/design/actions/get-design-surface-index.ts +2 -18
- package/corpus/templates/design/actions/get-design.ts +2 -1
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +7 -1
- package/corpus/templates/design/actions/import-design-tokens.ts +114 -76
- package/corpus/templates/design/actions/index-components.ts +2 -18
- package/corpus/templates/design/actions/list-design-source-capabilities.ts +23 -28
- package/corpus/templates/design/actions/list-local-files.ts +9 -2
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +82 -98
- package/corpus/templates/design/actions/open-component-source.ts +2 -18
- package/corpus/templates/design/actions/open-visual-edit.ts +19 -1
- package/corpus/templates/design/actions/present-design-variants.ts +70 -70
- package/corpus/templates/design/actions/preview-component-prop-edit.ts +4 -14
- package/corpus/templates/design/actions/read-local-file.ts +9 -2
- package/corpus/templates/design/actions/remove-breakpoint.ts +40 -61
- package/corpus/templates/design/actions/rename-screen.ts +425 -0
- package/corpus/templates/design/actions/request-localhost-write-consent.ts +12 -2
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +9 -2
- package/corpus/templates/design/actions/sync-fusion-app.ts +56 -39
- package/corpus/templates/design/actions/update-design.ts +376 -61
- package/corpus/templates/design/actions/update-file.ts +455 -188
- package/corpus/templates/design/actions/write-local-file.ts +10 -2
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +685 -608
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +43 -15
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +576 -2015
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +62 -14
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +263 -25
- package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +34 -0
- package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +40 -0
- package/corpus/templates/design/app/components/design/design-canvas/creation.ts +47 -0
- package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +27 -0
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +62 -0
- package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +137 -0
- package/corpus/templates/design/app/components/design/design-canvas/file-drop.ts +10 -0
- package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +23 -0
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +23 -0
- package/corpus/templates/design/app/components/design/design-canvas/iframe-pan.ts +177 -0
- package/corpus/templates/design/app/components/design/design-canvas/motion-types.ts +7 -0
- package/corpus/templates/design/app/components/design/design-canvas/pending-text-edit.ts +62 -0
- package/corpus/templates/design/app/components/design/index.ts +2 -2
- package/corpus/templates/design/app/components/design/multi-screen/canvas-tools.ts +100 -0
- package/corpus/templates/design/app/components/design/multi-screen/coordinate-transforms.ts +81 -0
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +23 -13
- package/corpus/templates/design/app/components/design/multi-screen/culling.ts +238 -19
- package/corpus/templates/design/app/components/design/multi-screen/draft-primitives.ts +424 -0
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +341 -0
- package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +52 -0
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +62 -0
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +283 -0
- package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +272 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +5 -1
- package/corpus/templates/design/app/components/design/multi-screen/wheel-gesture-state.ts +12 -0
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +325 -84
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +15 -1
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +119 -47
- package/corpus/templates/design/app/i18n/zh-TW.ts +9 -0
- package/corpus/templates/design/app/i18n-data.ts +223 -0
- package/corpus/templates/design/app/lib/design-save-outbox.ts +379 -0
- package/corpus/templates/design/app/lib/png-clipboard.ts +113 -0
- package/corpus/templates/design/app/pages/design-editor/canvas-primitives.ts +229 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +918 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +43 -0
- package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +336 -0
- package/corpus/templates/design/app/pages/design-editor/data-operations.ts +270 -0
- package/corpus/templates/design/app/pages/design-editor/dom-guards.ts +24 -0
- package/corpus/templates/design/app/pages/design-editor/dom-utils.ts +11 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +20 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +408 -0
- package/corpus/templates/design/app/pages/design-editor/export-capture.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/geometry-persistence.ts +93 -0
- package/corpus/templates/design/app/pages/design-editor/history.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +185 -0
- package/corpus/templates/design/app/pages/design-editor/motion-state.ts +309 -0
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +438 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +510 -0
- package/corpus/templates/design/app/pages/design-editor/portable-style.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +337 -0
- package/corpus/templates/design/app/pages/design-editor/style-utils.ts +5 -0
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +92 -0
- package/corpus/templates/design/app/pages/design-editor/tweak-save.ts +87 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +36 -0
- package/corpus/templates/design/app/routes/design.$id.tsx +11 -1
- package/corpus/templates/design/changelog/2026-07-09-design-edits-canvas-positions-tools-and-tab-context-now-pers.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-figma-style-shortcuts-drawing-annotations-and-cross-screen-d.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-hand-and-scale-tools-now-keep-their-active-toolbar-identity-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-large-multi-screen-designs-now-stay-responsive-during-long-c.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layer-drags-now-land-exactly-where-the-insertion-indicator-s.md +6 -0
- package/corpus/templates/design/server/db/index.ts +2 -52
- package/corpus/templates/design/server/db/schema.ts +16 -0
- package/corpus/templates/design/server/lib/design-data-access.ts +70 -0
- package/corpus/templates/design/server/lib/design-data-mutation.ts +249 -0
- package/corpus/templates/design/server/lib/fusion-screens.ts +89 -76
- package/corpus/templates/design/server/lib/import-design-files.ts +76 -35
- package/corpus/templates/design/server/lib/verify-write-grant.ts +7 -2
- package/corpus/templates/design/server/plugins/db.ts +19 -0
- package/corpus/templates/design/server/source-workspace.ts +12 -13
- package/corpus/templates/design/shared/resolve-tweaks.ts +15 -0
- package/corpus/templates/design/shared/screen-rename.ts +42 -0
- package/corpus/templates/design/shared/source-mode.ts +84 -4
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builtin.js +1 -1
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/agent/model-config.d.ts +9 -9
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +30 -30
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +60 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +106 -7
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/design-connect.d.ts +30 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +359 -75
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/recap.js +2 -2
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/sync-builder-starter-manifest.js +1 -1
- package/dist/cli/sync-builder-starter-manifest.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +6 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +10 -5
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/TiptapComposer.js +1 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/TeamPage.d.ts.map +1 -1
- package/dist/client/org/TeamPage.js +6 -5
- package/dist/client/org/TeamPage.js.map +1 -1
- package/dist/client/use-action.d.ts +32 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +68 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/client.d.ts +3 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +7 -2
- package/dist/db/client.js.map +1 -1
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +2 -2
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.js +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.js +1 -1
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +13 -4
- package/dist/usage/store.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +36 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
- package/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
- package/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
- package/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
- package/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
- package/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
- package/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
- package/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
- package/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
- package/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
- package/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
- package/docs/content/pr-visual-recap.mdx +3 -3
- package/docs/content/pure-agent-apps.mdx +22 -0
- package/package.json +2 -2
|
@@ -1925,8 +1925,14 @@ declare var __DESIGN_CANVAS_BOARD_SURFACE__: boolean;
|
|
|
1925
1925
|
var persistentNodes = Array.prototype.slice.call(
|
|
1926
1926
|
document.querySelectorAll("[data-agent-native-edit-overlay]"),
|
|
1927
1927
|
);
|
|
1928
|
-
|
|
1929
|
-
|
|
1928
|
+
// A forced whole-document replace is used for structural edits (duplicate,
|
|
1929
|
+
// delete, cut/paste, undo/redo). Never fall back to the current selection
|
|
1930
|
+
// in that mode: doing so activates the single-subtree fast path below,
|
|
1931
|
+
// which can faithfully replace the selected node while silently omitting
|
|
1932
|
+
// newly inserted or removed siblings elsewhere in the document.
|
|
1933
|
+
var activeSelector = forceFullDocument
|
|
1934
|
+
? ""
|
|
1935
|
+
: preferredSelector || (selectedEl ? getSelector(selectedEl) : "");
|
|
1930
1936
|
var activeCandidates: string[] = [];
|
|
1931
1937
|
if (Array.isArray(selectorCandidates)) {
|
|
1932
1938
|
selectorCandidates.forEach(function (selector) {
|
|
@@ -8378,6 +8384,7 @@ declare var __DESIGN_CANVAS_BOARD_SURFACE__: boolean;
|
|
|
8378
8384
|
target.removeEventListener("keyup", onSelectionChange, true);
|
|
8379
8385
|
target.removeEventListener("mouseup", onSelectionChange, true);
|
|
8380
8386
|
document.removeEventListener("selectionchange", onSelectionChange);
|
|
8387
|
+
window.removeEventListener("blur", onWindowBlur, true);
|
|
8381
8388
|
target.removeAttribute("contenteditable");
|
|
8382
8389
|
target.removeAttribute("data-agent-native-text-editing");
|
|
8383
8390
|
document.documentElement.removeAttribute(
|
|
@@ -8443,19 +8450,39 @@ declare var __DESIGN_CANVAS_BOARD_SURFACE__: boolean;
|
|
|
8443
8450
|
// Escape/blur would take, instead of only resetting activeTextEditEl.
|
|
8444
8451
|
finishActiveTextEdit = finish;
|
|
8445
8452
|
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
return;
|
|
8453
|
+
var emptyProgrammaticRefocusScheduled = false;
|
|
8454
|
+
function refocusEmptyProgrammaticEdit() {
|
|
8455
|
+
if (
|
|
8456
|
+
emptyProgrammaticRefocusScheduled ||
|
|
8457
|
+
!programmaticTextEdit ||
|
|
8458
|
+
(target.textContent || "").trim()
|
|
8459
|
+
) {
|
|
8460
|
+
return false;
|
|
8455
8461
|
}
|
|
8462
|
+
emptyProgrammaticRefocusScheduled = true;
|
|
8463
|
+
window.setTimeout(function () {
|
|
8464
|
+
emptyProgrammaticRefocusScheduled = false;
|
|
8465
|
+
if (committed || (target.textContent || "").trim()) return;
|
|
8466
|
+
target.focus();
|
|
8467
|
+
updateTextEditingChrome(target, originalMinWidth, originalMinHeight);
|
|
8468
|
+
postTextEditingState(target, true);
|
|
8469
|
+
}, 0);
|
|
8470
|
+
return true;
|
|
8471
|
+
}
|
|
8472
|
+
|
|
8473
|
+
function onBlur() {
|
|
8474
|
+
if (refocusEmptyProgrammaticEdit()) return;
|
|
8456
8475
|
finish(true);
|
|
8457
8476
|
}
|
|
8458
8477
|
|
|
8478
|
+
// Moving focus from a child browsing context back to the host canvas does
|
|
8479
|
+
// not consistently blur the iframe's activeElement in Chromium. Listen at
|
|
8480
|
+
// the window boundary too so the newly created empty text field keeps the
|
|
8481
|
+
// keyboard until the user types or explicitly exits.
|
|
8482
|
+
function onWindowBlur() {
|
|
8483
|
+
refocusEmptyProgrammaticEdit();
|
|
8484
|
+
}
|
|
8485
|
+
|
|
8459
8486
|
function onKeyDown(ev) {
|
|
8460
8487
|
// T3: bail out on IME composition input (e.g. CJK/Korean input method
|
|
8461
8488
|
// candidate selection) so a composing Enter/Escape keystroke isn't
|
|
@@ -8525,6 +8552,7 @@ declare var __DESIGN_CANVAS_BOARD_SURFACE__: boolean;
|
|
|
8525
8552
|
target.addEventListener("keyup", onSelectionChange, true);
|
|
8526
8553
|
target.addEventListener("mouseup", onSelectionChange, true);
|
|
8527
8554
|
document.addEventListener("selectionchange", onSelectionChange);
|
|
8555
|
+
window.addEventListener("blur", onWindowBlur, true);
|
|
8528
8556
|
target.focus();
|
|
8529
8557
|
if (programmaticTextEdit) {
|
|
8530
8558
|
// The synthesized point sits at the (0×0) node's edge and resolves to the
|
|
@@ -8560,8 +8588,27 @@ declare var __DESIGN_CANVAS_BOARD_SURFACE__: boolean;
|
|
|
8560
8588
|
textTarget: HTMLElement,
|
|
8561
8589
|
force: boolean,
|
|
8562
8590
|
): void {
|
|
8563
|
-
//
|
|
8564
|
-
|
|
8591
|
+
// The host canvas can reclaim keyboard focus while React settles a newly
|
|
8592
|
+
// created layer. In that case this document still reports the same
|
|
8593
|
+
// activeElement even though its browsing context no longer has focus, so
|
|
8594
|
+
// treating the session as already active makes every retry a no-op and the
|
|
8595
|
+
// user's first keystroke hits host shortcuts. Re-focus the existing
|
|
8596
|
+
// session instead of rebuilding it.
|
|
8597
|
+
if (activeTextEditEl && activeTextEditEl === textTarget) {
|
|
8598
|
+
if (document.activeElement !== textTarget || !document.hasFocus()) {
|
|
8599
|
+
textTarget.focus();
|
|
8600
|
+
try {
|
|
8601
|
+
var refocusRange = document.createRange();
|
|
8602
|
+
refocusRange.selectNodeContents(textTarget);
|
|
8603
|
+
refocusRange.collapse(false);
|
|
8604
|
+
var refocusSelection = window.getSelection();
|
|
8605
|
+
refocusSelection.removeAllRanges();
|
|
8606
|
+
refocusSelection.addRange(refocusRange);
|
|
8607
|
+
} catch {}
|
|
8608
|
+
postTextEditingState(textTarget, true);
|
|
8609
|
+
}
|
|
8610
|
+
return;
|
|
8611
|
+
}
|
|
8565
8612
|
// Synthesise coordinates at the end of the element content so the caret
|
|
8566
8613
|
// lands at the insertion point (right after any placeholder text).
|
|
8567
8614
|
var bteRect = textTarget.getBoundingClientRect();
|
|
@@ -9019,7 +9066,8 @@ declare var __DESIGN_CANVAS_BOARD_SURFACE__: boolean;
|
|
|
9019
9066
|
);
|
|
9020
9067
|
if (
|
|
9021
9068
|
textEditStatusEditingEl &&
|
|
9022
|
-
document.activeElement === textEditStatusEditingEl
|
|
9069
|
+
document.activeElement === textEditStatusEditingEl &&
|
|
9070
|
+
document.hasFocus()
|
|
9023
9071
|
) {
|
|
9024
9072
|
textEditStatus = "active";
|
|
9025
9073
|
} else if (
|
|
@@ -1,62 +1,300 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Embedded
|
|
2
|
+
* Embedded canvas gesture bridge — injected into every canvas iframe.
|
|
3
3
|
*
|
|
4
|
-
* A screen preview is a real iframe, so
|
|
5
|
-
* the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* A screen preview is a real iframe, so wheel and pointer-drag events never
|
|
5
|
+
* bubble to the canvas underneath. In embedded mode we forward bounded wheel
|
|
6
|
+
* payloads to the parent. In every canvas mode we also forward middle-button
|
|
7
|
+
* drags, plus left-button drags while the host's hand/Space tool is armed, so
|
|
8
|
+
* the parent can reuse its existing single/overview pan implementation.
|
|
8
9
|
*
|
|
9
10
|
* Runtime placeholder (replaced by DesignCanvas.tsx before injection):
|
|
10
11
|
* __EMBEDDED_WHEEL_FORWARDING_ENABLED__ — boolean literal "true"/"false"
|
|
12
|
+
* __EMBEDDED_SPACE_KEY_FORWARDING_ENABLED__ — boolean literal; true only
|
|
13
|
+
* when the editor-chrome bridge is absent (Interact mode)
|
|
11
14
|
*
|
|
12
15
|
* Protocol (iframe → parent, only when enabled):
|
|
13
16
|
*
|
|
14
17
|
* { type: 'embedded-canvas-wheel', deltaX, deltaY, deltaZ, deltaMode,
|
|
15
18
|
* clientX, clientY, ctrlKey, metaKey, shiftKey, altKey }
|
|
16
19
|
*
|
|
20
|
+
* { type: 'embedded-canvas-pan', phase: 'start'|'move'|'end'|'cancel',
|
|
21
|
+
* pointerId, button, buttons, clientX, clientY,
|
|
22
|
+
* ctrlKey, metaKey, shiftKey, altKey }
|
|
23
|
+
*
|
|
24
|
+
* Protocol (parent → iframe):
|
|
25
|
+
*
|
|
26
|
+
* { type: 'embedded-canvas-pan-mode', leftButtonEnabled }
|
|
27
|
+
* { type: 'embedded-canvas-pan-cancel' }
|
|
28
|
+
*
|
|
17
29
|
* Rules:
|
|
18
30
|
* • No import/require of any module (DOM globals only).
|
|
19
31
|
* • No references to outer/module scope (the code runs inside an iframe).
|
|
20
32
|
* • Wrap everything in a self-executing IIFE.
|
|
21
33
|
*/
|
|
22
34
|
declare var __EMBEDDED_WHEEL_FORWARDING_ENABLED__: boolean;
|
|
35
|
+
declare var __EMBEDDED_SPACE_KEY_FORWARDING_ENABLED__: boolean;
|
|
23
36
|
|
|
24
37
|
(function () {
|
|
25
|
-
var
|
|
26
|
-
|
|
38
|
+
var wheelEnabled = __EMBEDDED_WHEEL_FORWARDING_ENABLED__;
|
|
39
|
+
var spaceKeyForwardingEnabled = __EMBEDDED_SPACE_KEY_FORWARDING_ENABLED__;
|
|
40
|
+
var leftButtonEnabled = false;
|
|
41
|
+
var temporarySpacePanEnabled = false;
|
|
42
|
+
var activePointerId: number | null = null;
|
|
43
|
+
var activeButton: 0 | 1 | null = null;
|
|
44
|
+
var captureTarget: Element | null = null;
|
|
45
|
+
var suppressClick = false;
|
|
46
|
+
var clearSuppressClickTimer: number | null = null;
|
|
47
|
+
var lastClientX = 0;
|
|
48
|
+
var lastClientY = 0;
|
|
49
|
+
var lastCtrlKey = false;
|
|
50
|
+
var lastMetaKey = false;
|
|
51
|
+
var lastShiftKey = false;
|
|
52
|
+
var lastAltKey = false;
|
|
53
|
+
|
|
27
54
|
function clamp(value: number, limit: number): number {
|
|
28
55
|
var number = Number(value) || 0;
|
|
29
56
|
if (number > limit) return limit;
|
|
30
57
|
if (number < -limit) return -limit;
|
|
31
58
|
return number;
|
|
32
59
|
}
|
|
33
|
-
|
|
60
|
+
|
|
61
|
+
function stopNativeInteraction(e: Event): void {
|
|
34
62
|
e.preventDefault();
|
|
35
63
|
e.stopPropagation();
|
|
36
64
|
if (e.stopImmediatePropagation) e.stopImmediatePropagation();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function postToParent(message: Record<string, unknown>): void {
|
|
68
|
+
try {
|
|
69
|
+
(window.parent as Window).postMessage(message, "*");
|
|
70
|
+
} catch {}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function onWheel(e: WheelEvent): void {
|
|
74
|
+
if (!wheelEnabled) return;
|
|
75
|
+
stopNativeInteraction(e);
|
|
76
|
+
postToParent({
|
|
77
|
+
type: "embedded-canvas-wheel",
|
|
78
|
+
deltaX: clamp(e.deltaX, 240),
|
|
79
|
+
deltaY: clamp(e.deltaY, 240),
|
|
80
|
+
deltaZ: clamp(e.deltaZ, 240),
|
|
81
|
+
deltaMode: e.deltaMode,
|
|
82
|
+
clientX: clamp(e.clientX, 100000),
|
|
83
|
+
clientY: clamp(e.clientY, 100000),
|
|
84
|
+
ctrlKey: !!e.ctrlKey,
|
|
85
|
+
metaKey: !!e.metaKey,
|
|
86
|
+
shiftKey: !!e.shiftKey,
|
|
87
|
+
altKey: !!e.altKey,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function shouldStartPan(e: PointerEvent): boolean {
|
|
92
|
+
if (e.button === 1) return true;
|
|
93
|
+
return e.button === 0 && (leftButtonEnabled || temporarySpacePanEnabled);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function postPan(
|
|
97
|
+
phase: "start" | "move" | "end" | "cancel",
|
|
98
|
+
e: PointerEvent,
|
|
99
|
+
): void {
|
|
100
|
+
if (activeButton === null) return;
|
|
101
|
+
lastClientX = clamp(e.clientX, 100000);
|
|
102
|
+
lastClientY = clamp(e.clientY, 100000);
|
|
103
|
+
lastCtrlKey = !!e.ctrlKey;
|
|
104
|
+
lastMetaKey = !!e.metaKey;
|
|
105
|
+
lastShiftKey = !!e.shiftKey;
|
|
106
|
+
lastAltKey = !!e.altKey;
|
|
107
|
+
postToParent({
|
|
108
|
+
type: "embedded-canvas-pan",
|
|
109
|
+
phase: phase,
|
|
110
|
+
pointerId: Math.max(0, Math.min(0x7fffffff, Math.trunc(e.pointerId))),
|
|
111
|
+
button: activeButton,
|
|
112
|
+
buttons: phase === "end" || phase === "cancel" ? 0 : e.buttons,
|
|
113
|
+
clientX: lastClientX,
|
|
114
|
+
clientY: lastClientY,
|
|
115
|
+
ctrlKey: lastCtrlKey,
|
|
116
|
+
metaKey: lastMetaKey,
|
|
117
|
+
shiftKey: lastShiftKey,
|
|
118
|
+
altKey: lastAltKey,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function releasePointerCapture(pointerId: number): void {
|
|
123
|
+
if (!captureTarget) return;
|
|
124
|
+
try {
|
|
125
|
+
if (captureTarget.hasPointerCapture(pointerId)) {
|
|
126
|
+
captureTarget.releasePointerCapture(pointerId);
|
|
127
|
+
}
|
|
128
|
+
} catch {}
|
|
129
|
+
captureTarget = null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function scheduleClickSuppressionReset(): void {
|
|
133
|
+
if (clearSuppressClickTimer !== null) {
|
|
134
|
+
window.clearTimeout(clearSuppressClickTimer);
|
|
135
|
+
}
|
|
136
|
+
clearSuppressClickTimer = window.setTimeout(function () {
|
|
137
|
+
suppressClick = false;
|
|
138
|
+
clearSuppressClickTimer = null;
|
|
139
|
+
}, 0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function onPointerDown(e: PointerEvent): void {
|
|
143
|
+
if (activePointerId !== null || !shouldStartPan(e)) return;
|
|
144
|
+
activePointerId = e.pointerId;
|
|
145
|
+
activeButton = e.button === 1 ? 1 : 0;
|
|
146
|
+
suppressClick = true;
|
|
147
|
+
captureTarget =
|
|
148
|
+
e.target instanceof Element ? e.target : document.documentElement;
|
|
37
149
|
try {
|
|
38
|
-
(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
deltaY: clamp(e.deltaY, 240),
|
|
43
|
-
deltaZ: clamp(e.deltaZ, 240),
|
|
44
|
-
deltaMode: e.deltaMode,
|
|
45
|
-
clientX: e.clientX,
|
|
46
|
-
clientY: e.clientY,
|
|
47
|
-
ctrlKey: !!e.ctrlKey,
|
|
48
|
-
metaKey: !!e.metaKey,
|
|
49
|
-
shiftKey: !!e.shiftKey,
|
|
50
|
-
altKey: !!e.altKey,
|
|
51
|
-
},
|
|
52
|
-
"*",
|
|
53
|
-
);
|
|
54
|
-
} catch (_err) {}
|
|
150
|
+
captureTarget.setPointerCapture(e.pointerId);
|
|
151
|
+
} catch {}
|
|
152
|
+
stopNativeInteraction(e);
|
|
153
|
+
postPan("start", e);
|
|
55
154
|
}
|
|
155
|
+
|
|
156
|
+
function onPointerMove(e: PointerEvent): void {
|
|
157
|
+
if (activePointerId !== e.pointerId || activeButton === null) return;
|
|
158
|
+
stopNativeInteraction(e);
|
|
159
|
+
postPan("move", e);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function finishPan(phase: "end" | "cancel", e: PointerEvent): void {
|
|
163
|
+
if (activePointerId !== e.pointerId || activeButton === null) return;
|
|
164
|
+
stopNativeInteraction(e);
|
|
165
|
+
postPan(phase, e);
|
|
166
|
+
releasePointerCapture(e.pointerId);
|
|
167
|
+
activePointerId = null;
|
|
168
|
+
activeButton = null;
|
|
169
|
+
scheduleClickSuppressionReset();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function onPointerUp(e: PointerEvent): void {
|
|
173
|
+
finishPan("end", e);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function onPointerCancel(e: PointerEvent): void {
|
|
177
|
+
finishPan("cancel", e);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function suppressTrailingClick(e: MouseEvent): void {
|
|
181
|
+
if (!suppressClick) return;
|
|
182
|
+
stopNativeInteraction(e);
|
|
183
|
+
suppressClick = false;
|
|
184
|
+
if (clearSuppressClickTimer !== null) {
|
|
185
|
+
window.clearTimeout(clearSuppressClickTimer);
|
|
186
|
+
clearSuppressClickTimer = null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function isTypingTarget(target: EventTarget | null): boolean {
|
|
191
|
+
return !!(
|
|
192
|
+
target instanceof Element &&
|
|
193
|
+
target.closest(
|
|
194
|
+
'input, textarea, select, [contenteditable], [role="textbox"], [data-agent-native-text-editing]',
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function onKeyDown(e: KeyboardEvent): void {
|
|
200
|
+
if (
|
|
201
|
+
!spaceKeyForwardingEnabled ||
|
|
202
|
+
e.key !== " " ||
|
|
203
|
+
e.code !== "Space" ||
|
|
204
|
+
e.metaKey ||
|
|
205
|
+
e.ctrlKey ||
|
|
206
|
+
e.altKey ||
|
|
207
|
+
e.shiftKey ||
|
|
208
|
+
isTypingTarget(e.target)
|
|
209
|
+
) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
temporarySpacePanEnabled = true;
|
|
213
|
+
stopNativeInteraction(e);
|
|
214
|
+
if (e.repeat) return;
|
|
215
|
+
postToParent({
|
|
216
|
+
type: "design-hotkey",
|
|
217
|
+
key: e.key,
|
|
218
|
+
code: e.code,
|
|
219
|
+
metaKey: false,
|
|
220
|
+
ctrlKey: false,
|
|
221
|
+
shiftKey: false,
|
|
222
|
+
altKey: false,
|
|
223
|
+
repeat: false,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function onKeyUp(e: KeyboardEvent): void {
|
|
228
|
+
if (!spaceKeyForwardingEnabled || e.key !== " " || e.code !== "Space") {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
var wasTemporarySpacePanEnabled = temporarySpacePanEnabled;
|
|
232
|
+
temporarySpacePanEnabled = false;
|
|
233
|
+
if (!wasTemporarySpacePanEnabled && isTypingTarget(e.target)) return;
|
|
234
|
+
stopNativeInteraction(e);
|
|
235
|
+
postToParent({ type: "design-hotkey-up", key: e.key, code: e.code });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function onHostMessage(e: MessageEvent): void {
|
|
239
|
+
if (e.source !== window.parent) return;
|
|
240
|
+
if (!e.data) return;
|
|
241
|
+
if (e.data.type === "embedded-canvas-pan-cancel") {
|
|
242
|
+
cancelActivePan();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (e.data.type === "embedded-canvas-pan-mode") {
|
|
246
|
+
leftButtonEnabled = !!e.data.leftButtonEnabled;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function cancelActivePan(): void {
|
|
251
|
+
temporarySpacePanEnabled = false;
|
|
252
|
+
if (activePointerId === null || activeButton === null) return;
|
|
253
|
+
var pointerId = activePointerId;
|
|
254
|
+
postToParent({
|
|
255
|
+
type: "embedded-canvas-pan",
|
|
256
|
+
phase: "cancel",
|
|
257
|
+
pointerId: pointerId,
|
|
258
|
+
button: activeButton,
|
|
259
|
+
buttons: 0,
|
|
260
|
+
clientX: lastClientX,
|
|
261
|
+
clientY: lastClientY,
|
|
262
|
+
ctrlKey: lastCtrlKey,
|
|
263
|
+
metaKey: lastMetaKey,
|
|
264
|
+
shiftKey: lastShiftKey,
|
|
265
|
+
altKey: lastAltKey,
|
|
266
|
+
});
|
|
267
|
+
releasePointerCapture(pointerId);
|
|
268
|
+
activePointerId = null;
|
|
269
|
+
activeButton = null;
|
|
270
|
+
suppressClick = false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function onWindowBlur(): void {
|
|
274
|
+
// Moving focus from an iframe gesture into the parent canvas can blur the
|
|
275
|
+
// child window while the top-level Design window is still active. The
|
|
276
|
+
// parent separately sends embedded-canvas-pan-cancel on a real top-level
|
|
277
|
+
// blur; this local guard handles page/tab hiding without killing that
|
|
278
|
+
// intentional in-app focus transfer.
|
|
279
|
+
if (document.visibilityState === "hidden") cancelActivePan();
|
|
280
|
+
}
|
|
281
|
+
|
|
56
282
|
var wheelTarget: EventTarget =
|
|
57
283
|
document.documentElement || document.body || document;
|
|
58
284
|
wheelTarget.addEventListener("wheel", onWheel as EventListener, {
|
|
59
285
|
passive: false,
|
|
60
286
|
capture: true,
|
|
61
287
|
});
|
|
288
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
289
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
290
|
+
document.addEventListener("pointerup", onPointerUp, true);
|
|
291
|
+
document.addEventListener("pointercancel", onPointerCancel, true);
|
|
292
|
+
document.addEventListener("click", suppressTrailingClick, true);
|
|
293
|
+
document.addEventListener("auxclick", suppressTrailingClick, true);
|
|
294
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
295
|
+
document.addEventListener("keyup", onKeyUp, true);
|
|
296
|
+
window.addEventListener("message", onHostMessage);
|
|
297
|
+
window.addEventListener("blur", onWindowBlur);
|
|
298
|
+
document.addEventListener("visibilitychange", onWindowBlur);
|
|
299
|
+
window.addEventListener("pagehide", cancelActivePan);
|
|
62
300
|
})();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
interface SubmitDesignAnnotationsOptions {
|
|
2
|
+
message: string;
|
|
3
|
+
hasQueuedPins: boolean;
|
|
4
|
+
send: (message: string) => void;
|
|
5
|
+
markQueuedPinsSubmitted: () => void;
|
|
6
|
+
exitDrawMode: () => void;
|
|
7
|
+
onError: (error: unknown) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Submit a drawing/comment batch as one atomic UI transition.
|
|
12
|
+
*
|
|
13
|
+
* The overlay and queued pins must remain intact when chat handoff fails so the
|
|
14
|
+
* user can retry without recreating their annotation work.
|
|
15
|
+
*/
|
|
16
|
+
export function submitDesignAnnotations({
|
|
17
|
+
message,
|
|
18
|
+
hasQueuedPins,
|
|
19
|
+
send,
|
|
20
|
+
markQueuedPinsSubmitted,
|
|
21
|
+
exitDrawMode,
|
|
22
|
+
onError,
|
|
23
|
+
}: SubmitDesignAnnotationsOptions): boolean {
|
|
24
|
+
try {
|
|
25
|
+
send(message);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
onError(error);
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (hasQueuedPins) markQueuedPinsSubmitted();
|
|
32
|
+
exitDrawMode();
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a viewport point into the iframe's unscaled content coordinates.
|
|
3
|
+
*/
|
|
4
|
+
export function getScreenContentPointFromClient(
|
|
5
|
+
clientX: number,
|
|
6
|
+
clientY: number,
|
|
7
|
+
iframeRect: { left: number; top: number; width: number; height: number },
|
|
8
|
+
iframeContentSize: { width: number; height: number },
|
|
9
|
+
): { x: number; y: number } {
|
|
10
|
+
const scaleX =
|
|
11
|
+
iframeContentSize.width > 0
|
|
12
|
+
? iframeRect.width / iframeContentSize.width
|
|
13
|
+
: 1;
|
|
14
|
+
const scaleY =
|
|
15
|
+
iframeContentSize.height > 0
|
|
16
|
+
? iframeRect.height / iframeContentSize.height
|
|
17
|
+
: 1;
|
|
18
|
+
return {
|
|
19
|
+
x: (clientX - iframeRect.left) / (scaleX || 1),
|
|
20
|
+
y: (clientY - iframeRect.top) / (scaleY || 1),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Computes the scroll delta needed to keep a viewport point anchored while
|
|
26
|
+
* zooming a top-left-origin canvas layer.
|
|
27
|
+
*/
|
|
28
|
+
export function getZoomToCursorScrollDelta(
|
|
29
|
+
anchorClient: { x: number; y: number },
|
|
30
|
+
containerRect: { left: number; top: number },
|
|
31
|
+
scrollOffset: { scrollLeft: number; scrollTop: number },
|
|
32
|
+
zoomRatio: number,
|
|
33
|
+
): { dx: number; dy: number } {
|
|
34
|
+
const cx = anchorClient.x - containerRect.left + scrollOffset.scrollLeft;
|
|
35
|
+
const cy = anchorClient.y - containerRect.top + scrollOffset.scrollTop;
|
|
36
|
+
return {
|
|
37
|
+
dx: cx * (zoomRatio - 1),
|
|
38
|
+
dy: cy * (zoomRatio - 1),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { PenPath } from "@shared/pen-path";
|
|
2
|
+
|
|
3
|
+
export type CreationTool =
|
|
4
|
+
| "rectangle"
|
|
5
|
+
| "ellipse"
|
|
6
|
+
| "line"
|
|
7
|
+
| "arrow"
|
|
8
|
+
| "text"
|
|
9
|
+
| "pen"
|
|
10
|
+
| "frame";
|
|
11
|
+
|
|
12
|
+
export interface CreatePrimitiveSpec {
|
|
13
|
+
tool: CreationTool;
|
|
14
|
+
rect?: { x: number; y: number; width: number; height: number };
|
|
15
|
+
points?: Array<{ x: number; y: number }>;
|
|
16
|
+
/** Structured pen geometry, including Bezier handles and closed state. */
|
|
17
|
+
penPath?: PenPath;
|
|
18
|
+
fromClick: boolean;
|
|
19
|
+
/** Commit an in-progress pen path without overriding a newly chosen tool. */
|
|
20
|
+
preserveActiveTool?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A browser double-click is two complete pointer gestures followed by a
|
|
25
|
+
* `dblclick` event. Both gestures therefore add the final pen anchor before
|
|
26
|
+
* the overlay commits. Collapse only the coincident trailing pair, retaining
|
|
27
|
+
* the anchor from the second gesture so the final clicked point is never
|
|
28
|
+
* omitted from the committed path.
|
|
29
|
+
*/
|
|
30
|
+
export function collapseDoubleClickPenAnchor(path: PenPath): PenPath {
|
|
31
|
+
const last = path.nodes[path.nodes.length - 1];
|
|
32
|
+
const previous = path.nodes[path.nodes.length - 2];
|
|
33
|
+
if (
|
|
34
|
+
!last ||
|
|
35
|
+
!previous ||
|
|
36
|
+
Math.hypot(
|
|
37
|
+
last.point.x - previous.point.x,
|
|
38
|
+
last.point.y - previous.point.y,
|
|
39
|
+
) > 0.5
|
|
40
|
+
) {
|
|
41
|
+
return path;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
nodes: [...path.nodes.slice(0, -2), last],
|
|
45
|
+
closed: false,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ElementInfo } from "../types";
|
|
2
|
+
|
|
3
|
+
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
|
4
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function isFiniteRect(value: unknown): value is ElementInfo["boundingRect"] {
|
|
8
|
+
if (!isPlainRecord(value)) return false;
|
|
9
|
+
return (
|
|
10
|
+
Number.isFinite(value.x) &&
|
|
11
|
+
Number.isFinite(value.y) &&
|
|
12
|
+
Number.isFinite(value.width) &&
|
|
13
|
+
Number.isFinite(value.height)
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isElementInfoPayload(value: unknown): value is ElementInfo {
|
|
18
|
+
if (!isPlainRecord(value)) return false;
|
|
19
|
+
return (
|
|
20
|
+
typeof value.tagName === "string" &&
|
|
21
|
+
Array.isArray(value.classes) &&
|
|
22
|
+
isPlainRecord(value.computedStyles) &&
|
|
23
|
+
isFiniteRect(value.boundingRect) &&
|
|
24
|
+
typeof value.isFlexChild === "boolean" &&
|
|
25
|
+
typeof value.isFlexContainer === "boolean"
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const TRANSPARENT_EMBEDDED_FRAME_STYLE =
|
|
2
|
+
"<style data-agent-native-transparent-frame>html,body{background:transparent!important;}body{background-color:transparent!important;}</style>";
|
|
3
|
+
|
|
4
|
+
function embeddedFrameBackgroundStyle(background: string | undefined): string {
|
|
5
|
+
const trimmed = background?.trim();
|
|
6
|
+
if (!trimmed || /[;{}<>]/.test(trimmed)) return "";
|
|
7
|
+
return `<style data-agent-native-frame-background>html,body{background:${trimmed}!important;}body{background-color:${trimmed}!important;}</style>`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getEmbeddedFrameBackgroundStyle(args: {
|
|
11
|
+
embeddedFrameBackground?: string;
|
|
12
|
+
transparentBackground?: boolean;
|
|
13
|
+
}): string {
|
|
14
|
+
return args.transparentBackground
|
|
15
|
+
? TRANSPARENT_EMBEDDED_FRAME_STYLE
|
|
16
|
+
: embeddedFrameBackgroundStyle(args.embeddedFrameBackground);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getEmbeddedIframeBackgroundColor(args: {
|
|
20
|
+
embeddedFrameBackground?: string;
|
|
21
|
+
transparentBackground?: boolean;
|
|
22
|
+
}): string {
|
|
23
|
+
return args.transparentBackground
|
|
24
|
+
? "transparent"
|
|
25
|
+
: (args.embeddedFrameBackground ?? "transparent");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function embeddedContentOffsetStyle(x: number, y: number): string {
|
|
29
|
+
if (x === 0 && y === 0) return "";
|
|
30
|
+
return `<style data-agent-native-content-offset>body > [data-agent-native-node-id]{translate:${Math.round(x)}px ${Math.round(y)}px;}</style>`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function injectEmbeddedFrameStyle(content: string, style: string): string {
|
|
34
|
+
if (!style) return content;
|
|
35
|
+
if (/<\/head>/i.test(content)) {
|
|
36
|
+
return content.replace(/<\/head>/i, `${style}</head>`);
|
|
37
|
+
}
|
|
38
|
+
if (/<body\b/i.test(content)) {
|
|
39
|
+
return content.replace(/<body\b/i, `${style}<body`);
|
|
40
|
+
}
|
|
41
|
+
return `${style}${content}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getEmbeddedFrameDocumentContent(args: {
|
|
45
|
+
content: string;
|
|
46
|
+
embeddedFrameBackground?: string;
|
|
47
|
+
transparentBackground?: boolean;
|
|
48
|
+
contentOffsetX?: number;
|
|
49
|
+
contentOffsetY?: number;
|
|
50
|
+
}): string {
|
|
51
|
+
const frameStyle = [
|
|
52
|
+
getEmbeddedFrameBackgroundStyle({
|
|
53
|
+
embeddedFrameBackground: args.embeddedFrameBackground,
|
|
54
|
+
transparentBackground: args.transparentBackground,
|
|
55
|
+
}),
|
|
56
|
+
embeddedContentOffsetStyle(
|
|
57
|
+
args.contentOffsetX ?? 0,
|
|
58
|
+
args.contentOffsetY ?? 0,
|
|
59
|
+
),
|
|
60
|
+
].join("");
|
|
61
|
+
return injectEmbeddedFrameStyle(args.content, frameStyle);
|
|
62
|
+
}
|