@agent-native/core 0.141.7 → 0.144.1
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 +9 -0
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +19 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/analytics/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/analytics/AGENTS.md +35 -38
- package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +1 -1
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +17 -22
- package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +1 -1
- package/corpus/templates/analytics/actions/navigate.ts +4 -5
- package/corpus/templates/analytics/actions/provider-api-register.ts +50 -0
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +44 -11
- package/corpus/templates/analytics/actions/test-custom-api-connection.ts +106 -0
- package/corpus/templates/analytics/app/components/CustomApiCard.tsx +430 -0
- package/corpus/templates/analytics/app/i18n-data.ts +680 -0
- package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +6 -0
- package/corpus/templates/analytics/app/lib/sql-query.ts +33 -6
- package/corpus/templates/analytics/app/pages/DataSources.tsx +4 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-load-reliably-during-background-data-sw.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-remain-responsive-while-historical-data.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-analytics-query-results-now-render-as-a-table-with-csv-downl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-connect-public-https-custom-apis-and-hand-tested-endpoints-t.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-durable-agent-worker-memory.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-live-dashboard-panels-use-the-shared-query-timeout.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-on-demand-billing-is-available-as-a-native-dashboard-with-ta.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-06-visible-dashboard-names-are-unique.md +6 -0
- package/corpus/templates/analytics/netlify.toml +7 -0
- package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +4 -0
- package/corpus/templates/analytics/server/db/index.ts +27 -0
- package/corpus/templates/analytics/server/db/schema.ts +10 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +227 -60
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +156 -45
- package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +227 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
- package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +1 -0
- package/corpus/templates/analytics/server/plugins/db.ts +52 -18
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +28 -2
- package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +16 -1
- package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/assets/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/assets/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/brain/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/brain/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/brain/actions/list-connection-providers.ts +24 -3
- package/corpus/templates/brain/app/lib/dispatch-links.ts +44 -0
- package/corpus/templates/brain/app/routes/sources.tsx +15 -7
- package/corpus/templates/brain/changelog/2026-08-06-brain-provider-setup-links-open-dispatch-correctly-in-standa.md +6 -0
- package/corpus/templates/brain/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +26 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/calendar/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/calendar/AGENTS.md +11 -32
- package/corpus/templates/calendar/actions/update-event.ts +107 -1
- package/corpus/templates/calendar/app/components/calendar/EventCalendarSelect.tsx +83 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +57 -0
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +59 -73
- package/corpus/templates/calendar/app/hooks/use-events.ts +4 -1
- package/corpus/templates/calendar/app/i18n-data.ts +20 -0
- package/corpus/templates/calendar/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-06-existing-events-can-move-between-connected-google-account-ca.md +6 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +101 -0
- package/corpus/templates/calendar/server/plugins/agent-chat.ts +7 -1
- package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/clips/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/clips/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +9 -24
- package/corpus/templates/clips/app/components/editor/timeline-geometry.ts +15 -0
- package/corpus/templates/clips/app/components/editor/waveform.tsx +4 -17
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +14 -3
- package/corpus/templates/clips/app/components/player/player-controls.tsx +0 -3
- package/corpus/templates/clips/app/components/player/scrubber.tsx +2 -33
- package/corpus/templates/clips/app/components/player/video-player.tsx +58 -11
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +28 -38
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -27
- package/corpus/templates/clips/changelog/2026-08-06-clips-recovers-from-stalled-recording-setup-without-requirin.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-clips-starts-faster-after-a-deploy-or-idle-period-startup-no.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-deleting-a-recording-returns-cleanly-to-the-library-and-fit-.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-hide-clip-insights-from-viewers-without-analytics-access.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-06-trimmed-clips-play-on-a-clean-timeline-without-cut-markers.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +48 -20
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +275 -74
- package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +84 -0
- package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +14 -4
- package/corpus/templates/clips/server/plugins/db.ts +214 -26
- package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/content/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/content/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/crm/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/crm/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/crm/changelog/2026-08-06-crm-starts-faster-after-a-deploy-or-idle-period-one-time-dat.md +6 -0
- package/corpus/templates/crm/server/plugins/db.ts +11 -8
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +36 -1
- package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/design/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/design/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/design/actions/import-from-url.ts +1 -1
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +27 -18
- package/corpus/templates/design/app/pages/Index.tsx +6 -2
- package/corpus/templates/design/changelog/2026-08-05-deleting-a-design-from-the-home-page-no-longer-leaves-the-ap.md +6 -0
- package/corpus/templates/design/changelog/2026-08-05-renaming-a-layer-now-focuses-its-name-field-automatically.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/dispatch/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/dispatch/AGENTS.md +8 -1
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -0
- package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +30 -15
- package/corpus/templates/dispatch/app/i18n-data.ts +131 -0
- package/corpus/templates/dispatch/app/routes/admin._index.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.agents.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.approvals.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.apps.$appId.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.apps.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.audit.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.automations.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.destinations.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.dreams.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.identities.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.integrations.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.messaging.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.metrics.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.new-app.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.operations.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.thread-debug.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.transactional-email.$appId.$id.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.transactional-email.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/admin.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.vault.tsx +1 -0
- package/corpus/templates/dispatch/app/routes/admin.workspace.tsx +1 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-dispatch-keeps-everyday-navigation-focused-while-management-.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-ready-workspace-apps-stay-one-click-away-in-a-compact-dispat.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-06-shared-vault-values-and-management-are-now-restricted-to-wor.md +6 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/factory/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/factory/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/forms/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/forms/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/forms/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/macros/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/macros/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/mail/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/mail/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/mail/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/plan/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/plan/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +48 -5
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +37 -1
- package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +6 -0
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +15 -2
- package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +29 -24
- package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/slides/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/slides/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/corpus/templates/slides/AGENTS.md +17 -21
- package/corpus/templates/slides/_gitignore +1 -0
- package/corpus/templates/slides/actions/export-pptx.ts +470 -36
- package/corpus/templates/slides/actions/get-deck.ts +12 -0
- package/corpus/templates/slides/actions/import-file.ts +175 -139
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +271 -12
- package/corpus/templates/slides/actions/import-pptx.ts +193 -68
- package/corpus/templates/slides/actions/patch-deck.ts +51 -0
- package/corpus/templates/slides/actions/update-slide.ts +29 -3
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -13
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +5 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +25 -12
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +112 -57
- package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +202 -0
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +26 -14
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +173 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +182 -141
- package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +18 -0
- package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +85 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -0
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +15 -0
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +27 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +72 -11
- package/corpus/templates/slides/app/lib/deck-preview-frame.ts +15 -0
- package/corpus/templates/slides/app/lib/deck-share-links.ts +9 -0
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +89 -0
- package/corpus/templates/slides/app/lib/import-uploaded-deck.ts +89 -0
- package/corpus/templates/slides/app/lib/slide-animation-elements.ts +3 -0
- package/corpus/templates/slides/app/pages/Index.tsx +172 -15
- package/corpus/templates/slides/changelog/2026-08-06-clicking-the-gray-canvas-around-a-slide-clears-its-selection.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-deck-thumbnails-keep-a-consistent-listing-frame-across-aspec.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-deep-linked-decks-open-directly-instead-of-being-interrupted.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-google-slides-exports-now-show-clear-import-steps-when-direc.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-import-pdf-google-slides-and-powerpoint-decks-directly-from-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-imported-powerpoint-exports-keep-text-and-images-editable-an.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-presentation-prompts-continue-adding-rendered-slides-until-t.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-public-decks-now-share-read-only-presentation-links-by-defau.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-slides-offers-a-direct-connect-google-button-when-a-drive-co.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-slides-preserve-uploaded-pdf-layouts-accept-larger-reference.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-styled-words-stay-part-of-their-text-box-instead-of-becoming.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-06-uploaded-decks-keep-their-slides-and-visuals-when-you-improv.md +6 -0
- package/corpus/templates/slides/server/handlers/google-docs-auth.ts +7 -20
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +247 -13
- package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +67 -0
- package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +2 -0
- package/corpus/templates/slides/server/handlers/uploads.ts +7 -3
- package/corpus/templates/slides/server/lib/chat-attachments.ts +7 -4
- package/corpus/templates/slides/server/lib/emails.ts +7 -2
- package/corpus/templates/slides/server/lib/google-docs-error.ts +50 -0
- package/corpus/templates/slides/server/lib/google-docs-oauth.ts +1 -0
- package/corpus/templates/slides/server/lib/import-asset-storage.ts +127 -0
- package/corpus/templates/slides/server/lib/source-import.ts +167 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +12 -3
- package/corpus/templates/slides/server/routes/api/import-assets/[token].get.ts +70 -0
- package/corpus/templates/slides/shared/upload-types.ts +3 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/corpus/templates/tasks/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/agent/production-agent.d.ts +17 -0
- package/dist/agent/production-agent.js +72 -1
- package/dist/cli/agent-plugin.d.ts +112 -0
- package/dist/cli/agent-plugin.js +1081 -0
- package/dist/cli/app-skill.js +39 -1
- package/dist/cli/code-agent-executor.d.ts +3 -0
- package/dist/cli/code-agent-executor.js +51 -13
- package/dist/cli/index.js +13 -0
- package/dist/cli/templates-meta.js +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.js +9 -2
- package/dist/client/AssistantChat.d.ts +8 -0
- package/dist/client/AssistantChat.js +23 -8
- package/dist/client/NewWorkspaceAppFlow.js +1 -0
- package/dist/client/agent-chat-adapter.js +123 -4
- package/dist/client/assistant-ui-recovery.d.ts +2 -1
- package/dist/client/assistant-ui-recovery.js +7 -3
- package/dist/client/onboarding/FirstRunOnboarding.js +11 -4
- package/dist/client/org/TeamPage.js +1 -1
- package/dist/client/require-session.js +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
- package/dist/client/resources/McpConnectionSuggestion.js +27 -10
- package/dist/client/resources/McpIntegrationDialog.js +77 -45
- package/dist/client/resources/mcp-integration-catalog.d.ts +13 -1
- package/dist/client/resources/mcp-integration-catalog.js +255 -2
- package/dist/client/resources/mcp-integration-logos.js +18 -2
- package/dist/client/settings/AccountSettingsCard.js +2 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts +9 -0
- package/dist/db/client.js +51 -16
- package/dist/db/create-get-db.js +2 -2
- package/dist/db/ddl-guard.d.ts +11 -10
- package/dist/db/ddl-guard.js +40 -12
- package/dist/deploy/build.d.ts +2 -0
- package/dist/deploy/build.js +97 -4
- package/dist/deploy/workspace-deploy.js +0 -2
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/guards/no-env-credentials.js +9 -0
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/pptx.d.ts +68 -0
- package/dist/ingestion/pptx.js +660 -213
- package/dist/integrations/plugin.js +9 -6
- package/dist/jobs/scheduler.js +79 -23
- package/dist/localization/default-messages.d.ts +54 -0
- package/dist/localization/default-messages.js +57 -2
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp-client/oauth-routes.d.ts +2 -0
- package/dist/mcp-client/oauth-routes.js +73 -6
- package/dist/observability/routes.d.ts +5 -5
- package/dist/onboarding/app-profile.js +11 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.js +15 -1
- package/dist/scripts/call-agent.js +34 -4
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -1
- package/dist/server/agent-chat/action-filters-a2a.js +36 -1
- package/dist/server/agent-chat-plugin.js +29 -8
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +47 -11
- package/dist/server/better-auth-instance.js +5 -3
- package/dist/server/core-routes-plugin.d.ts +8 -1
- package/dist/server/core-routes-plugin.js +28 -3
- package/dist/server/credential-provider.d.ts +3 -3
- package/dist/server/credential-provider.js +90 -4
- package/dist/server/onboarding-html.d.ts +2 -0
- package/dist/server/onboarding-html.js +115 -29
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/self-dispatch.d.ts +5 -4
- package/dist/server/self-dispatch.js +25 -14
- package/dist/server/ssr-handler.d.ts +1 -1
- package/dist/server/ssr-handler.js +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/cache-control.d.ts +26 -2
- package/dist/shared/cache-control.js +43 -2
- package/dist/shared/password-policy.d.ts +3 -0
- package/dist/shared/password-policy.js +3 -0
- package/dist/sharing/actions/set-resource-visibility.js +16 -4
- package/dist/sharing/registry.d.ts +14 -0
- package/dist/styles/agent-native.css +6 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/dist/templates/workspace-root/AGENTS.md +7 -0
- package/dist/user-profile/actions/change-password.js +8 -3
- package/dist/user-profile/actions/set-password.js +5 -1
- package/dist/vite/action-types-plugin.js +59 -0
- package/docs/content/creating-templates.mdx +1 -1
- package/docs/content/getting-started-actions.mdx +38 -189
- package/docs/content/getting-started-database.mdx +80 -164
- package/docs/content/getting-started-pages.mdx +44 -155
- package/docs/content/getting-started.mdx +26 -106
- package/docs/content/skills-guide.mdx +13 -0
- package/package.json +6 -2
- package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
- package/src/templates/workspace-root/AGENTS.md +7 -0
|
@@ -26,6 +26,11 @@ import { z } from "zod";
|
|
|
26
26
|
import { normalizeSlidePadding } from "../app/lib/normalize-slide-padding.js";
|
|
27
27
|
import { getDb, schema } from "../server/db/index.js";
|
|
28
28
|
import { notifyClients } from "../server/handlers/decks.js";
|
|
29
|
+
import {
|
|
30
|
+
assertSourceSlidePreserved,
|
|
31
|
+
sourceImportForDeck,
|
|
32
|
+
type SourceImportMetadata,
|
|
33
|
+
} from "../server/lib/source-import.js";
|
|
29
34
|
import { ASPECT_RATIO_VALUES } from "../shared/aspect-ratios.js";
|
|
30
35
|
|
|
31
36
|
// ---------------------------------------------------------------------------
|
|
@@ -79,6 +84,13 @@ const PatchSlideOp = z.object({
|
|
|
79
84
|
op: z.literal("patch-slide"),
|
|
80
85
|
slideId: z.string(),
|
|
81
86
|
fields: SlideFieldsSchema,
|
|
87
|
+
preserveSource: z
|
|
88
|
+
.boolean()
|
|
89
|
+
.optional()
|
|
90
|
+
.default(true)
|
|
91
|
+
.describe(
|
|
92
|
+
"Keep source-imported images and factual copy (default true). Set false only for an explicit rewrite.",
|
|
93
|
+
),
|
|
82
94
|
});
|
|
83
95
|
|
|
84
96
|
/** Delete a single slide by ID */
|
|
@@ -141,6 +153,24 @@ export const OperationSchema = z.discriminatedUnion("op", [
|
|
|
141
153
|
|
|
142
154
|
export type Operation = z.infer<typeof OperationSchema>;
|
|
143
155
|
|
|
156
|
+
export function assertSourceImportOperationsPreserved(
|
|
157
|
+
metadata: SourceImportMetadata | null,
|
|
158
|
+
operations: Operation[],
|
|
159
|
+
): void {
|
|
160
|
+
if (!metadata) return;
|
|
161
|
+
const structuralOperation = operations.find(
|
|
162
|
+
(operation) =>
|
|
163
|
+
operation.op === "delete-slide" ||
|
|
164
|
+
operation.op === "reorder-slides" ||
|
|
165
|
+
operation.op === "add-slide",
|
|
166
|
+
);
|
|
167
|
+
if (!structuralOperation) return;
|
|
168
|
+
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Cannot ${structuralOperation.op} on a source-imported deck while source preservation is enabled. Preserve the imported slide structure, or use an explicit source rewrite workflow.`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
144
174
|
// The browser uses the full operation union above. Agents additionally use
|
|
145
175
|
// this action for one bounded, deck-wide layout repair: one patch-slide per
|
|
146
176
|
// slide in a single SQL transaction, followed by a fresh read for verification.
|
|
@@ -404,6 +434,27 @@ export default defineAction({
|
|
|
404
434
|
);
|
|
405
435
|
}
|
|
406
436
|
|
|
437
|
+
const sourceImport = sourceImportForDeck(deck.sourceImport);
|
|
438
|
+
assertSourceImportOperationsPreserved(sourceImport, operations);
|
|
439
|
+
for (const op of operations) {
|
|
440
|
+
if (
|
|
441
|
+
op.op !== "patch-slide" ||
|
|
442
|
+
(op.fields.content === undefined && op.fields.notes === undefined)
|
|
443
|
+
) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
assertSourceSlidePreserved({
|
|
447
|
+
metadata: sourceImport,
|
|
448
|
+
slideId: op.slideId,
|
|
449
|
+
nextContent:
|
|
450
|
+
op.fields.content === undefined
|
|
451
|
+
? undefined
|
|
452
|
+
: normalizeSlidePadding(op.fields.content),
|
|
453
|
+
nextNotes: op.fields.notes,
|
|
454
|
+
preserveSource: op.preserveSource,
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
|
|
407
458
|
for (const op of operations) {
|
|
408
459
|
applyOperation(deck, op);
|
|
409
460
|
}
|
|
@@ -16,6 +16,10 @@ import { normalizeSlidePadding } from "../app/lib/normalize-slide-padding.js";
|
|
|
16
16
|
import { getDb, schema } from "../server/db/index.js"; // ensure registerShareableResource runs
|
|
17
17
|
import { notifyClients } from "../server/handlers/decks.js";
|
|
18
18
|
import { createDeckVersionSnapshot } from "../server/lib/deck-versions.js";
|
|
19
|
+
import {
|
|
20
|
+
assertSourceSlidePreserved,
|
|
21
|
+
sourceImportForDeck,
|
|
22
|
+
} from "../server/lib/source-import.js";
|
|
19
23
|
import { hashSlideContent } from "../shared/slide-fit.js";
|
|
20
24
|
import { slideLabelFor, touchAgentSlidePresence } from "./_agent-presence.js";
|
|
21
25
|
import {
|
|
@@ -89,7 +93,7 @@ function storedCreativeContext(value: unknown): {
|
|
|
89
93
|
export default defineAction({
|
|
90
94
|
description:
|
|
91
95
|
"Surgically edit a slide's content using search-replace or full replacement. " +
|
|
92
|
-
"Syncs live to open editors. Prefer this over full deck rewrites.",
|
|
96
|
+
"Syncs live to open editors. Prefer this over full deck rewrites. Source-imported slides preserve their original images and factual copy by default.",
|
|
93
97
|
schema: z.object({
|
|
94
98
|
deckId: z.string().describe("Deck ID"),
|
|
95
99
|
slideId: z.string().describe("Slide ID"),
|
|
@@ -105,6 +109,13 @@ export default defineAction({
|
|
|
105
109
|
.string()
|
|
106
110
|
.optional()
|
|
107
111
|
.describe("Full HTML to replace entire slide content"),
|
|
112
|
+
preserveSource: z
|
|
113
|
+
.boolean()
|
|
114
|
+
.optional()
|
|
115
|
+
.default(true)
|
|
116
|
+
.describe(
|
|
117
|
+
"Keep source-imported images and factual copy (default true). Set false only when the user explicitly asks to rewrite the source slide.",
|
|
118
|
+
),
|
|
108
119
|
contextPackId: z
|
|
109
120
|
.string()
|
|
110
121
|
.optional()
|
|
@@ -131,6 +142,7 @@ export default defineAction({
|
|
|
131
142
|
find,
|
|
132
143
|
replace,
|
|
133
144
|
fullContent,
|
|
145
|
+
preserveSource,
|
|
134
146
|
contextPackId,
|
|
135
147
|
contextModeOverride,
|
|
136
148
|
reuseLabels,
|
|
@@ -205,17 +217,31 @@ export default defineAction({
|
|
|
205
217
|
let notFound = false;
|
|
206
218
|
|
|
207
219
|
if (fullContent) {
|
|
208
|
-
|
|
220
|
+
const nextContent = normalizeSlidePadding(fullContent);
|
|
221
|
+
assertSourceSlidePreserved({
|
|
222
|
+
metadata: sourceImportForDeck(deck.sourceImport),
|
|
223
|
+
slideId,
|
|
224
|
+
nextContent,
|
|
225
|
+
preserveSource,
|
|
226
|
+
});
|
|
227
|
+
slide.content = nextContent;
|
|
209
228
|
applied = true;
|
|
210
229
|
} else if (find) {
|
|
211
230
|
const idx = (slide.content as string).indexOf(find);
|
|
212
231
|
if (idx === -1) {
|
|
213
232
|
notFound = true;
|
|
214
233
|
} else {
|
|
215
|
-
|
|
234
|
+
const nextContent =
|
|
216
235
|
slide.content.slice(0, idx) +
|
|
217
236
|
(replace ?? "") +
|
|
218
237
|
slide.content.slice(idx + find.length);
|
|
238
|
+
assertSourceSlidePreserved({
|
|
239
|
+
metadata: sourceImportForDeck(deck.sourceImport),
|
|
240
|
+
slideId,
|
|
241
|
+
nextContent,
|
|
242
|
+
preserveSource,
|
|
243
|
+
});
|
|
244
|
+
slide.content = nextContent;
|
|
219
245
|
applied = true;
|
|
220
246
|
}
|
|
221
247
|
}
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
DropdownMenuSeparator,
|
|
24
24
|
} from "@/components/ui/dropdown-menu";
|
|
25
25
|
import type { Deck } from "@/context/DeckContext";
|
|
26
|
-
import {
|
|
26
|
+
import { getDeckListingPreviewFrameStyle } from "@/lib/deck-preview-frame";
|
|
27
27
|
|
|
28
28
|
import SlideRenderer from "./SlideRenderer";
|
|
29
29
|
|
|
@@ -52,7 +52,7 @@ export default function DeckCard({
|
|
|
52
52
|
}: DeckCardProps) {
|
|
53
53
|
const t = useT();
|
|
54
54
|
const firstSlide = deck.slides?.[0];
|
|
55
|
-
const
|
|
55
|
+
const previewFrameStyle = getDeckListingPreviewFrameStyle(deck.aspectRatio);
|
|
56
56
|
const [isRenaming, setIsRenaming] = useState(false);
|
|
57
57
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
58
58
|
const [renameValue, setRenameValue] = useState(deck.title);
|
|
@@ -106,18 +106,15 @@ export default function DeckCard({
|
|
|
106
106
|
}}
|
|
107
107
|
>
|
|
108
108
|
{/* Slide Preview */}
|
|
109
|
-
<div
|
|
110
|
-
className="relative overflow-hidden bg-muted/30"
|
|
111
|
-
style={{
|
|
112
|
-
aspectRatio: `${previewDims.width} / ${previewDims.height}`,
|
|
113
|
-
}}
|
|
114
|
-
>
|
|
109
|
+
<div className="relative flex aspect-video items-center justify-center overflow-hidden bg-muted/30">
|
|
115
110
|
{firstSlide && (
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
111
|
+
<div className="relative overflow-hidden" style={previewFrameStyle}>
|
|
112
|
+
<SlideRenderer
|
|
113
|
+
slide={firstSlide}
|
|
114
|
+
className="rounded-none"
|
|
115
|
+
aspectRatio={deck.aspectRatio}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
121
118
|
)}
|
|
122
119
|
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-[hsl(240,5%,8%)] via-transparent to-transparent opacity-60" />
|
|
123
120
|
</div>
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
} from "@/components/editor/PromptDialog";
|
|
14
14
|
import { addSlideAgentMessage } from "@/lib/agent-visible-message";
|
|
15
15
|
|
|
16
|
+
import { MAX_REFERENCE_FILE_BYTES } from "../../../shared/upload-types";
|
|
17
|
+
|
|
16
18
|
const MAX_SOURCE_CONTEXT_CHARS = 60_000;
|
|
17
19
|
|
|
18
20
|
function truncateSourceForContext(prompt: string): {
|
|
@@ -46,7 +48,7 @@ function describeUploadedFilesForAgent(
|
|
|
46
48
|
"",
|
|
47
49
|
"File handling rules:",
|
|
48
50
|
`- PPTX files: call \`import-pptx --filePath "<path>" --deckId ${deckId}\` when the user wants the deck/slides imported, or to extract slide source from a presentation.`,
|
|
49
|
-
`- PDF and DOCX files: call \`import-file --filePath "<path>" --format auto --deckId ${deckId}\` and use the returned extracted text as source material.
|
|
51
|
+
`- PDF and DOCX files: call \`import-file --filePath "<path>" --format auto --deckId ${deckId}\` and use the returned extracted text as source material. For a visual PDF whose original layout should be preserved, pass \`--importIntoDeck true\` instead of rebuilding the pages from extracted text.`,
|
|
50
52
|
"- Text-like files: use the uploaded-text-file blocks already included in the prompt; do not call import-file for them.",
|
|
51
53
|
'- Image files with an embeddable URL can be inserted directly into slide HTML as `<img src="...">` or used as visual references.',
|
|
52
54
|
"- Image files without a URL are visual/reference assets only; do not claim to have processed a PPTX/PDF/DOCX unless the relevant import action succeeds.",
|
|
@@ -241,6 +243,8 @@ export function AddSlidePopover({
|
|
|
241
243
|
)}
|
|
242
244
|
<PromptComposer
|
|
243
245
|
autoFocus
|
|
246
|
+
maxDocumentAttachmentBytes={MAX_REFERENCE_FILE_BYTES}
|
|
247
|
+
documentAttachmentLimitLabel="Slides reference files"
|
|
244
248
|
placeholder={t("editorSidebar.promptPlaceholder")}
|
|
245
249
|
draftScope={`slides:add-slide:${deckId}`}
|
|
246
250
|
onSubmit={handleSubmit}
|
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
type AspectRatio,
|
|
68
68
|
DEFAULT_ASPECT_RATIO,
|
|
69
69
|
} from "@/lib/aspect-ratios";
|
|
70
|
+
import { getDeckShareLinkOrder } from "@/lib/deck-share-links";
|
|
70
71
|
import type { GoogleSlidesExportResult } from "@/lib/export-google-slides-client";
|
|
71
72
|
import { parseUploadResponse } from "@/lib/upload-response";
|
|
72
73
|
import { shortcutLabel } from "@/lib/utils";
|
|
@@ -288,10 +289,9 @@ export default function EditorToolbar({
|
|
|
288
289
|
canEdit = true,
|
|
289
290
|
}: EditorToolbarProps) {
|
|
290
291
|
const t = useT();
|
|
291
|
-
//
|
|
292
|
-
//
|
|
293
|
-
//
|
|
294
|
-
// open either link.
|
|
292
|
+
// Public decks default to the read-only presentation URL so recipients do
|
|
293
|
+
// not get sent through the editor's auth gate. Restricted decks keep the
|
|
294
|
+
// editor URL primary, where auth resolves viewer access.
|
|
295
295
|
const editorUrl =
|
|
296
296
|
typeof window === "undefined"
|
|
297
297
|
? `/deck/${deckId}`
|
|
@@ -300,6 +300,21 @@ export default function EditorToolbar({
|
|
|
300
300
|
typeof window === "undefined"
|
|
301
301
|
? `/p/${deckId}`
|
|
302
302
|
: `${window.location.origin}${appPath(`/p/${deckId}`)}`;
|
|
303
|
+
const shareLinks = {
|
|
304
|
+
editor: {
|
|
305
|
+
url: editorUrl,
|
|
306
|
+
label: t("editorToolbar.editorLink"),
|
|
307
|
+
description: t("editorToolbar.editorLinkDescription"),
|
|
308
|
+
},
|
|
309
|
+
presentation: {
|
|
310
|
+
url: presentationUrl,
|
|
311
|
+
label: t("editorToolbar.presentationLink"),
|
|
312
|
+
description: t("editorToolbar.presentationLinkDescription"),
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
const shareLinkOrder = getDeckShareLinkOrder(deck.visibility);
|
|
316
|
+
const primaryShareLink = shareLinks[shareLinkOrder.primary];
|
|
317
|
+
const secondaryShareLink = shareLinks[shareLinkOrder.secondary];
|
|
303
318
|
|
|
304
319
|
// Live save state for the toolbar indicator, so users always see whether
|
|
305
320
|
// their work has committed (a lost-deck report motivated surfacing this).
|
|
@@ -940,14 +955,12 @@ graph TD
|
|
|
940
955
|
resourceType="deck"
|
|
941
956
|
resourceId={deckId}
|
|
942
957
|
resourceTitle={deckTitle}
|
|
943
|
-
shareUrl={
|
|
944
|
-
shareUrlLabel={
|
|
945
|
-
shareUrlDescription={
|
|
946
|
-
secondaryShareUrl={
|
|
947
|
-
secondaryShareUrlLabel={
|
|
948
|
-
secondaryShareUrlDescription={
|
|
949
|
-
"editorToolbar.presentationLinkDescription",
|
|
950
|
-
)}
|
|
958
|
+
shareUrl={primaryShareLink.url}
|
|
959
|
+
shareUrlLabel={primaryShareLink.label}
|
|
960
|
+
shareUrlDescription={primaryShareLink.description}
|
|
961
|
+
secondaryShareUrl={secondaryShareLink.url}
|
|
962
|
+
secondaryShareUrlLabel={secondaryShareLink.label}
|
|
963
|
+
secondaryShareUrlDescription={secondaryShareLink.description}
|
|
951
964
|
shareTabs={{
|
|
952
965
|
tabs: [
|
|
953
966
|
{
|
|
@@ -13,8 +13,18 @@ import {
|
|
|
13
13
|
IconBrandGoogle,
|
|
14
14
|
IconPlugConnected,
|
|
15
15
|
} from "@tabler/icons-react";
|
|
16
|
+
import { useRef, useState } from "react";
|
|
16
17
|
import { toast } from "sonner";
|
|
17
18
|
|
|
19
|
+
import { Button } from "@/components/ui/button";
|
|
20
|
+
import {
|
|
21
|
+
Dialog,
|
|
22
|
+
DialogContent,
|
|
23
|
+
DialogDescription,
|
|
24
|
+
DialogFooter,
|
|
25
|
+
DialogHeader,
|
|
26
|
+
DialogTitle,
|
|
27
|
+
} from "@/components/ui/dialog";
|
|
18
28
|
import {
|
|
19
29
|
DropdownMenu,
|
|
20
30
|
DropdownMenuContent,
|
|
@@ -51,6 +61,8 @@ export function ExportMenu({
|
|
|
51
61
|
onShareTeam,
|
|
52
62
|
}: ExportMenuProps) {
|
|
53
63
|
const t = useT();
|
|
64
|
+
const [googleSlidesImportOpen, setGoogleSlidesImportOpen] = useState(false);
|
|
65
|
+
const googleSlidesImportTarget = useRef<Window | null>(null);
|
|
54
66
|
const triggerBlobDownload = (blob: Blob, filename: string) => {
|
|
55
67
|
const url = URL.createObjectURL(blob);
|
|
56
68
|
const a = document.createElement("a");
|
|
@@ -100,9 +112,11 @@ export function ExportMenu({
|
|
|
100
112
|
// Opened up-front: browsers only honour window.open() inside the click
|
|
101
113
|
// gesture, and building the PPTX is async.
|
|
102
114
|
const target = window.open("", "_blank");
|
|
115
|
+
googleSlidesImportTarget.current = target;
|
|
103
116
|
try {
|
|
104
117
|
const result = await onExportGoogleSlides();
|
|
105
118
|
if (result.url !== null) {
|
|
119
|
+
googleSlidesImportTarget.current = null;
|
|
106
120
|
if (target) target.location.href = result.url;
|
|
107
121
|
toast.success(t("editorExport.googleSlidesCreated"), {
|
|
108
122
|
description: t("editorExport.googleSlidesCreatedHint"),
|
|
@@ -111,10 +125,12 @@ export function ExportMenu({
|
|
|
111
125
|
}
|
|
112
126
|
console.warn("Google Slides upload unavailable:", result.reason);
|
|
113
127
|
if (target) target.location.href = GOOGLE_SLIDES_IMPORT_URL;
|
|
128
|
+
setGoogleSlidesImportOpen(true);
|
|
114
129
|
toast.success(t("editorExport.googleSlidesDownloaded"), {
|
|
115
130
|
description: t("editorExport.googleSlidesImportHint"),
|
|
116
131
|
});
|
|
117
132
|
} catch (err) {
|
|
133
|
+
googleSlidesImportTarget.current = null;
|
|
118
134
|
target?.close();
|
|
119
135
|
console.error("Export failed:", err);
|
|
120
136
|
toast.error(t("editorExport.exportFailed"), {
|
|
@@ -207,66 +223,105 @@ export function ExportMenu({
|
|
|
207
223
|
};
|
|
208
224
|
|
|
209
225
|
return (
|
|
210
|
-
|
|
211
|
-
<
|
|
212
|
-
<
|
|
213
|
-
<
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
<
|
|
224
|
-
|
|
226
|
+
<>
|
|
227
|
+
<DropdownMenu>
|
|
228
|
+
<DropdownMenuTrigger asChild>
|
|
229
|
+
<button className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent text-xs cursor-pointer whitespace-nowrap">
|
|
230
|
+
<IconUpload className="w-3.5 h-3.5" />
|
|
231
|
+
<span className="hidden md:inline">{t("editorExport.export")}</span>
|
|
232
|
+
</button>
|
|
233
|
+
</DropdownMenuTrigger>
|
|
234
|
+
<DropdownMenuContent align="end" className="w-52">
|
|
235
|
+
<DropdownMenuLabel className="text-[11px] text-muted-foreground">
|
|
236
|
+
{t("editorExport.exportAndDuplicate")}
|
|
237
|
+
</DropdownMenuLabel>
|
|
238
|
+
{onShareTeam && (
|
|
239
|
+
<DropdownMenuItem onClick={onShareTeam} className="cursor-pointer">
|
|
240
|
+
<IconShare2 className="w-4 h-4 mr-2" />
|
|
241
|
+
{t("editorExport.shareWithTeam")}
|
|
242
|
+
</DropdownMenuItem>
|
|
243
|
+
)}
|
|
244
|
+
{onShareLink && (
|
|
245
|
+
<DropdownMenuItem onClick={onShareLink} className="cursor-pointer">
|
|
246
|
+
<IconShare2 className="w-4 h-4 mr-2" />
|
|
247
|
+
{t("editorExport.publicShareLink")}
|
|
248
|
+
</DropdownMenuItem>
|
|
249
|
+
)}
|
|
250
|
+
<DropdownMenuSeparator />
|
|
251
|
+
<DropdownMenuItem
|
|
252
|
+
onClick={handleExportHtml}
|
|
253
|
+
className="cursor-pointer"
|
|
254
|
+
>
|
|
255
|
+
<IconCode className="w-4 h-4 mr-2" />
|
|
256
|
+
{t("editorExport.downloadHtml")}
|
|
225
257
|
</DropdownMenuItem>
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
<IconShare2 className="w-4 h-4 mr-2" />
|
|
230
|
-
{t("editorExport.publicShareLink")}
|
|
258
|
+
<DropdownMenuItem onClick={onExportPdf} className="cursor-pointer">
|
|
259
|
+
<IconFileTypePdf className="w-4 h-4 mr-2" />
|
|
260
|
+
{t("editorExport.exportPdf")}
|
|
231
261
|
</DropdownMenuItem>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
262
|
+
<DropdownMenuItem
|
|
263
|
+
onClick={handleExportPptx}
|
|
264
|
+
className="cursor-pointer"
|
|
265
|
+
>
|
|
266
|
+
<IconDownload className="w-4 h-4 mr-2" />
|
|
267
|
+
{t("editorExport.exportPptx")}
|
|
268
|
+
</DropdownMenuItem>
|
|
269
|
+
{onExportGoogleSlides && (
|
|
270
|
+
<>
|
|
271
|
+
<DropdownMenuItem
|
|
272
|
+
onClick={handleConnectGoogle}
|
|
273
|
+
className="cursor-pointer"
|
|
274
|
+
>
|
|
275
|
+
<IconPlugConnected className="w-4 h-4 mr-2" />
|
|
276
|
+
{t("editorExport.connectGoogle")}
|
|
277
|
+
</DropdownMenuItem>
|
|
278
|
+
<DropdownMenuItem
|
|
279
|
+
onClick={handleExportGoogleSlides}
|
|
280
|
+
className="cursor-pointer"
|
|
281
|
+
>
|
|
282
|
+
<IconBrandGoogle className="w-4 h-4 mr-2" />
|
|
283
|
+
{t("editorExport.openInGoogleSlides")}
|
|
284
|
+
</DropdownMenuItem>
|
|
285
|
+
</>
|
|
286
|
+
)}
|
|
287
|
+
<DropdownMenuSeparator />
|
|
288
|
+
<DropdownMenuItem onClick={onDuplicate} className="cursor-pointer">
|
|
289
|
+
<IconCopy className="w-4 h-4 mr-2" />
|
|
290
|
+
{t("editorExport.duplicateDeck")}
|
|
291
|
+
</DropdownMenuItem>
|
|
292
|
+
</DropdownMenuContent>
|
|
293
|
+
</DropdownMenu>
|
|
294
|
+
<Dialog
|
|
295
|
+
open={googleSlidesImportOpen}
|
|
296
|
+
onOpenChange={setGoogleSlidesImportOpen}
|
|
297
|
+
>
|
|
298
|
+
<DialogContent>
|
|
299
|
+
<DialogHeader>
|
|
300
|
+
<DialogTitle>
|
|
301
|
+
{t("editorExport.googleSlidesDownloaded")}
|
|
302
|
+
</DialogTitle>
|
|
303
|
+
<DialogDescription>
|
|
304
|
+
{t("editorExport.googleSlidesImportHint")}
|
|
305
|
+
</DialogDescription>
|
|
306
|
+
</DialogHeader>
|
|
307
|
+
<DialogFooter>
|
|
308
|
+
<Button
|
|
309
|
+
type="button"
|
|
310
|
+
onClick={() => {
|
|
311
|
+
const target = googleSlidesImportTarget.current;
|
|
312
|
+
if (target && !target.closed) {
|
|
313
|
+
target.focus?.();
|
|
314
|
+
} else {
|
|
315
|
+
window.open(GOOGLE_SLIDES_IMPORT_URL, "_blank");
|
|
316
|
+
}
|
|
317
|
+
setGoogleSlidesImportOpen(false);
|
|
318
|
+
}}
|
|
258
319
|
>
|
|
259
|
-
<IconBrandGoogle className="w-4 h-4 mr-2" />
|
|
260
320
|
{t("editorExport.openInGoogleSlides")}
|
|
261
|
-
</
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
<IconCopy className="w-4 h-4 mr-2" />
|
|
267
|
-
{t("editorExport.duplicateDeck")}
|
|
268
|
-
</DropdownMenuItem>
|
|
269
|
-
</DropdownMenuContent>
|
|
270
|
-
</DropdownMenu>
|
|
321
|
+
</Button>
|
|
322
|
+
</DialogFooter>
|
|
323
|
+
</DialogContent>
|
|
324
|
+
</Dialog>
|
|
325
|
+
</>
|
|
271
326
|
);
|
|
272
327
|
}
|