@agent-native/core 0.169.1 → 0.170.0
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/agent-native.eject.json +4 -1
- package/bin/agent-native.js +23 -5
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +28 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
- package/corpus/templates/analytics/app/routes/$.tsx +10 -0
- package/corpus/templates/analytics/app/routes.ts +3 -1
- package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
- package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
- package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
- package/corpus/templates/analytics/server/lib/slack.ts +4 -2
- package/corpus/templates/analytics/vitest.config.ts +6 -1
- package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/assets/app/routes/library.tsx +5 -3
- package/corpus/templates/assets/app/routes.ts +3 -1
- package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
- package/corpus/templates/assets/vitest.config.ts +6 -1
- package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/brain/app/routes/sources.tsx +8 -3
- package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
- package/corpus/templates/brain/vitest.config.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
- package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
- package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
- package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
- package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
- package/corpus/templates/calendar/app/routes.ts +3 -1
- package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
- package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
- package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
- package/corpus/templates/calendar/server/onboarding.ts +85 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/calendar/shared/api.ts +9 -1
- package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/chat/app/routes.ts +3 -1
- package/corpus/templates/chat/vitest.config.ts +8 -0
- package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/clips/actions/get-meeting.ts +9 -4
- package/corpus/templates/clips/actions/list-recordings.ts +16 -3
- package/corpus/templates/clips/actions/search-meetings.ts +1 -0
- package/corpus/templates/clips/actions/view-screen.ts +8 -1
- package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
- package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
- package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
- package/corpus/templates/clips/desktop/src/app.tsx +53 -24
- package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
- package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
- package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
- package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
- package/corpus/templates/clips/server/lib/emails.ts +17 -33
- package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
- package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
- package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
- package/corpus/templates/content/app/i18n-data.ts +25 -0
- package/corpus/templates/content/app/routes.ts +3 -1
- package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
- package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
- package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
- package/corpus/templates/content/vitest.config.ts +7 -1
- package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
- package/corpus/templates/design/actions/generate-design.ts +98 -47
- package/corpus/templates/design/actions/get-design-system.ts +6 -1
- package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
- package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
- package/corpus/templates/design/app/i18n-data.ts +1 -0
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
- package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
- package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
- package/corpus/templates/design/app/pages/Index.tsx +2 -0
- package/corpus/templates/design/app/pages/Templates.tsx +0 -10
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
- package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
- package/corpus/templates/design/app/routes.ts +3 -1
- package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
- package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
- package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
- package/corpus/templates/design/package.json +2 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
- package/corpus/templates/design/shared/canvas-math.ts +612 -206
- package/corpus/templates/design/shared/pen-path.ts +37 -0
- package/corpus/templates/design/vitest.config.ts +7 -1
- package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
- package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
- package/corpus/templates/dispatch/app/routes.ts +3 -1
- package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/factory/.env.example +2 -7
- package/corpus/templates/factory/AGENTS.md +3 -0
- package/corpus/templates/factory/README.md +5 -3
- package/corpus/templates/factory/actions/create-factory.ts +16 -3
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
- package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
- package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
- package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
- package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
- package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
- package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
- package/corpus/templates/factory/app/routes/factory.tsx +84 -11
- package/corpus/templates/factory/app/routes.ts +3 -1
- package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
- package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
- package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
- package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
- package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
- package/corpus/templates/factory/vitest.config.ts +17 -2
- package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
- package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
- package/corpus/templates/forms/vitest.config.ts +1 -0
- package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/macros/app/routes.ts +3 -1
- package/corpus/templates/macros/vitest.config.ts +6 -1
- package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
- package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
- package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
- package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
- package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
- package/corpus/templates/mail/app/routes/$.tsx +9 -0
- package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
- package/corpus/templates/mail/app/routes/$view.tsx +47 -1
- package/corpus/templates/mail/app/routes.ts +3 -1
- package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
- package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
- package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
- package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
- package/corpus/templates/mail/server/onboarding.ts +66 -18
- package/corpus/templates/mail/vitest.config.ts +6 -1
- package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/plan/app/routes/settings.tsx +4 -1
- package/corpus/templates/plan/app/routes.ts +3 -1
- package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/plan/netlify.toml +1 -1
- package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/slides/actions/patch-deck.ts +79 -10
- package/corpus/templates/slides/actions/update-slide.ts +11 -1
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
- package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
- package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
- package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
- package/corpus/templates/slides/app/routes.ts +3 -1
- package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
- package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
- package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
- package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
- package/corpus/templates/slides/tsconfig.json +5 -0
- package/corpus/templates/slides/vitest.config.ts +6 -1
- package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
- package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
- package/corpus/templates/tasks/app/routes.ts +3 -1
- package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
- package/corpus/templates/tasks/vitest.config.ts +7 -1
- package/dist/action.d.ts +91 -0
- package/dist/action.js +50 -0
- package/dist/agent/abort-reasons.d.ts +38 -0
- package/dist/agent/abort-reasons.js +49 -0
- package/dist/agent/engine/ai-sdk-engine.js +8 -5
- package/dist/agent/engine/anthropic-engine.js +7 -5
- package/dist/agent/engine/first-event-timeout.d.ts +42 -17
- package/dist/agent/engine/first-event-timeout.js +67 -25
- package/dist/agent/production-agent.d.ts +23 -0
- package/dist/agent/production-agent.js +107 -102
- package/dist/agent/run-loop-with-resume.d.ts +2 -28
- package/dist/agent/run-loop-with-resume.js +25 -40
- package/dist/agent/run-manager.js +5 -4
- package/dist/agent/run-store.d.ts +55 -0
- package/dist/agent/run-store.js +124 -1
- package/dist/agent/tool-search.js +2 -1
- package/dist/agent/types.d.ts +9 -4
- package/dist/app-config/configuration-error.d.ts +11 -0
- package/dist/app-config/configuration-error.js +14 -0
- package/dist/app-config/index.d.ts +1 -0
- package/dist/app-config/index.js +1 -0
- package/dist/app-config/integrations.d.ts +1 -0
- package/dist/app-config/integrations.js +10 -0
- package/dist/app-config/plugins.d.ts +34 -0
- package/dist/app-config/plugins.js +39 -0
- package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
- package/dist/app-config/run-lifecycle-invariants.js +18 -25
- package/dist/app-config/schema.d.ts +16 -0
- package/dist/app-config/schema.js +2 -0
- package/dist/chat-threads/schema-migrations.js +20 -0
- package/dist/chat-threads/store.js +21 -4
- package/dist/cli/native-dependencies.d.ts +4 -0
- package/dist/cli/native-dependencies.js +15 -0
- package/dist/client/EnvironmentBadge.d.ts +1 -1
- package/dist/client/EnvironmentBadge.js +40 -5
- package/dist/client/MultiTabAssistantChat.d.ts +1 -1
- package/dist/client/MultiTabAssistantChat.js +35 -14
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/agent-page/use-jobs.d.ts +2 -1
- package/dist/client/agent-page/use-jobs.js +3 -5
- package/dist/client/agent-sidebar-state.js +3 -1
- package/dist/client/blocks/library/code-tabs.js +5 -0
- package/dist/client/blocks/library/code.js +1 -0
- package/dist/client/chat-first/apps-rail.js +2 -2
- package/dist/client/chat-model-groups.d.ts +12 -0
- package/dist/client/chat-model-groups.js +3 -2
- package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
- package/dist/client/integrations/GoogleProductLogo.js +45 -0
- package/dist/client/integrations/index.d.ts +2 -0
- package/dist/client/integrations/index.js +2 -0
- package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
- package/dist/client/integrations/workspace-provider-oauth.js +13 -0
- package/dist/client/resources/mcp-integration-catalog.js +0 -29
- package/dist/client/settings/SettingsTabsPage.js +10 -6
- package/dist/client/sharing/ShareButton.js +11 -2
- package/dist/client/use-chat-models.d.ts +6 -0
- package/dist/client/use-chat-models.js +10 -0
- package/dist/client/use-db-sync.js +27 -9
- package/dist/connections/catalog.d.ts +111 -9
- package/dist/connections/catalog.js +86 -30
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/ddl-guard.d.ts +0 -4
- package/dist/db/ddl-guard.js +46 -0
- package/dist/deploy/build.d.ts +19 -0
- package/dist/deploy/build.js +190 -16
- package/dist/deploy/function-bundle.d.ts +45 -0
- package/dist/deploy/function-bundle.js +337 -0
- package/dist/deploy/workspace-deploy.js +19 -1
- package/dist/eject/workspace-connections.js +4 -0
- package/dist/email-catalog/registry.d.ts +4 -0
- package/dist/email-catalog/registry.js +79 -14
- package/dist/extensions/content-patch.js +14 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/plugin.d.ts +10 -0
- package/dist/integrations/plugin.js +40 -6
- package/dist/jobs/actions/run-automation-now.d.ts +2 -1
- package/dist/jobs/actions/run-automation-now.js +11 -5
- package/dist/jobs/frontmatter.js +53 -2
- package/dist/jobs/run-now.d.ts +11 -1
- package/dist/jobs/run-now.js +42 -7
- package/dist/jobs/scheduler.d.ts +1 -0
- package/dist/jobs/scheduler.js +2 -1
- package/dist/localization/core-messages/ar-SA.js +3 -0
- package/dist/localization/core-messages/de-DE.js +3 -0
- package/dist/localization/core-messages/en-US.d.ts +3 -0
- package/dist/localization/core-messages/en-US.js +3 -0
- package/dist/localization/core-messages/es-ES.js +3 -0
- package/dist/localization/core-messages/fr-FR.js +3 -0
- package/dist/localization/core-messages/hi-IN.js +3 -0
- package/dist/localization/core-messages/ja-JP.js +3 -0
- package/dist/localization/core-messages/ko-KR.js +3 -0
- package/dist/localization/core-messages/pt-BR.js +3 -0
- package/dist/localization/core-messages/zh-CN.js +3 -0
- package/dist/localization/core-messages/zh-TW.js +3 -0
- package/dist/localization/core-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts +2 -5
- package/dist/localization/default-messages.js +2 -5
- package/dist/mcp/build-server.d.ts +9 -0
- package/dist/mcp/build-server.js +37 -8
- package/dist/mcp-client/oauth-client.d.ts +7 -0
- package/dist/mcp-client/oauth-client.js +12 -1
- package/dist/oauth-tokens/index.d.ts +1 -1
- package/dist/oauth-tokens/index.js +1 -1
- package/dist/oauth-tokens/lifecycle.d.ts +11 -0
- package/dist/oauth-tokens/lifecycle.js +17 -0
- package/dist/oauth-tokens/store.js +7 -0
- package/dist/observability/posthog-ai.d.ts +15 -1
- package/dist/observability/posthog-ai.js +24 -12
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/traces.js +158 -28
- package/dist/onboarding/app-profile.js +2 -2
- package/dist/onboarding/plugin.js +10 -2
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/provider-api/index.js +2 -0
- package/dist/resources/store.js +13 -4
- package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
- package/dist/secrets/register-framework-secrets.js +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
- package/dist/server/agent-chat/action-filters-a2a.js +48 -9
- package/dist/server/agent-chat-plugin.js +36 -9
- package/dist/server/agent-discovery.js +43 -20
- package/dist/server/auth.js +18 -16
- package/dist/server/beta-opt-out-html.js +45 -4
- package/dist/server/better-auth-instance.d.ts +2 -1
- package/dist/server/better-auth-instance.js +23 -7
- package/dist/server/builder-design-systems.d.ts +4 -1
- package/dist/server/builder-design-systems.js +87 -6
- package/dist/server/builder-oauth.d.ts +1 -7
- package/dist/server/builder-oauth.js +80 -163
- package/dist/server/core-routes-plugin.d.ts +29 -0
- package/dist/server/core-routes-plugin.js +100 -20
- package/dist/server/default-plugins.d.ts +18 -0
- package/dist/server/default-plugins.js +22 -0
- package/dist/server/edge.d.ts +1 -0
- package/dist/server/edge.js +1 -0
- package/dist/server/framework-request-handler.js +31 -3
- package/dist/server/google-oauth.d.ts +3 -0
- package/dist/server/google-oauth.js +3 -0
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/onboarding-html.js +37 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +6 -1
- package/dist/server/workspace-provider-oauth.js +72 -20
- package/dist/shared/agent-sidebar-url.d.ts +1 -0
- package/dist/shared/agent-sidebar-url.js +1 -0
- package/dist/shared/environment-lanes.d.ts +2 -0
- package/dist/shared/environment-lanes.js +3 -1
- package/dist/shared/index.d.ts +3 -1
- package/dist/shared/index.js +3 -1
- package/dist/shared/surface-visibility.d.ts +31 -0
- package/dist/shared/surface-visibility.js +57 -0
- package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/chat/app/routes.ts +3 -1
- package/dist/templates/chat/vitest.config.ts +8 -0
- package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/default/app/routes.ts +3 -1
- package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
- package/dist/tracking/registry.d.ts +11 -0
- package/dist/tracking/registry.js +5 -2
- package/dist/triggers/actions.js +10 -3
- package/dist/usage/store.js +23 -3
- package/dist/user-profile/actions/get-auth-methods.js +18 -5
- package/dist/vite/client.js +24 -5
- package/docs/content/actions-access-control.mdx +43 -4
- package/docs/content/actions-defining.mdx +16 -0
- package/docs/content/template-clips-capture-everywhere.mdx +29 -30
- package/docs/content/template-clips-developers.mdx +4 -4
- package/docs/content/template-clips.mdx +3 -1
- package/package.json +2 -2
- package/src/eject/workspace-connections.ts +4 -0
- package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/chat/app/routes.ts +3 -1
- package/src/templates/chat/vitest.config.ts +8 -0
- package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/default/app/routes.ts +3 -1
- package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts
CHANGED
|
@@ -7,6 +7,7 @@ import * as Y from "yjs";
|
|
|
7
7
|
|
|
8
8
|
import { trace } from "@/components/design/design-trace";
|
|
9
9
|
import type { ClipboardContentMutationPublication } from "@/lib/clipboard-content-lineage";
|
|
10
|
+
import { writeCollabText } from "@/pages/design-editor/collab-sync";
|
|
10
11
|
import {
|
|
11
12
|
LOCAL_EDIT_ORIGIN,
|
|
12
13
|
TAB_ID,
|
|
@@ -289,17 +290,16 @@ export function runApplyLocalContentUpdate(
|
|
|
289
290
|
const ytext = ydoc.getText("content");
|
|
290
291
|
if (ytext.toString() !== nextContent) {
|
|
291
292
|
if (!yjsHistoryAvailable) {
|
|
292
|
-
// Untracked
|
|
293
|
+
// Untracked write (recordHistory:false callers such as the
|
|
293
294
|
// code-layer id-stamping effect, or history-suppressed replays) —
|
|
294
295
|
// see U1 note above: clear the undo stack so a stale tracked
|
|
295
296
|
// delta can't be replayed against content it no longer matches.
|
|
296
297
|
undoManagerRef.current?.clear(true, false);
|
|
297
298
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
},
|
|
299
|
+
writeCollabText(
|
|
300
|
+
ydoc,
|
|
301
|
+
ytext,
|
|
302
|
+
nextContent,
|
|
303
303
|
yjsHistoryAvailable ? LOCAL_EDIT_ORIGIN : TAB_ID,
|
|
304
304
|
);
|
|
305
305
|
}
|
|
@@ -50,7 +50,7 @@ export interface ApplyPendingVisualStylesWithAgentArgs {
|
|
|
50
50
|
pendingStructureVerificationStatus: PendingStructureVerificationStatus;
|
|
51
51
|
pendingVisualStyleEdits: PendingVisualStyleEdit[];
|
|
52
52
|
pendingVisualStylePrompt: string;
|
|
53
|
-
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel>>;
|
|
53
|
+
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel | null>>;
|
|
54
54
|
setApplyingViaHost: Dispatch<SetStateAction<boolean>>;
|
|
55
55
|
setPendingAgentHandoffBusy: Dispatch<SetStateAction<boolean>>;
|
|
56
56
|
setPendingStructureAckRequest: Dispatch<
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
resolveCodeLayerTargetFromBridge,
|
|
26
26
|
resolveCodeLayerTargetFromElementInfo,
|
|
27
27
|
} from "@/pages/design-editor/code-layer-state";
|
|
28
|
+
import { writeCollabText } from "@/pages/design-editor/collab-sync";
|
|
28
29
|
import type {
|
|
29
30
|
LiveScreenSnapshot,
|
|
30
31
|
PatchProofState,
|
|
@@ -176,6 +177,9 @@ export function runCommitVisualStyles(
|
|
|
176
177
|
elementInfo?: ElementInfo;
|
|
177
178
|
/** Pre-gesture values, for the pending-edit revert stack. */
|
|
178
179
|
originalStyles?: Record<string, string>;
|
|
180
|
+
/** The write is a side effect of a gesture on another element, so it must
|
|
181
|
+
* not move the selection onto the element it touched. */
|
|
182
|
+
preserveSelection?: boolean;
|
|
179
183
|
} = {},
|
|
180
184
|
) {
|
|
181
185
|
trace("persist", "commit-styles", {
|
|
@@ -657,17 +661,16 @@ export function runCommitVisualStyles(
|
|
|
657
661
|
const ytext = ydoc.getText("content");
|
|
658
662
|
if (ytext.toString() !== resolvedNextContent) {
|
|
659
663
|
if (!yjsHistoryAvailable) {
|
|
660
|
-
// Untracked
|
|
664
|
+
// Untracked write (overview mode with a still-live
|
|
661
665
|
// single-mode UndoManager, or history-suppressed replay) —
|
|
662
666
|
// see U1 note: clear the undo stack so a stale tracked delta
|
|
663
667
|
// can't be replayed against content it no longer matches.
|
|
664
668
|
undoManagerRef.current?.clear(true, false);
|
|
665
669
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
},
|
|
670
|
+
writeCollabText(
|
|
671
|
+
ydoc,
|
|
672
|
+
ytext,
|
|
673
|
+
resolvedNextContent,
|
|
671
674
|
yjsHistoryAvailable ? LOCAL_EDIT_ORIGIN : TAB_ID,
|
|
672
675
|
);
|
|
673
676
|
}
|
|
@@ -687,7 +690,15 @@ export function runCommitVisualStyles(
|
|
|
687
690
|
setContentRenderRevision((revision) => revision + 1);
|
|
688
691
|
}
|
|
689
692
|
}
|
|
690
|
-
if (
|
|
693
|
+
if (options.preserveSelection) return;
|
|
694
|
+
// A commit must never shrink the selection: a group transform commits one
|
|
695
|
+
// style change per member, so selecting the committed node keeps only the
|
|
696
|
+
// member that happened to commit last.
|
|
697
|
+
if (resolvedNode) {
|
|
698
|
+
setSelectedLayerIdsState((current) =>
|
|
699
|
+
current.includes(resolvedNode.id) ? current : [resolvedNode.id],
|
|
700
|
+
);
|
|
701
|
+
}
|
|
691
702
|
setSelectedElement((prev) => {
|
|
692
703
|
if (options.elementInfo) return options.elementInfo;
|
|
693
704
|
if (!prev) return prev;
|
|
@@ -1,33 +1,13 @@
|
|
|
1
|
-
import type { CodeLayerNode, CodeLayerTreeNode } from "@shared/code-layer";
|
|
2
1
|
import type { Dispatch, RefObject, SetStateAction } from "react";
|
|
3
2
|
|
|
4
3
|
import type { ElementInfo } from "@/components/design/types";
|
|
5
|
-
import {
|
|
6
|
-
collectCodeLayerAncestors,
|
|
7
|
-
elementInfoFromCodeLayerNode,
|
|
8
|
-
} from "@/pages/design-editor/code-layer-state";
|
|
9
|
-
import {
|
|
10
|
-
hasSelectableCodeLayerParent,
|
|
11
|
-
resolveEscapePopSelectionAction,
|
|
12
|
-
shouldEscapeToOverview,
|
|
13
|
-
} from "@/pages/design-editor/selection-state";
|
|
4
|
+
import { shouldEscapeToOverview } from "@/pages/design-editor/selection-state";
|
|
14
5
|
import type { DesignTool, EditorMode } from "@/pages/design-editor/types";
|
|
15
6
|
|
|
16
7
|
export interface EscapeHotkeyArgs {
|
|
17
8
|
activeBreakpointWidthStateRef: RefObject<number | undefined>;
|
|
18
9
|
activeTool: DesignTool;
|
|
19
10
|
cancelActiveEditorDrag: () => boolean;
|
|
20
|
-
codeLayerOwnerByNodeIdRef: RefObject<
|
|
21
|
-
Map<
|
|
22
|
-
string,
|
|
23
|
-
{
|
|
24
|
-
fileId: string;
|
|
25
|
-
node: CodeLayerNode;
|
|
26
|
-
tree: CodeLayerTreeNode[];
|
|
27
|
-
runtimeOnly: boolean;
|
|
28
|
-
}
|
|
29
|
-
>
|
|
30
|
-
>;
|
|
31
11
|
drawMode: boolean;
|
|
32
12
|
enterOverviewFromZoom: (nextMode?: EditorMode) => void;
|
|
33
13
|
focusedAnnotationSending: boolean;
|
|
@@ -40,11 +20,8 @@ export interface EscapeHotkeyArgs {
|
|
|
40
20
|
overviewAnnotationSending: boolean;
|
|
41
21
|
pinMode: boolean;
|
|
42
22
|
selectedElement: ElementInfo | null;
|
|
43
|
-
selectedLayerIdsState: string[];
|
|
44
|
-
setActiveFileId: Dispatch<SetStateAction<string | null>>;
|
|
45
23
|
setActiveTool: Dispatch<SetStateAction<DesignTool>>;
|
|
46
24
|
setDrawMode: Dispatch<SetStateAction<boolean>>;
|
|
47
|
-
setExpandedLayerIds: Dispatch<SetStateAction<string[]>>;
|
|
48
25
|
setHoveredElement: Dispatch<SetStateAction<ElementInfo | null>>;
|
|
49
26
|
setMode: Dispatch<SetStateAction<EditorMode>>;
|
|
50
27
|
setOverviewClearSelectionRequest: Dispatch<SetStateAction<number>>;
|
|
@@ -59,7 +36,6 @@ export function runEscapeHotkey({
|
|
|
59
36
|
activeBreakpointWidthStateRef,
|
|
60
37
|
activeTool,
|
|
61
38
|
cancelActiveEditorDrag,
|
|
62
|
-
codeLayerOwnerByNodeIdRef,
|
|
63
39
|
drawMode,
|
|
64
40
|
enterOverviewFromZoom,
|
|
65
41
|
focusedAnnotationSending,
|
|
@@ -72,11 +48,8 @@ export function runEscapeHotkey({
|
|
|
72
48
|
overviewAnnotationSending,
|
|
73
49
|
pinMode,
|
|
74
50
|
selectedElement,
|
|
75
|
-
selectedLayerIdsState,
|
|
76
|
-
setActiveFileId,
|
|
77
51
|
setActiveTool,
|
|
78
52
|
setDrawMode,
|
|
79
|
-
setExpandedLayerIds,
|
|
80
53
|
setHoveredElement,
|
|
81
54
|
setMode,
|
|
82
55
|
setOverviewClearSelectionRequest,
|
|
@@ -133,68 +106,9 @@ export function runEscapeHotkey({
|
|
|
133
106
|
enterOverviewFromZoom();
|
|
134
107
|
return;
|
|
135
108
|
}
|
|
136
|
-
// Figma
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
// The decision itself is a pure, unit-tested function
|
|
140
|
-
// (resolveEscapePopSelectionAction in design-editor/selection-state.ts);
|
|
141
|
-
// this reuses the same codeLayerOwnerByNodeIdRef/parentId ancestor walk
|
|
142
|
-
// handleSelectParentLayer (Shift+Enter / "\\") already uses, inlined
|
|
143
|
-
// here (rather than calling selectCodeLayerNodesForHotkey directly)
|
|
144
|
-
// since that helper is declared later in this component and referencing
|
|
145
|
-
// it from this callback's deps would hit its temporal-dead-zone before
|
|
146
|
-
// this render's declarations run.
|
|
147
|
-
const escapeSelectedLayerId =
|
|
148
|
-
selectedLayerIdsState[selectedLayerIdsState.length - 1];
|
|
149
|
-
const escapeOwner = escapeSelectedLayerId
|
|
150
|
-
? codeLayerOwnerByNodeIdRef.current.get(escapeSelectedLayerId)
|
|
151
|
-
: undefined;
|
|
152
|
-
// BUG-ESCAPE-SHELL: the flat codeLayerOwnerByNodeIdRef map (built from
|
|
153
|
-
// projection.nodes) still contains <html>/<body> entries with real
|
|
154
|
-
// parentId links even though the VISUAL layers tree collapses them away
|
|
155
|
-
// (shared/code-layer.ts's isCollapsibleDocumentShellNode). A bare
|
|
156
|
-
// Boolean(escapeOwner?.node.parentId) check treats a top-level layer's
|
|
157
|
-
// collapsed <body> ancestor as a selectable parent, so popping from the
|
|
158
|
-
// screen root would select <body> then <html> instead of stopping at the
|
|
159
|
-
// screen/frame level. hasSelectableCodeLayerParent excludes those shell
|
|
160
|
-
// nodes so the pop walk matches what the layers panel shows.
|
|
161
|
-
const escapeParentOwner = escapeOwner?.node.parentId
|
|
162
|
-
? codeLayerOwnerByNodeIdRef.current.get(escapeOwner.node.parentId)
|
|
163
|
-
: undefined;
|
|
164
|
-
const popAction = resolveEscapePopSelectionAction({
|
|
165
|
-
hasSelectedLayer: Boolean(escapeOwner),
|
|
166
|
-
hasLayerParent: hasSelectableCodeLayerParent({
|
|
167
|
-
parentNode: escapeParentOwner?.node,
|
|
168
|
-
}),
|
|
169
|
-
viewMode,
|
|
170
|
-
});
|
|
171
|
-
if (popAction.kind === "pop-to-parent-layer" && escapeOwner) {
|
|
172
|
-
const parentOwner = escapeParentOwner;
|
|
173
|
-
if (parentOwner && parentOwner.fileId === escapeOwner.fileId) {
|
|
174
|
-
setActiveFileId(parentOwner.fileId);
|
|
175
|
-
setOverviewSelectedScreenIds([]);
|
|
176
|
-
setSelectedLayerIdsState([parentOwner.node.id]);
|
|
177
|
-
setSelectedElement(elementInfoFromCodeLayerNode(parentOwner.node));
|
|
178
|
-
setExpandedLayerIds((current) => {
|
|
179
|
-
const next = new Set(current);
|
|
180
|
-
next.add(parentOwner.fileId);
|
|
181
|
-
collectCodeLayerAncestors(
|
|
182
|
-
parentOwner.tree,
|
|
183
|
-
parentOwner.node.id,
|
|
184
|
-
).forEach((ancestorId) => next.add(ancestorId));
|
|
185
|
-
return next.size === current.length ? current : Array.from(next);
|
|
186
|
-
});
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
// Parent couldn't be resolved (e.g. cross-file) — fall through to a
|
|
190
|
-
// full deselect below rather than silently doing nothing.
|
|
191
|
-
} else if (popAction.kind === "pop-to-screen-frame" && escapeOwner) {
|
|
192
|
-
setSelectedElement(null);
|
|
193
|
-
setSelectedLayerIdsState([]);
|
|
194
|
-
setOverviewSelectedScreenIds([escapeOwner.fileId]);
|
|
195
|
-
setOverviewClearSelectionRequest((request) => request + 1);
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
109
|
+
// Figma's Esc is "select none". Walking up one ancestor per press belongs to
|
|
110
|
+
// Shift+Enter / "\\" (handleSelectParentLayer) — Escape must never leave
|
|
111
|
+
// something selected, or there is no keystroke that reaches an empty canvas.
|
|
198
112
|
setSelectedElement(null);
|
|
199
113
|
setHoveredElement(null);
|
|
200
114
|
setOverviewSelectedScreenIds([]);
|
package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
isScreenRootElementInfo,
|
|
16
16
|
shouldClearBridgeSelectionOnEmptyMarquee,
|
|
17
17
|
} from "@/pages/design-editor/selection-state";
|
|
18
|
+
import { resolveToolAfterSelection } from "@/pages/design-editor/tool-state";
|
|
18
19
|
import type { DesignTool, EditorMode } from "@/pages/design-editor/types";
|
|
19
20
|
|
|
20
21
|
export interface LayerMarqueeSelectionChangeArgs {
|
|
@@ -158,6 +159,6 @@ export function runLayerMarqueeSelectionChange(
|
|
|
158
159
|
setOverviewClearSelectionRequest((request) => request + 1);
|
|
159
160
|
}
|
|
160
161
|
|
|
161
|
-
setActiveTool(
|
|
162
|
+
setActiveTool(resolveToolAfterSelection);
|
|
162
163
|
setMode("edit");
|
|
163
164
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
getOverviewScreenIdsFromLayerSelection,
|
|
10
10
|
getSidebarCodeLayerSelectionState,
|
|
11
11
|
} from "@/pages/design-editor/selection-state";
|
|
12
|
+
import { resolveToolAfterSelection } from "@/pages/design-editor/tool-state";
|
|
12
13
|
import type {
|
|
13
14
|
DesignFile,
|
|
14
15
|
DesignTool,
|
|
@@ -130,13 +131,13 @@ export function runLayerSelectionChange(
|
|
|
130
131
|
if (layerCanvasBlocked) {
|
|
131
132
|
setSelectedElement(null);
|
|
132
133
|
focusDesignInspectorForSelection();
|
|
133
|
-
setActiveTool(
|
|
134
|
+
setActiveTool(resolveToolAfterSelection);
|
|
134
135
|
setMode("edit");
|
|
135
136
|
return;
|
|
136
137
|
}
|
|
137
138
|
setSelectedElement(elementInfoFromCodeLayerNode(codeLayerOwner.node));
|
|
138
139
|
focusDesignInspectorForSelection();
|
|
139
|
-
setActiveTool(
|
|
140
|
+
setActiveTool(resolveToolAfterSelection);
|
|
140
141
|
setMode("edit");
|
|
141
142
|
return;
|
|
142
143
|
}
|
|
@@ -153,7 +154,7 @@ export function runLayerSelectionChange(
|
|
|
153
154
|
? nextLayerIds
|
|
154
155
|
: [fileId],
|
|
155
156
|
);
|
|
156
|
-
setActiveTool(
|
|
157
|
+
setActiveTool(resolveToolAfterSelection);
|
|
157
158
|
setMode("edit");
|
|
158
159
|
viewModeRef.current = "overview";
|
|
159
160
|
setViewMode("overview");
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
isScreenRootElementInfo,
|
|
21
21
|
shouldIgnoreOverviewLayerCreationEcho,
|
|
22
22
|
} from "@/pages/design-editor/selection-state";
|
|
23
|
+
import { resolveToolAfterSelection } from "@/pages/design-editor/tool-state";
|
|
23
24
|
import type { DesignTool, EditorMode } from "@/pages/design-editor/types";
|
|
24
25
|
|
|
25
26
|
export interface ScreenElementSelectArgs {
|
|
@@ -234,8 +235,17 @@ export function runScreenElementSelect(
|
|
|
234
235
|
}
|
|
235
236
|
return dedupeStringIds([...current, node.id]);
|
|
236
237
|
});
|
|
238
|
+
} else if (node) {
|
|
239
|
+
// An intent-less select is the bridge re-anchoring after a content
|
|
240
|
+
// replace, not a user picking one object, so it must not collapse a live
|
|
241
|
+
// multi-selection down to the member it re-found.
|
|
242
|
+
setSelectedLayerIdsState((current) =>
|
|
243
|
+
!intent && current.length > 1 && current.includes(node.id)
|
|
244
|
+
? current
|
|
245
|
+
: [node.id],
|
|
246
|
+
);
|
|
237
247
|
} else {
|
|
238
|
-
setSelectedLayerIdsState(
|
|
248
|
+
setSelectedLayerIdsState([]);
|
|
239
249
|
}
|
|
240
250
|
if (viewModeRef.current === "overview") {
|
|
241
251
|
setOverviewSelectedScreenIds([]);
|
|
@@ -256,7 +266,7 @@ export function runScreenElementSelect(
|
|
|
256
266
|
handleBreakpointBarSelect(undefined);
|
|
257
267
|
}
|
|
258
268
|
}
|
|
259
|
-
setActiveTool(
|
|
269
|
+
setActiveTool(resolveToolAfterSelection);
|
|
260
270
|
setMode("edit");
|
|
261
271
|
focusDesignInspectorForSelection();
|
|
262
272
|
}
|
package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts
CHANGED
|
@@ -39,7 +39,10 @@ export interface ScreenVisualStyleChangeArgs {
|
|
|
39
39
|
selector: string,
|
|
40
40
|
styles: Record<string, string>,
|
|
41
41
|
elementInfo?: ElementInfo,
|
|
42
|
-
metadata?: {
|
|
42
|
+
metadata?: {
|
|
43
|
+
originalStyles?: Record<string, string>;
|
|
44
|
+
preserveSelection?: boolean;
|
|
45
|
+
},
|
|
43
46
|
) => void;
|
|
44
47
|
overviewScreens: OverviewScreen[];
|
|
45
48
|
recordPendingVisualStyleEdit: (
|
|
@@ -49,6 +52,7 @@ export interface ScreenVisualStyleChangeArgs {
|
|
|
49
52
|
elementInfo?: ElementInfo,
|
|
50
53
|
metadata?: {
|
|
51
54
|
originalStyles?: Record<string, string>;
|
|
55
|
+
preserveSelection?: boolean;
|
|
52
56
|
interactionState?: InteractionState;
|
|
53
57
|
},
|
|
54
58
|
) => void;
|
|
@@ -75,7 +79,10 @@ export function runScreenVisualStyleChange(
|
|
|
75
79
|
selector: string,
|
|
76
80
|
styles: Record<string, string>,
|
|
77
81
|
elementInfo?: ElementInfo,
|
|
78
|
-
metadata?: {
|
|
82
|
+
metadata?: {
|
|
83
|
+
originalStyles?: Record<string, string>;
|
|
84
|
+
preserveSelection?: boolean;
|
|
85
|
+
},
|
|
79
86
|
) {
|
|
80
87
|
if (screenId === activeFile?.id) {
|
|
81
88
|
handleVisualStyleChange(selector, styles, elementInfo, metadata);
|
|
@@ -29,7 +29,7 @@ export interface SendRuntimeLayerMoveSemanticHandoffArgs {
|
|
|
29
29
|
localhostConnectionRootPathByIdRef: RefObject<Map<string, string>>;
|
|
30
30
|
overviewScreens: OverviewScreen[];
|
|
31
31
|
runtimeLayerSnapshotsById: Record<string, RuntimeLayerSnapshot>;
|
|
32
|
-
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel>>;
|
|
32
|
+
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel | null>>;
|
|
33
33
|
t: (key: string, options?: Record<string, unknown>) => string;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -29,7 +29,7 @@ export interface SendRuntimeLayerSemanticHandoffArgs {
|
|
|
29
29
|
localhostConnectionRootPathByIdRef: RefObject<Map<string, string>>;
|
|
30
30
|
overviewScreens: OverviewScreen[];
|
|
31
31
|
runtimeLayerSnapshotsById: Record<string, RuntimeLayerSnapshot>;
|
|
32
|
-
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel>>;
|
|
32
|
+
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel | null>>;
|
|
33
33
|
t: (key: string, options?: Record<string, unknown>) => string;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -32,7 +32,7 @@ export interface SendRuntimeLayerStateSemanticHandoffArgs {
|
|
|
32
32
|
localhostConnectionRootPathByIdRef: RefObject<Map<string, string>>;
|
|
33
33
|
overviewScreens: OverviewScreen[];
|
|
34
34
|
runtimeLayerSnapshotsById: Record<string, RuntimeLayerSnapshot>;
|
|
35
|
-
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel>>;
|
|
35
|
+
setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel | null>>;
|
|
36
36
|
t: (key: string, options?: Record<string, unknown>) => string;
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
import type { DesignLeftPanel } from "@/pages/design-editor/types";
|
|
9
9
|
|
|
10
10
|
export interface StartSidebarResizeArgs {
|
|
11
|
-
activeLeftPanel: DesignLeftPanel;
|
|
11
|
+
activeLeftPanel: DesignLeftPanel | null;
|
|
12
12
|
leftSidebarContentRef: RefObject<HTMLDivElement | null>;
|
|
13
13
|
leftSidebarWidth: number;
|
|
14
14
|
rightSidebarContentRef: RefObject<HTMLDivElement | null>;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { isStandaloneHttpUrl } from "@shared/html-content";
|
|
2
2
|
|
|
3
|
+
import { trace } from "@/components/design/design-trace";
|
|
4
|
+
|
|
3
5
|
import { normalizeDesignLeftPanel } from "./tool-state";
|
|
4
6
|
import {
|
|
5
7
|
type DesignFile,
|
|
@@ -24,10 +26,18 @@ export type PreviewContentReplaceResult =
|
|
|
24
26
|
| "skipped-caller-owns-preview"
|
|
25
27
|
| "unavailable";
|
|
26
28
|
|
|
29
|
+
/**
|
|
30
|
+
* True when the in-place bridge patch could not run and the caller must fall
|
|
31
|
+
* back to rebuilding srcdoc — a real iframe reload that re-executes the editor
|
|
32
|
+
* bridge, Tailwind and Alpine. Traced because it is the one escalation a user
|
|
33
|
+
* perceives as "the frame refreshed", and it is otherwise invisible.
|
|
34
|
+
*/
|
|
27
35
|
export function previewContentReplaceNeedsRenderFallback(
|
|
28
36
|
result: PreviewContentReplaceResult,
|
|
29
37
|
): boolean {
|
|
30
|
-
|
|
38
|
+
if (result !== "unavailable") return false;
|
|
39
|
+
trace("persist", "preview-bridge-unavailable-reload");
|
|
40
|
+
return true;
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
/**
|
|
@@ -3,6 +3,7 @@ import { sourceContentHash } from "@shared/source-workspace";
|
|
|
3
3
|
import type { Dispatch, RefObject, SetStateAction } from "react";
|
|
4
4
|
import * as Y from "yjs";
|
|
5
5
|
|
|
6
|
+
import { writeCollabText } from "@/pages/design-editor/collab-sync";
|
|
6
7
|
import {
|
|
7
8
|
TAB_ID,
|
|
8
9
|
shouldAdoptExternalReconcileContent,
|
|
@@ -103,16 +104,13 @@ export function runAdoptDbFileContent({
|
|
|
103
104
|
if (isLeadClient && ydoc) {
|
|
104
105
|
const ytext = ydoc.getText("content");
|
|
105
106
|
if (ytext.toString() !== dbContent) {
|
|
106
|
-
// Untracked
|
|
107
|
-
//
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
107
|
+
// Untracked write (agent edit / external DB content replacing a
|
|
108
|
+
// live doc that diverged) — clear the undo stack so a stale
|
|
109
|
+
// tracked delta can't be replayed against content it no longer
|
|
110
|
+
// matches (see U1: this is the primary corruption path — agent
|
|
111
|
+
// edits, motion autosave, and id-stamping all land here).
|
|
111
112
|
undoManagerRef.current?.clear(true, false);
|
|
112
|
-
ydoc
|
|
113
|
-
ytext.delete(0, ytext.length);
|
|
114
|
-
ytext.insert(0, dbContent);
|
|
115
|
-
}, TAB_ID);
|
|
113
|
+
writeCollabText(ydoc, ytext, dbContent, TAB_ID);
|
|
116
114
|
}
|
|
117
115
|
}
|
|
118
116
|
return;
|
|
@@ -182,12 +180,9 @@ export function runAdoptDbFileContent({
|
|
|
182
180
|
if (isLeadClient && ydoc) {
|
|
183
181
|
const ytext = ydoc.getText("content");
|
|
184
182
|
if (ytext.toString() !== expectedContent) {
|
|
185
|
-
// Untracked
|
|
183
|
+
// Untracked write — see U1 note above.
|
|
186
184
|
undoManagerRef.current?.clear(true, false);
|
|
187
|
-
ydoc
|
|
188
|
-
ytext.delete(0, ytext.length);
|
|
189
|
-
ytext.insert(0, expectedContent);
|
|
190
|
-
}, TAB_ID);
|
|
185
|
+
writeCollabText(ydoc, ytext, expectedContent, TAB_ID);
|
|
191
186
|
}
|
|
192
187
|
}
|
|
193
188
|
}, 1200);
|
|
@@ -258,13 +253,10 @@ export function runAdoptDbFileContent({
|
|
|
258
253
|
if (isLeadClient && ydoc) {
|
|
259
254
|
const ytext = ydoc.getText("content");
|
|
260
255
|
if (ytext.toString() !== dbContent) {
|
|
261
|
-
// Untracked
|
|
256
|
+
// Untracked write — see U1 note above. The view-appropriate
|
|
262
257
|
// checkpoint recorded above (U21) is what Cmd+Z now falls back to.
|
|
263
258
|
undoManagerRef.current?.clear(true, false);
|
|
264
|
-
ydoc
|
|
265
|
-
ytext.delete(0, ytext.length);
|
|
266
|
-
ytext.insert(0, dbContent);
|
|
267
|
-
}, TAB_ID);
|
|
259
|
+
writeCollabText(ydoc, ytext, dbContent, TAB_ID);
|
|
268
260
|
}
|
|
269
261
|
}
|
|
270
262
|
}
|
|
@@ -3,7 +3,10 @@ import * as Y from "yjs";
|
|
|
3
3
|
|
|
4
4
|
import type { ElementInfo } from "@/components/design/types";
|
|
5
5
|
import { refreshElementInfoFromContent } from "@/pages/design-editor/code-layer-state";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
shouldApplyRemotePreviewContent,
|
|
8
|
+
writeCollabText,
|
|
9
|
+
} from "@/pages/design-editor/collab-sync";
|
|
7
10
|
import {
|
|
8
11
|
LOCAL_EDIT_ORIGIN,
|
|
9
12
|
TAB_ID,
|
|
@@ -120,12 +123,9 @@ export function runObserveCollabText({
|
|
|
120
123
|
) {
|
|
121
124
|
setContentRenderRevision((revision) => revision + 1);
|
|
122
125
|
}
|
|
123
|
-
// Untracked
|
|
126
|
+
// Untracked write — see clear() note in the seed effect above.
|
|
124
127
|
undoManagerRef.current?.clear(true, false);
|
|
125
|
-
ydoc
|
|
126
|
-
ytext.delete(0, ytext.length);
|
|
127
|
-
ytext.insert(0, pendingLocalContent);
|
|
128
|
-
}, TAB_ID);
|
|
128
|
+
writeCollabText(ydoc, ytext, pendingLocalContent, TAB_ID);
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
131
|
setCollabContent(next);
|
package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface PublishAgentSelectionContextArgs {
|
|
|
20
20
|
activeCodeFile: CodeWorkbenchActiveFile | null;
|
|
21
21
|
activeFile: DesignFile;
|
|
22
22
|
activeInspectorTab: InspectorTab;
|
|
23
|
-
activeLeftPanel: DesignLeftPanel;
|
|
23
|
+
activeLeftPanel: DesignLeftPanel | null;
|
|
24
24
|
activeTool: DesignTool;
|
|
25
25
|
design: DesignData | null;
|
|
26
26
|
designDataJson: Record<string, unknown>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Dispatch, RefObject, SetStateAction } from "react";
|
|
2
2
|
import * as Y from "yjs";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
shouldRebaseCollabDocFromStoredContent,
|
|
6
|
+
writeCollabText,
|
|
7
|
+
} from "@/pages/design-editor/collab-sync";
|
|
5
8
|
import { TAB_ID } from "@/pages/design-editor/editor-session";
|
|
6
9
|
import type { PreviewContentReplaceResult } from "@/pages/design-editor/editor-state";
|
|
7
10
|
import { previewContentReplaceNeedsRenderFallback } from "@/pages/design-editor/editor-state";
|
|
@@ -69,16 +72,13 @@ export function runSeedCollabContent({
|
|
|
69
72
|
) {
|
|
70
73
|
setContentRenderRevision((revision) => revision + 1);
|
|
71
74
|
}
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
75
|
+
// Untracked origin: the UndoManager only tracks LOCAL_EDIT_ORIGIN, so
|
|
76
|
+
// this write is invisible to it. Clear the undo stack so a subsequent
|
|
77
|
+
// Cmd+Z can't replay a tracked delta from before it against content it
|
|
78
|
+
// no longer matches (see the DE:5135-style mitigation below for the
|
|
79
|
+
// same hazard).
|
|
77
80
|
undoManagerRef.current?.clear(true, false);
|
|
78
|
-
ydoc
|
|
79
|
-
ytext.delete(0, ytext.length);
|
|
80
|
-
ytext.insert(0, pendingLocalContent);
|
|
81
|
-
}, TAB_ID);
|
|
81
|
+
writeCollabText(ydoc, ytext, pendingLocalContent, TAB_ID);
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
if (text.length > 0) {
|
|
@@ -115,12 +115,9 @@ export function runSeedCollabContent({
|
|
|
115
115
|
) {
|
|
116
116
|
setContentRenderRevision((revision) => revision + 1);
|
|
117
117
|
}
|
|
118
|
-
// Untracked
|
|
118
|
+
// Untracked write — see clear() note above.
|
|
119
119
|
undoManagerRef.current?.clear(true, false);
|
|
120
|
-
ydoc
|
|
121
|
-
ytext.delete(0, ytext.length);
|
|
122
|
-
ytext.insert(0, storedContent);
|
|
123
|
-
}, TAB_ID);
|
|
120
|
+
writeCollabText(ydoc, ytext, storedContent, TAB_ID);
|
|
124
121
|
return;
|
|
125
122
|
}
|
|
126
123
|
// Y.Doc snapshots are a render seed, not the SQL source of truth; the
|
|
@@ -401,15 +401,8 @@ export function shouldEscapeToOverview(args: {
|
|
|
401
401
|
* node already carries `tag`/`layerNameSource` without needing a separate
|
|
402
402
|
* lookup map.
|
|
403
403
|
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
* in DesignEditor.tsx) must treat a parent that resolves to a document-shell
|
|
407
|
-
* node as NO parent at all — otherwise popping from a top-level layer selects
|
|
408
|
-
* the raw `<body>`/`<html>` DOM nodes instead of stopping at the screen/frame
|
|
409
|
-
* level (or fully deselecting), which produces a permanently broken 0x0
|
|
410
|
-
* inspector with no way back to a deselected state.
|
|
411
|
-
*
|
|
412
|
-
* Exported for unit testing.
|
|
404
|
+
* Select-parent must treat a document-shell parent as NO parent, or walking up
|
|
405
|
+
* from a top-level layer selects raw `<body>` and strands the inspector at 0x0.
|
|
413
406
|
*/
|
|
414
407
|
export function isDocumentShellCodeLayerNode(node: {
|
|
415
408
|
tag: string;
|
|
@@ -422,14 +415,9 @@ export function isDocumentShellCodeLayerNode(node: {
|
|
|
422
415
|
}
|
|
423
416
|
|
|
424
417
|
/**
|
|
425
|
-
*
|
|
426
|
-
* `
|
|
427
|
-
*
|
|
428
|
-
* this instead of a bare `Boolean(parentNode)` truthiness check, or a
|
|
429
|
-
* top-level layer's collapsed `<body>`/`<html>` ancestor gets treated as a
|
|
430
|
-
* selectable parent layer.
|
|
431
|
-
*
|
|
432
|
-
* Exported for unit testing.
|
|
418
|
+
* Callers walking the flat code-layer ownership map must use this instead of a
|
|
419
|
+
* bare `Boolean(parentNode)` check, or a top-level layer's collapsed
|
|
420
|
+
* `<body>`/`<html>` ancestor gets treated as a selectable parent layer.
|
|
433
421
|
*/
|
|
434
422
|
export function hasSelectableCodeLayerParent(args: {
|
|
435
423
|
parentNode: { tag: string; layerNameSource: string } | null | undefined;
|
|
@@ -439,48 +427,6 @@ export function hasSelectableCodeLayerParent(args: {
|
|
|
439
427
|
);
|
|
440
428
|
}
|
|
441
429
|
|
|
442
|
-
export type EscapePopSelectionAction =
|
|
443
|
-
| { kind: "pop-to-parent-layer" }
|
|
444
|
-
| { kind: "pop-to-screen-frame" }
|
|
445
|
-
| { kind: "deselect" };
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Figma parity — Escape on a plain canvas selection pops one level at a
|
|
449
|
-
* time (child layer -> parent layer -> containing screen/frame -> fully
|
|
450
|
-
* deselected) instead of deselecting everything on the first press.
|
|
451
|
-
*
|
|
452
|
-
* - A selected layer that has a code-layer parent (`hasLayerParent`) pops to
|
|
453
|
-
* that parent, reusing the same ancestor-walk `handleSelectParentLayer`
|
|
454
|
-
* (Shift+Enter / "\\") already uses via `codeLayerOwnerByNodeIdRef`.
|
|
455
|
-
* - A selected TOP-level layer (no code-layer parent) in overview mode pops
|
|
456
|
-
* to selecting its containing screen/frame — the same selection kind
|
|
457
|
-
* (`overviewSelectedScreenIds`) clicking a frame directly in overview
|
|
458
|
-
* already produces.
|
|
459
|
-
* - Anything else — nothing selected, or a top-level layer in single-screen
|
|
460
|
-
* mode where there's no separate "frame" to pop to (the screen already
|
|
461
|
-
* fills the view, so top-level already reads as "the frame boundary") —
|
|
462
|
-
* falls straight through to a full deselect, matching the previous
|
|
463
|
-
* unconditional Escape behavior.
|
|
464
|
-
*
|
|
465
|
-
* Callers must have already handled every higher-priority Escape consumer
|
|
466
|
-
* (an in-progress marquee/drag, an active breakpoint edit target,
|
|
467
|
-
* `shouldEscapeToOverview`'s zoom-out-to-overview case) before calling this
|
|
468
|
-
* — it only decides the remaining plain-canvas-selection case.
|
|
469
|
-
*
|
|
470
|
-
* Exported for unit testing.
|
|
471
|
-
*/
|
|
472
|
-
export function resolveEscapePopSelectionAction(args: {
|
|
473
|
-
hasSelectedLayer: boolean;
|
|
474
|
-
hasLayerParent: boolean;
|
|
475
|
-
viewMode: "single" | "overview";
|
|
476
|
-
}): EscapePopSelectionAction {
|
|
477
|
-
if (args.hasSelectedLayer) {
|
|
478
|
-
if (args.hasLayerParent) return { kind: "pop-to-parent-layer" };
|
|
479
|
-
if (args.viewMode === "overview") return { kind: "pop-to-screen-frame" };
|
|
480
|
-
}
|
|
481
|
-
return { kind: "deselect" };
|
|
482
|
-
}
|
|
483
|
-
|
|
484
430
|
/**
|
|
485
431
|
* B5-1: an empty-canvas click (a marquee/hit-test that resolved to zero
|
|
486
432
|
* elements) must deselect ANY current selection kind — a selected
|