@agent-native/core 0.85.7 → 0.86.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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +133 -1
- package/corpus/core/README.md +0 -11
- package/corpus/core/docs/content/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/ar-SA/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
- package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/de-DE/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/es-ES/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/fr-FR/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/hi-IN/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/ja-JP/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/ko-KR/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/pt-BR/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/zh-CN/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/zh-TW/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/plan-plugin.mdx +12 -11
- package/corpus/core/docs/content/sharing.mdx +1 -2
- package/corpus/core/docs/content/skills-guide.mdx +4 -3
- package/corpus/core/docs/content/template-plan.mdx +37 -6
- package/corpus/core/docs/content/tracking.mdx +1 -1
- package/corpus/core/docs/content/workspace-connections.mdx +1 -1
- package/corpus/core/package.json +7 -6
- package/corpus/core/src/agent/run-store.ts +1 -1
- package/corpus/core/src/chat-threads/store.ts +73 -11
- package/corpus/core/src/checkpoints/store.ts +13 -2
- package/corpus/core/src/cli/create.ts +3 -4
- package/corpus/core/src/cli/design-connect.ts +469 -9
- package/corpus/core/src/cli/index.ts +13 -0
- package/corpus/core/src/cli/plan-local.ts +281 -24
- package/corpus/core/src/cli/skills.ts +177 -21
- package/corpus/core/src/cli/templates-meta.ts +0 -13
- package/corpus/core/src/cli/visualize-repo.ts +715 -0
- package/corpus/core/src/client/AgentPanel.tsx +10 -0
- package/corpus/core/src/client/AssistantChat.tsx +194 -21
- package/corpus/core/src/client/ErrorBoundary.tsx +67 -12
- package/corpus/core/src/client/ErrorReportActions.tsx +69 -0
- package/corpus/core/src/client/FeedbackButton.tsx +8 -4
- package/corpus/core/src/client/agent-chat-adapter.ts +6 -5
- package/corpus/core/src/client/app-providers.tsx +2 -2
- package/corpus/core/src/client/collab/index.ts +31 -0
- package/corpus/core/src/client/components/LiveCursorOverlay.tsx +16 -1
- package/corpus/core/src/client/components/PresenceBar.tsx +14 -1
- package/corpus/core/src/client/components/RecentEditHighlights.tsx +219 -0
- package/corpus/core/src/client/components/RemoteSelectionRings.tsx +40 -6
- package/corpus/core/src/client/db-admin/DbAdminPage.tsx +41 -13
- package/corpus/core/src/client/db-admin/SqlEditor.tsx +10 -3
- package/corpus/core/src/client/db-admin/TableEditor.tsx +12 -5
- package/corpus/core/src/client/db-admin/useAgentSync.ts +10 -3
- package/corpus/core/src/client/db-admin/useDbAdmin.ts +65 -16
- package/corpus/core/src/client/error-reporting.ts +100 -0
- package/corpus/core/src/client/index.ts +59 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +0 -4
- package/corpus/core/src/client/org/RequireActiveOrg.tsx +12 -0
- package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +49 -32
- package/corpus/core/src/client/rich-markdown-editor/index.ts +6 -0
- package/corpus/core/src/client/rich-markdown-editor/surgical-apply.ts +192 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +59 -8
- package/corpus/core/src/client/session-replay.ts +181 -15
- package/corpus/core/src/client/sse-event-processor.ts +90 -1
- package/corpus/core/src/client/use-action.ts +123 -25
- package/corpus/core/src/client/use-agent-engine-configured.ts +7 -1
- package/corpus/core/src/client/use-chat-threads.ts +18 -7
- package/corpus/core/src/client/use-db-sync.ts +104 -19
- package/corpus/core/src/client/visual-style-controls.tsx +1088 -0
- package/corpus/core/src/collab/agent-presence.ts +191 -62
- package/corpus/core/src/collab/awareness.ts +83 -6
- package/corpus/core/src/collab/client.ts +89 -146
- package/corpus/core/src/collab/index.ts +34 -0
- package/corpus/core/src/collab/recent-edits.ts +171 -0
- package/corpus/core/src/collab/undo.ts +432 -0
- package/corpus/core/src/collab/ydoc-manager.ts +68 -0
- package/corpus/core/src/connections/catalog.ts +2 -3
- package/corpus/core/src/db/create-get-db.ts +86 -1
- package/corpus/core/src/db/ensure-additive-columns.ts +430 -0
- package/corpus/core/src/db/index.ts +6 -0
- package/corpus/core/src/db/migrations.ts +236 -35
- package/corpus/core/src/db-admin/index.ts +26 -0
- package/corpus/core/src/db-admin/operations.ts +87 -49
- package/corpus/core/src/jobs/scheduler.ts +17 -14
- package/corpus/core/src/localization/default-messages.ts +4 -0
- package/corpus/core/src/observability/traces.ts +182 -1
- package/corpus/core/src/org/context.ts +79 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +10 -6
- package/corpus/core/src/server/auth-marketing.ts +0 -11
- package/corpus/core/src/server/auth.ts +11 -4
- package/corpus/core/src/server/builder-design-systems.ts +328 -9
- package/corpus/core/src/server/collab-plugin.ts +56 -13
- package/corpus/core/src/server/design-token-utils.ts +1 -1
- package/corpus/core/src/server/fusion-app.ts +447 -0
- package/corpus/core/src/server/index.ts +28 -0
- package/corpus/core/src/server/onboarding-html.ts +3 -4
- package/corpus/core/src/server/poll-events.ts +14 -2
- package/corpus/core/src/server/poll.ts +219 -12
- package/corpus/core/src/server/schema-prompt.ts +28 -9
- package/corpus/core/src/settings/store.ts +33 -2
- package/corpus/core/src/sharing/actions/set-resource-visibility.ts +2 -0
- package/corpus/core/src/sharing/actions/share-resource.ts +3 -0
- package/corpus/core/src/sharing/actions/unshare-resource.ts +2 -0
- package/corpus/core/src/styles/agent-native.css +0 -5
- package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/core/src/templates/default/app/root.tsx +47 -0
- package/corpus/core/src/templates/default/package.json +3 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
- package/corpus/core/src/tracking/providers.ts +22 -1
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +20 -5
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/analytics/AGENTS.md +35 -6
- package/corpus/templates/analytics/actions/delete-db-admin-connection.ts +19 -0
- package/corpus/templates/analytics/actions/list-db-admin-connections.ts +18 -0
- package/corpus/templates/analytics/actions/navigate.ts +28 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/actions/save-db-admin-connection.ts +33 -0
- package/corpus/templates/analytics/actions/view-screen.ts +65 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +23 -1
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +16 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +36 -1
- package/corpus/templates/analytics/app/i18n-data.ts +361 -10
- package/corpus/templates/analytics/app/pages/Agents.tsx +512 -0
- package/corpus/templates/analytics/app/pages/DataSources.tsx +11 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +76 -40
- package/corpus/templates/analytics/app/pages/sessions/session-replay-devtools.ts +5 -0
- package/corpus/templates/analytics/app/routes/agents.tsx +10 -0
- package/corpus/templates/analytics/changelog/2026-07-03-agent-admin-tools-page.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-03-agent-llm-observability-dashboard.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-03-connect-other-app-databases-from-analytics.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-03-session-recordings-now-include-response-bodies-for-5xx-error.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +34 -0
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +6 -0
- package/corpus/templates/analytics/package.json +3 -3
- package/corpus/templates/analytics/seeds/dashboards/agent-observability-llm.json +173 -0
- package/corpus/templates/analytics/server/db/schema.ts +27 -0
- package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +23 -5
- package/corpus/templates/analytics/server/lib/analytics-alerts.ts +58 -13
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +23 -0
- package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +5 -0
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +458 -0
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +120 -8
- package/corpus/templates/analytics/server/lib/session-replay.ts +3 -2
- package/corpus/templates/analytics/server/plugins/db.ts +128 -2
- package/corpus/templates/analytics/server/routes/[base]/_agent-native/analytics-db-admin/[...path].ts +1 -0
- package/corpus/templates/analytics/server/routes/_agent-native/analytics-db-admin/[...path].ts +160 -0
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +45 -1
- package/corpus/templates/analytics/shared/session-replay-diagnostics.ts +10 -0
- package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/assets/package.json +3 -3
- package/corpus/templates/assets/server/plugins/db.ts +63 -2
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/brain/package.json +3 -3
- package/corpus/templates/brain/server/plugins/db.ts +75 -2
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/calendar/package.json +3 -3
- package/corpus/templates/calendar/server/plugins/db.ts +64 -2
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/chat/package.json +3 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +50 -40
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +8 -6
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -3
- package/corpus/templates/clips/changelog/2026-07-03-mobile-recording-pages-keep-videos-in-a-16-9-player-with-act.md +6 -0
- package/corpus/templates/clips/package.json +3 -3
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +56 -0
- package/corpus/templates/clips/server/plugins/db.ts +68 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +27 -3
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/content/actions/edit-document.ts +48 -1
- package/corpus/templates/content/actions/list-documents.ts +101 -94
- package/corpus/templates/content/actions/search-documents.ts +19 -3
- package/corpus/templates/content/actions/update-document.ts +54 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -7
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +97 -2
- package/corpus/templates/content/app/root.tsx +9 -0
- package/corpus/templates/content/changelog/2026-07-03-agent-document-edits-now-appear-as-a-live-collaborator-prese.md +6 -0
- package/corpus/templates/content/changelog/2026-07-03-document-search-and-list-views-load-faster-on-large-workspac.md +6 -0
- package/corpus/templates/content/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
- package/corpus/templates/content/package.json +3 -3
- package/corpus/templates/content/server/plugins/db.ts +57 -1
- package/corpus/templates/design/.agents/skills/full-app-build/SKILL.md +140 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +20 -0
- package/corpus/templates/design/AGENTS.md +63 -19
- package/corpus/templates/design/actions/add-fusion-screens.ts +91 -0
- package/corpus/templates/design/actions/apply-a11y-fix.ts +5 -1
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +10 -2
- package/corpus/templates/design/actions/apply-fusion-edits.ts +161 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +34 -1
- package/corpus/templates/design/actions/create-component.ts +5 -1
- package/corpus/templates/design/actions/create-fusion-app.ts +202 -0
- package/corpus/templates/design/actions/deploy-fusion-app.ts +123 -0
- package/corpus/templates/design/actions/edit-design.ts +13 -16
- package/corpus/templates/design/actions/get-design-system.ts +21 -0
- package/corpus/templates/design/actions/get-fusion-deploy-status.ts +86 -0
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +14 -37
- package/corpus/templates/design/actions/list-fusion-edits.ts +96 -0
- package/corpus/templates/design/actions/list-local-files.ts +133 -0
- package/corpus/templates/design/actions/push-fusion-app.ts +62 -0
- package/corpus/templates/design/actions/queue-fusion-edit.ts +112 -0
- package/corpus/templates/design/actions/read-local-file.ts +139 -0
- package/corpus/templates/design/actions/send-fusion-message.ts +69 -0
- package/corpus/templates/design/actions/sync-fusion-app.ts +196 -0
- package/corpus/templates/design/actions/write-local-file.ts +115 -14
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +12 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +379 -0
- package/corpus/templates/design/app/components/design/EditPanel.tsx +149 -73
- package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +328 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +148 -30
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +1 -1
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +567 -6
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -98
- package/corpus/templates/design/app/components/design/code-workbench/ActivityBar.tsx +85 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +466 -0
- package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +114 -0
- package/corpus/templates/design/app/components/design/code-workbench/commands.ts +339 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/Breadcrumbs.tsx +42 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/BufferSync.tsx +128 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +372 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +268 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/StatusBar.tsx +208 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +61 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme-palette.ts +191 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme.ts +29 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/status-bar-lang.ts +21 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/tab-drag.ts +27 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +161 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +555 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/file-icons.tsx +115 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +65 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/prettier-format.ts +182 -0
- package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +133 -0
- package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +563 -0
- package/corpus/templates/design/app/components/design/code-workbench/quickinput/fuzzy.ts +170 -0
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +508 -0
- package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +280 -0
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +782 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +39 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/inline-provider.ts +196 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +177 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/tree.ts +110 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +103 -0
- package/corpus/templates/design/app/components/design/code-workbench-theme.ts +68 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +127 -10
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +52 -29
- package/corpus/templates/design/app/components/design/inspector/index.ts +9 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +56 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +80 -1
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +6 -16
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +6 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +17 -15
- package/corpus/templates/design/app/i18n-data.ts +185 -160
- package/corpus/templates/design/app/pages/DesignEditor.tsx +1474 -175
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +32 -14
- package/corpus/templates/design/app/pages/Index.tsx +90 -17
- package/corpus/templates/design/changelog/2026-07-03-design-system-setup-now-indexes-figma-code-and-design-md-sou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-the-ai-now-edits-like-a-collaborator-on-canvas-its-cursor-gl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-the-code-editor-is-easier-to-use-with-top-sidebar-tabs-clear.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-the-code-panel-is-now-a-full-vs-code-style-editor-with-a-fil.md +6 -0
- package/corpus/templates/design/package.json +4 -3
- package/corpus/templates/design/server/db/schema.ts +31 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +16 -106
- package/corpus/templates/design/server/lib/fusion-screens.ts +246 -0
- package/corpus/templates/design/server/plugins/db.ts +89 -2
- package/corpus/templates/design/shared/collab-selection.ts +52 -0
- package/corpus/templates/design/shared/full-app.ts +126 -0
- package/corpus/templates/design/shared/pen-path.ts +296 -0
- package/corpus/templates/dispatch/package.json +3 -3
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/forms/package.json +3 -3
- package/corpus/templates/forms/server/plugins/db.ts +62 -2
- package/corpus/templates/macros/package.json +3 -3
- package/corpus/templates/macros/server/plugins/db.ts +63 -2
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/mail/app/root.tsx +60 -1
- package/corpus/templates/mail/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
- package/corpus/templates/mail/package.json +3 -3
- package/corpus/templates/mail/server/lib/contact-frequency.ts +42 -15
- package/corpus/templates/mail/server/plugins/db.ts +63 -2
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +9 -3
- package/corpus/templates/plan/.agents/skills/visualize-repo/SKILL.md +92 -0
- package/corpus/templates/plan/actions/export-visual-plan.ts +5 -0
- package/corpus/templates/plan/actions/get-local-plan-folder.ts +4 -22
- package/corpus/templates/plan/actions/get-plan-version.ts +6 -16
- package/corpus/templates/plan/actions/list-plan-versions.ts +48 -20
- package/corpus/templates/plan/actions/patch-visual-plan-source.ts +41 -1
- package/corpus/templates/plan/actions/promote-local-plan-folder.ts +4 -22
- package/corpus/templates/plan/actions/update-local-plan-comments.ts +4 -2
- package/corpus/templates/plan/actions/update-local-plan-folder.ts +4 -22
- package/corpus/templates/plan/actions/update-visual-plan.ts +60 -1
- package/corpus/templates/plan/agent-native.app-skill.json +10 -0
- package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +138 -39
- package/corpus/templates/plan/app/components/editor/usePlanUndoStack.ts +165 -23
- package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +80 -4
- package/corpus/templates/plan/app/global.css +11 -9
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +10 -1
- package/corpus/templates/plan/app/hooks/use-plan-presence.ts +66 -0
- package/corpus/templates/plan/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/plan/app/i18n/de-DE.ts +4 -0
- package/corpus/templates/plan/app/i18n/en-US.ts +4 -0
- package/corpus/templates/plan/app/i18n/es-ES.ts +4 -0
- package/corpus/templates/plan/app/i18n/fr-FR.ts +4 -0
- package/corpus/templates/plan/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/plan/app/i18n/ja-JP.ts +4 -0
- package/corpus/templates/plan/app/i18n/ko-KR.ts +4 -0
- package/corpus/templates/plan/app/i18n/pt-BR.ts +4 -0
- package/corpus/templates/plan/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/plan/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +289 -66
- package/corpus/templates/plan/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-local-visual-plans-and-recaps-can-save-comments-without-sign.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-plan-tabs-render-nested-text-instead-of-raw-json.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-plans-are-now-fully-real-time-collaborative-multiple-people-.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-plans-open-and-refresh-faster-especially-long-lived-plans-wi.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-undo-now-survives-agent-edits-cmd-z-keeps-working-on-your-ow.md +6 -0
- package/corpus/templates/plan/package.json +5 -3
- package/corpus/templates/plan/server/db/schema.ts +12 -0
- package/corpus/templates/plan/server/lib/local-plan-kind.ts +25 -0
- package/corpus/templates/plan/server/lib/plan-versions.ts +83 -1
- package/corpus/templates/plan/server/lib/public-action-paths.ts +0 -2
- package/corpus/templates/plan/server/plans.ts +26 -3
- package/corpus/templates/plan/server/plugins/db.ts +105 -2
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +8 -4
- package/corpus/templates/slides/AGENTS.md +11 -3
- package/corpus/templates/slides/actions/_agent-presence.ts +48 -0
- package/corpus/templates/slides/actions/add-slide.ts +16 -18
- package/corpus/templates/slides/actions/get-design-system.ts +21 -0
- package/corpus/templates/slides/actions/import-file.ts +15 -7
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +14 -37
- package/corpus/templates/slides/actions/patch-deck.ts +4 -2
- package/corpus/templates/slides/actions/update-slide.ts +114 -77
- package/corpus/templates/slides/actions/view-screen.ts +39 -0
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +32 -8
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +47 -3
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +34 -39
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +507 -72
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +346 -0
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +56 -6
- package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +46 -96
- package/corpus/templates/slides/app/components/layout/Layout.tsx +6 -1
- package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +8 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +589 -176
- package/corpus/templates/slides/app/hooks/use-deck-presence.ts +84 -42
- package/corpus/templates/slides/app/i18n/ar-SA.ts +54 -7
- package/corpus/templates/slides/app/i18n/de-DE.ts +53 -8
- package/corpus/templates/slides/app/i18n/en-US.ts +54 -7
- package/corpus/templates/slides/app/i18n/es-ES.ts +53 -8
- package/corpus/templates/slides/app/i18n/fr-FR.ts +53 -8
- package/corpus/templates/slides/app/i18n/hi-IN.ts +54 -7
- package/corpus/templates/slides/app/i18n/ja-JP.ts +53 -8
- package/corpus/templates/slides/app/i18n/ko-KR.ts +53 -7
- package/corpus/templates/slides/app/i18n/pt-BR.ts +53 -8
- package/corpus/templates/slides/app/i18n/zh-CN.ts +54 -7
- package/corpus/templates/slides/app/i18n/zh-TW.ts +54 -7
- package/corpus/templates/slides/app/lib/canvas-zoom.ts +16 -1
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +28 -16
- package/corpus/templates/slides/changelog/2026-07-03-design-system-setup-now-indexes-figma-code-and-design-md-sou.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-figma-style-slide-editing.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-see-the-ai-working-with-you-when-the-agent-edits-a-slide-it-.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-slide-editing-now-keeps-thumbnails-speaker-notes-styling-and.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-undo-redo-is-now-precise-and-safe-with-collaborators-it-only.md +6 -0
- package/corpus/templates/slides/package.json +3 -3
- package/corpus/templates/slides/server/handlers/decks.ts +31 -3
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +16 -104
- package/corpus/templates/slides/server/plugins/db.ts +65 -2
- package/corpus/templates/videos/netlify.toml +1 -12
- package/dist/agent/run-store.js +1 -1
- package/dist/agent/run-store.js.map +1 -1
- package/dist/chat-threads/store.d.ts +9 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +63 -11
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/store.d.ts.map +1 -1
- package/dist/checkpoints/store.js +10 -2
- package/dist/checkpoints/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +3 -5
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts +49 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +414 -9
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +12 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-local.d.ts +24 -0
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +188 -20
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +173 -21
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +0 -14
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/visualize-repo.d.ts +49 -0
- package/dist/cli/visualize-repo.d.ts.map +1 -0
- package/dist/cli/visualize-repo.js +561 -0
- package/dist/cli/visualize-repo.js.map +1 -0
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +175 -18
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +37 -2
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/ErrorReportActions.d.ts +13 -0
- package/dist/client/ErrorReportActions.d.ts.map +1 -0
- package/dist/client/ErrorReportActions.js +14 -0
- package/dist/client/ErrorReportActions.js.map +1 -0
- package/dist/client/FeedbackButton.d.ts +3 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +6 -5
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +6 -5
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/app-providers.d.ts +2 -2
- package/dist/client/app-providers.js.map +1 -1
- package/dist/client/collab/index.d.ts +4 -1
- package/dist/client/collab/index.d.ts.map +1 -1
- package/dist/client/collab/index.js +3 -0
- package/dist/client/collab/index.js.map +1 -1
- package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
- package/dist/client/components/LiveCursorOverlay.js +11 -3
- package/dist/client/components/LiveCursorOverlay.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts.map +1 -1
- package/dist/client/components/PresenceBar.js +6 -1
- package/dist/client/components/PresenceBar.js.map +1 -1
- package/dist/client/components/RecentEditHighlights.d.ts +43 -0
- package/dist/client/components/RecentEditHighlights.d.ts.map +1 -0
- package/dist/client/components/RecentEditHighlights.js +146 -0
- package/dist/client/components/RecentEditHighlights.js.map +1 -0
- package/dist/client/components/RemoteSelectionRings.d.ts +9 -0
- package/dist/client/components/RemoteSelectionRings.d.ts.map +1 -1
- package/dist/client/components/RemoteSelectionRings.js +22 -8
- package/dist/client/components/RemoteSelectionRings.js.map +1 -1
- package/dist/client/db-admin/DbAdminPage.d.ts +9 -1
- package/dist/client/db-admin/DbAdminPage.d.ts.map +1 -1
- package/dist/client/db-admin/DbAdminPage.js +17 -13
- package/dist/client/db-admin/DbAdminPage.js.map +1 -1
- package/dist/client/db-admin/SqlEditor.d.ts +3 -1
- package/dist/client/db-admin/SqlEditor.d.ts.map +1 -1
- package/dist/client/db-admin/SqlEditor.js +3 -3
- package/dist/client/db-admin/SqlEditor.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts +3 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +6 -6
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/client/db-admin/useAgentSync.d.ts +3 -2
- package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
- package/dist/client/db-admin/useAgentSync.js +8 -4
- package/dist/client/db-admin/useAgentSync.js.map +1 -1
- package/dist/client/db-admin/useDbAdmin.d.ts +11 -7
- package/dist/client/db-admin/useDbAdmin.d.ts.map +1 -1
- package/dist/client/db-admin/useDbAdmin.js +45 -20
- package/dist/client/db-admin/useDbAdmin.js.map +1 -1
- package/dist/client/error-reporting.d.ts +19 -0
- package/dist/client/error-reporting.d.ts.map +1 -0
- package/dist/client/error-reporting.js +71 -0
- package/dist/client/error-reporting.js.map +1 -0
- package/dist/client/index.d.ts +8 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +9 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +1 -3
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
- package/dist/client/org/RequireActiveOrg.js +2 -1
- package/dist/client/org/RequireActiveOrg.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +8 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +8 -2
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/index.d.ts +1 -0
- package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/index.js +1 -0
- package/dist/client/rich-markdown-editor/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/surgical-apply.d.ts +66 -0
- package/dist/client/rich-markdown-editor/surgical-apply.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/surgical-apply.js +147 -0
- package/dist/client/rich-markdown-editor/surgical-apply.js.map +1 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +18 -2
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +39 -8
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/client/session-replay.d.ts +10 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +134 -7
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +81 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-action.d.ts +24 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +109 -27
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +7 -1
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +11 -3
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +36 -0
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +68 -12
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/visual-style-controls.d.ts +90 -0
- package/dist/client/visual-style-controls.d.ts.map +1 -0
- package/dist/client/visual-style-controls.js +499 -0
- package/dist/client/visual-style-controls.js.map +1 -0
- package/dist/collab/agent-presence.d.ts +51 -5
- package/dist/collab/agent-presence.d.ts.map +1 -1
- package/dist/collab/agent-presence.js +144 -58
- package/dist/collab/agent-presence.js.map +1 -1
- package/dist/collab/awareness-store.d.ts +32 -0
- package/dist/collab/awareness-store.d.ts.map +1 -0
- package/dist/collab/awareness-store.js +0 -0
- package/dist/collab/awareness-store.js.map +1 -0
- package/dist/collab/awareness.d.ts +12 -1
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/awareness.js +53 -5
- package/dist/collab/awareness.js.map +1 -1
- package/dist/collab/client.d.ts +2 -0
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +79 -119
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +3 -1
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +5 -1
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +87 -0
- package/dist/collab/recent-edits.d.ts.map +1 -0
- package/dist/collab/recent-edits.js +116 -0
- package/dist/collab/recent-edits.js.map +1 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/undo.d.ts +121 -0
- package/dist/collab/undo.d.ts.map +1 -0
- package/dist/collab/undo.js +244 -0
- package/dist/collab/undo.js.map +1 -0
- package/dist/collab/ydoc-manager.d.ts +10 -0
- package/dist/collab/ydoc-manager.d.ts.map +1 -1
- package/dist/collab/ydoc-manager.js +57 -0
- package/dist/collab/ydoc-manager.js.map +1 -1
- package/dist/connections/catalog.d.ts +2 -2
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +1 -1
- package/dist/connections/catalog.js.map +1 -1
- package/dist/db/create-get-db.d.ts +22 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +73 -1
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/ensure-additive-columns.d.ts +93 -0
- package/dist/db/ensure-additive-columns.d.ts.map +1 -0
- package/dist/db/ensure-additive-columns.js +355 -0
- package/dist/db/ensure-additive-columns.js.map +1 -0
- package/dist/db/index.d.ts +1 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +70 -0
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +196 -33
- package/dist/db/migrations.js.map +1 -1
- package/dist/db-admin/index.d.ts +3 -0
- package/dist/db-admin/index.d.ts.map +1 -0
- package/dist/db-admin/index.js +2 -0
- package/dist/db-admin/index.js.map +1 -0
- package/dist/db-admin/operations.d.ts +26 -5
- package/dist/db-admin/operations.d.ts.map +1 -1
- package/dist/db-admin/operations.js +66 -55
- package/dist/db-admin/operations.js.map +1 -1
- package/dist/jobs/scheduler.js +17 -10
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +3 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +2 -2
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +155 -1
- package/dist/observability/traces.js.map +1 -1
- package/dist/org/context.d.ts +7 -0
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +54 -2
- package/dist/org/context.js.map +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +10 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth-marketing.d.ts.map +1 -1
- package/dist/server/auth-marketing.js +0 -10
- package/dist/server/auth-marketing.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +6 -4
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-design-systems.d.ts +61 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +219 -14
- package/dist/server/builder-design-systems.js.map +1 -1
- package/dist/server/collab-plugin.d.ts.map +1 -1
- package/dist/server/collab-plugin.js +45 -13
- package/dist/server/collab-plugin.js.map +1 -1
- package/dist/server/design-token-utils.d.ts +1 -1
- package/dist/server/design-token-utils.js +1 -1
- package/dist/server/design-token-utils.js.map +1 -1
- package/dist/server/fusion-app.d.ts +107 -0
- package/dist/server/fusion-app.d.ts.map +1 -0
- package/dist/server/fusion-app.js +371 -0
- package/dist/server/fusion-app.js.map +1 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +3 -4
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/poll-events.d.ts +2 -0
- package/dist/server/poll-events.d.ts.map +1 -1
- package/dist/server/poll-events.js +7 -2
- package/dist/server/poll-events.js.map +1 -1
- package/dist/server/poll.d.ts +47 -3
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +176 -10
- package/dist/server/poll.js.map +1 -1
- package/dist/server/schema-prompt.d.ts.map +1 -1
- package/dist/server/schema-prompt.js +24 -7
- package/dist/server/schema-prompt.js.map +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +32 -3
- package/dist/settings/store.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +2 -0
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +3 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/actions/unshare-resource.js +2 -0
- package/dist/sharing/actions/unshare-resource.js.map +1 -1
- package/dist/styles/agent-native.css +0 -5
- package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
- package/dist/templates/default/app/root.tsx +47 -0
- package/dist/templates/default/package.json +3 -3
- package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
- package/dist/tracking/providers.d.ts.map +1 -1
- package/dist/tracking/providers.js +17 -1
- package/dist/tracking/providers.js.map +1 -1
- package/docs/content/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
- package/docs/content/locales/ar-SA/sharing.mdx +1 -2
- package/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
- package/docs/content/locales/ar-SA/template-plan.mdx +23 -7
- package/docs/content/locales/ar-SA/tracking.mdx +1 -1
- package/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
- package/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
- package/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
- package/docs/content/locales/de-DE/sharing.mdx +1 -2
- package/docs/content/locales/de-DE/skills-guide.mdx +2 -3
- package/docs/content/locales/de-DE/template-plan.mdx +23 -7
- package/docs/content/locales/de-DE/tracking.mdx +1 -1
- package/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
- package/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
- package/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
- package/docs/content/locales/es-ES/sharing.mdx +1 -2
- package/docs/content/locales/es-ES/skills-guide.mdx +2 -3
- package/docs/content/locales/es-ES/template-plan.mdx +23 -7
- package/docs/content/locales/es-ES/tracking.mdx +1 -1
- package/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
- package/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
- package/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
- package/docs/content/locales/fr-FR/sharing.mdx +1 -2
- package/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
- package/docs/content/locales/fr-FR/template-plan.mdx +23 -7
- package/docs/content/locales/fr-FR/tracking.mdx +1 -1
- package/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
- package/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
- package/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
- package/docs/content/locales/hi-IN/sharing.mdx +1 -2
- package/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
- package/docs/content/locales/hi-IN/template-plan.mdx +23 -7
- package/docs/content/locales/hi-IN/tracking.mdx +1 -1
- package/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
- package/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
- package/docs/content/locales/ja-JP/sharing.mdx +1 -2
- package/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
- package/docs/content/locales/ja-JP/template-plan.mdx +23 -7
- package/docs/content/locales/ja-JP/tracking.mdx +1 -1
- package/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
- package/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
- package/docs/content/locales/ko-KR/sharing.mdx +1 -2
- package/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
- package/docs/content/locales/ko-KR/template-plan.mdx +23 -7
- package/docs/content/locales/ko-KR/tracking.mdx +1 -1
- package/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
- package/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
- package/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
- package/docs/content/locales/pt-BR/sharing.mdx +1 -2
- package/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
- package/docs/content/locales/pt-BR/template-plan.mdx +23 -7
- package/docs/content/locales/pt-BR/tracking.mdx +1 -1
- package/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
- package/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
- package/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
- package/docs/content/locales/zh-CN/sharing.mdx +1 -2
- package/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
- package/docs/content/locales/zh-CN/template-plan.mdx +23 -7
- package/docs/content/locales/zh-CN/tracking.mdx +1 -1
- package/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
- package/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
- package/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
- package/docs/content/locales/zh-TW/sharing.mdx +1 -2
- package/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
- package/docs/content/locales/zh-TW/template-plan.mdx +23 -7
- package/docs/content/locales/zh-TW/tracking.mdx +1 -1
- package/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
- package/docs/content/plan-plugin.mdx +12 -11
- package/docs/content/sharing.mdx +1 -2
- package/docs/content/skills-guide.mdx +4 -3
- package/docs/content/template-plan.mdx +37 -6
- package/docs/content/tracking.mdx +1 -1
- package/docs/content/workspace-connections.mdx +1 -1
- package/package.json +7 -6
- package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
- package/src/templates/default/app/root.tsx +47 -0
- package/src/templates/default/package.json +3 -3
- package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
- package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
- package/corpus/core/docs/content/locales/ar-SA/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/de-DE/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/es-ES/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/fr-FR/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/hi-IN/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/ja-JP/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/ko-KR/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/pt-BR/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/zh-CN/template-videos.mdx +0 -334
- package/corpus/core/docs/content/locales/zh-TW/template-videos.mdx +0 -334
- package/corpus/core/docs/content/template-videos.mdx +0 -332
- package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +0 -697
- package/corpus/templates/slides/app/components/editor/CodeEditor.tsx +0 -49
- package/corpus/templates/videos/.agents/skills/actions/SKILL.md +0 -432
- package/corpus/templates/videos/.agents/skills/animation-tracks/SKILL.md +0 -99
- package/corpus/templates/videos/.agents/skills/capture-learnings/SKILL.md +0 -76
- package/corpus/templates/videos/.agents/skills/composition-management/SKILL.md +0 -106
- package/corpus/templates/videos/.agents/skills/create-skill/SKILL.md +0 -221
- package/corpus/templates/videos/.agents/skills/delegate-to-agent/SKILL.md +0 -263
- package/corpus/templates/videos/.agents/skills/frontend-design/SKILL.md +0 -112
- package/corpus/templates/videos/.agents/skills/security/SKILL.md +0 -263
- package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +0 -88
- package/corpus/templates/videos/.agents/skills/shadcn-ui/SKILL.md +0 -95
- package/corpus/templates/videos/.builder/ANIMATED_PROPERTIES.md +0 -335
- package/corpus/templates/videos/.builder/KEYFRAME_SYNC.md +0 -166
- package/corpus/templates/videos/.builder/SEAMLESS_SYNC.md +0 -211
- package/corpus/templates/videos/.builder/rules/deploy-app.mdc +0 -22
- package/corpus/templates/videos/.builder/rules/organize-ui.mdc +0 -9
- package/corpus/templates/videos/.builder/skills/remotion/SKILL.md +0 -29
- package/corpus/templates/videos/.builder/skills/remotion/rules/animations.md +0 -27
- package/corpus/templates/videos/.builder/skills/remotion/rules/assets.md +0 -43
- package/corpus/templates/videos/.builder/skills/remotion/rules/audio.md +0 -58
- package/corpus/templates/videos/.builder/skills/remotion/rules/compositions.md +0 -129
- package/corpus/templates/videos/.builder/skills/remotion/rules/fonts.md +0 -47
- package/corpus/templates/videos/.builder/skills/remotion/rules/images.md +0 -41
- package/corpus/templates/videos/.builder/skills/remotion/rules/parameters.md +0 -59
- package/corpus/templates/videos/.builder/skills/remotion/rules/sequencing.md +0 -54
- package/corpus/templates/videos/.builder/skills/remotion/rules/tailwind.md +0 -11
- package/corpus/templates/videos/.builder/skills/remotion/rules/text-animations.md +0 -18
- package/corpus/templates/videos/.builder/skills/remotion/rules/timing.md +0 -103
- package/corpus/templates/videos/.builder/skills/remotion/rules/transparent-videos.md +0 -35
- package/corpus/templates/videos/.builder/skills/remotion/rules/trimming.md +0 -38
- package/corpus/templates/videos/.builder/skills/remotion/rules/videos.md +0 -54
- package/corpus/templates/videos/.dockerignore +0 -62
- package/corpus/templates/videos/.env.example +0 -4
- package/corpus/templates/videos/.oxfmtrc.json +0 -8
- package/corpus/templates/videos/AGENTS.md +0 -46
- package/corpus/templates/videos/CHANGELOG.md +0 -10
- package/corpus/templates/videos/DEVELOPING.md +0 -143
- package/corpus/templates/videos/README.md +0 -33
- package/corpus/templates/videos/actions/analyze-brand-assets.ts +0 -151
- package/corpus/templates/videos/actions/apply-design-system.ts +0 -35
- package/corpus/templates/videos/actions/create-design-system.ts +0 -84
- package/corpus/templates/videos/actions/create-folder.ts +0 -48
- package/corpus/templates/videos/actions/db-connect.ts +0 -45
- package/corpus/templates/videos/actions/db-health.ts +0 -24
- package/corpus/templates/videos/actions/db-status.ts +0 -28
- package/corpus/templates/videos/actions/delete-composition.ts +0 -272
- package/corpus/templates/videos/actions/delete-folder.ts +0 -27
- package/corpus/templates/videos/actions/generate-animated-component.ts +0 -470
- package/corpus/templates/videos/actions/get-composition.ts +0 -36
- package/corpus/templates/videos/actions/get-design-system.ts +0 -35
- package/corpus/templates/videos/actions/import-code.ts +0 -67
- package/corpus/templates/videos/actions/import-design-project.ts +0 -42
- package/corpus/templates/videos/actions/import-document.ts +0 -125
- package/corpus/templates/videos/actions/import-from-url.ts +0 -18
- package/corpus/templates/videos/actions/import-github.ts +0 -182
- package/corpus/templates/videos/actions/list-compositions.ts +0 -32
- package/corpus/templates/videos/actions/list-design-systems.ts +0 -66
- package/corpus/templates/videos/actions/list-folders.ts +0 -61
- package/corpus/templates/videos/actions/move-composition-to-folder.ts +0 -59
- package/corpus/templates/videos/actions/navigate.ts +0 -40
- package/corpus/templates/videos/actions/rename-folder.ts +0 -41
- package/corpus/templates/videos/actions/run.ts +0 -2
- package/corpus/templates/videos/actions/save-composition.ts +0 -114
- package/corpus/templates/videos/actions/set-default-design-system.ts +0 -40
- package/corpus/templates/videos/actions/update-composition.ts +0 -81
- package/corpus/templates/videos/actions/update-design-system.ts +0 -68
- package/corpus/templates/videos/actions/validate-compositions.ts +0 -502
- package/corpus/templates/videos/actions/view-screen.ts +0 -48
- package/corpus/templates/videos/app/components/CameraControls.tsx +0 -442
- package/corpus/templates/videos/app/components/CameraToolbar.tsx +0 -437
- package/corpus/templates/videos/app/components/CloudUpgrade.tsx +0 -287
- package/corpus/templates/videos/app/components/CollabPresenceBar.tsx +0 -81
- package/corpus/templates/videos/app/components/CompSettingsEditor.tsx +0 -107
- package/corpus/templates/videos/app/components/ComponentLibrarySidebar.tsx +0 -457
- package/corpus/templates/videos/app/components/ComponentPropsPanel.tsx +0 -227
- package/corpus/templates/videos/app/components/ComponentsSidebar.tsx +0 -70
- package/corpus/templates/videos/app/components/CompositionCard.tsx +0 -147
- package/corpus/templates/videos/app/components/CurrentElementPanel.tsx +0 -835
- package/corpus/templates/videos/app/components/CursorControls.tsx +0 -664
- package/corpus/templates/videos/app/components/CursorPositioningOverlay.tsx +0 -238
- package/corpus/templates/videos/app/components/LibraryFolderRow.tsx +0 -235
- package/corpus/templates/videos/app/components/MotionCurveSelect.tsx +0 -61
- package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +0 -192
- package/corpus/templates/videos/app/components/PropsEditor.tsx +0 -210
- package/corpus/templates/videos/app/components/QuestionFlow.tsx +0 -40
- package/corpus/templates/videos/app/components/Sidebar.tsx +0 -609
- package/corpus/templates/videos/app/components/StudioHeader.tsx +0 -109
- package/corpus/templates/videos/app/components/Timeline.tsx +0 -2067
- package/corpus/templates/videos/app/components/TrackPropertiesPanel.tsx +0 -922
- package/corpus/templates/videos/app/components/TweaksPanel.tsx +0 -277
- package/corpus/templates/videos/app/components/VideoPlayer.tsx +0 -487
- package/corpus/templates/videos/app/components/design-system/DesignSystemCard.tsx +0 -134
- package/corpus/templates/videos/app/components/design-system/DesignSystemPreview.tsx +0 -176
- package/corpus/templates/videos/app/components/design-system/DesignSystemSetup.tsx +0 -707
- package/corpus/templates/videos/app/components/keyframes/KeyframeActionButtons.tsx +0 -78
- package/corpus/templates/videos/app/components/keyframes/KeyframeNavigation.tsx +0 -59
- package/corpus/templates/videos/app/components/keyframes/PropertyNumberInput.tsx +0 -56
- package/corpus/templates/videos/app/components/layout/Header.tsx +0 -64
- package/corpus/templates/videos/app/components/layout/HeaderActions.tsx +0 -84
- package/corpus/templates/videos/app/components/layout/Layout.tsx +0 -132
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -180
- package/corpus/templates/videos/app/components/ui/accordion.tsx +0 -56
- package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +0 -139
- package/corpus/templates/videos/app/components/ui/alert.tsx +0 -59
- package/corpus/templates/videos/app/components/ui/aspect-ratio.tsx +0 -5
- package/corpus/templates/videos/app/components/ui/avatar.tsx +0 -48
- package/corpus/templates/videos/app/components/ui/badge.tsx +0 -37
- package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +0 -115
- package/corpus/templates/videos/app/components/ui/button.tsx +0 -57
- package/corpus/templates/videos/app/components/ui/calendar.tsx +0 -68
- package/corpus/templates/videos/app/components/ui/card.tsx +0 -86
- package/corpus/templates/videos/app/components/ui/carousel.tsx +0 -260
- package/corpus/templates/videos/app/components/ui/chart.tsx +0 -375
- package/corpus/templates/videos/app/components/ui/checkbox.tsx +0 -28
- package/corpus/templates/videos/app/components/ui/collapsible.tsx +0 -9
- package/corpus/templates/videos/app/components/ui/command.tsx +0 -154
- package/corpus/templates/videos/app/components/ui/context-menu.tsx +0 -202
- package/corpus/templates/videos/app/components/ui/dialog.tsx +0 -130
- package/corpus/templates/videos/app/components/ui/drawer.tsx +0 -116
- package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +0 -212
- package/corpus/templates/videos/app/components/ui/form.tsx +0 -177
- package/corpus/templates/videos/app/components/ui/hover-card.tsx +0 -27
- package/corpus/templates/videos/app/components/ui/input-otp.tsx +0 -69
- package/corpus/templates/videos/app/components/ui/input.tsx +0 -22
- package/corpus/templates/videos/app/components/ui/label.tsx +0 -24
- package/corpus/templates/videos/app/components/ui/menubar.tsx +0 -234
- package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +0 -128
- package/corpus/templates/videos/app/components/ui/pagination.tsx +0 -121
- package/corpus/templates/videos/app/components/ui/popover.tsx +0 -44
- package/corpus/templates/videos/app/components/ui/progress.tsx +0 -26
- package/corpus/templates/videos/app/components/ui/radio-group.tsx +0 -42
- package/corpus/templates/videos/app/components/ui/resizable.tsx +0 -43
- package/corpus/templates/videos/app/components/ui/scroll-area.tsx +0 -46
- package/corpus/templates/videos/app/components/ui/select.tsx +0 -158
- package/corpus/templates/videos/app/components/ui/separator.tsx +0 -29
- package/corpus/templates/videos/app/components/ui/sheet.tsx +0 -160
- package/corpus/templates/videos/app/components/ui/sidebar.tsx +0 -782
- package/corpus/templates/videos/app/components/ui/skeleton.tsx +0 -15
- package/corpus/templates/videos/app/components/ui/slider.tsx +0 -26
- package/corpus/templates/videos/app/components/ui/sonner.tsx +0 -58
- package/corpus/templates/videos/app/components/ui/spinner.tsx +0 -17
- package/corpus/templates/videos/app/components/ui/switch.tsx +0 -27
- package/corpus/templates/videos/app/components/ui/table.tsx +0 -117
- package/corpus/templates/videos/app/components/ui/tabs.tsx +0 -53
- package/corpus/templates/videos/app/components/ui/textarea.tsx +0 -23
- package/corpus/templates/videos/app/components/ui/toast.tsx +0 -127
- package/corpus/templates/videos/app/components/ui/toaster.tsx +0 -33
- package/corpus/templates/videos/app/components/ui/toggle-group.tsx +0 -59
- package/corpus/templates/videos/app/components/ui/toggle.tsx +0 -43
- package/corpus/templates/videos/app/components/ui/tooltip.tsx +0 -30
- package/corpus/templates/videos/app/components/ui/use-toast.ts +0 -3
- package/corpus/templates/videos/app/config/constants.ts +0 -204
- package/corpus/templates/videos/app/contexts/CompositionContext.tsx +0 -437
- package/corpus/templates/videos/app/contexts/CurrentElementContext.tsx +0 -247
- package/corpus/templates/videos/app/contexts/PlaybackContext.tsx +0 -65
- package/corpus/templates/videos/app/contexts/TimelineContext.tsx +0 -433
- package/corpus/templates/videos/app/entry.client.tsx +0 -19
- package/corpus/templates/videos/app/entry.server.tsx +0 -10
- package/corpus/templates/videos/app/global.css +0 -171
- package/corpus/templates/videos/app/hooks/use-composition-collab.ts +0 -269
- package/corpus/templates/videos/app/hooks/use-composition-design-system.ts +0 -47
- package/corpus/templates/videos/app/hooks/use-database-compositions.ts +0 -144
- package/corpus/templates/videos/app/hooks/use-db-status.ts +0 -30
- package/corpus/templates/videos/app/hooks/use-design-systems.ts +0 -21
- package/corpus/templates/videos/app/hooks/use-folders.ts +0 -199
- package/corpus/templates/videos/app/hooks/use-mobile.tsx +0 -21
- package/corpus/templates/videos/app/hooks/use-navigation-state.ts +0 -52
- package/corpus/templates/videos/app/hooks/use-question-flow.ts +0 -14
- package/corpus/templates/videos/app/hooks/use-toast.ts +0 -188
- package/corpus/templates/videos/app/hooks/useUnsavedChanges.ts +0 -48
- package/corpus/templates/videos/app/i18n/ar-SA.ts +0 -446
- package/corpus/templates/videos/app/i18n/de-DE.ts +0 -470
- package/corpus/templates/videos/app/i18n/en-US.ts +0 -452
- package/corpus/templates/videos/app/i18n/es-ES.ts +0 -468
- package/corpus/templates/videos/app/i18n/fr-FR.ts +0 -469
- package/corpus/templates/videos/app/i18n/hi-IN.ts +0 -446
- package/corpus/templates/videos/app/i18n/index.ts +0 -34
- package/corpus/templates/videos/app/i18n/ja-JP.ts +0 -460
- package/corpus/templates/videos/app/i18n/ko-KR.ts +0 -453
- package/corpus/templates/videos/app/i18n/pt-BR.ts +0 -461
- package/corpus/templates/videos/app/i18n/zh-CN.ts +0 -437
- package/corpus/templates/videos/app/i18n/zh-TW.ts +0 -437
- package/corpus/templates/videos/app/lib/database-compositions.ts +0 -67
- package/corpus/templates/videos/app/lib/design-systems.ts +0 -234
- package/corpus/templates/videos/app/lib/tab-id.ts +0 -1
- package/corpus/templates/videos/app/lib/utils.ts +0 -1
- package/corpus/templates/videos/app/pages/ComponentLibrary.tsx +0 -134
- package/corpus/templates/videos/app/pages/ComponentLibraryView.tsx +0 -362
- package/corpus/templates/videos/app/pages/CompositionView.tsx +0 -715
- package/corpus/templates/videos/app/pages/DesignSystems.tsx +0 -180
- package/corpus/templates/videos/app/pages/Index.tsx +0 -258
- package/corpus/templates/videos/app/pages/NewComposition.tsx +0 -95
- package/corpus/templates/videos/app/pages/NotFound.tsx +0 -36
- package/corpus/templates/videos/app/remotion/CameraHost.tsx +0 -223
- package/corpus/templates/videos/app/remotion/animations/useElementAnimations.ts +0 -231
- package/corpus/templates/videos/app/remotion/componentRegistry.ts +0 -473
- package/corpus/templates/videos/app/remotion/components/AnimatedElement.tsx +0 -436
- package/corpus/templates/videos/app/remotion/components/InteractiveElement.tsx +0 -159
- package/corpus/templates/videos/app/remotion/components/InteractiveZoneEditor.tsx +0 -273
- package/corpus/templates/videos/app/remotion/compositions/BlankComposition.tsx +0 -204
- package/corpus/templates/videos/app/remotion/compositions/index.ts +0 -2
- package/corpus/templates/videos/app/remotion/createComponentCursorTrack.ts +0 -132
- package/corpus/templates/videos/app/remotion/docs/CURSOR_TRACKS.md +0 -285
- package/corpus/templates/videos/app/remotion/easingFunctions.ts +0 -255
- package/corpus/templates/videos/app/remotion/hooks/createInteractiveComposition.tsx +0 -283
- package/corpus/templates/videos/app/remotion/hooks/useCursorHistory.ts +0 -72
- package/corpus/templates/videos/app/remotion/hooks/useCursorTypeFromHover.ts +0 -35
- package/corpus/templates/videos/app/remotion/hooks/useEditableZones.tsx +0 -267
- package/corpus/templates/videos/app/remotion/hooks/useHoverAnimation.ts +0 -90
- package/corpus/templates/videos/app/remotion/hooks/useHoverAnimationSmooth.ts +0 -146
- package/corpus/templates/videos/app/remotion/hooks/useInteractiveComponent.ts +0 -711
- package/corpus/templates/videos/app/remotion/hooks/useRegisterInteractiveElement.ts +0 -56
- package/corpus/templates/videos/app/remotion/library-components/Button.tsx +0 -252
- package/corpus/templates/videos/app/remotion/library-components/Card.tsx +0 -241
- package/corpus/templates/videos/app/remotion/library-components/CodePanel.tsx +0 -1005
- package/corpus/templates/videos/app/remotion/library-components/FileItem.tsx +0 -196
- package/corpus/templates/videos/app/remotion/library-components/FolderItem.tsx +0 -199
- package/corpus/templates/videos/app/remotion/library-components/PrimaryButton.tsx +0 -177
- package/corpus/templates/videos/app/remotion/library-components/SecondaryButton.tsx +0 -167
- package/corpus/templates/videos/app/remotion/library-components/SectionHeader.tsx +0 -108
- package/corpus/templates/videos/app/remotion/library-components/TEMPLATE.tsx +0 -211
- package/corpus/templates/videos/app/remotion/library-components/index.ts +0 -10
- package/corpus/templates/videos/app/remotion/registry.ts +0 -91
- package/corpus/templates/videos/app/remotion/testing/animationTestUtils.ts +0 -366
- package/corpus/templates/videos/app/remotion/trackAnimation.ts +0 -179
- package/corpus/templates/videos/app/remotion/trackHelpers.ts +0 -110
- package/corpus/templates/videos/app/remotion/ui-components/Cursor.tsx +0 -182
- package/corpus/templates/videos/app/remotion/ui-components/InteractiveButton.tsx +0 -116
- package/corpus/templates/videos/app/remotion/ui-components/InteractiveCard.tsx +0 -126
- package/corpus/templates/videos/app/remotion/ui-components/index.ts +0 -16
- package/corpus/templates/videos/app/remotion/utils/animationHelpers.ts +0 -444
- package/corpus/templates/videos/app/remotion/utils/interactiveElements.ts +0 -235
- package/corpus/templates/videos/app/remotion/utils/springAnimation.ts +0 -76
- package/corpus/templates/videos/app/root.tsx +0 -165
- package/corpus/templates/videos/app/routes/$.tsx +0 -10
- package/corpus/templates/videos/app/routes/_index.tsx +0 -25
- package/corpus/templates/videos/app/routes/c.$compositionId.tsx +0 -10
- package/corpus/templates/videos/app/routes/components.tsx +0 -10
- package/corpus/templates/videos/app/routes/design-systems.tsx +0 -10
- package/corpus/templates/videos/app/routes/extensions.$id.$slug.tsx +0 -2
- package/corpus/templates/videos/app/routes/extensions.$id.tsx +0 -5
- package/corpus/templates/videos/app/routes/extensions._index.tsx +0 -5
- package/corpus/templates/videos/app/routes/extensions.tsx +0 -5
- package/corpus/templates/videos/app/routes/settings.tsx +0 -88
- package/corpus/templates/videos/app/routes/team.tsx +0 -11
- package/corpus/templates/videos/app/routes.ts +0 -4
- package/corpus/templates/videos/app/state.ts +0 -77
- package/corpus/templates/videos/app/types/elementAnimations.ts +0 -121
- package/corpus/templates/videos/app/types.ts +0 -200
- package/corpus/templates/videos/app/utils/compositionHelpers.ts +0 -445
- package/corpus/templates/videos/app/utils/debug.ts +0 -63
- package/corpus/templates/videos/app/utils/keyframeUtils.ts +0 -331
- package/corpus/templates/videos/app/utils/timelineCoordinates.ts +0 -79
- package/corpus/templates/videos/app/vite-env.d.ts +0 -6
- package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
- package/corpus/templates/videos/components.json +0 -20
- package/corpus/templates/videos/data/sync-config.json +0 -3
- package/corpus/templates/videos/docs/examples/create-composition.example.ts +0 -128
- package/corpus/templates/videos/drizzle.config.ts +0 -3
- package/corpus/templates/videos/learnings.defaults.md +0 -5
- package/corpus/templates/videos/package.json +0 -114
- package/corpus/templates/videos/public/agent-native-icon-dark.svg +0 -10
- package/corpus/templates/videos/public/agent-native-icon-light.svg +0 -10
- package/corpus/templates/videos/public/agent-native-logo-dark.svg +0 -21
- package/corpus/templates/videos/public/agent-native-logo-light.svg +0 -21
- package/corpus/templates/videos/public/favicon.svg +0 -1
- package/corpus/templates/videos/public/icon-180.svg +0 -1
- package/corpus/templates/videos/public/icon-192.svg +0 -1
- package/corpus/templates/videos/public/icon-512.svg +0 -1
- package/corpus/templates/videos/public/manifest.json +0 -21
- package/corpus/templates/videos/public/placeholder.svg +0 -1
- package/corpus/templates/videos/public/robots.txt +0 -14
- package/corpus/templates/videos/react-router.config.ts +0 -7
- package/corpus/templates/videos/server/db/index.ts +0 -37
- package/corpus/templates/videos/server/db/schema.ts +0 -55
- package/corpus/templates/videos/server/middleware/auth.ts +0 -15
- package/corpus/templates/videos/server/plugins/agent-chat.ts +0 -29
- package/corpus/templates/videos/server/plugins/auth.ts +0 -14
- package/corpus/templates/videos/server/plugins/collab.ts +0 -11
- package/corpus/templates/videos/server/plugins/core-routes.ts +0 -22
- package/corpus/templates/videos/server/plugins/db.ts +0 -160
- package/corpus/templates/videos/server/routes/[...page].get.ts +0 -5
- package/corpus/templates/videos/server/routes/[...page].head.ts +0 -1
- package/corpus/templates/videos/server/routes/api/save-composition-defaults.post.ts +0 -274
- package/corpus/templates/videos/shared/api.ts +0 -75
- package/corpus/templates/videos/ssr-entry.ts +0 -15
- package/corpus/templates/videos/tsconfig.json +0 -21
- package/corpus/templates/videos/vite.config.ts +0 -19
- package/corpus/templates/videos/vitest.config.ts +0 -16
- package/docs/content/locales/ar-SA/template-videos.mdx +0 -336
- package/docs/content/locales/de-DE/template-videos.mdx +0 -336
- package/docs/content/locales/es-ES/template-videos.mdx +0 -336
- package/docs/content/locales/fr-FR/template-videos.mdx +0 -336
- package/docs/content/locales/hi-IN/template-videos.mdx +0 -336
- package/docs/content/locales/ja-JP/template-videos.mdx +0 -336
- package/docs/content/locales/ko-KR/template-videos.mdx +0 -336
- package/docs/content/locales/pt-BR/template-videos.mdx +0 -336
- package/docs/content/locales/zh-CN/template-videos.mdx +0 -334
- package/docs/content/locales/zh-TW/template-videos.mdx +0 -334
- package/docs/content/template-videos.mdx +0 -332
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* RemoteSelectionRings — renders colored outline rings + name tags over
|
|
4
4
|
* elements selected by remote participants.
|
|
@@ -32,10 +32,13 @@ const RingItem = memo(function RingItem({ ring }) {
|
|
|
32
32
|
pointerEvents: "none",
|
|
33
33
|
boxShadow: `0 0 0 1px ${ring.color}40`,
|
|
34
34
|
zIndex: 9998,
|
|
35
|
-
}, children:
|
|
35
|
+
}, children: _jsxs("div", { style: {
|
|
36
36
|
position: "absolute",
|
|
37
37
|
top: -20,
|
|
38
38
|
left: 0,
|
|
39
|
+
display: "flex",
|
|
40
|
+
alignItems: "center",
|
|
41
|
+
gap: 4,
|
|
39
42
|
backgroundColor: ring.color,
|
|
40
43
|
color: "#fff",
|
|
41
44
|
fontSize: 10,
|
|
@@ -43,10 +46,15 @@ const RingItem = memo(function RingItem({ ring }) {
|
|
|
43
46
|
padding: "1px 5px",
|
|
44
47
|
borderRadius: 3,
|
|
45
48
|
whiteSpace: "nowrap",
|
|
46
|
-
maxWidth:
|
|
49
|
+
maxWidth: 160,
|
|
47
50
|
overflow: "hidden",
|
|
48
51
|
textOverflow: "ellipsis",
|
|
49
|
-
}, children: ring.
|
|
52
|
+
}, children: [ring.avatarUrl ? (_jsx("img", { src: ring.avatarUrl, alt: "", style: {
|
|
53
|
+
width: 12,
|
|
54
|
+
height: 12,
|
|
55
|
+
borderRadius: "50%",
|
|
56
|
+
flexShrink: 0,
|
|
57
|
+
} })) : null, ring.label] }) }));
|
|
50
58
|
});
|
|
51
59
|
export function RemoteSelectionRings({ others, selectionKey = "selection", resolveRect, containerRef, className, }) {
|
|
52
60
|
const overlayRef = useRef(null);
|
|
@@ -61,10 +69,12 @@ export function RemoteSelectionRings({ others, selectionKey = "selection", resol
|
|
|
61
69
|
const containerRect = container.getBoundingClientRect();
|
|
62
70
|
const next = [];
|
|
63
71
|
for (const other of others) {
|
|
64
|
-
const
|
|
65
|
-
|
|
72
|
+
const raw = other.presence[selectionKey];
|
|
73
|
+
const selector = typeof raw === "string" ? raw : raw ? raw.selector : undefined;
|
|
74
|
+
if (!selector || typeof selector !== "string")
|
|
66
75
|
continue;
|
|
67
|
-
const
|
|
76
|
+
const selectionLabel = raw && typeof raw === "object" ? raw.label : undefined;
|
|
77
|
+
const domRect = resolveRect(selector);
|
|
68
78
|
if (!domRect)
|
|
69
79
|
continue;
|
|
70
80
|
// Convert viewport-relative rect to container-relative.
|
|
@@ -76,10 +86,14 @@ export function RemoteSelectionRings({ others, selectionKey = "selection", resol
|
|
|
76
86
|
top > containerRect.height) {
|
|
77
87
|
continue; // Out of container bounds — skip.
|
|
78
88
|
}
|
|
89
|
+
const baseName = other.isAgent
|
|
90
|
+
? "AI"
|
|
91
|
+
: other.user.name || other.user.email;
|
|
79
92
|
next.push({
|
|
80
93
|
clientId: other.clientId,
|
|
81
94
|
color: other.user.color || "#94a3b8",
|
|
82
|
-
label:
|
|
95
|
+
label: selectionLabel ? `${baseName} — ${selectionLabel}` : baseName,
|
|
96
|
+
avatarUrl: other.user.avatarUrl,
|
|
83
97
|
isAgent: other.isAgent,
|
|
84
98
|
rect: { top, left, width: domRect.width, height: domRect.height },
|
|
85
99
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteSelectionRings.js","sourceRoot":"","sources":["../../../src/client/components/RemoteSelectionRings.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * RemoteSelectionRings — renders colored outline rings + name tags over\n * elements selected by remote participants.\n *\n * Each participant's presence payload may contain a `selection` key with an\n * opaque descriptor (e.g. a CSS selector). The `resolveRect` callback maps\n * a descriptor to a DOMRect (or null when the element isn't found). Rings\n * are rendered as absolutely-positioned outlines anchored to the container.\n *\n * Usage:\n * <div style={{ position: \"relative\" }}>\n * {content}\n * <RemoteSelectionRings\n * others={others}\n * resolveRect={(selector) => document.querySelector(selector)?.getBoundingClientRect() ?? null}\n * containerRef={containerRef}\n * />\n * </div>\n */\n\nimport { useState, useEffect, useRef, useLayoutEffect, memo } from \"react\";\n\nimport type { OtherPresence } from \"../../collab/presence.js\";\n\nexport interface RemoteSelectionRingsProps {\n /** Remote participants. */\n others: OtherPresence[];\n /**\n * Key inside presence payload that carries the selection descriptor.\n * Default: \"selection\"\n */\n selectionKey?: string;\n /**\n * Resolver: maps a selection descriptor to a DOMRect relative to the\n * viewport. Return null when the element is not found.\n */\n resolveRect: (descriptor: string) => DOMRect | null;\n /**\n * Container element ref. Rings are positioned relative to this element's\n * bounding box.\n */\n containerRef: React.RefObject<HTMLElement | null>;\n /** Additional CSS class for the overlay div. */\n className?: string;\n}\n\ninterface Ring {\n clientId: number;\n color: string;\n label: string;\n isAgent: boolean;\n rect: { top: number; left: number; width: number; height: number };\n}\n\nconst RingItem = memo(function RingItem({ ring }: { ring: Ring }) {\n return (\n <div\n aria-label={`${ring.label} selection`}\n style={{\n position: \"absolute\",\n top: ring.rect.top,\n left: ring.rect.left,\n width: ring.rect.width,\n height: ring.rect.height,\n outline: `2px solid ${ring.color}`,\n outlineOffset: 2,\n borderRadius: 3,\n pointerEvents: \"none\",\n boxShadow: `0 0 0 1px ${ring.color}40`,\n zIndex: 9998,\n }}\n >\n {/* Name tag in top-left corner of the ring */}\n <div\n style={{\n position: \"absolute\",\n top: -20,\n left: 0,\n backgroundColor: ring.color,\n color: \"#fff\",\n fontSize: 10,\n fontWeight: 600,\n padding: \"1px 5px\",\n borderRadius: 3,\n whiteSpace: \"nowrap\",\n maxWidth: 120,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {ring.isAgent ? `AI — ${ring.label}` : ring.label}\n </div>\n </div>\n );\n});\n\nexport function RemoteSelectionRings({\n others,\n selectionKey = \"selection\",\n resolveRect,\n containerRef,\n className,\n}: RemoteSelectionRingsProps) {\n const overlayRef = useRef<HTMLDivElement>(null);\n const [rings, setRings] = useState<Ring[]>([]);\n\n // Recompute rings whenever others change or on animation frame.\n const recompute = () => {\n const container = containerRef.current;\n if (!container) {\n setRings([]);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const next: Ring[] = [];\n\n for (const other of others) {\n const descriptor = other.presence[selectionKey] as string | undefined;\n if (!descriptor || typeof descriptor !== \"string\") continue;\n\n const domRect = resolveRect(descriptor);\n if (!domRect) continue;\n\n // Convert viewport-relative rect to container-relative.\n const top = domRect.top - containerRect.top;\n const left = domRect.left - containerRect.left;\n if (\n left + domRect.width < 0 ||\n top + domRect.height < 0 ||\n left > containerRect.width ||\n top > containerRect.height\n ) {\n continue; // Out of container bounds — skip.\n }\n\n next.push({\n clientId: other.clientId,\n color: other.user.color || \"#94a3b8\",\n label: other.isAgent ? \"AI\" : other.user.name || other.user.email,\n isAgent: other.isAgent,\n rect: { top, left, width: domRect.width, height: domRect.height },\n });\n }\n\n setRings(next);\n };\n\n // Recompute on scroll/resize of the container to keep rings in sync.\n useLayoutEffect(() => {\n recompute();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [others, selectionKey]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() => recompute());\n observer.observe(container);\n container.addEventListener(\"scroll\", recompute, { passive: true });\n window.addEventListener(\"scroll\", recompute, { passive: true });\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", recompute);\n window.removeEventListener(\"scroll\", recompute);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [containerRef]);\n\n return (\n <div\n ref={overlayRef}\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n >\n {rings.map((ring) => (\n <RingItem key={ring.clientId} ring={ring} />\n ))}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"RemoteSelectionRings.js","sourceRoot":"","sources":["../../../src/client/components/RemoteSelectionRings.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * RemoteSelectionRings — renders colored outline rings + name tags over\n * elements selected by remote participants.\n *\n * Each participant's presence payload may contain a `selection` key with an\n * opaque descriptor (e.g. a CSS selector). The `resolveRect` callback maps\n * a descriptor to a DOMRect (or null when the element isn't found). Rings\n * are rendered as absolutely-positioned outlines anchored to the container.\n *\n * Usage:\n * <div style={{ position: \"relative\" }}>\n * {content}\n * <RemoteSelectionRings\n * others={others}\n * resolveRect={(selector) => document.querySelector(selector)?.getBoundingClientRect() ?? null}\n * containerRef={containerRef}\n * />\n * </div>\n */\n\nimport { useState, useEffect, useRef, useLayoutEffect, memo } from \"react\";\n\nimport type { OtherPresence } from \"../../collab/presence.js\";\n\n/**\n * Selection descriptors may be a plain string (treated as the resolver\n * input) or an object carrying a resolver input plus a human label\n * (\"Editing hero section\").\n */\nexport type SelectionDescriptor = string | { selector: string; label?: string };\n\nexport interface RemoteSelectionRingsProps {\n /** Remote participants. */\n others: OtherPresence[];\n /**\n * Key inside presence payload that carries the selection descriptor.\n * Default: \"selection\"\n */\n selectionKey?: string;\n /**\n * Resolver: maps a selection descriptor to a DOMRect relative to the\n * viewport. Return null when the element is not found.\n */\n resolveRect: (descriptor: string) => DOMRect | null;\n /**\n * Container element ref. Rings are positioned relative to this element's\n * bounding box.\n */\n containerRef: React.RefObject<HTMLElement | null>;\n /** Additional CSS class for the overlay div. */\n className?: string;\n}\n\ninterface Ring {\n clientId: number;\n color: string;\n label: string;\n avatarUrl?: string;\n isAgent: boolean;\n rect: { top: number; left: number; width: number; height: number };\n}\n\nconst RingItem = memo(function RingItem({ ring }: { ring: Ring }) {\n return (\n <div\n aria-label={`${ring.label} selection`}\n style={{\n position: \"absolute\",\n top: ring.rect.top,\n left: ring.rect.left,\n width: ring.rect.width,\n height: ring.rect.height,\n outline: `2px solid ${ring.color}`,\n outlineOffset: 2,\n borderRadius: 3,\n pointerEvents: \"none\",\n boxShadow: `0 0 0 1px ${ring.color}40`,\n zIndex: 9998,\n }}\n >\n {/* Name tag in top-left corner of the ring */}\n <div\n style={{\n position: \"absolute\",\n top: -20,\n left: 0,\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n backgroundColor: ring.color,\n color: \"#fff\",\n fontSize: 10,\n fontWeight: 600,\n padding: \"1px 5px\",\n borderRadius: 3,\n whiteSpace: \"nowrap\",\n maxWidth: 160,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {ring.avatarUrl ? (\n <img\n src={ring.avatarUrl}\n alt=\"\"\n style={{\n width: 12,\n height: 12,\n borderRadius: \"50%\",\n flexShrink: 0,\n }}\n />\n ) : null}\n {ring.label}\n </div>\n </div>\n );\n});\n\nexport function RemoteSelectionRings({\n others,\n selectionKey = \"selection\",\n resolveRect,\n containerRef,\n className,\n}: RemoteSelectionRingsProps) {\n const overlayRef = useRef<HTMLDivElement>(null);\n const [rings, setRings] = useState<Ring[]>([]);\n\n // Recompute rings whenever others change or on animation frame.\n const recompute = () => {\n const container = containerRef.current;\n if (!container) {\n setRings([]);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const next: Ring[] = [];\n\n for (const other of others) {\n const raw = other.presence[selectionKey] as\n | SelectionDescriptor\n | null\n | undefined;\n const selector =\n typeof raw === \"string\" ? raw : raw ? raw.selector : undefined;\n if (!selector || typeof selector !== \"string\") continue;\n const selectionLabel =\n raw && typeof raw === \"object\" ? raw.label : undefined;\n\n const domRect = resolveRect(selector);\n if (!domRect) continue;\n\n // Convert viewport-relative rect to container-relative.\n const top = domRect.top - containerRect.top;\n const left = domRect.left - containerRect.left;\n if (\n left + domRect.width < 0 ||\n top + domRect.height < 0 ||\n left > containerRect.width ||\n top > containerRect.height\n ) {\n continue; // Out of container bounds — skip.\n }\n\n const baseName = other.isAgent\n ? \"AI\"\n : other.user.name || other.user.email;\n next.push({\n clientId: other.clientId,\n color: other.user.color || \"#94a3b8\",\n label: selectionLabel ? `${baseName} — ${selectionLabel}` : baseName,\n avatarUrl: (other.user as { avatarUrl?: string }).avatarUrl,\n isAgent: other.isAgent,\n rect: { top, left, width: domRect.width, height: domRect.height },\n });\n }\n\n setRings(next);\n };\n\n // Recompute on scroll/resize of the container to keep rings in sync.\n useLayoutEffect(() => {\n recompute();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [others, selectionKey]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const observer = new ResizeObserver(() => recompute());\n observer.observe(container);\n container.addEventListener(\"scroll\", recompute, { passive: true });\n window.addEventListener(\"scroll\", recompute, { passive: true });\n return () => {\n observer.disconnect();\n container.removeEventListener(\"scroll\", recompute);\n window.removeEventListener(\"scroll\", recompute);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [containerRef]);\n\n return (\n <div\n ref={overlayRef}\n aria-hidden\n style={{\n position: \"absolute\",\n inset: 0,\n pointerEvents: \"none\",\n overflow: \"hidden\",\n }}\n className={className}\n >\n {rings.map((ring) => (\n <RingItem key={ring.clientId} ring={ring} />\n ))}\n </div>\n );\n}\n"]}
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface DbAdminPageProps {
|
|
2
|
+
apiBasePath?: string;
|
|
3
|
+
cacheScope?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
subtitle?: string;
|
|
6
|
+
codeModeGate?: boolean;
|
|
7
|
+
syncNavigation?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function DbAdminPage({ apiBasePath, cacheScope, title, subtitle, codeModeGate, syncNavigation, }?: DbAdminPageProps): import("react").JSX.Element;
|
|
2
10
|
//# sourceMappingURL=DbAdminPage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DbAdminPage.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/DbAdminPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DbAdminPage.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/DbAdminPage.tsx"],"names":[],"mappings":"AAyBA,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,WAAW,CAAC,EAC1B,WAAW,EACX,UAAU,EACV,KAAkB,EAClB,QAAQ,EACR,YAAmB,EACnB,cAAqB,GACtB,GAAE,gBAAqB,+BAmIvB"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { IconDatabase, IconLoader2 } from "@tabler/icons-react";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Database admin page — the shell that hosts the table browser, the table
|
|
5
|
+
* editor, and the SQL editor.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* backend also enforces this with a 403, so this is purely a friendlier UX.
|
|
7
|
+
* By default this is gated to Code mode for the core dev route. Trusted hosts
|
|
8
|
+
* can opt out and point it at their own admin-gated API path.
|
|
10
9
|
*/
|
|
11
10
|
import { useEffect, useMemo, useState } from "react";
|
|
12
11
|
import { useCodeMode } from "../use-dev-mode.js";
|
|
@@ -21,9 +20,14 @@ const DIALECT_LABEL = {
|
|
|
21
20
|
sqlite: "SQLite",
|
|
22
21
|
d1: "Cloudflare D1",
|
|
23
22
|
};
|
|
24
|
-
export function DbAdminPage() {
|
|
23
|
+
export function DbAdminPage({ apiBasePath, cacheScope, title = "Database", subtitle, codeModeGate = true, syncNavigation = true, } = {}) {
|
|
25
24
|
const { canToggle, isLoading: devLoading } = useCodeMode();
|
|
26
|
-
const
|
|
25
|
+
const requestConfig = useMemo(() => {
|
|
26
|
+
if (!apiBasePath && !cacheScope)
|
|
27
|
+
return undefined;
|
|
28
|
+
return { basePath: apiBasePath, scopeKey: cacheScope };
|
|
29
|
+
}, [apiBasePath, cacheScope]);
|
|
30
|
+
const { data: overview, isLoading: overviewLoading } = useOverview(requestConfig);
|
|
27
31
|
const [selectedTable, setSelectedTable] = useState(null);
|
|
28
32
|
const [mode, setMode] = useState("table");
|
|
29
33
|
const [fkFilters, setFkFilters] = useState(undefined);
|
|
@@ -36,25 +40,25 @@ export function DbAdminPage() {
|
|
|
36
40
|
}
|
|
37
41
|
}, [selectedTable, tables]);
|
|
38
42
|
// Keep the agent's <current-screen> in sync, and let it drive navigation.
|
|
39
|
-
useDbAdminAgentSync({ table: selectedTable, mode });
|
|
43
|
+
useDbAdminAgentSync({ table: selectedTable, mode, enabled: syncNavigation });
|
|
40
44
|
useNavigateConsumer((table) => {
|
|
41
45
|
setSelectedTable(table);
|
|
42
46
|
setMode("table");
|
|
43
47
|
setFkFilters(undefined);
|
|
44
|
-
});
|
|
48
|
+
}, syncNavigation);
|
|
45
49
|
const tableNames = useMemo(() => tables.map((t) => t.name), [tables]);
|
|
46
50
|
// SqlEditor degrades gracefully without per-table columns; pass an empty map.
|
|
47
51
|
// (Table-name autocomplete still works; column autocomplete fills in lazily.)
|
|
48
52
|
const columnsByTable = useMemo(() => ({}), []);
|
|
49
53
|
// ─── Code mode gate ──────────────────────────────────────────────────────
|
|
50
|
-
if (!devLoading && !canToggle) {
|
|
54
|
+
if (codeModeGate && !devLoading && !canToggle) {
|
|
51
55
|
return (_jsx("div", { className: "flex h-full w-full items-center justify-center bg-background p-6", children: _jsxs("div", { className: "flex max-w-md flex-col items-center rounded-lg border bg-card p-8 text-center shadow-sm", children: [_jsx("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted", children: _jsx(IconDatabase, { className: "h-6 w-6 text-muted-foreground", stroke: 1.75 }) }), _jsx("h2", { className: "text-base font-semibold text-foreground", children: "Code mode only" }), _jsx("p", { className: "mt-1.5 text-sm text-muted-foreground", children: "Database admin is available in Code mode only." })] }) }));
|
|
52
56
|
}
|
|
53
|
-
const showInitialLoading = (devLoading || overviewLoading) && !overview;
|
|
54
|
-
return (_jsxs("div", { className: "flex h-full w-full flex-col bg-background text-foreground", children: [_jsxs("header", { className: "flex h-12 shrink-0 items-center gap-3 border-b px-4", children: [_jsx(IconDatabase, { className: "h-5 w-5 text-muted-foreground", stroke: 1.75 }), _jsx("span", { className: "text-sm font-semibold", children:
|
|
57
|
+
const showInitialLoading = ((codeModeGate && devLoading) || overviewLoading) && !overview;
|
|
58
|
+
return (_jsxs("div", { className: "flex h-full w-full flex-col bg-background text-foreground", children: [_jsxs("header", { className: "flex h-12 shrink-0 items-center gap-3 border-b px-4", children: [_jsx(IconDatabase, { className: "h-5 w-5 text-muted-foreground", stroke: 1.75 }), _jsx("span", { className: "text-sm font-semibold", children: title }), _jsx("span", { className: "inline-flex items-center rounded-full border bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground", children: DIALECT_LABEL[dialect] ?? dialect }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [tables.length, " ", tables.length === 1 ? "table" : "tables"] }), subtitle ? (_jsx("span", { className: "min-w-0 truncate text-xs text-muted-foreground", children: subtitle })) : null] }), _jsxs("div", { className: "flex min-h-0 flex-1", children: [_jsx("aside", { className: "w-[260px] shrink-0 border-r", children: showInitialLoading ? (_jsx(SidebarSkeleton, {})) : (_jsx(TableBrowser, { tables: tables, selected: selectedTable, onSelect: (t) => {
|
|
55
59
|
setSelectedTable(t);
|
|
56
60
|
setFkFilters(undefined);
|
|
57
|
-
}, mode: mode, onModeChange: setMode })) }), _jsx("main", { className: "min-w-0 flex-1 overflow-hidden", children: showInitialLoading ? (_jsx(MainLoading, {})) : mode === "sql" ? (_jsx(SqlEditor, { dialect: dialect, tableNames: tableNames, columnsByTable: columnsByTable })) : selectedTable ? (_jsx(TableEditor, { table: selectedTable, dialect: dialect, initialFilters: fkFilters, onNavigateToRow: (t, filters) => {
|
|
61
|
+
}, mode: mode, onModeChange: setMode })) }), _jsx("main", { className: "min-w-0 flex-1 overflow-hidden", children: showInitialLoading ? (_jsx(MainLoading, {})) : mode === "sql" ? (_jsx(SqlEditor, { dialect: dialect, tableNames: tableNames, columnsByTable: columnsByTable, requestConfig: requestConfig })) : selectedTable ? (_jsx(TableEditor, { table: selectedTable, dialect: dialect, requestConfig: requestConfig, initialFilters: fkFilters, onNavigateToRow: (t, filters) => {
|
|
58
62
|
setSelectedTable(t);
|
|
59
63
|
setMode("table");
|
|
60
64
|
setFkFilters(filters);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DbAdminPage.js","sourceRoot":"","sources":["../../../src/client/db-admin/DbAdminPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconDatabase, IconLoader2 } from \"@tabler/icons-react\";\n/**\n * Code-mode database admin page — the shell that hosts the table browser, the\n * table editor, and the SQL editor.\n *\n * Gated to Code mode: when the app cannot toggle into Code mode\n * (`canToggle` is false) we render a clean notice instead of the tool. The\n * backend also enforces this with a 403, so this is purely a friendlier UX.\n */\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport type { DbAdminFilter } from \"../../db-admin/types.js\";\nimport { useCodeMode } from \"../use-dev-mode.js\";\nimport { cn } from \"../utils.js\";\nimport { SqlEditor } from \"./SqlEditor.js\";\nimport { TableBrowser } from \"./TableBrowser.js\";\nimport { TableEditor } from \"./TableEditor.js\";\nimport { useDbAdminAgentSync, useNavigateConsumer } from \"./useAgentSync.js\";\nimport { useOverview } from \"./useDbAdmin.js\";\n\nconst DIALECT_LABEL: Record<string, string> = {\n postgres: \"Postgres\",\n sqlite: \"SQLite\",\n d1: \"Cloudflare D1\",\n};\n\nexport function DbAdminPage() {\n const { canToggle, isLoading: devLoading } = useCodeMode();\n const { data: overview, isLoading: overviewLoading } = useOverview();\n\n const [selectedTable, setSelectedTable] = useState<string | null>(null);\n const [mode, setMode] = useState<\"table\" | \"sql\">(\"table\");\n const [fkFilters, setFkFilters] = useState<DbAdminFilter[] | undefined>(\n undefined,\n );\n\n const tables = overview?.tables ?? [];\n const dialect = overview?.dialect ?? \"sqlite\";\n\n // Default selection to the first table once the overview loads.\n useEffect(() => {\n if (selectedTable === null && tables.length > 0) {\n setSelectedTable(tables[0].name);\n }\n }, [selectedTable, tables]);\n\n // Keep the agent's <current-screen> in sync, and let it drive navigation.\n useDbAdminAgentSync({ table: selectedTable, mode });\n useNavigateConsumer((table) => {\n setSelectedTable(table);\n setMode(\"table\");\n setFkFilters(undefined);\n });\n\n const tableNames = useMemo(() => tables.map((t) => t.name), [tables]);\n // SqlEditor degrades gracefully without per-table columns; pass an empty map.\n // (Table-name autocomplete still works; column autocomplete fills in lazily.)\n const columnsByTable = useMemo<Record<string, string[]>>(() => ({}), []);\n\n // ─── Code mode gate ──────────────────────────────────────────────────────\n if (!devLoading && !canToggle) {\n return (\n <div className=\"flex h-full w-full items-center justify-center bg-background p-6\">\n <div className=\"flex max-w-md flex-col items-center rounded-lg border bg-card p-8 text-center shadow-sm\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <IconDatabase\n className=\"h-6 w-6 text-muted-foreground\"\n stroke={1.75}\n />\n </div>\n <h2 className=\"text-base font-semibold text-foreground\">\n Code mode only\n </h2>\n <p className=\"mt-1.5 text-sm text-muted-foreground\">\n Database admin is available in Code mode only.\n </p>\n </div>\n </div>\n );\n }\n\n const showInitialLoading = (devLoading || overviewLoading) && !overview;\n\n return (\n <div className=\"flex h-full w-full flex-col bg-background text-foreground\">\n {/* Header */}\n <header className=\"flex h-12 shrink-0 items-center gap-3 border-b px-4\">\n <IconDatabase className=\"h-5 w-5 text-muted-foreground\" stroke={1.75} />\n <span className=\"text-sm font-semibold\">Database</span>\n <span className=\"inline-flex items-center rounded-full border bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground\">\n {DIALECT_LABEL[dialect] ?? dialect}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {tables.length} {tables.length === 1 ? \"table\" : \"tables\"}\n </span>\n </header>\n\n {/* Body: fixed sidebar + flexible main */}\n <div className=\"flex min-h-0 flex-1\">\n <aside className=\"w-[260px] shrink-0 border-r\">\n {showInitialLoading ? (\n <SidebarSkeleton />\n ) : (\n <TableBrowser\n tables={tables}\n selected={selectedTable}\n onSelect={(t) => {\n setSelectedTable(t);\n setFkFilters(undefined);\n }}\n mode={mode}\n onModeChange={setMode}\n />\n )}\n </aside>\n\n <main className=\"min-w-0 flex-1 overflow-hidden\">\n {showInitialLoading ? (\n <MainLoading />\n ) : mode === \"sql\" ? (\n <SqlEditor\n dialect={dialect}\n tableNames={tableNames}\n columnsByTable={columnsByTable}\n />\n ) : selectedTable ? (\n <TableEditor\n key={selectedTable}\n table={selectedTable}\n dialect={dialect}\n initialFilters={fkFilters}\n onNavigateToRow={(t, filters) => {\n setSelectedTable(t);\n setMode(\"table\");\n setFkFilters(filters);\n }}\n />\n ) : (\n <NoTableSelected />\n )}\n </main>\n </div>\n </div>\n );\n}\n\nfunction SidebarSkeleton() {\n return (\n <div className=\"flex h-full flex-col bg-card p-2\">\n <div className=\"mb-2 h-9 animate-pulse rounded-md bg-muted\" />\n <div className=\"mb-3 h-9 animate-pulse rounded-md bg-muted\" />\n <div className=\"space-y-1.5\">\n {Array.from({ length: 8 }).map((_, i) => (\n <div\n key={i}\n className=\"h-8 animate-pulse rounded-md bg-muted\"\n style={{ opacity: 1 - i * 0.08 }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction MainLoading() {\n return (\n <div className=\"flex h-full w-full items-center justify-center\">\n <IconLoader2\n className={cn(\"h-5 w-5 animate-spin text-muted-foreground\")}\n />\n </div>\n );\n}\n\nfunction NoTableSelected() {\n return (\n <div className=\"flex h-full w-full items-center justify-center p-6 text-center\">\n <div className=\"flex flex-col items-center\">\n <IconDatabase\n className=\"mb-3 h-8 w-8 text-muted-foreground/50\"\n stroke={1.5}\n />\n <p className=\"text-sm font-medium text-foreground\">No table selected</p>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Pick a table from the sidebar to browse and edit its rows.\n </p>\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DbAdminPage.js","sourceRoot":"","sources":["../../../src/client/db-admin/DbAdminPage.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconDatabase, IconLoader2 } from \"@tabler/icons-react\";\n/**\n * Database admin page — the shell that hosts the table browser, the table\n * editor, and the SQL editor.\n *\n * By default this is gated to Code mode for the core dev route. Trusted hosts\n * can opt out and point it at their own admin-gated API path.\n */\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport type { DbAdminFilter } from \"../../db-admin/types.js\";\nimport { useCodeMode } from \"../use-dev-mode.js\";\nimport { cn } from \"../utils.js\";\nimport { SqlEditor } from \"./SqlEditor.js\";\nimport { TableBrowser } from \"./TableBrowser.js\";\nimport { TableEditor } from \"./TableEditor.js\";\nimport { useDbAdminAgentSync, useNavigateConsumer } from \"./useAgentSync.js\";\nimport { useOverview, type DbAdminRequestConfig } from \"./useDbAdmin.js\";\n\nconst DIALECT_LABEL: Record<string, string> = {\n postgres: \"Postgres\",\n sqlite: \"SQLite\",\n d1: \"Cloudflare D1\",\n};\n\nexport interface DbAdminPageProps {\n apiBasePath?: string;\n cacheScope?: string;\n title?: string;\n subtitle?: string;\n codeModeGate?: boolean;\n syncNavigation?: boolean;\n}\n\nexport function DbAdminPage({\n apiBasePath,\n cacheScope,\n title = \"Database\",\n subtitle,\n codeModeGate = true,\n syncNavigation = true,\n}: DbAdminPageProps = {}) {\n const { canToggle, isLoading: devLoading } = useCodeMode();\n const requestConfig = useMemo<DbAdminRequestConfig | undefined>(() => {\n if (!apiBasePath && !cacheScope) return undefined;\n return { basePath: apiBasePath, scopeKey: cacheScope };\n }, [apiBasePath, cacheScope]);\n const { data: overview, isLoading: overviewLoading } =\n useOverview(requestConfig);\n\n const [selectedTable, setSelectedTable] = useState<string | null>(null);\n const [mode, setMode] = useState<\"table\" | \"sql\">(\"table\");\n const [fkFilters, setFkFilters] = useState<DbAdminFilter[] | undefined>(\n undefined,\n );\n\n const tables = overview?.tables ?? [];\n const dialect = overview?.dialect ?? \"sqlite\";\n\n // Default selection to the first table once the overview loads.\n useEffect(() => {\n if (selectedTable === null && tables.length > 0) {\n setSelectedTable(tables[0].name);\n }\n }, [selectedTable, tables]);\n\n // Keep the agent's <current-screen> in sync, and let it drive navigation.\n useDbAdminAgentSync({ table: selectedTable, mode, enabled: syncNavigation });\n useNavigateConsumer((table) => {\n setSelectedTable(table);\n setMode(\"table\");\n setFkFilters(undefined);\n }, syncNavigation);\n\n const tableNames = useMemo(() => tables.map((t) => t.name), [tables]);\n // SqlEditor degrades gracefully without per-table columns; pass an empty map.\n // (Table-name autocomplete still works; column autocomplete fills in lazily.)\n const columnsByTable = useMemo<Record<string, string[]>>(() => ({}), []);\n\n // ─── Code mode gate ──────────────────────────────────────────────────────\n if (codeModeGate && !devLoading && !canToggle) {\n return (\n <div className=\"flex h-full w-full items-center justify-center bg-background p-6\">\n <div className=\"flex max-w-md flex-col items-center rounded-lg border bg-card p-8 text-center shadow-sm\">\n <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <IconDatabase\n className=\"h-6 w-6 text-muted-foreground\"\n stroke={1.75}\n />\n </div>\n <h2 className=\"text-base font-semibold text-foreground\">\n Code mode only\n </h2>\n <p className=\"mt-1.5 text-sm text-muted-foreground\">\n Database admin is available in Code mode only.\n </p>\n </div>\n </div>\n );\n }\n\n const showInitialLoading =\n ((codeModeGate && devLoading) || overviewLoading) && !overview;\n\n return (\n <div className=\"flex h-full w-full flex-col bg-background text-foreground\">\n {/* Header */}\n <header className=\"flex h-12 shrink-0 items-center gap-3 border-b px-4\">\n <IconDatabase className=\"h-5 w-5 text-muted-foreground\" stroke={1.75} />\n <span className=\"text-sm font-semibold\">{title}</span>\n <span className=\"inline-flex items-center rounded-full border bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground\">\n {DIALECT_LABEL[dialect] ?? dialect}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {tables.length} {tables.length === 1 ? \"table\" : \"tables\"}\n </span>\n {subtitle ? (\n <span className=\"min-w-0 truncate text-xs text-muted-foreground\">\n {subtitle}\n </span>\n ) : null}\n </header>\n\n {/* Body: fixed sidebar + flexible main */}\n <div className=\"flex min-h-0 flex-1\">\n <aside className=\"w-[260px] shrink-0 border-r\">\n {showInitialLoading ? (\n <SidebarSkeleton />\n ) : (\n <TableBrowser\n tables={tables}\n selected={selectedTable}\n onSelect={(t) => {\n setSelectedTable(t);\n setFkFilters(undefined);\n }}\n mode={mode}\n onModeChange={setMode}\n />\n )}\n </aside>\n\n <main className=\"min-w-0 flex-1 overflow-hidden\">\n {showInitialLoading ? (\n <MainLoading />\n ) : mode === \"sql\" ? (\n <SqlEditor\n dialect={dialect}\n tableNames={tableNames}\n columnsByTable={columnsByTable}\n requestConfig={requestConfig}\n />\n ) : selectedTable ? (\n <TableEditor\n key={selectedTable}\n table={selectedTable}\n dialect={dialect}\n requestConfig={requestConfig}\n initialFilters={fkFilters}\n onNavigateToRow={(t, filters) => {\n setSelectedTable(t);\n setMode(\"table\");\n setFkFilters(filters);\n }}\n />\n ) : (\n <NoTableSelected />\n )}\n </main>\n </div>\n </div>\n );\n}\n\nfunction SidebarSkeleton() {\n return (\n <div className=\"flex h-full flex-col bg-card p-2\">\n <div className=\"mb-2 h-9 animate-pulse rounded-md bg-muted\" />\n <div className=\"mb-3 h-9 animate-pulse rounded-md bg-muted\" />\n <div className=\"space-y-1.5\">\n {Array.from({ length: 8 }).map((_, i) => (\n <div\n key={i}\n className=\"h-8 animate-pulse rounded-md bg-muted\"\n style={{ opacity: 1 - i * 0.08 }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction MainLoading() {\n return (\n <div className=\"flex h-full w-full items-center justify-center\">\n <IconLoader2\n className={cn(\"h-5 w-5 animate-spin text-muted-foreground\")}\n />\n </div>\n );\n}\n\nfunction NoTableSelected() {\n return (\n <div className=\"flex h-full w-full items-center justify-center p-6 text-center\">\n <div className=\"flex flex-col items-center\">\n <IconDatabase\n className=\"mb-3 h-8 w-8 text-muted-foreground/50\"\n stroke={1.5}\n />\n <p className=\"text-sm font-medium text-foreground\">No table selected</p>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Pick a table from the sidebar to browse and edit its rows.\n </p>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { DbAdminDialect } from "../../db-admin/types.js";
|
|
2
|
+
import { type DbAdminRequestConfig } from "./useDbAdmin.js";
|
|
2
3
|
export interface SqlEditorProps {
|
|
3
4
|
dialect: DbAdminDialect;
|
|
4
5
|
tableNames: string[];
|
|
5
6
|
columnsByTable: Record<string, string[]>;
|
|
7
|
+
requestConfig?: DbAdminRequestConfig;
|
|
6
8
|
}
|
|
7
|
-
export declare function SqlEditor({ dialect, tableNames, columnsByTable, }: SqlEditorProps): import("react").JSX.Element;
|
|
9
|
+
export declare function SqlEditor({ dialect, tableNames, columnsByTable, requestConfig, }: SqlEditorProps): import("react").JSX.Element;
|
|
8
10
|
//# sourceMappingURL=SqlEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditor.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/SqlEditor.tsx"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"SqlEditor.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/SqlEditor.tsx"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAwB9D,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAiMD,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,UAAU,EACV,cAAc,EACd,aAAa,GACd,EAAE,cAAc,+BA+iBhB"}
|
|
@@ -137,7 +137,7 @@ const isMac = typeof navigator !== "undefined" &&
|
|
|
137
137
|
/Mac|iPhone|iPad/.test(navigator.platform);
|
|
138
138
|
const MOD = isMac ? "Cmd" : "Ctrl";
|
|
139
139
|
// ─── Main component ──────────────────────────────────────────────────────────
|
|
140
|
-
export function SqlEditor({ dialect, tableNames, columnsByTable, }) {
|
|
140
|
+
export function SqlEditor({ dialect, tableNames, columnsByTable, requestConfig, }) {
|
|
141
141
|
const isDark = useIsDark();
|
|
142
142
|
const editorRef = useRef(null);
|
|
143
143
|
const [value, setValue] = useState("");
|
|
@@ -168,7 +168,7 @@ export function SqlEditor({ dialect, tableNames, columnsByTable, }) {
|
|
|
168
168
|
setRunning(true);
|
|
169
169
|
setError(null);
|
|
170
170
|
try {
|
|
171
|
-
const res = await runQuery(trimmed, undefined, confirmDestructive);
|
|
171
|
+
const res = await runQuery(trimmed, undefined, confirmDestructive, requestConfig);
|
|
172
172
|
setResult({
|
|
173
173
|
columns: res.columns,
|
|
174
174
|
rows: res.rows,
|
|
@@ -196,7 +196,7 @@ export function SqlEditor({ dialect, tableNames, columnsByTable, }) {
|
|
|
196
196
|
finally {
|
|
197
197
|
setRunning(false);
|
|
198
198
|
}
|
|
199
|
-
}, []);
|
|
199
|
+
}, [requestConfig]);
|
|
200
200
|
const runActiveStatement = useCallback(() => {
|
|
201
201
|
const view = editorRef.current?.view;
|
|
202
202
|
const target = resolveRunTarget(view, valueRef.current);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditor.js","sourceRoot":"","sources":["../../../src/client/db-admin/SqlEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { sql, PostgreSQL } from \"@codemirror/lang-sql\";\nimport { oneDark } from \"@codemirror/theme-one-dark\";\nimport {\n IconPlayerPlayFilled,\n IconHistory,\n IconBookmark,\n IconBookmarkPlus,\n IconDownload,\n IconAlertTriangle,\n IconLoader2,\n IconTrash,\n IconX,\n IconChevronDown,\n} from \"@tabler/icons-react\";\nimport CodeMirror, {\n type ReactCodeMirrorRef,\n EditorView,\n keymap,\n Prec,\n} from \"@uiw/react-codemirror\";\n/**\n * Production-grade SQL editor for the dev-mode database admin.\n *\n * Layout: a CodeMirror editor pane on top, a resizable results panel below.\n * Features schema-aware autocomplete, keyboard run shortcuts, history, named\n * snippets, CSV/JSON export, and a confirm modal for destructive statements.\n *\n * Data access goes through `runQuery` from `./useDbAdmin.js` (the shared\n * contract). On a destructive statement without confirmation, `runQuery` throws\n * an Error whose `needsConfirm` flag is `true`; we catch that and re-run after\n * the user confirms in a locally-built modal.\n */\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport type { DbAdminDialect } from \"../../db-admin/types.js\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../components/ui/dropdown-menu.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { cn } from \"../utils.js\";\nimport { toCSV, toJSON, downloadFile } from \"./export-utils.js\";\nimport { ResultsGrid } from \"./ResultsGrid.js\";\nimport {\n loadHistory,\n pushHistory,\n clearHistory,\n loadSnippets,\n saveSnippet,\n deleteSnippet,\n type SqlSnippet,\n} from \"./sql-storage.js\";\nimport { runQuery } from \"./useDbAdmin.js\";\n\nexport interface SqlEditorProps {\n dialect: DbAdminDialect;\n tableNames: string[];\n columnsByTable: Record<string, string[]>;\n}\n\ninterface QueryResult {\n columns: string[];\n rows: Record<string, unknown>[];\n rowsAffected: number;\n durationMs: number;\n}\n\n// ─── Dark-mode detection ─────────────────────────────────────────────────────\n\nfunction useIsDark(): boolean {\n const [isDark, setIsDark] = useState(false);\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const update = () => setIsDark(root.classList.contains(\"dark\"));\n update();\n const observer = new MutationObserver(update);\n observer.observe(root, { attributes: true, attributeFilter: [\"class\"] });\n return () => observer.disconnect();\n }, []);\n return isDark;\n}\n\n// ─── Statement-under-cursor helpers ──────────────────────────────────────────\n\n/**\n * Best-effort split of a SQL buffer into statements by top-level `;`, ignoring\n * semicolons inside single/double quotes or line/block comments. Returns each\n * statement with its character offsets so we can pick the one under the cursor.\n */\nfunction splitStatements(\n text: string,\n): { sql: string; start: number; end: number }[] {\n const out: { sql: string; start: number; end: number }[] = [];\n let start = 0;\n let inSingle = false;\n let inDouble = false;\n let inLineComment = false;\n let inBlockComment = false;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n const next = text[i + 1];\n\n if (inLineComment) {\n if (ch === \"\\n\") inLineComment = false;\n continue;\n }\n if (inBlockComment) {\n if (ch === \"*\" && next === \"/\") {\n inBlockComment = false;\n i++;\n }\n continue;\n }\n if (inSingle) {\n if (ch === \"'\") inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n inLineComment = true;\n i++;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n inBlockComment = true;\n i++;\n continue;\n }\n if (ch === \"'\") {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === \";\") {\n out.push({ sql: text.slice(start, i + 1), start, end: i + 1 });\n start = i + 1;\n }\n }\n if (start < text.length) {\n out.push({ sql: text.slice(start), start, end: text.length });\n }\n return out;\n}\n\n/** Resolve which SQL to run given the current selection and cursor position. */\nfunction resolveRunTarget(\n view: EditorView | undefined,\n buffer: string,\n): string {\n if (!view) return buffer;\n const sel = view.state.selection.main;\n if (!sel.empty) {\n return view.state.sliceDoc(sel.from, sel.to);\n }\n const cursor = sel.head;\n const statements = splitStatements(buffer);\n const hit = statements.find((s) => cursor >= s.start && cursor <= s.end);\n return (hit?.sql ?? buffer).trim() || buffer;\n}\n\n// ─── Local modal primitive ───────────────────────────────────────────────────\n\nfunction Modal({\n title,\n children,\n onClose,\n}: {\n title: string;\n children: ReactNode;\n onClose: () => void;\n}) {\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onClose]);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <div\n className=\"absolute inset-0 bg-black/50\"\n onClick={onClose}\n aria-hidden\n />\n <div className=\"relative z-10 w-full max-w-md rounded-lg border border-border bg-background shadow-xl\">\n <div className=\"flex items-center justify-between border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold text-foreground\">{title}</h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"cursor-pointer rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground\"\n aria-label=\"Close\"\n >\n <IconX size={16} />\n </button>\n </div>\n <div className=\"p-4\">{children}</div>\n </div>\n </div>\n );\n}\n\n// ─── Toolbar button ──────────────────────────────────────────────────────────\n\nfunction ToolbarButton({\n children,\n onClick,\n className,\n title,\n disabled,\n}: {\n children: ReactNode;\n onClick?: () => void;\n className?: string;\n title?: string;\n disabled?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={title}\n disabled={disabled}\n className={cn(\n \"inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n >\n {children}\n </button>\n );\n}\n\nconst isMac =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad/.test(navigator.platform);\nconst MOD = isMac ? \"Cmd\" : \"Ctrl\";\n\n// ─── Main component ──────────────────────────────────────────────────────────\n\nexport function SqlEditor({\n dialect,\n tableNames,\n columnsByTable,\n}: SqlEditorProps) {\n const isDark = useIsDark();\n const editorRef = useRef<ReactCodeMirrorRef>(null);\n\n const [value, setValue] = useState(\"\");\n const [running, setRunning] = useState(false);\n const [result, setResult] = useState<QueryResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [status, setStatus] = useState<string | null>(null);\n\n const [history, setHistory] = useState<string[]>([]);\n const [snippets, setSnippets] = useState<SqlSnippet[]>([]);\n\n const [confirmSql, setConfirmSql] = useState<string | null>(null);\n const [saveModalOpen, setSaveModalOpen] = useState(false);\n const [snippetName, setSnippetName] = useState(\"\");\n\n // Editor height (px) — draggable splitter between editor and results.\n const [editorHeight, setEditorHeight] = useState(240);\n const dragState = useRef<{ startY: number; startHeight: number } | null>(\n null,\n );\n\n // Keep the latest buffer accessible inside CodeMirror keymap closures.\n const valueRef = useRef(value);\n valueRef.current = value;\n\n useEffect(() => {\n setHistory(loadHistory());\n setSnippets(loadSnippets());\n }, []);\n\n // ─── Run logic ────────────────────────────────────────────────────────────\n\n const execute = useCallback(\n async (sqlText: string, confirmDestructive?: boolean) => {\n const trimmed = sqlText.trim();\n if (!trimmed) return;\n setRunning(true);\n setError(null);\n try {\n const res = await runQuery(trimmed, undefined, confirmDestructive);\n setResult({\n columns: res.columns,\n rows: res.rows,\n rowsAffected: res.rowsAffected,\n durationMs: res.durationMs,\n });\n if (res.columns.length > 0) {\n setStatus(`${res.rows.length} rows · ${res.durationMs}ms`);\n } else {\n setStatus(\n `Query OK · ${res.rowsAffected} rows affected · ${res.durationMs}ms`,\n );\n }\n setHistory(pushHistory(trimmed));\n } catch (err) {\n const e = err as Error & { needsConfirm?: boolean };\n if (e.needsConfirm) {\n setConfirmSql(trimmed);\n } else {\n setError(e.message || \"Query failed\");\n setStatus(null);\n }\n } finally {\n setRunning(false);\n }\n },\n [],\n );\n\n const runActiveStatement = useCallback(() => {\n const view = editorRef.current?.view;\n const target = resolveRunTarget(view, valueRef.current);\n void execute(target);\n }, [execute]);\n\n const runWholeBuffer = useCallback(() => {\n void execute(valueRef.current);\n }, [execute]);\n\n const confirmAndRun = useCallback(() => {\n const sqlText = confirmSql;\n setConfirmSql(null);\n if (sqlText) void execute(sqlText, true);\n }, [confirmSql, execute]);\n\n // ─── CodeMirror extensions ──────────────────────────────────────────────\n\n const extensions = useMemo(() => {\n const langExt = sql({\n dialect: dialect === \"postgres\" ? PostgreSQL : undefined,\n schema: columnsByTable,\n tables: tableNames.map((t) => ({ label: t })),\n upperCaseKeywords: true,\n });\n\n const runKeymap = Prec.highest(\n keymap.of([\n {\n key: \"Mod-Enter\",\n preventDefault: true,\n run: () => {\n runActiveStatement();\n return true;\n },\n },\n {\n key: \"Mod-Shift-Enter\",\n preventDefault: true,\n run: () => {\n runWholeBuffer();\n return true;\n },\n },\n ]),\n );\n\n return [runKeymap, langExt, EditorView.lineWrapping];\n // tableNames / columnsByTable identity is stable enough for our purposes;\n // re-derive when the dialect or schema reference changes.\n }, [dialect, columnsByTable, tableNames, runActiveStatement, runWholeBuffer]);\n\n // ─── Splitter drag ───────────────────────────────────────────────────────\n\n useEffect(() => {\n const onMove = (e: MouseEvent) => {\n if (!dragState.current) return;\n const delta = e.clientY - dragState.current.startY;\n const next = Math.min(\n Math.max(dragState.current.startHeight + delta, 120),\n 640,\n );\n setEditorHeight(next);\n };\n const onUp = () => {\n dragState.current = null;\n document.body.style.userSelect = \"\";\n };\n window.addEventListener(\"mousemove\", onMove);\n window.addEventListener(\"mouseup\", onUp);\n return () => {\n window.removeEventListener(\"mousemove\", onMove);\n window.removeEventListener(\"mouseup\", onUp);\n };\n }, []);\n\n const startDrag = (e: React.MouseEvent) => {\n dragState.current = { startY: e.clientY, startHeight: editorHeight };\n document.body.style.userSelect = \"none\";\n };\n\n // ─── Loading editor content from history / snippets ───────────────────────\n\n const loadIntoEditor = useCallback((sqlText: string) => {\n setValue(sqlText);\n // Focus and place cursor at end after the controlled value updates.\n requestAnimationFrame(() => {\n const view = editorRef.current?.view;\n if (view) {\n view.focus();\n view.dispatch({ selection: { anchor: view.state.doc.length } });\n }\n });\n }, []);\n\n // ─── Export ────────────────────────────────────────────────────────────────\n\n const exportAs = (format: \"csv\" | \"json\") => {\n if (!result || result.columns.length === 0) return;\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\").slice(0, 19);\n if (format === \"csv\") {\n downloadFile(\n `query-result-${stamp}.csv`,\n \"text/csv;charset=utf-8\",\n toCSV(result.columns, result.rows),\n );\n } else {\n downloadFile(\n `query-result-${stamp}.json`,\n \"application/json\",\n toJSON(result.rows),\n );\n }\n };\n\n // ─── Snippet save ────────────────────────────────────────────────────────\n\n const openSaveModal = () => {\n if (!value.trim()) return;\n setSnippetName(\"\");\n setSaveModalOpen(true);\n };\n\n const commitSnippet = () => {\n const name = snippetName.trim();\n if (!name || !value.trim()) return;\n setSnippets(saveSnippet({ name, sql: value }));\n setSaveModalOpen(false);\n };\n\n const removeSnippet = (id: string) => {\n setSnippets(deleteSnippet(id));\n };\n\n // ─── Example queries (empty state) ─────────────────────────────────────────\n\n const firstTable = tableNames[0];\n const examples = useMemo(() => {\n const list: { label: string; sql: string }[] = [];\n if (firstTable) {\n list.push({\n label: `Select rows from ${firstTable}`,\n sql: `SELECT * FROM ${firstTable} LIMIT 100;`,\n });\n }\n list.push({\n label: \"List tables\",\n sql:\n dialect === \"postgres\"\n ? \"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name;\"\n : \"SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;\",\n });\n if (firstTable) {\n list.push({\n label: `Count rows in ${firstTable}`,\n sql: `SELECT COUNT(*) AS total FROM ${firstTable};`,\n });\n }\n return list;\n }, [firstTable, dialect]);\n\n const hasResults = result !== null;\n const canExport = hasResults && result!.columns.length > 0;\n\n // ─── Render ──────────────────────────────────────────────────────────────\n\n return (\n <div className=\"flex h-full flex-col\">\n {/* Toolbar */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border bg-background px-3 py-2\">\n <button\n type=\"button\"\n onClick={runActiveStatement}\n disabled={running || !value.trim()}\n title={`Run selection / statement (${MOD}+Enter)`}\n className=\"inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md bg-primary px-3 text-xs font-semibold text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {running ? (\n <IconLoader2 size={14} className=\"animate-spin\" />\n ) : (\n <IconPlayerPlayFilled size={14} />\n )}\n Run\n </button>\n\n <span className=\"hidden text-[11px] text-muted-foreground sm:inline\">\n {MOD}+Enter runs selection / statement · {MOD}+Shift+Enter runs all\n </span>\n\n <div className=\"ml-auto flex items-center gap-2\">\n {/* History */}\n <Popover>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Query history\">\n <IconHistory size={14} />\n History\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-96 p-0\">\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2\">\n <span className=\"text-xs font-semibold text-foreground\">\n Recent queries\n </span>\n {history.length > 0 && (\n <button\n type=\"button\"\n onClick={() => {\n clearHistory();\n setHistory([]);\n }}\n className=\"cursor-pointer text-[11px] text-muted-foreground hover:text-foreground\"\n >\n Clear\n </button>\n )}\n </div>\n <div className=\"max-h-80 overflow-auto py-1\">\n {history.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-xs text-muted-foreground\">\n No queries yet\n </div>\n ) : (\n history.map((h, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={() => loadIntoEditor(h)}\n className=\"block w-full cursor-pointer truncate px-3 py-1.5 text-left font-mono text-[11px] text-foreground hover:bg-accent\"\n title={h}\n >\n {h.replace(/\\s+/g, \" \").trim()}\n </button>\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n\n {/* Snippets */}\n <Popover>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Saved snippets\">\n <IconBookmark size={14} />\n Snippets\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-96 p-0\">\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2\">\n <span className=\"text-xs font-semibold text-foreground\">\n Saved snippets\n </span>\n <button\n type=\"button\"\n onClick={openSaveModal}\n disabled={!value.trim()}\n className=\"inline-flex cursor-pointer items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconBookmarkPlus size={13} />\n Save current\n </button>\n </div>\n <div className=\"max-h-80 overflow-auto py-1\">\n {snippets.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-xs text-muted-foreground\">\n No saved snippets\n </div>\n ) : (\n snippets.map((s) => (\n <div\n key={s.id}\n className=\"group flex items-center gap-2 px-3 py-1.5 hover:bg-accent\"\n >\n <button\n type=\"button\"\n onClick={() => loadIntoEditor(s.sql)}\n className=\"min-w-0 flex-1 cursor-pointer text-left\"\n title={s.sql}\n >\n <div className=\"truncate text-xs font-medium text-foreground\">\n {s.name}\n </div>\n <div className=\"truncate font-mono text-[10px] text-muted-foreground\">\n {s.sql.replace(/\\s+/g, \" \").trim()}\n </div>\n </button>\n <button\n type=\"button\"\n onClick={() => removeSnippet(s.id)}\n className=\"cursor-pointer rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:text-red-500 group-hover:opacity-100\"\n title=\"Delete snippet\"\n >\n <IconTrash size={13} />\n </button>\n </div>\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n\n {/* Export */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <ToolbarButton title=\"Export results\" disabled={!canExport}>\n <IconDownload size={14} />\n Export\n <IconChevronDown size={12} className=\"opacity-60\" />\n </ToolbarButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => exportAs(\"csv\")}>\n Download CSV\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => exportAs(\"json\")}>\n Download JSON\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n\n {/* Editor pane */}\n <div\n className=\"shrink-0 overflow-hidden border-b border-border\"\n style={{ height: editorHeight }}\n >\n <CodeMirror\n ref={editorRef}\n value={value}\n onChange={setValue}\n height={`${editorHeight}px`}\n theme={isDark ? oneDark : undefined}\n extensions={extensions}\n placeholder=\"Write SQL here…\"\n basicSetup={{\n lineNumbers: true,\n highlightActiveLine: true,\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n }}\n style={{ fontSize: 13, height: \"100%\" }}\n />\n </div>\n\n {/* Splitter */}\n <div\n onMouseDown={startDrag}\n className=\"h-1.5 shrink-0 cursor-row-resize bg-border/40 transition-colors hover:bg-primary/40\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n />\n\n {/* Status / error bar */}\n {(status || error) && (\n <div className=\"shrink-0 px-3 py-1.5\">\n {error ? (\n <div className=\"flex items-start gap-2 rounded-md border border-red-500/40 bg-red-500/10 px-3 py-2 text-xs text-red-500\">\n <IconAlertTriangle size={14} className=\"mt-px shrink-0\" />\n <span className=\"break-words font-mono\">{error}</span>\n </div>\n ) : (\n <div className=\"font-mono text-[11px] text-muted-foreground\">\n {status}\n </div>\n )}\n </div>\n )}\n\n {/* Results panel */}\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n {hasResults ? (\n <ResultsGrid columns={result!.columns} rows={result!.rows} />\n ) : (\n <div className=\"flex h-full flex-col items-center justify-center gap-4 p-6 text-center\">\n <div className=\"text-sm text-muted-foreground\">\n Run a query to see results, or start with an example:\n </div>\n <div className=\"flex flex-col gap-2\">\n {examples.map((ex, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={() => loadIntoEditor(ex.sql)}\n className=\"cursor-pointer rounded-md border border-border bg-background px-4 py-2 text-left transition-colors hover:bg-accent\"\n >\n <div className=\"text-xs font-medium text-foreground\">\n {ex.label}\n </div>\n <div className=\"mt-0.5 font-mono text-[11px] text-muted-foreground\">\n {ex.sql}\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Destructive-confirm modal */}\n {confirmSql && (\n <Modal\n title=\"Confirm destructive query\"\n onClose={() => setConfirmSql(null)}\n >\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-2 text-sm text-foreground\">\n <IconAlertTriangle\n size={18}\n className=\"mt-px shrink-0 text-yellow-500\"\n />\n <p>\n This looks like a destructive query (DROP / TRUNCATE / DELETE\n without WHERE). Run it?\n </p>\n </div>\n <pre className=\"max-h-40 overflow-auto rounded-md border border-border bg-muted/50 p-3 font-mono text-[11px] text-foreground\">\n {confirmSql}\n </pre>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => setConfirmSql(null)}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={confirmAndRun}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md bg-red-500 px-3 text-xs font-semibold text-white hover:bg-red-600\"\n >\n Run anyway\n </button>\n </div>\n </div>\n </Modal>\n )}\n\n {/* Save-snippet modal */}\n {saveModalOpen && (\n <Modal title=\"Save snippet\" onClose={() => setSaveModalOpen(false)}>\n <div className=\"space-y-4\">\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-muted-foreground\">\n Snippet name\n </label>\n <input\n autoFocus\n value={snippetName}\n onChange={(e) => setSnippetName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") commitSnippet();\n }}\n placeholder=\"e.g. Active users this week\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary focus:ring-1 focus:ring-primary\"\n />\n </div>\n <pre className=\"max-h-40 overflow-auto rounded-md border border-border bg-muted/50 p-3 font-mono text-[11px] text-foreground\">\n {value.trim()}\n </pre>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => setSaveModalOpen(false)}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={commitSnippet}\n disabled={!snippetName.trim()}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md bg-primary px-3 text-xs font-semibold text-primary-foreground hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Save\n </button>\n </div>\n </div>\n </Modal>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SqlEditor.js","sourceRoot":"","sources":["../../../src/client/db-admin/SqlEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { sql, PostgreSQL } from \"@codemirror/lang-sql\";\nimport { oneDark } from \"@codemirror/theme-one-dark\";\nimport {\n IconPlayerPlayFilled,\n IconHistory,\n IconBookmark,\n IconBookmarkPlus,\n IconDownload,\n IconAlertTriangle,\n IconLoader2,\n IconTrash,\n IconX,\n IconChevronDown,\n} from \"@tabler/icons-react\";\nimport CodeMirror, {\n type ReactCodeMirrorRef,\n EditorView,\n keymap,\n Prec,\n} from \"@uiw/react-codemirror\";\n/**\n * Production-grade SQL editor for the dev-mode database admin.\n *\n * Layout: a CodeMirror editor pane on top, a resizable results panel below.\n * Features schema-aware autocomplete, keyboard run shortcuts, history, named\n * snippets, CSV/JSON export, and a confirm modal for destructive statements.\n *\n * Data access goes through `runQuery` from `./useDbAdmin.js` (the shared\n * contract). On a destructive statement without confirmation, `runQuery` throws\n * an Error whose `needsConfirm` flag is `true`; we catch that and re-run after\n * the user confirms in a locally-built modal.\n */\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nimport type { DbAdminDialect } from \"../../db-admin/types.js\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"../components/ui/dropdown-menu.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { cn } from \"../utils.js\";\nimport { toCSV, toJSON, downloadFile } from \"./export-utils.js\";\nimport { ResultsGrid } from \"./ResultsGrid.js\";\nimport {\n loadHistory,\n pushHistory,\n clearHistory,\n loadSnippets,\n saveSnippet,\n deleteSnippet,\n type SqlSnippet,\n} from \"./sql-storage.js\";\nimport { runQuery, type DbAdminRequestConfig } from \"./useDbAdmin.js\";\n\nexport interface SqlEditorProps {\n dialect: DbAdminDialect;\n tableNames: string[];\n columnsByTable: Record<string, string[]>;\n requestConfig?: DbAdminRequestConfig;\n}\n\ninterface QueryResult {\n columns: string[];\n rows: Record<string, unknown>[];\n rowsAffected: number;\n durationMs: number;\n}\n\n// ─── Dark-mode detection ─────────────────────────────────────────────────────\n\nfunction useIsDark(): boolean {\n const [isDark, setIsDark] = useState(false);\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n const update = () => setIsDark(root.classList.contains(\"dark\"));\n update();\n const observer = new MutationObserver(update);\n observer.observe(root, { attributes: true, attributeFilter: [\"class\"] });\n return () => observer.disconnect();\n }, []);\n return isDark;\n}\n\n// ─── Statement-under-cursor helpers ──────────────────────────────────────────\n\n/**\n * Best-effort split of a SQL buffer into statements by top-level `;`, ignoring\n * semicolons inside single/double quotes or line/block comments. Returns each\n * statement with its character offsets so we can pick the one under the cursor.\n */\nfunction splitStatements(\n text: string,\n): { sql: string; start: number; end: number }[] {\n const out: { sql: string; start: number; end: number }[] = [];\n let start = 0;\n let inSingle = false;\n let inDouble = false;\n let inLineComment = false;\n let inBlockComment = false;\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n const next = text[i + 1];\n\n if (inLineComment) {\n if (ch === \"\\n\") inLineComment = false;\n continue;\n }\n if (inBlockComment) {\n if (ch === \"*\" && next === \"/\") {\n inBlockComment = false;\n i++;\n }\n continue;\n }\n if (inSingle) {\n if (ch === \"'\") inSingle = false;\n continue;\n }\n if (inDouble) {\n if (ch === '\"') inDouble = false;\n continue;\n }\n\n if (ch === \"-\" && next === \"-\") {\n inLineComment = true;\n i++;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n inBlockComment = true;\n i++;\n continue;\n }\n if (ch === \"'\") {\n inSingle = true;\n continue;\n }\n if (ch === '\"') {\n inDouble = true;\n continue;\n }\n if (ch === \";\") {\n out.push({ sql: text.slice(start, i + 1), start, end: i + 1 });\n start = i + 1;\n }\n }\n if (start < text.length) {\n out.push({ sql: text.slice(start), start, end: text.length });\n }\n return out;\n}\n\n/** Resolve which SQL to run given the current selection and cursor position. */\nfunction resolveRunTarget(\n view: EditorView | undefined,\n buffer: string,\n): string {\n if (!view) return buffer;\n const sel = view.state.selection.main;\n if (!sel.empty) {\n return view.state.sliceDoc(sel.from, sel.to);\n }\n const cursor = sel.head;\n const statements = splitStatements(buffer);\n const hit = statements.find((s) => cursor >= s.start && cursor <= s.end);\n return (hit?.sql ?? buffer).trim() || buffer;\n}\n\n// ─── Local modal primitive ───────────────────────────────────────────────────\n\nfunction Modal({\n title,\n children,\n onClose,\n}: {\n title: string;\n children: ReactNode;\n onClose: () => void;\n}) {\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onClose]);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <div\n className=\"absolute inset-0 bg-black/50\"\n onClick={onClose}\n aria-hidden\n />\n <div className=\"relative z-10 w-full max-w-md rounded-lg border border-border bg-background shadow-xl\">\n <div className=\"flex items-center justify-between border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold text-foreground\">{title}</h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"cursor-pointer rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground\"\n aria-label=\"Close\"\n >\n <IconX size={16} />\n </button>\n </div>\n <div className=\"p-4\">{children}</div>\n </div>\n </div>\n );\n}\n\n// ─── Toolbar button ──────────────────────────────────────────────────────────\n\nfunction ToolbarButton({\n children,\n onClick,\n className,\n title,\n disabled,\n}: {\n children: ReactNode;\n onClick?: () => void;\n className?: string;\n title?: string;\n disabled?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={title}\n disabled={disabled}\n className={cn(\n \"inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n >\n {children}\n </button>\n );\n}\n\nconst isMac =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad/.test(navigator.platform);\nconst MOD = isMac ? \"Cmd\" : \"Ctrl\";\n\n// ─── Main component ──────────────────────────────────────────────────────────\n\nexport function SqlEditor({\n dialect,\n tableNames,\n columnsByTable,\n requestConfig,\n}: SqlEditorProps) {\n const isDark = useIsDark();\n const editorRef = useRef<ReactCodeMirrorRef>(null);\n\n const [value, setValue] = useState(\"\");\n const [running, setRunning] = useState(false);\n const [result, setResult] = useState<QueryResult | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [status, setStatus] = useState<string | null>(null);\n\n const [history, setHistory] = useState<string[]>([]);\n const [snippets, setSnippets] = useState<SqlSnippet[]>([]);\n\n const [confirmSql, setConfirmSql] = useState<string | null>(null);\n const [saveModalOpen, setSaveModalOpen] = useState(false);\n const [snippetName, setSnippetName] = useState(\"\");\n\n // Editor height (px) — draggable splitter between editor and results.\n const [editorHeight, setEditorHeight] = useState(240);\n const dragState = useRef<{ startY: number; startHeight: number } | null>(\n null,\n );\n\n // Keep the latest buffer accessible inside CodeMirror keymap closures.\n const valueRef = useRef(value);\n valueRef.current = value;\n\n useEffect(() => {\n setHistory(loadHistory());\n setSnippets(loadSnippets());\n }, []);\n\n // ─── Run logic ────────────────────────────────────────────────────────────\n\n const execute = useCallback(\n async (sqlText: string, confirmDestructive?: boolean) => {\n const trimmed = sqlText.trim();\n if (!trimmed) return;\n setRunning(true);\n setError(null);\n try {\n const res = await runQuery(\n trimmed,\n undefined,\n confirmDestructive,\n requestConfig,\n );\n setResult({\n columns: res.columns,\n rows: res.rows,\n rowsAffected: res.rowsAffected,\n durationMs: res.durationMs,\n });\n if (res.columns.length > 0) {\n setStatus(`${res.rows.length} rows · ${res.durationMs}ms`);\n } else {\n setStatus(\n `Query OK · ${res.rowsAffected} rows affected · ${res.durationMs}ms`,\n );\n }\n setHistory(pushHistory(trimmed));\n } catch (err) {\n const e = err as Error & { needsConfirm?: boolean };\n if (e.needsConfirm) {\n setConfirmSql(trimmed);\n } else {\n setError(e.message || \"Query failed\");\n setStatus(null);\n }\n } finally {\n setRunning(false);\n }\n },\n [requestConfig],\n );\n\n const runActiveStatement = useCallback(() => {\n const view = editorRef.current?.view;\n const target = resolveRunTarget(view, valueRef.current);\n void execute(target);\n }, [execute]);\n\n const runWholeBuffer = useCallback(() => {\n void execute(valueRef.current);\n }, [execute]);\n\n const confirmAndRun = useCallback(() => {\n const sqlText = confirmSql;\n setConfirmSql(null);\n if (sqlText) void execute(sqlText, true);\n }, [confirmSql, execute]);\n\n // ─── CodeMirror extensions ──────────────────────────────────────────────\n\n const extensions = useMemo(() => {\n const langExt = sql({\n dialect: dialect === \"postgres\" ? PostgreSQL : undefined,\n schema: columnsByTable,\n tables: tableNames.map((t) => ({ label: t })),\n upperCaseKeywords: true,\n });\n\n const runKeymap = Prec.highest(\n keymap.of([\n {\n key: \"Mod-Enter\",\n preventDefault: true,\n run: () => {\n runActiveStatement();\n return true;\n },\n },\n {\n key: \"Mod-Shift-Enter\",\n preventDefault: true,\n run: () => {\n runWholeBuffer();\n return true;\n },\n },\n ]),\n );\n\n return [runKeymap, langExt, EditorView.lineWrapping];\n // tableNames / columnsByTable identity is stable enough for our purposes;\n // re-derive when the dialect or schema reference changes.\n }, [dialect, columnsByTable, tableNames, runActiveStatement, runWholeBuffer]);\n\n // ─── Splitter drag ───────────────────────────────────────────────────────\n\n useEffect(() => {\n const onMove = (e: MouseEvent) => {\n if (!dragState.current) return;\n const delta = e.clientY - dragState.current.startY;\n const next = Math.min(\n Math.max(dragState.current.startHeight + delta, 120),\n 640,\n );\n setEditorHeight(next);\n };\n const onUp = () => {\n dragState.current = null;\n document.body.style.userSelect = \"\";\n };\n window.addEventListener(\"mousemove\", onMove);\n window.addEventListener(\"mouseup\", onUp);\n return () => {\n window.removeEventListener(\"mousemove\", onMove);\n window.removeEventListener(\"mouseup\", onUp);\n };\n }, []);\n\n const startDrag = (e: React.MouseEvent) => {\n dragState.current = { startY: e.clientY, startHeight: editorHeight };\n document.body.style.userSelect = \"none\";\n };\n\n // ─── Loading editor content from history / snippets ───────────────────────\n\n const loadIntoEditor = useCallback((sqlText: string) => {\n setValue(sqlText);\n // Focus and place cursor at end after the controlled value updates.\n requestAnimationFrame(() => {\n const view = editorRef.current?.view;\n if (view) {\n view.focus();\n view.dispatch({ selection: { anchor: view.state.doc.length } });\n }\n });\n }, []);\n\n // ─── Export ────────────────────────────────────────────────────────────────\n\n const exportAs = (format: \"csv\" | \"json\") => {\n if (!result || result.columns.length === 0) return;\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\").slice(0, 19);\n if (format === \"csv\") {\n downloadFile(\n `query-result-${stamp}.csv`,\n \"text/csv;charset=utf-8\",\n toCSV(result.columns, result.rows),\n );\n } else {\n downloadFile(\n `query-result-${stamp}.json`,\n \"application/json\",\n toJSON(result.rows),\n );\n }\n };\n\n // ─── Snippet save ────────────────────────────────────────────────────────\n\n const openSaveModal = () => {\n if (!value.trim()) return;\n setSnippetName(\"\");\n setSaveModalOpen(true);\n };\n\n const commitSnippet = () => {\n const name = snippetName.trim();\n if (!name || !value.trim()) return;\n setSnippets(saveSnippet({ name, sql: value }));\n setSaveModalOpen(false);\n };\n\n const removeSnippet = (id: string) => {\n setSnippets(deleteSnippet(id));\n };\n\n // ─── Example queries (empty state) ─────────────────────────────────────────\n\n const firstTable = tableNames[0];\n const examples = useMemo(() => {\n const list: { label: string; sql: string }[] = [];\n if (firstTable) {\n list.push({\n label: `Select rows from ${firstTable}`,\n sql: `SELECT * FROM ${firstTable} LIMIT 100;`,\n });\n }\n list.push({\n label: \"List tables\",\n sql:\n dialect === \"postgres\"\n ? \"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name;\"\n : \"SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name;\",\n });\n if (firstTable) {\n list.push({\n label: `Count rows in ${firstTable}`,\n sql: `SELECT COUNT(*) AS total FROM ${firstTable};`,\n });\n }\n return list;\n }, [firstTable, dialect]);\n\n const hasResults = result !== null;\n const canExport = hasResults && result!.columns.length > 0;\n\n // ─── Render ──────────────────────────────────────────────────────────────\n\n return (\n <div className=\"flex h-full flex-col\">\n {/* Toolbar */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border bg-background px-3 py-2\">\n <button\n type=\"button\"\n onClick={runActiveStatement}\n disabled={running || !value.trim()}\n title={`Run selection / statement (${MOD}+Enter)`}\n className=\"inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-md bg-primary px-3 text-xs font-semibold text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {running ? (\n <IconLoader2 size={14} className=\"animate-spin\" />\n ) : (\n <IconPlayerPlayFilled size={14} />\n )}\n Run\n </button>\n\n <span className=\"hidden text-[11px] text-muted-foreground sm:inline\">\n {MOD}+Enter runs selection / statement · {MOD}+Shift+Enter runs all\n </span>\n\n <div className=\"ml-auto flex items-center gap-2\">\n {/* History */}\n <Popover>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Query history\">\n <IconHistory size={14} />\n History\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-96 p-0\">\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2\">\n <span className=\"text-xs font-semibold text-foreground\">\n Recent queries\n </span>\n {history.length > 0 && (\n <button\n type=\"button\"\n onClick={() => {\n clearHistory();\n setHistory([]);\n }}\n className=\"cursor-pointer text-[11px] text-muted-foreground hover:text-foreground\"\n >\n Clear\n </button>\n )}\n </div>\n <div className=\"max-h-80 overflow-auto py-1\">\n {history.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-xs text-muted-foreground\">\n No queries yet\n </div>\n ) : (\n history.map((h, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={() => loadIntoEditor(h)}\n className=\"block w-full cursor-pointer truncate px-3 py-1.5 text-left font-mono text-[11px] text-foreground hover:bg-accent\"\n title={h}\n >\n {h.replace(/\\s+/g, \" \").trim()}\n </button>\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n\n {/* Snippets */}\n <Popover>\n <PopoverTrigger asChild>\n <ToolbarButton title=\"Saved snippets\">\n <IconBookmark size={14} />\n Snippets\n </ToolbarButton>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-96 p-0\">\n <div className=\"flex items-center justify-between border-b border-border px-3 py-2\">\n <span className=\"text-xs font-semibold text-foreground\">\n Saved snippets\n </span>\n <button\n type=\"button\"\n onClick={openSaveModal}\n disabled={!value.trim()}\n className=\"inline-flex cursor-pointer items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <IconBookmarkPlus size={13} />\n Save current\n </button>\n </div>\n <div className=\"max-h-80 overflow-auto py-1\">\n {snippets.length === 0 ? (\n <div className=\"px-3 py-6 text-center text-xs text-muted-foreground\">\n No saved snippets\n </div>\n ) : (\n snippets.map((s) => (\n <div\n key={s.id}\n className=\"group flex items-center gap-2 px-3 py-1.5 hover:bg-accent\"\n >\n <button\n type=\"button\"\n onClick={() => loadIntoEditor(s.sql)}\n className=\"min-w-0 flex-1 cursor-pointer text-left\"\n title={s.sql}\n >\n <div className=\"truncate text-xs font-medium text-foreground\">\n {s.name}\n </div>\n <div className=\"truncate font-mono text-[10px] text-muted-foreground\">\n {s.sql.replace(/\\s+/g, \" \").trim()}\n </div>\n </button>\n <button\n type=\"button\"\n onClick={() => removeSnippet(s.id)}\n className=\"cursor-pointer rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:text-red-500 group-hover:opacity-100\"\n title=\"Delete snippet\"\n >\n <IconTrash size={13} />\n </button>\n </div>\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n\n {/* Export */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <ToolbarButton title=\"Export results\" disabled={!canExport}>\n <IconDownload size={14} />\n Export\n <IconChevronDown size={12} className=\"opacity-60\" />\n </ToolbarButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => exportAs(\"csv\")}>\n Download CSV\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => exportAs(\"json\")}>\n Download JSON\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n\n {/* Editor pane */}\n <div\n className=\"shrink-0 overflow-hidden border-b border-border\"\n style={{ height: editorHeight }}\n >\n <CodeMirror\n ref={editorRef}\n value={value}\n onChange={setValue}\n height={`${editorHeight}px`}\n theme={isDark ? oneDark : undefined}\n extensions={extensions}\n placeholder=\"Write SQL here…\"\n basicSetup={{\n lineNumbers: true,\n highlightActiveLine: true,\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n }}\n style={{ fontSize: 13, height: \"100%\" }}\n />\n </div>\n\n {/* Splitter */}\n <div\n onMouseDown={startDrag}\n className=\"h-1.5 shrink-0 cursor-row-resize bg-border/40 transition-colors hover:bg-primary/40\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n />\n\n {/* Status / error bar */}\n {(status || error) && (\n <div className=\"shrink-0 px-3 py-1.5\">\n {error ? (\n <div className=\"flex items-start gap-2 rounded-md border border-red-500/40 bg-red-500/10 px-3 py-2 text-xs text-red-500\">\n <IconAlertTriangle size={14} className=\"mt-px shrink-0\" />\n <span className=\"break-words font-mono\">{error}</span>\n </div>\n ) : (\n <div className=\"font-mono text-[11px] text-muted-foreground\">\n {status}\n </div>\n )}\n </div>\n )}\n\n {/* Results panel */}\n <div className=\"min-h-0 flex-1 overflow-hidden\">\n {hasResults ? (\n <ResultsGrid columns={result!.columns} rows={result!.rows} />\n ) : (\n <div className=\"flex h-full flex-col items-center justify-center gap-4 p-6 text-center\">\n <div className=\"text-sm text-muted-foreground\">\n Run a query to see results, or start with an example:\n </div>\n <div className=\"flex flex-col gap-2\">\n {examples.map((ex, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={() => loadIntoEditor(ex.sql)}\n className=\"cursor-pointer rounded-md border border-border bg-background px-4 py-2 text-left transition-colors hover:bg-accent\"\n >\n <div className=\"text-xs font-medium text-foreground\">\n {ex.label}\n </div>\n <div className=\"mt-0.5 font-mono text-[11px] text-muted-foreground\">\n {ex.sql}\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Destructive-confirm modal */}\n {confirmSql && (\n <Modal\n title=\"Confirm destructive query\"\n onClose={() => setConfirmSql(null)}\n >\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-2 text-sm text-foreground\">\n <IconAlertTriangle\n size={18}\n className=\"mt-px shrink-0 text-yellow-500\"\n />\n <p>\n This looks like a destructive query (DROP / TRUNCATE / DELETE\n without WHERE). Run it?\n </p>\n </div>\n <pre className=\"max-h-40 overflow-auto rounded-md border border-border bg-muted/50 p-3 font-mono text-[11px] text-foreground\">\n {confirmSql}\n </pre>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => setConfirmSql(null)}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={confirmAndRun}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md bg-red-500 px-3 text-xs font-semibold text-white hover:bg-red-600\"\n >\n Run anyway\n </button>\n </div>\n </div>\n </Modal>\n )}\n\n {/* Save-snippet modal */}\n {saveModalOpen && (\n <Modal title=\"Save snippet\" onClose={() => setSaveModalOpen(false)}>\n <div className=\"space-y-4\">\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-muted-foreground\">\n Snippet name\n </label>\n <input\n autoFocus\n value={snippetName}\n onChange={(e) => setSnippetName(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") commitSnippet();\n }}\n placeholder=\"e.g. Active users this week\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground outline-none focus:border-primary focus:ring-1 focus:ring-primary\"\n />\n </div>\n <pre className=\"max-h-40 overflow-auto rounded-md border border-border bg-muted/50 p-3 font-mono text-[11px] text-foreground\">\n {value.trim()}\n </pre>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => setSaveModalOpen(false)}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={commitSnippet}\n disabled={!snippetName.trim()}\n className=\"inline-flex h-8 cursor-pointer items-center rounded-md bg-primary px-3 text-xs font-semibold text-primary-foreground hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Save\n </button>\n </div>\n </div>\n </Modal>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { DbAdminDialect, DbAdminFilter } from "../../db-admin/types.js";
|
|
2
|
+
import { type DbAdminRequestConfig } from "./useDbAdmin.js";
|
|
2
3
|
export interface TableEditorProps {
|
|
3
4
|
table: string;
|
|
4
5
|
dialect: DbAdminDialect;
|
|
6
|
+
requestConfig?: DbAdminRequestConfig;
|
|
5
7
|
initialFilters?: DbAdminFilter[];
|
|
6
8
|
onNavigateToRow: (table: string, filters: DbAdminFilter[]) => void;
|
|
7
9
|
}
|
|
8
|
-
export declare function TableEditor({ table, dialect: _dialect, initialFilters, onNavigateToRow, }: TableEditorProps): import("react").JSX.Element;
|
|
10
|
+
export declare function TableEditor({ table, dialect: _dialect, requestConfig, initialFilters, onNavigateToRow, }: TableEditorProps): import("react").JSX.Element;
|
|
9
11
|
//# sourceMappingURL=TableEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableEditor.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/TableEditor.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAId,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"TableEditor.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/TableEditor.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAId,MAAM,yBAAyB,CAAC;AAYjC,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;CACpE;AAKD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EAAE,QAAQ,EACjB,aAAa,EACb,cAAc,EACd,eAAe,GAChB,EAAE,gBAAgB,+BAqelB"}
|