@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
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { CSSProperties } from "react";
|
|
2
2
|
|
|
3
|
-
import { SURFACE_PADDING } from "../MultiScreenCanvas";
|
|
4
3
|
import type { PortableStyleSnapshot } from "../types";
|
|
4
|
+
import { screenLocalRectToBoardGeometry } from "./coordinate-transforms";
|
|
5
|
+
import { SURFACE_PADDING } from "./overview-layout";
|
|
5
6
|
import type {
|
|
6
7
|
CrossScreenDropAxis,
|
|
7
8
|
CrossScreenDropGuide,
|
|
@@ -67,19 +68,14 @@ export function getCrossScreenDropGuideForHitTest(args: {
|
|
|
67
68
|
if (!rect) return null;
|
|
68
69
|
const placement = args.hit.placement ?? "inside";
|
|
69
70
|
const axis = args.hit.axis ?? "y";
|
|
70
|
-
const scaleX =
|
|
71
|
-
args.targetGeometry.width / Math.max(1, args.targetMetadata.width);
|
|
72
|
-
const scaleY =
|
|
73
|
-
args.targetGeometry.height / Math.max(1, args.targetMetadata.height);
|
|
74
71
|
return {
|
|
75
72
|
placement,
|
|
76
73
|
axis,
|
|
77
|
-
boardRect:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
},
|
|
74
|
+
boardRect: screenLocalRectToBoardGeometry(
|
|
75
|
+
rect,
|
|
76
|
+
args.targetGeometry,
|
|
77
|
+
args.targetMetadata,
|
|
78
|
+
),
|
|
83
79
|
};
|
|
84
80
|
}
|
|
85
81
|
|
|
@@ -93,6 +89,7 @@ export function getCrossScreenDropGuideStyle(args: {
|
|
|
93
89
|
const top = args.pan.y + (SURFACE_PADDING + boardRect.y) * args.scale;
|
|
94
90
|
const width = Math.max(1, boardRect.width * args.scale);
|
|
95
91
|
const height = Math.max(1, boardRect.height * args.scale);
|
|
92
|
+
const rotation = boardRect.rotation ?? 0;
|
|
96
93
|
|
|
97
94
|
if (placement === "inside") {
|
|
98
95
|
return {
|
|
@@ -105,30 +102,43 @@ export function getCrossScreenDropGuideStyle(args: {
|
|
|
105
102
|
"color-mix(in srgb, var(--design-editor-accent-color) 14%, transparent)",
|
|
106
103
|
borderRadius: 2,
|
|
107
104
|
boxShadow: "none",
|
|
105
|
+
transform: rotation ? `rotate(${rotation}deg)` : undefined,
|
|
108
106
|
};
|
|
109
107
|
}
|
|
110
108
|
|
|
111
109
|
if (axis === "x") {
|
|
112
110
|
const x = placement === "before" ? left : left + width;
|
|
111
|
+
const lineLeft = x - 1;
|
|
113
112
|
return {
|
|
114
|
-
left:
|
|
113
|
+
left: lineLeft,
|
|
115
114
|
top,
|
|
116
115
|
width: 2,
|
|
117
116
|
height: Math.max(8, height),
|
|
118
117
|
background: "var(--design-editor-accent-color)",
|
|
119
118
|
borderRadius: 999,
|
|
120
119
|
boxShadow: "0 0 0 1px var(--design-editor-accent-color)",
|
|
120
|
+
transform: rotation ? `rotate(${rotation}deg)` : undefined,
|
|
121
|
+
// Rotate the insertion line around the anchor rect's center, not its
|
|
122
|
+
// own center, so before/after edges stay attached to a rotated target.
|
|
123
|
+
transformOrigin: rotation
|
|
124
|
+
? `${left + width / 2 - lineLeft}px ${height / 2}px`
|
|
125
|
+
: undefined,
|
|
121
126
|
};
|
|
122
127
|
}
|
|
123
128
|
|
|
124
129
|
const y = placement === "before" ? top : top + height;
|
|
130
|
+
const lineTop = y - 1;
|
|
125
131
|
return {
|
|
126
132
|
left,
|
|
127
|
-
top:
|
|
133
|
+
top: lineTop,
|
|
128
134
|
width: Math.max(8, width),
|
|
129
135
|
height: 2,
|
|
130
136
|
background: "var(--design-editor-accent-color)",
|
|
131
137
|
borderRadius: 999,
|
|
132
138
|
boxShadow: "0 0 0 1px var(--design-editor-accent-color)",
|
|
139
|
+
transform: rotation ? `rotate(${rotation}deg)` : undefined,
|
|
140
|
+
transformOrigin: rotation
|
|
141
|
+
? `${width / 2}px ${top + height / 2 - lineTop}px`
|
|
142
|
+
: undefined,
|
|
133
143
|
};
|
|
134
144
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getRotatedFrameAABB } from "@shared/canvas-math";
|
|
2
2
|
|
|
3
|
-
import { SURFACE_PADDING } from "
|
|
3
|
+
import { SURFACE_PADDING } from "./overview-layout";
|
|
4
4
|
import type { FrameGeometry, Point } from "./types";
|
|
5
5
|
|
|
6
6
|
// ── Overview viewport culling (PF22) ────────────────────────────────────────
|
|
@@ -20,12 +20,11 @@ import type { FrameGeometry, Point } from "./types";
|
|
|
20
20
|
// screen (the debounced commit lags real cursor position by up to
|
|
21
21
|
// ~120ms — see scheduleViewCommit) is already mounted by the time it's
|
|
22
22
|
// reachable.
|
|
23
|
-
// -
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// unmount.
|
|
23
|
+
// - A bounded live-context pool keeps nearby screens warm without retaining
|
|
24
|
+
// every browsing context ever visited. Active/selected/in-progress screens
|
|
25
|
+
// are protected; the remaining budget is filled by viewport distance and
|
|
26
|
+
// then by recency. Evicted screens keep their lightweight React content-cache
|
|
27
|
+
// entry so revisiting can remount directly without rebuilding source HTML.
|
|
29
28
|
|
|
30
29
|
/** Escape hatch: flip to `false` to fully disable culling in one line if a
|
|
31
30
|
* regression appears — every screen goes back to always rendering full
|
|
@@ -40,17 +39,236 @@ export const OVERVIEW_CULLING_ENABLED = true;
|
|
|
40
39
|
* recomputes. */
|
|
41
40
|
export const OVERVIEW_CULLING_OVERSCAN_FACTOR = 1.5;
|
|
42
41
|
|
|
42
|
+
/** Maximum number of evictable overview browsing contexts kept mounted at
|
|
43
|
+
* once. One screen costs its primary preview plus every breakpoint preview.
|
|
44
|
+
* Interaction-protected screens are the sole safety exception: if the user
|
|
45
|
+
* explicitly selects more than this budget, preserving their live editor
|
|
46
|
+
* state wins until that interaction ends, after which the pool contracts on
|
|
47
|
+
* the next culling pass. */
|
|
48
|
+
export const OVERVIEW_LIVE_IFRAME_BUDGET = 32;
|
|
49
|
+
|
|
43
50
|
export type ScreenCullTier =
|
|
44
51
|
/** Full content (iframe/DesignCanvas) is mounted and rendered normally. */
|
|
45
52
|
| "visible"
|
|
46
53
|
/** Has been visible before this session; content stays mounted (iframes
|
|
47
|
-
*
|
|
54
|
+
* remains inside the bounded warm pool) but is skipped from paint via
|
|
48
55
|
* visibility/content-visibility, not display:none or will-change. */
|
|
49
56
|
| "culled"
|
|
57
|
+
/** Has rendered before but was least-recently-used outside the bounded live
|
|
58
|
+
* iframe pool. Its browsing contexts are unmounted; the cached React node
|
|
59
|
+
* is retained so a revisit can remount without regenerating content. */
|
|
60
|
+
| "evicted"
|
|
50
61
|
/** Has never been visible this session; renders a lightweight placeholder
|
|
51
62
|
* with no iframe/content node at all. */
|
|
52
63
|
| "placeholder";
|
|
53
64
|
|
|
65
|
+
/** Shared render lifecycle for every iframe belonging to one screen, including
|
|
66
|
+
* breakpoint previews. Warm offscreen screens remain mounted and hidden;
|
|
67
|
+
* never-seen and LRU-evicted screens own no browsing contexts. */
|
|
68
|
+
export function getScreenContentCullState(tier: ScreenCullTier): {
|
|
69
|
+
shouldMount: boolean;
|
|
70
|
+
isHidden: boolean;
|
|
71
|
+
} {
|
|
72
|
+
return {
|
|
73
|
+
shouldMount: tier === "visible" || tier === "culled",
|
|
74
|
+
isHidden: tier === "culled",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ScreenCullCandidate {
|
|
79
|
+
id: string;
|
|
80
|
+
geometry: FrameGeometry;
|
|
81
|
+
/** Primary preview plus all breakpoint preview iframes for this screen. */
|
|
82
|
+
iframeCount: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface BoundedScreenCullState {
|
|
86
|
+
tierByScreenId: Map<string, ScreenCullTier>;
|
|
87
|
+
liveScreenIds: Set<string>;
|
|
88
|
+
everVisibleScreenIds: Set<string>;
|
|
89
|
+
lastVisibleEpochByScreenId: Map<string, number>;
|
|
90
|
+
mountedIframeCount: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function normalizedIframeCount(candidate: ScreenCullCandidate): number {
|
|
94
|
+
return Math.max(1, Math.floor(candidate.iframeCount));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function distanceSquaredToViewportCenter(
|
|
98
|
+
geometry: FrameGeometry,
|
|
99
|
+
viewport: OverscannedViewportBounds,
|
|
100
|
+
): number {
|
|
101
|
+
const bounds = getRotatedFrameAABB(geometry);
|
|
102
|
+
const dx =
|
|
103
|
+
(bounds.left + bounds.right) / 2 - (viewport.left + viewport.right) / 2;
|
|
104
|
+
const dy =
|
|
105
|
+
(bounds.top + bounds.bottom) / 2 - (viewport.top + viewport.bottom) / 2;
|
|
106
|
+
return dx * dx + dy * dy;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Allocate overview browsing contexts under a bounded LRU/distance budget.
|
|
111
|
+
*
|
|
112
|
+
* Allocation order is intentional:
|
|
113
|
+
* 1. protected interactions (active, selected, dragged, text/layer edited),
|
|
114
|
+
* 2. screens inside the overscanned viewport, nearest the viewport center,
|
|
115
|
+
* 3. previously-mounted offscreen screens, most recently visible first.
|
|
116
|
+
*
|
|
117
|
+
* This keeps imminent pan/zoom destinations live while guaranteeing that a
|
|
118
|
+
* long tour through a 100+ screen board cannot accumulate 100+ hidden iframe
|
|
119
|
+
* documents. The function is pure: callers own the returned Set/Map snapshots
|
|
120
|
+
* and can feed them into the next committed pan/zoom pass.
|
|
121
|
+
*/
|
|
122
|
+
export function computeBoundedScreenCullState({
|
|
123
|
+
candidates,
|
|
124
|
+
viewport,
|
|
125
|
+
protectedScreenIds,
|
|
126
|
+
previousLiveScreenIds,
|
|
127
|
+
everVisibleScreenIds,
|
|
128
|
+
lastVisibleEpochByScreenId,
|
|
129
|
+
accessEpoch,
|
|
130
|
+
liveIframeBudget = OVERVIEW_LIVE_IFRAME_BUDGET,
|
|
131
|
+
}: {
|
|
132
|
+
candidates: readonly ScreenCullCandidate[];
|
|
133
|
+
viewport: OverscannedViewportBounds | null;
|
|
134
|
+
protectedScreenIds: ReadonlySet<string>;
|
|
135
|
+
previousLiveScreenIds: ReadonlySet<string>;
|
|
136
|
+
everVisibleScreenIds: ReadonlySet<string>;
|
|
137
|
+
lastVisibleEpochByScreenId: ReadonlyMap<string, number>;
|
|
138
|
+
accessEpoch: number;
|
|
139
|
+
liveIframeBudget?: number;
|
|
140
|
+
}): BoundedScreenCullState {
|
|
141
|
+
if (!OVERVIEW_CULLING_ENABLED) {
|
|
142
|
+
const allIds = new Set(candidates.map((candidate) => candidate.id));
|
|
143
|
+
return {
|
|
144
|
+
tierByScreenId: new Map(
|
|
145
|
+
candidates.map((candidate) => [candidate.id, "visible"] as const),
|
|
146
|
+
),
|
|
147
|
+
liveScreenIds: allIds,
|
|
148
|
+
everVisibleScreenIds: allIds,
|
|
149
|
+
lastVisibleEpochByScreenId: new Map(
|
|
150
|
+
candidates.map((candidate) => [candidate.id, accessEpoch] as const),
|
|
151
|
+
),
|
|
152
|
+
mountedIframeCount: candidates.reduce(
|
|
153
|
+
(total, candidate) => total + normalizedIframeCount(candidate),
|
|
154
|
+
0,
|
|
155
|
+
),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const candidateById = new Map(
|
|
160
|
+
candidates.map((candidate) => [candidate.id, candidate] as const),
|
|
161
|
+
);
|
|
162
|
+
const viewportScreenIds = new Set<string>();
|
|
163
|
+
if (viewport) {
|
|
164
|
+
for (const candidate of candidates) {
|
|
165
|
+
if (isFrameWithinOverscannedViewport(candidate.geometry, viewport)) {
|
|
166
|
+
viewportScreenIds.add(candidate.id);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const nextLastVisible = new Map(lastVisibleEpochByScreenId);
|
|
172
|
+
for (const id of protectedScreenIds) {
|
|
173
|
+
if (candidateById.has(id)) nextLastVisible.set(id, accessEpoch);
|
|
174
|
+
}
|
|
175
|
+
for (const id of viewportScreenIds) nextLastVisible.set(id, accessEpoch);
|
|
176
|
+
|
|
177
|
+
const nextLive = new Set<string>();
|
|
178
|
+
let mountedIframeCount = 0;
|
|
179
|
+
const add = (candidate: ScreenCullCandidate) => {
|
|
180
|
+
if (nextLive.has(candidate.id)) return;
|
|
181
|
+
nextLive.add(candidate.id);
|
|
182
|
+
mountedIframeCount += normalizedIframeCount(candidate);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Protected editor interactions must never be destroyed mid-gesture/edit.
|
|
186
|
+
for (const candidate of candidates) {
|
|
187
|
+
if (protectedScreenIds.has(candidate.id)) add(candidate);
|
|
188
|
+
}
|
|
189
|
+
// Protected screens can temporarily exceed the normal pool. In that case
|
|
190
|
+
// no evictable iframe is admitted until the interaction set shrinks again.
|
|
191
|
+
const effectiveBudget = Math.max(
|
|
192
|
+
Math.max(0, Math.floor(liveIframeBudget)),
|
|
193
|
+
mountedIframeCount,
|
|
194
|
+
);
|
|
195
|
+
const tryAddWithinBudget = (candidate: ScreenCullCandidate) => {
|
|
196
|
+
if (nextLive.has(candidate.id)) return;
|
|
197
|
+
if (
|
|
198
|
+
mountedIframeCount + normalizedIframeCount(candidate) <=
|
|
199
|
+
effectiveBudget
|
|
200
|
+
) {
|
|
201
|
+
add(candidate);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const visibleCandidates = candidates
|
|
206
|
+
.filter(
|
|
207
|
+
(candidate) =>
|
|
208
|
+
viewportScreenIds.has(candidate.id) &&
|
|
209
|
+
!protectedScreenIds.has(candidate.id),
|
|
210
|
+
)
|
|
211
|
+
.sort((a, b) => {
|
|
212
|
+
if (!viewport) return a.id.localeCompare(b.id);
|
|
213
|
+
const distanceDelta =
|
|
214
|
+
distanceSquaredToViewportCenter(a.geometry, viewport) -
|
|
215
|
+
distanceSquaredToViewportCenter(b.geometry, viewport);
|
|
216
|
+
if (distanceDelta !== 0) return distanceDelta;
|
|
217
|
+
const recencyDelta =
|
|
218
|
+
(nextLastVisible.get(b.id) ?? -1) - (nextLastVisible.get(a.id) ?? -1);
|
|
219
|
+
return recencyDelta || a.id.localeCompare(b.id);
|
|
220
|
+
});
|
|
221
|
+
visibleCandidates.forEach(tryAddWithinBudget);
|
|
222
|
+
|
|
223
|
+
const warmCandidates = candidates
|
|
224
|
+
.filter(
|
|
225
|
+
(candidate) =>
|
|
226
|
+
previousLiveScreenIds.has(candidate.id) &&
|
|
227
|
+
!viewportScreenIds.has(candidate.id) &&
|
|
228
|
+
!protectedScreenIds.has(candidate.id),
|
|
229
|
+
)
|
|
230
|
+
.sort((a, b) => {
|
|
231
|
+
const recencyDelta =
|
|
232
|
+
(nextLastVisible.get(b.id) ?? -1) - (nextLastVisible.get(a.id) ?? -1);
|
|
233
|
+
return recencyDelta || a.id.localeCompare(b.id);
|
|
234
|
+
});
|
|
235
|
+
warmCandidates.forEach(tryAddWithinBudget);
|
|
236
|
+
|
|
237
|
+
const nextEverVisible = new Set(everVisibleScreenIds);
|
|
238
|
+
const tierByScreenId = new Map<string, ScreenCullTier>();
|
|
239
|
+
for (const candidate of candidates) {
|
|
240
|
+
const isProtected = protectedScreenIds.has(candidate.id);
|
|
241
|
+
const isInViewport = viewportScreenIds.has(candidate.id);
|
|
242
|
+
const isLive = nextLive.has(candidate.id);
|
|
243
|
+
if (isLive && (isProtected || isInViewport)) {
|
|
244
|
+
nextEverVisible.add(candidate.id);
|
|
245
|
+
tierByScreenId.set(candidate.id, "visible");
|
|
246
|
+
} else if (isLive) {
|
|
247
|
+
tierByScreenId.set(candidate.id, "culled");
|
|
248
|
+
} else if (nextEverVisible.has(candidate.id)) {
|
|
249
|
+
tierByScreenId.set(candidate.id, "evicted");
|
|
250
|
+
} else {
|
|
251
|
+
tierByScreenId.set(candidate.id, "placeholder");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const liveIds = new Set(candidateById.keys());
|
|
256
|
+
for (const id of nextEverVisible) {
|
|
257
|
+
if (!liveIds.has(id)) nextEverVisible.delete(id);
|
|
258
|
+
}
|
|
259
|
+
for (const id of nextLastVisible.keys()) {
|
|
260
|
+
if (!liveIds.has(id)) nextLastVisible.delete(id);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
tierByScreenId,
|
|
265
|
+
liveScreenIds: nextLive,
|
|
266
|
+
everVisibleScreenIds: nextEverVisible,
|
|
267
|
+
lastVisibleEpochByScreenId: nextLastVisible,
|
|
268
|
+
mountedIframeCount,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
54
272
|
/** The world-space (canvas-space) rectangle currently visible inside the
|
|
55
273
|
* pannable surface, expanded by `overscanFactor` viewport-widths/heights in
|
|
56
274
|
* every direction. Built from the *committed* pan/zoom state, matching the
|
|
@@ -72,8 +290,9 @@ export interface OverscannedViewportBounds {
|
|
|
72
290
|
* `SURFACE_PADDING`-relative space — compare directly against
|
|
73
291
|
* `geometry.x`/`geometry.y`-based frame bounds, no further offset needed.
|
|
74
292
|
* Returns `null` when the surface has no measured size yet (e.g. before the
|
|
75
|
-
* first layout pass)
|
|
76
|
-
*
|
|
293
|
+
* first layout pass). Callers keep only active/selected or previously-live
|
|
294
|
+
* screens mounted until measurement; otherwise a cold open would eagerly
|
|
295
|
+
* instantiate every iframe and permanently defeat placeholder culling. */
|
|
77
296
|
export function getOverscannedViewportCanvasBounds(
|
|
78
297
|
surfaceSize: { width: number; height: number },
|
|
79
298
|
pan: Point,
|
|
@@ -158,12 +377,13 @@ export function clampFrameGeometryToViewport(
|
|
|
158
377
|
* itself never culls the object you're actively editing or have selected,
|
|
159
378
|
* and keeping these paths iframe-backed avoids any risk of interrupting
|
|
160
379
|
* in-progress edits/bridge state on the screen the user is looking at.
|
|
161
|
-
* `viewport` is `null` when surface size isn't known yet (initial layout)
|
|
162
|
-
*
|
|
380
|
+
* `viewport` is `null` when surface size isn't known yet (initial layout).
|
|
381
|
+
* Active/selected screens stay visible, previously-live screens stay mounted
|
|
382
|
+
* but culled, and never-seen screens remain placeholders until measurement.
|
|
163
383
|
* `hasBeenVisible` should reflect whether this screen id has *ever* been
|
|
164
|
-
* visible this session (see the hasBeenVisibleRef Set in MultiScreenCanvas)
|
|
165
|
-
*
|
|
166
|
-
* "
|
|
384
|
+
* visible this session (see the hasBeenVisibleRef Set in MultiScreenCanvas).
|
|
385
|
+
* This low-level geometry helper does not apply the live-iframe budget;
|
|
386
|
+
* computeBoundedScreenCullState layers the separate "evicted" tier on top. */
|
|
167
387
|
export function computeScreenCullTier({
|
|
168
388
|
geometry,
|
|
169
389
|
viewport,
|
|
@@ -176,10 +396,9 @@ export function computeScreenCullTier({
|
|
|
176
396
|
hasBeenVisible: boolean;
|
|
177
397
|
}): ScreenCullTier {
|
|
178
398
|
if (!OVERVIEW_CULLING_ENABLED) return "visible";
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
isFrameWithinOverscannedViewport(geometry, viewport);
|
|
399
|
+
if (alwaysVisible) return "visible";
|
|
400
|
+
if (!viewport) return hasBeenVisible ? "culled" : "placeholder";
|
|
401
|
+
const isWithinViewport = isFrameWithinOverscannedViewport(geometry, viewport);
|
|
183
402
|
if (isWithinViewport) return "visible";
|
|
184
403
|
return hasBeenVisible ? "culled" : "placeholder";
|
|
185
404
|
}
|