@agent-native/core 0.30.6 → 0.31.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/dist/a2a/client.d.ts +2 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +7 -5
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/handlers.d.ts.map +1 -1
- package/dist/a2a/handlers.js +3 -0
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/server.d.ts.map +1 -1
- package/dist/a2a/server.js.map +1 -1
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +5 -1
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/action.js +22 -4
- package/dist/action.js.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +5 -0
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +0 -7
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +4 -0
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
- package/dist/agent/engine/translate-ai-sdk.js +5 -3
- package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +31 -4
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +21 -8
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +5 -1
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/tool-search.js.map +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +18 -7
- package/dist/application-state/store.js.map +1 -1
- package/dist/brand-kit/brand-signals.d.ts +31 -0
- package/dist/brand-kit/brand-signals.d.ts.map +1 -0
- package/dist/brand-kit/brand-signals.js +101 -0
- package/dist/brand-kit/brand-signals.js.map +1 -0
- package/dist/brand-kit/index.d.ts +21 -0
- package/dist/brand-kit/index.d.ts.map +1 -0
- package/dist/brand-kit/index.js +34 -0
- package/dist/brand-kit/index.js.map +1 -0
- package/dist/brand-kit/types.d.ts +103 -0
- package/dist/brand-kit/types.d.ts.map +1 -0
- package/dist/brand-kit/types.js +17 -0
- package/dist/brand-kit/types.js.map +1 -0
- package/dist/browser-sessions/store.d.ts.map +1 -1
- package/dist/browser-sessions/store.js +6 -1
- package/dist/browser-sessions/store.js.map +1 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +6 -2
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/store.d.ts.map +1 -1
- package/dist/checkpoints/store.js +5 -1
- package/dist/checkpoints/store.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +0 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/client/AgentNative.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +18 -20
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +69 -17
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/IframeEmbed.d.ts.map +1 -1
- package/dist/client/IframeEmbed.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/agent-chat.d.ts +0 -3
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +0 -3
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/builder-mark.d.ts.map +1 -1
- package/dist/client/builder-mark.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +0 -7
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/client/components/MissingKeyCard.d.ts.map +1 -1
- package/dist/client/components/MissingKeyCard.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +6 -3
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +5 -0
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/VoiceButton.js +9 -0
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/composer/extensions/FileReference.d.ts.map +1 -1
- package/dist/client/composer/extensions/FileReference.js.map +1 -1
- package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -1
- package/dist/client/composer/extensions/MentionReference.js.map +1 -1
- package/dist/client/composer/extensions/SkillReference.d.ts.map +1 -1
- package/dist/client/composer/extensions/SkillReference.js.map +1 -1
- package/dist/client/composer/use-file-search.d.ts.map +1 -1
- package/dist/client/composer/use-file-search.js +14 -3
- package/dist/client/composer/use-file-search.js.map +1 -1
- package/dist/client/conversation/AgentConversation.js +8 -6
- package/dist/client/conversation/AgentConversation.js.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js +133 -35
- package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
- package/dist/client/db-admin/DbAdminPage.js.map +1 -1
- package/dist/client/db-admin/EditableCell.js +1 -1
- package/dist/client/db-admin/EditableCell.js.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.d.ts +0 -2
- package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.js +1 -2
- package/dist/client/dev-overlay/DevOverlay.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +19 -0
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +11 -3
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/mcp-app-host.d.ts.map +1 -1
- package/dist/client/mcp-app-host.js +25 -3
- package/dist/client/mcp-app-host.js.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.js +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/client/notifications/NotificationsBell.js.map +1 -1
- package/dist/client/onboarding/SetupButton.d.ts.map +1 -1
- package/dist/client/onboarding/SetupButton.js +6 -0
- package/dist/client/onboarding/SetupButton.js.map +1 -1
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/resources/McpServerDetail.d.ts.map +1 -1
- package/dist/client/resources/McpServerDetail.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +0 -1
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/settings/AgentsSection.d.ts.map +1 -1
- package/dist/client/settings/AgentsSection.js +1 -1
- package/dist/client/settings/AgentsSection.js.map +1 -1
- package/dist/client/settings/AutomationsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.js +2 -2
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +0 -4
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +13 -3
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
- package/dist/client/terminal/AgentTerminal.js +1 -1
- package/dist/client/terminal/AgentTerminal.js.map +1 -1
- package/dist/client/use-agent-chat.d.ts.map +1 -1
- package/dist/client/use-agent-chat.js +20 -4
- package/dist/client/use-agent-chat.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +39 -25
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +24 -0
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-dev-mode.d.ts.map +1 -1
- package/dist/client/use-dev-mode.js +25 -9
- package/dist/client/use-dev-mode.js.map +1 -1
- package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
- package/dist/client/use-run-stuck-detection.js +7 -1
- package/dist/client/use-run-stuck-detection.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +6 -2
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/collab/agent-presence.d.ts +0 -3
- package/dist/collab/agent-presence.d.ts.map +1 -1
- package/dist/collab/agent-presence.js +3 -5
- package/dist/collab/agent-presence.js.map +1 -1
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/awareness.js +11 -1
- package/dist/collab/awareness.js.map +1 -1
- package/dist/collab/client-struct.js.map +1 -1
- package/dist/collab/storage.d.ts.map +1 -1
- package/dist/collab/storage.js +5 -1
- package/dist/collab/storage.js.map +1 -1
- package/dist/collab/ydoc-manager.d.ts.map +1 -1
- package/dist/collab/ydoc-manager.js +35 -8
- package/dist/collab/ydoc-manager.js.map +1 -1
- package/dist/deploy/build.js +0 -5
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/content-patch.js +1 -1
- package/dist/extensions/content-patch.js.map +1 -1
- package/dist/extensions/fetch-tool.d.ts.map +1 -1
- package/dist/extensions/fetch-tool.js +4 -1
- package/dist/extensions/fetch-tool.js.map +1 -1
- package/dist/extensions/routes.js +12 -12
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/slots/store.d.ts.map +1 -1
- package/dist/extensions/slots/store.js +5 -1
- package/dist/extensions/slots/store.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts.map +1 -1
- package/dist/file-upload/actions/upload-image.js +39 -4
- package/dist/file-upload/actions/upload-image.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +5 -1
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/adapters/email.d.ts.map +1 -1
- package/dist/integrations/adapters/email.js +5 -2
- package/dist/integrations/adapters/email.js.map +1 -1
- package/dist/integrations/adapters/slack.d.ts.map +1 -1
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/google-docs-poller.d.ts.map +1 -1
- package/dist/integrations/google-docs-poller.js +16 -5
- package/dist/integrations/google-docs-poller.js.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +6 -2
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-store.js +5 -1
- package/dist/integrations/pending-tasks-store.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +14 -3
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/remote-commands-store.d.ts.map +1 -1
- package/dist/integrations/remote-commands-store.js +5 -1
- package/dist/integrations/remote-commands-store.js.map +1 -1
- package/dist/integrations/remote-devices-store.d.ts.map +1 -1
- package/dist/integrations/remote-devices-store.js +5 -1
- package/dist/integrations/remote-devices-store.js.map +1 -1
- package/dist/integrations/remote-push-store.d.ts.map +1 -1
- package/dist/integrations/remote-push-store.js +5 -1
- package/dist/integrations/remote-push-store.js.map +1 -1
- package/dist/integrations/remote-retry-job.js +1 -1
- package/dist/integrations/remote-retry-job.js.map +1 -1
- package/dist/integrations/remote-run-events-store.d.ts.map +1 -1
- package/dist/integrations/remote-run-events-store.js +5 -1
- package/dist/integrations/remote-run-events-store.js.map +1 -1
- package/dist/integrations/thread-mapping-store.d.ts.map +1 -1
- package/dist/integrations/thread-mapping-store.js +5 -1
- package/dist/integrations/thread-mapping-store.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +10 -1
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +31 -15
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/jobs/tools.d.ts.map +1 -1
- package/dist/jobs/tools.js +4 -1
- package/dist/jobs/tools.js.map +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +24 -9
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/connect-store.d.ts +3 -4
- package/dist/mcp/connect-store.d.ts.map +1 -1
- package/dist/mcp/connect-store.js +5 -5
- package/dist/mcp/connect-store.js.map +1 -1
- package/dist/mcp-client/routes.js +6 -1
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/notifications/channels.d.ts.map +1 -1
- package/dist/notifications/channels.js +3 -2
- package/dist/notifications/channels.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +5 -1
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/observability/evals.d.ts.map +1 -1
- package/dist/observability/evals.js +7 -7
- package/dist/observability/evals.js.map +1 -1
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +15 -5
- package/dist/observability/traces.js.map +1 -1
- package/dist/org/accept-pending.js +1 -1
- package/dist/org/accept-pending.js.map +1 -1
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +3 -2
- package/dist/org/handlers.js.map +1 -1
- package/dist/progress/store.d.ts.map +1 -1
- package/dist/progress/store.js +11 -1
- package/dist/progress/store.js.map +1 -1
- package/dist/resources/handlers.d.ts +5 -5
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +0 -2
- package/dist/resources/handlers.js.map +1 -1
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +23 -13
- package/dist/resources/store.js.map +1 -1
- package/dist/scripts/db/query.d.ts.map +1 -1
- package/dist/scripts/db/query.js +1 -2
- package/dist/scripts/db/query.js.map +1 -1
- package/dist/scripts/db/schema.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +10 -3
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +13 -9
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +0 -3
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +1 -2
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +0 -23
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +0 -3
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/identity-sso-store.d.ts.map +1 -1
- package/dist/server/identity-sso-store.js +14 -3
- package/dist/server/identity-sso-store.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +67 -18
- package/dist/server/poll.js.map +1 -1
- package/dist/server/schema-prompt.js +1 -1
- package/dist/server/schema-prompt.js.map +1 -1
- package/dist/server/security-headers.d.ts +5 -4
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +5 -4
- package/dist/server/security-headers.js.map +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +5 -1
- package/dist/settings/store.js.map +1 -1
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +25 -4
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +8 -1
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/triggers/actions.d.ts.map +1 -1
- package/dist/triggers/actions.js +1 -2
- package/dist/triggers/actions.js.map +1 -1
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +36 -8
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +5 -1
- package/dist/usage/store.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +7 -5
- package/dist/vite/client.js.map +1 -1
- package/package.json +3 -2
- package/dist/client/conversation/AgentConversation.spec.d.ts +0 -2
- package/dist/client/conversation/AgentConversation.spec.d.ts.map +0 -1
- package/dist/client/conversation/AgentConversation.spec.js +0 -69
- package/dist/client/conversation/AgentConversation.spec.js.map +0 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.d.ts +0 -2
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.d.ts.map +0 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.js +0 -110
- package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.js.map +0 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.d.ts +0 -2
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.d.ts.map +0 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.js +0 -68
- package/dist/client/extensions/AgentNativeExtensionFrame.spec.js.map +0 -1
- package/dist/client/extensions/ExtensionViewer.spec.d.ts +0 -2
- package/dist/client/extensions/ExtensionViewer.spec.d.ts.map +0 -1
- package/dist/client/extensions/ExtensionViewer.spec.js +0 -94
- package/dist/client/extensions/ExtensionViewer.spec.js.map +0 -1
- package/dist/client/guided-questions.flow.spec.d.ts +0 -2
- package/dist/client/guided-questions.flow.spec.d.ts.map +0 -1
- package/dist/client/guided-questions.flow.spec.js +0 -147
- package/dist/client/guided-questions.flow.spec.js.map +0 -1
- package/dist/client/settings/useBuilderStatus.spec.d.ts +0 -2
- package/dist/client/settings/useBuilderStatus.spec.d.ts.map +0 -1
- package/dist/client/settings/useBuilderStatus.spec.js +0 -487
- package/dist/client/settings/useBuilderStatus.spec.js.map +0 -1
- package/dist/client/sharing/ShareButton.spec.d.ts +0 -2
- package/dist/client/sharing/ShareButton.spec.d.ts.map +0 -1
- package/dist/client/sharing/ShareButton.spec.js +0 -196
- package/dist/client/sharing/ShareButton.spec.js.map +0 -1
- package/dist/client/use-chat-models.spec.d.ts +0 -2
- package/dist/client/use-chat-models.spec.d.ts.map +0 -1
- package/dist/client/use-chat-models.spec.js +0 -39
- package/dist/client/use-chat-models.spec.js.map +0 -1
- package/dist/client/use-chat-threads.spec.d.ts +0 -2
- package/dist/client/use-chat-threads.spec.d.ts.map +0 -1
- package/dist/client/use-chat-threads.spec.js +0 -760
- package/dist/client/use-chat-threads.spec.js.map +0 -1
- package/dist/client/use-db-sync.spec.d.ts +0 -2
- package/dist/client/use-db-sync.spec.d.ts.map +0 -1
- package/dist/client/use-db-sync.spec.js +0 -107
- package/dist/client/use-db-sync.spec.js.map +0 -1
- package/dist/server/script-discovery.d.ts +0 -6
- package/dist/server/script-discovery.d.ts.map +0 -1
- package/dist/server/script-discovery.js +0 -6
- package/dist/server/script-discovery.js.map +0 -1
|
@@ -1,62 +1,161 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
export function useNearBottomAutoscroll({ followKey, streaming = false, threshold =
|
|
2
|
+
export function useNearBottomAutoscroll({ followKey, streaming = false, threshold = 4, enabled = true, }) {
|
|
3
3
|
const scrollRef = useRef(null);
|
|
4
4
|
const isNearBottomRef = useRef(true);
|
|
5
|
+
const followGenerationRef = useRef(0);
|
|
6
|
+
const lastScrollTopRef = useRef(0);
|
|
7
|
+
const lastTouchYRef = useRef(null);
|
|
5
8
|
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
|
|
6
|
-
const
|
|
9
|
+
const isAtBottom = useCallback((el) => el.scrollHeight - el.scrollTop - el.clientHeight <= threshold, [threshold]);
|
|
10
|
+
const setFollowingBottom = useCallback((following, forceGeneration = false, el) => {
|
|
11
|
+
if (forceGeneration || isNearBottomRef.current !== following) {
|
|
12
|
+
followGenerationRef.current += 1;
|
|
13
|
+
}
|
|
14
|
+
isNearBottomRef.current = following;
|
|
15
|
+
const canScroll = !el || el.scrollHeight > el.clientHeight + threshold;
|
|
16
|
+
setShowScrollToBottom(!following && canScroll);
|
|
17
|
+
}, [threshold]);
|
|
18
|
+
const detachFromBottom = useCallback(() => {
|
|
19
|
+
setFollowingBottom(false, true, scrollRef.current ?? undefined);
|
|
20
|
+
}, [setFollowingBottom]);
|
|
21
|
+
const updateBottomState = useCallback(() => {
|
|
7
22
|
const el = scrollRef.current;
|
|
8
23
|
if (!el)
|
|
9
24
|
return;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
if (isAtBottom(el))
|
|
26
|
+
setFollowingBottom(true, false, el);
|
|
27
|
+
else if (!isNearBottomRef.current) {
|
|
28
|
+
setShowScrollToBottom(el.scrollHeight > el.clientHeight + threshold);
|
|
29
|
+
}
|
|
30
|
+
}, [isAtBottom, setFollowingBottom, threshold]);
|
|
31
|
+
const scrollToBottomIfFollowing = useCallback((generation) => {
|
|
32
|
+
if (followGenerationRef.current !== generation ||
|
|
33
|
+
!isNearBottomRef.current) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const el = scrollRef.current;
|
|
37
|
+
if (!el)
|
|
38
|
+
return;
|
|
39
|
+
el.scrollTop = Math.max(0, el.scrollHeight - el.clientHeight);
|
|
40
|
+
lastScrollTopRef.current = el.scrollTop;
|
|
41
|
+
setFollowingBottom(true, false, el);
|
|
42
|
+
}, [setFollowingBottom]);
|
|
14
43
|
const scrollToBottom = useCallback(() => {
|
|
15
44
|
const el = scrollRef.current;
|
|
16
45
|
if (!el)
|
|
17
46
|
return;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}, []);
|
|
47
|
+
setFollowingBottom(true, true, el);
|
|
48
|
+
el.scrollTop = Math.max(0, el.scrollHeight - el.clientHeight);
|
|
49
|
+
lastScrollTopRef.current = el.scrollTop;
|
|
50
|
+
}, [setFollowingBottom]);
|
|
22
51
|
useEffect(() => {
|
|
23
52
|
const el = scrollRef.current;
|
|
24
53
|
if (!el || !enabled)
|
|
25
54
|
return;
|
|
26
|
-
|
|
55
|
+
lastScrollTopRef.current = el.scrollTop;
|
|
56
|
+
const onWheel = (event) => {
|
|
57
|
+
if (event.deltaY < 0)
|
|
58
|
+
detachFromBottom();
|
|
59
|
+
};
|
|
60
|
+
const onTouchStart = (event) => {
|
|
61
|
+
lastTouchYRef.current = event.touches[0]?.clientY ?? null;
|
|
62
|
+
};
|
|
63
|
+
const onTouchMove = (event) => {
|
|
64
|
+
const nextTouchY = event.touches[0]?.clientY;
|
|
65
|
+
if (nextTouchY == null)
|
|
66
|
+
return;
|
|
67
|
+
const lastTouchY = lastTouchYRef.current;
|
|
68
|
+
if (lastTouchY != null && nextTouchY > lastTouchY) {
|
|
69
|
+
detachFromBottom();
|
|
70
|
+
}
|
|
71
|
+
lastTouchYRef.current = nextTouchY;
|
|
72
|
+
};
|
|
73
|
+
const onTouchEnd = () => {
|
|
74
|
+
lastTouchYRef.current = null;
|
|
75
|
+
};
|
|
76
|
+
const onScroll = () => {
|
|
77
|
+
const previousScrollTop = lastScrollTopRef.current;
|
|
78
|
+
const nextScrollTop = el.scrollTop;
|
|
79
|
+
lastScrollTopRef.current = nextScrollTop;
|
|
80
|
+
if (nextScrollTop < previousScrollTop) {
|
|
81
|
+
detachFromBottom();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
updateBottomState();
|
|
85
|
+
};
|
|
86
|
+
const onKeyDown = (event) => {
|
|
87
|
+
if (event.key === "ArrowUp" ||
|
|
88
|
+
event.key === "PageUp" ||
|
|
89
|
+
event.key === "Home" ||
|
|
90
|
+
(event.key === " " && event.shiftKey)) {
|
|
91
|
+
detachFromBottom();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
el.addEventListener("wheel", onWheel, { passive: true });
|
|
95
|
+
el.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
96
|
+
el.addEventListener("touchmove", onTouchMove, { passive: true });
|
|
97
|
+
el.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
98
|
+
el.addEventListener("touchcancel", onTouchEnd, { passive: true });
|
|
27
99
|
el.addEventListener("scroll", onScroll, { passive: true });
|
|
28
|
-
|
|
100
|
+
el.addEventListener("keydown", onKeyDown);
|
|
101
|
+
updateBottomState();
|
|
29
102
|
// Re-check near-bottom whenever the scroll container's content grows
|
|
30
103
|
// (e.g. new messages appended, images loaded, tool-call details expanded).
|
|
31
104
|
// Without this the "near bottom" flag can get stuck as `false` even though
|
|
32
105
|
// the user never scrolled away — the container just grew taller.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
106
|
+
let ro = null;
|
|
107
|
+
let mo = null;
|
|
108
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
109
|
+
const observeResizeTargets = () => {
|
|
110
|
+
ro?.disconnect();
|
|
111
|
+
ro = new ResizeObserver(() => {
|
|
112
|
+
if (isNearBottomRef.current) {
|
|
113
|
+
scrollToBottomIfFollowing(followGenerationRef.current);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
updateBottomState();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
ro.observe(el);
|
|
120
|
+
// Also watch direct children so inline content changes are caught.
|
|
121
|
+
for (const child of Array.from(el.children))
|
|
122
|
+
ro.observe(child);
|
|
123
|
+
};
|
|
124
|
+
observeResizeTargets();
|
|
125
|
+
if (typeof MutationObserver !== "undefined") {
|
|
126
|
+
mo = new MutationObserver(() => {
|
|
127
|
+
observeResizeTargets();
|
|
128
|
+
if (isNearBottomRef.current) {
|
|
129
|
+
scrollToBottomIfFollowing(followGenerationRef.current);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
mo.observe(el, { childList: true });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
43
135
|
return () => {
|
|
136
|
+
el.removeEventListener("wheel", onWheel);
|
|
137
|
+
el.removeEventListener("touchstart", onTouchStart);
|
|
138
|
+
el.removeEventListener("touchmove", onTouchMove);
|
|
139
|
+
el.removeEventListener("touchend", onTouchEnd);
|
|
140
|
+
el.removeEventListener("touchcancel", onTouchEnd);
|
|
44
141
|
el.removeEventListener("scroll", onScroll);
|
|
45
|
-
|
|
142
|
+
el.removeEventListener("keydown", onKeyDown);
|
|
143
|
+
ro?.disconnect();
|
|
144
|
+
mo?.disconnect();
|
|
46
145
|
};
|
|
47
|
-
}, [enabled,
|
|
146
|
+
}, [detachFromBottom, enabled, scrollToBottomIfFollowing, updateBottomState]);
|
|
48
147
|
const scrollToBottomAfterPaint = useCallback(() => {
|
|
49
|
-
|
|
148
|
+
const generation = followGenerationRef.current;
|
|
149
|
+
scrollToBottomIfFollowing(generation);
|
|
50
150
|
requestAnimationFrame(() => {
|
|
51
|
-
|
|
52
|
-
requestAnimationFrame(
|
|
151
|
+
scrollToBottomIfFollowing(generation);
|
|
152
|
+
requestAnimationFrame(() => scrollToBottomIfFollowing(generation));
|
|
53
153
|
});
|
|
54
|
-
window.setTimeout(
|
|
55
|
-
}, [
|
|
154
|
+
window.setTimeout(() => scrollToBottomIfFollowing(generation), 80);
|
|
155
|
+
}, [scrollToBottomIfFollowing]);
|
|
56
156
|
const markNearBottom = useCallback(() => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}, []);
|
|
157
|
+
setFollowingBottom(true, true, scrollRef.current ?? undefined);
|
|
158
|
+
}, [setFollowingBottom]);
|
|
60
159
|
useEffect(() => {
|
|
61
160
|
if (!enabled || !isNearBottomRef.current)
|
|
62
161
|
return;
|
|
@@ -66,11 +165,10 @@ export function useNearBottomAutoscroll({ followKey, streaming = false, threshol
|
|
|
66
165
|
if (!enabled || !streaming)
|
|
67
166
|
return;
|
|
68
167
|
const id = window.setInterval(() => {
|
|
69
|
-
|
|
70
|
-
scrollToBottom();
|
|
168
|
+
scrollToBottomIfFollowing(followGenerationRef.current);
|
|
71
169
|
}, 100);
|
|
72
170
|
return () => window.clearInterval(id);
|
|
73
|
-
}, [enabled,
|
|
171
|
+
}, [enabled, scrollToBottomIfFollowing, streaming]);
|
|
74
172
|
return {
|
|
75
173
|
scrollRef,
|
|
76
174
|
isNearBottomRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-near-bottom-autoscroll.js","sourceRoot":"","sources":["../../../src/client/conversation/use-near-bottom-autoscroll.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface UseNearBottomAutoscrollOptions {\n followKey: unknown;\n streaming?: boolean;\n threshold?: number;\n enabled?: boolean;\n}\n\nexport function useNearBottomAutoscroll<TElement extends HTMLElement>({\n followKey,\n streaming = false,\n threshold = 40,\n enabled = true,\n}: UseNearBottomAutoscrollOptions) {\n const scrollRef = useRef<TElement | null>(null);\n const isNearBottomRef = useRef(true);\n const [showScrollToBottom, setShowScrollToBottom] = useState(false);\n\n const updateNearBottom = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n const nearBottom =\n el.scrollHeight - el.scrollTop - el.clientHeight < threshold;\n isNearBottomRef.current = nearBottom;\n setShowScrollToBottom(!nearBottom);\n }, [threshold]);\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n el.scrollTop = el.scrollHeight;\n isNearBottomRef.current = true;\n setShowScrollToBottom(false);\n }, []);\n\n useEffect(() => {\n const el = scrollRef.current;\n if (!el || !enabled) return;\n const onScroll = () => updateNearBottom();\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n updateNearBottom();\n\n // Re-check near-bottom whenever the scroll container's content grows\n // (e.g. new messages appended, images loaded, tool-call details expanded).\n // Without this the \"near bottom\" flag can get stuck as `false` even though\n // the user never scrolled away — the container just grew taller.\n const ro = new ResizeObserver(() => {\n if (isNearBottomRef.current) scrollToBottom();\n else updateNearBottom();\n });\n ro.observe(el);\n // Also watch direct children so inline content changes are caught.\n for (const child of Array.from(el.children)) ro.observe(child);\n\n return () => {\n el.removeEventListener(\"scroll\", onScroll);\n ro.disconnect();\n };\n }, [enabled, updateNearBottom, scrollToBottom]);\n\n const scrollToBottomAfterPaint = useCallback(() => {\n scrollToBottom();\n requestAnimationFrame(() => {\n scrollToBottom();\n requestAnimationFrame(scrollToBottom);\n });\n window.setTimeout(scrollToBottom, 80);\n }, [scrollToBottom]);\n\n const markNearBottom = useCallback(() => {\n isNearBottomRef.current = true;\n setShowScrollToBottom(false);\n }, []);\n\n useEffect(() => {\n if (!enabled || !isNearBottomRef.current) return;\n scrollToBottomAfterPaint();\n }, [enabled, followKey, scrollToBottomAfterPaint]);\n\n useEffect(() => {\n if (!enabled || !streaming) return;\n const id = window.setInterval(() => {\n if (isNearBottomRef.current) scrollToBottom();\n }, 100);\n return () => window.clearInterval(id);\n }, [enabled, scrollToBottom, streaming]);\n\n return {\n scrollRef,\n isNearBottomRef,\n showScrollToBottom,\n markNearBottom,\n scrollToBottom,\n scrollToBottomAfterPaint,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-near-bottom-autoscroll.js","sourceRoot":"","sources":["../../../src/client/conversation/use-near-bottom-autoscroll.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface UseNearBottomAutoscrollOptions {\n followKey: unknown;\n streaming?: boolean;\n threshold?: number;\n enabled?: boolean;\n}\n\nexport function useNearBottomAutoscroll<TElement extends HTMLElement>({\n followKey,\n streaming = false,\n threshold = 4,\n enabled = true,\n}: UseNearBottomAutoscrollOptions) {\n const scrollRef = useRef<TElement | null>(null);\n const isNearBottomRef = useRef(true);\n const followGenerationRef = useRef(0);\n const lastScrollTopRef = useRef(0);\n const lastTouchYRef = useRef<number | null>(null);\n const [showScrollToBottom, setShowScrollToBottom] = useState(false);\n\n const isAtBottom = useCallback(\n (el: HTMLElement) =>\n el.scrollHeight - el.scrollTop - el.clientHeight <= threshold,\n [threshold],\n );\n\n const setFollowingBottom = useCallback(\n (following: boolean, forceGeneration = false, el?: HTMLElement) => {\n if (forceGeneration || isNearBottomRef.current !== following) {\n followGenerationRef.current += 1;\n }\n isNearBottomRef.current = following;\n const canScroll = !el || el.scrollHeight > el.clientHeight + threshold;\n setShowScrollToBottom(!following && canScroll);\n },\n [threshold],\n );\n\n const detachFromBottom = useCallback(() => {\n setFollowingBottom(false, true, scrollRef.current ?? undefined);\n }, [setFollowingBottom]);\n\n const updateBottomState = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n if (isAtBottom(el)) setFollowingBottom(true, false, el);\n else if (!isNearBottomRef.current) {\n setShowScrollToBottom(el.scrollHeight > el.clientHeight + threshold);\n }\n }, [isAtBottom, setFollowingBottom, threshold]);\n\n const scrollToBottomIfFollowing = useCallback(\n (generation: number) => {\n if (\n followGenerationRef.current !== generation ||\n !isNearBottomRef.current\n ) {\n return;\n }\n const el = scrollRef.current;\n if (!el) return;\n el.scrollTop = Math.max(0, el.scrollHeight - el.clientHeight);\n lastScrollTopRef.current = el.scrollTop;\n setFollowingBottom(true, false, el);\n },\n [setFollowingBottom],\n );\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n setFollowingBottom(true, true, el);\n el.scrollTop = Math.max(0, el.scrollHeight - el.clientHeight);\n lastScrollTopRef.current = el.scrollTop;\n }, [setFollowingBottom]);\n\n useEffect(() => {\n const el = scrollRef.current;\n if (!el || !enabled) return;\n lastScrollTopRef.current = el.scrollTop;\n\n const onWheel = (event: WheelEvent) => {\n if (event.deltaY < 0) detachFromBottom();\n };\n\n const onTouchStart = (event: TouchEvent) => {\n lastTouchYRef.current = event.touches[0]?.clientY ?? null;\n };\n\n const onTouchMove = (event: TouchEvent) => {\n const nextTouchY = event.touches[0]?.clientY;\n if (nextTouchY == null) return;\n const lastTouchY = lastTouchYRef.current;\n if (lastTouchY != null && nextTouchY > lastTouchY) {\n detachFromBottom();\n }\n lastTouchYRef.current = nextTouchY;\n };\n\n const onTouchEnd = () => {\n lastTouchYRef.current = null;\n };\n\n const onScroll = () => {\n const previousScrollTop = lastScrollTopRef.current;\n const nextScrollTop = el.scrollTop;\n lastScrollTopRef.current = nextScrollTop;\n if (nextScrollTop < previousScrollTop) {\n detachFromBottom();\n return;\n }\n updateBottomState();\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === \"ArrowUp\" ||\n event.key === \"PageUp\" ||\n event.key === \"Home\" ||\n (event.key === \" \" && event.shiftKey)\n ) {\n detachFromBottom();\n }\n };\n el.addEventListener(\"wheel\", onWheel, { passive: true });\n el.addEventListener(\"touchstart\", onTouchStart, { passive: true });\n el.addEventListener(\"touchmove\", onTouchMove, { passive: true });\n el.addEventListener(\"touchend\", onTouchEnd, { passive: true });\n el.addEventListener(\"touchcancel\", onTouchEnd, { passive: true });\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n el.addEventListener(\"keydown\", onKeyDown);\n updateBottomState();\n\n // Re-check near-bottom whenever the scroll container's content grows\n // (e.g. new messages appended, images loaded, tool-call details expanded).\n // Without this the \"near bottom\" flag can get stuck as `false` even though\n // the user never scrolled away — the container just grew taller.\n let ro: ResizeObserver | null = null;\n let mo: MutationObserver | null = null;\n if (typeof ResizeObserver !== \"undefined\") {\n const observeResizeTargets = () => {\n ro?.disconnect();\n ro = new ResizeObserver(() => {\n if (isNearBottomRef.current) {\n scrollToBottomIfFollowing(followGenerationRef.current);\n } else {\n updateBottomState();\n }\n });\n ro.observe(el);\n // Also watch direct children so inline content changes are caught.\n for (const child of Array.from(el.children)) ro.observe(child);\n };\n observeResizeTargets();\n if (typeof MutationObserver !== \"undefined\") {\n mo = new MutationObserver(() => {\n observeResizeTargets();\n if (isNearBottomRef.current) {\n scrollToBottomIfFollowing(followGenerationRef.current);\n }\n });\n mo.observe(el, { childList: true });\n }\n }\n\n return () => {\n el.removeEventListener(\"wheel\", onWheel);\n el.removeEventListener(\"touchstart\", onTouchStart);\n el.removeEventListener(\"touchmove\", onTouchMove);\n el.removeEventListener(\"touchend\", onTouchEnd);\n el.removeEventListener(\"touchcancel\", onTouchEnd);\n el.removeEventListener(\"scroll\", onScroll);\n el.removeEventListener(\"keydown\", onKeyDown);\n ro?.disconnect();\n mo?.disconnect();\n };\n }, [detachFromBottom, enabled, scrollToBottomIfFollowing, updateBottomState]);\n\n const scrollToBottomAfterPaint = useCallback(() => {\n const generation = followGenerationRef.current;\n scrollToBottomIfFollowing(generation);\n requestAnimationFrame(() => {\n scrollToBottomIfFollowing(generation);\n requestAnimationFrame(() => scrollToBottomIfFollowing(generation));\n });\n window.setTimeout(() => scrollToBottomIfFollowing(generation), 80);\n }, [scrollToBottomIfFollowing]);\n\n const markNearBottom = useCallback(() => {\n setFollowingBottom(true, true, scrollRef.current ?? undefined);\n }, [setFollowingBottom]);\n\n useEffect(() => {\n if (!enabled || !isNearBottomRef.current) return;\n scrollToBottomAfterPaint();\n }, [enabled, followKey, scrollToBottomAfterPaint]);\n\n useEffect(() => {\n if (!enabled || !streaming) return;\n const id = window.setInterval(() => {\n scrollToBottomIfFollowing(followGenerationRef.current);\n }, 100);\n return () => window.clearInterval(id);\n }, [enabled, scrollToBottomIfFollowing, streaming]);\n\n return {\n scrollRef,\n isNearBottomRef,\n showScrollToBottom,\n markNearBottom,\n scrollToBottom,\n scrollToBottomAfterPaint,\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DbAdminPage.js","sourceRoot":"","sources":["../../../src/client/db-admin/DbAdminPage.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\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\";\nimport { IconDatabase, IconLoader2 } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { useCodeMode } from \"../use-dev-mode.js\";\nimport type { DbAdminFilter, DbAdminColumn } from \"../../db-admin/types.js\";\nimport { useOverview } from \"./useDbAdmin.js\";\nimport { TableBrowser } from \"./TableBrowser.js\";\nimport { useDbAdminAgentSync, useNavigateConsumer } from \"./useAgentSync.js\";\nimport { TableEditor } from \"./TableEditor.js\";\nimport { SqlEditor } from \"./SqlEditor.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":["/**\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\";\nimport { IconDatabase, IconLoader2 } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport { useCodeMode } from \"../use-dev-mode.js\";\nimport type { DbAdminFilter } from \"../../db-admin/types.js\";\nimport { useOverview } from \"./useDbAdmin.js\";\nimport { TableBrowser } from \"./TableBrowser.js\";\nimport { useDbAdminAgentSync, useNavigateConsumer } from \"./useAgentSync.js\";\nimport { TableEditor } from \"./TableEditor.js\";\nimport { SqlEditor } from \"./SqlEditor.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"]}
|
|
@@ -74,7 +74,7 @@ function InlineTextEditor({ kind, value, nullable, onCommit, onCancel, onNavigat
|
|
|
74
74
|
setError(err instanceof ParseError ? err.message : String(err));
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
|
-
return (_jsxs("div", { className: "relative h-full w-full", children: [_jsx("input", { ref: ref, type:
|
|
77
|
+
return (_jsxs("div", { className: "relative h-full w-full", children: [_jsx("input", { ref: ref, type: "text", inputMode: kind === "number" ? "decimal" : undefined, value: text, onChange: (e) => setText(e.target.value), onBlur: () => commit(), onKeyDown: (e) => {
|
|
78
78
|
if (e.key === "Enter") {
|
|
79
79
|
e.preventDefault();
|
|
80
80
|
commit("down");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditableCell.js","sourceRoot":"","sources":["../../../src/client/db-admin/EditableCell.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n IconChevronDown,\n IconCircleX,\n IconMaximize,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n type EditorKind,\n formatCellValue,\n inferEnumValues,\n valueToEditString,\n parseEditValue,\n ParseError,\n cycleTriStateBoolean,\n formatJsonPretty,\n} from \"./cell-format.js\";\nimport type { DbAdminColumn } from \"../../db-admin/types.js\";\n\nexport interface EditableCellProps {\n column: DbAdminColumn;\n kind: EditorKind;\n value: unknown;\n /** Whether this cell holds a staged (uncommitted) edit. */\n dirty?: boolean;\n /** Whether editing is allowed (false when the table has no PK). */\n editable?: boolean;\n /** Whether this cell is the keyboard-focused/active cell in the grid. */\n active?: boolean;\n /** True if the editor should open immediately (e.g. typing began). */\n editing?: boolean;\n /** Commit a new value into the changeset. */\n onCommit: (value: unknown) => void;\n /** Request entering edit mode. */\n onStartEdit?: () => void;\n /** Request leaving edit mode without committing. */\n onCancelEdit?: () => void;\n /** Move focus after Enter (\"down\") or Tab (\"right\"). */\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n className?: string;\n}\n\nconst NULL_TOKEN = (\n <span className=\"italic text-muted-foreground/60 select-none\">NULL</span>\n);\n\nexport function EditableCell({\n column,\n kind,\n value,\n dirty,\n editable = true,\n active,\n editing,\n onCommit,\n onStartEdit,\n onCancelEdit,\n onNavigate,\n className,\n}: EditableCellProps) {\n const display = formatCellValue(value, kind);\n\n // Boolean cells toggle in place rather than opening a text editor.\n if (kind === \"boolean\") {\n return (\n <BooleanCell\n value={value}\n dirty={dirty}\n editable={editable}\n active={active}\n onCommit={onCommit}\n onNavigate={onNavigate}\n className={className}\n />\n );\n }\n\n const baseCell = cn(\n \"relative h-full w-full px-2 py-1 text-xs truncate outline-none\",\n \"font-mono\",\n active && \"ring-1 ring-inset ring-ring\",\n dirty && \"bg-amber-500/10 ring-1 ring-inset ring-amber-500/50\",\n editable && \"cursor-text\",\n className,\n );\n\n if (editing && editable) {\n if (kind === \"enum\") {\n return (\n <EnumEditor\n column={column}\n value={value}\n onCommit={onCommit}\n onCancel={onCancelEdit}\n onNavigate={onNavigate}\n />\n );\n }\n if (kind === \"json\") {\n return (\n <JsonEditor value={value} onCommit={onCommit} onCancel={onCancelEdit} />\n );\n }\n return (\n <InlineTextEditor\n kind={kind}\n value={value}\n nullable={column.nullable}\n onCommit={onCommit}\n onCancel={onCancelEdit}\n onNavigate={onNavigate}\n />\n );\n }\n\n return (\n <div\n role=\"gridcell\"\n tabIndex={active ? 0 : -1}\n className={baseCell}\n onDoubleClick={() => editable && onStartEdit?.()}\n onKeyDown={(e) => {\n if (!editable) return;\n if (e.key === \"Enter\" || e.key === \"F2\") {\n e.preventDefault();\n onStartEdit?.();\n }\n }}\n title={display.isNull ? \"NULL\" : display.text}\n >\n <div className=\"flex items-center gap-1\">\n <span className=\"truncate\">\n {display.isNull ? NULL_TOKEN : display.text}\n </span>\n {editable && (kind === \"json\" || kind === \"text\") && (\n <button\n type=\"button\"\n tabIndex={-1}\n onClick={(e) => {\n e.stopPropagation();\n onStartEdit?.();\n }}\n className=\"ml-auto shrink-0 text-muted-foreground/50 opacity-0 hover:text-foreground group-hover:opacity-100\"\n aria-label=\"Expand editor\"\n >\n <IconMaximize className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n </div>\n );\n}\n\n// ─── Boolean (tri-state) ─────────────────────────────────────────────────────\n\nfunction BooleanCell({\n value,\n dirty,\n editable,\n active,\n onCommit,\n onNavigate,\n className,\n}: {\n value: unknown;\n dirty?: boolean;\n editable: boolean;\n active?: boolean;\n onCommit: (v: unknown) => void;\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n className?: string;\n}) {\n const label = value === true ? \"true\" : value === false ? \"false\" : null;\n return (\n <div\n role=\"gridcell\"\n tabIndex={active ? 0 : -1}\n className={cn(\n \"h-full w-full px-2 py-1 text-xs font-mono outline-none cursor-pointer select-none\",\n active && \"ring-1 ring-inset ring-ring\",\n dirty && \"bg-amber-500/10 ring-1 ring-inset ring-amber-500/50\",\n className,\n )}\n onClick={() => editable && onCommit(cycleTriStateBoolean(value))}\n onKeyDown={(e) => {\n if (!editable) return;\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n onCommit(cycleTriStateBoolean(value));\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n onNavigate?.(\"down\");\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n onNavigate?.(\"up\");\n }\n }}\n >\n {label === null ? NULL_TOKEN : label}\n </div>\n );\n}\n\n// ─── Inline text / number / timestamp / uuid editor ──────────────────────────\n\nfunction InlineTextEditor({\n kind,\n value,\n nullable,\n onCommit,\n onCancel,\n onNavigate,\n}: {\n kind: EditorKind;\n value: unknown;\n nullable: boolean;\n onCommit: (v: unknown) => void;\n onCancel?: () => void;\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n}) {\n const ref = useRef<HTMLInputElement>(null);\n const [text, setText] = useState(() => valueToEditString(value, kind));\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n ref.current?.focus();\n ref.current?.select();\n }, []);\n\n const commit = (nav?: \"down\" | \"right\") => {\n try {\n const parsed = parseEditValue(text, kind);\n setError(null);\n onCommit(parsed);\n if (nav) onNavigate?.(nav);\n } catch (err) {\n setError(err instanceof ParseError ? err.message : String(err));\n }\n };\n\n return (\n <div className=\"relative h-full w-full\">\n <input\n ref={ref}\n type={kind === \"number\" ? \"text\" : \"text\"}\n inputMode={kind === \"number\" ? \"decimal\" : undefined}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={() => commit()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n commit(\"down\");\n } else if (e.key === \"Tab\") {\n e.preventDefault();\n commit(\"right\");\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n onCancel?.();\n }\n }}\n className={cn(\n \"h-full w-full bg-background px-2 py-1 text-xs font-mono outline-none\",\n \"ring-2 ring-inset ring-ring\",\n error && \"ring-destructive\",\n )}\n />\n {nullable && (\n <button\n type=\"button\"\n tabIndex={-1}\n title=\"Set NULL\"\n onMouseDown={(e) => {\n e.preventDefault();\n onCommit(null);\n }}\n className=\"absolute right-1 top-1/2 -translate-y-1/2 text-muted-foreground/50 hover:text-foreground\"\n >\n <IconCircleX className=\"h-3.5 w-3.5\" />\n </button>\n )}\n {error && (\n <div className=\"absolute left-0 top-full z-50 mt-0.5 rounded border border-destructive bg-popover px-2 py-1 text-[11px] text-destructive shadow-md\">\n {error}\n </div>\n )}\n </div>\n );\n}\n\n// ─── Enum (select) editor ────────────────────────────────────────────────────\n\nfunction EnumEditor({\n column,\n value,\n onCommit,\n onCancel,\n onNavigate,\n}: {\n column: DbAdminColumn;\n value: unknown;\n onCommit: (v: unknown) => void;\n onCancel?: () => void;\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n}) {\n const ref = useRef<HTMLSelectElement>(null);\n const options = inferEnumValues(column) ?? [];\n\n useEffect(() => {\n ref.current?.focus();\n }, []);\n\n return (\n <select\n ref={ref}\n defaultValue={value === null || value === undefined ? \"\" : String(value)}\n onChange={(e) => {\n const v = e.target.value;\n onCommit(v === \"\" ? null : v);\n onNavigate?.(\"down\");\n }}\n onBlur={() => onCancel?.()}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") onCancel?.();\n }}\n className=\"h-full w-full appearance-none bg-background px-2 py-1 text-xs font-mono outline-none ring-2 ring-inset ring-ring\"\n >\n {column.nullable && <option value=\"\">NULL</option>}\n {options.map((opt) => (\n <option key={opt} value={opt}>\n {opt}\n </option>\n ))}\n </select>\n );\n}\n\n// ─── JSON / long-text expanding editor ───────────────────────────────────────\n\nfunction JsonEditor({\n value,\n onCommit,\n onCancel,\n}: {\n value: unknown;\n onCommit: (v: unknown) => void;\n onCancel?: () => void;\n}) {\n const [open, setOpen] = useState(true);\n const [text, setText] = useState(() => formatJsonPretty(value));\n const [error, setError] = useState<string | null>(null);\n\n const commit = () => {\n if (text.trim() === \"\") {\n onCommit(null);\n setOpen(false);\n return;\n }\n try {\n const parsed = parseEditValue(text, \"json\");\n setError(null);\n onCommit(parsed);\n setOpen(false);\n } catch (err) {\n setError(err instanceof ParseError ? err.message : String(err));\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n if (!o) onCancel?.();\n setOpen(o);\n }}\n >\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"flex h-full w-full items-center gap-1 px-2 py-1 text-xs font-mono ring-2 ring-inset ring-ring outline-none\"\n >\n <span className=\"truncate\">{formatJsonPretty(value) || \"{}\"}</span>\n <IconChevronDown className=\"ml-auto h-3 w-3 shrink-0\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"w-[28rem] p-2\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <textarea\n autoFocus\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n commit();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n onCancel?.();\n }\n }}\n rows={10}\n spellCheck={false}\n className={cn(\n \"w-full resize-y rounded border border-border bg-background p-2 font-mono text-xs outline-none focus:ring-1 focus:ring-ring\",\n error && \"border-destructive\",\n )}\n />\n {error && (\n <div className=\"mt-1 text-[11px] text-destructive\">{error}</div>\n )}\n <div className=\"mt-2 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={() => {\n onCommit(null);\n setOpen(false);\n }}\n className=\"rounded px-2 py-1 text-[11px] text-muted-foreground hover:text-foreground\"\n >\n Set NULL\n </button>\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n onClick={() => onCancel?.()}\n className=\"rounded px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={commit}\n className=\"rounded bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground hover:bg-primary/90\"\n >\n Apply\n </button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"EditableCell.js","sourceRoot":"","sources":["../../../src/client/db-admin/EditableCell.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n IconChevronDown,\n IconCircleX,\n IconMaximize,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n type EditorKind,\n formatCellValue,\n inferEnumValues,\n valueToEditString,\n parseEditValue,\n ParseError,\n cycleTriStateBoolean,\n formatJsonPretty,\n} from \"./cell-format.js\";\nimport type { DbAdminColumn } from \"../../db-admin/types.js\";\n\nexport interface EditableCellProps {\n column: DbAdminColumn;\n kind: EditorKind;\n value: unknown;\n /** Whether this cell holds a staged (uncommitted) edit. */\n dirty?: boolean;\n /** Whether editing is allowed (false when the table has no PK). */\n editable?: boolean;\n /** Whether this cell is the keyboard-focused/active cell in the grid. */\n active?: boolean;\n /** True if the editor should open immediately (e.g. typing began). */\n editing?: boolean;\n /** Commit a new value into the changeset. */\n onCommit: (value: unknown) => void;\n /** Request entering edit mode. */\n onStartEdit?: () => void;\n /** Request leaving edit mode without committing. */\n onCancelEdit?: () => void;\n /** Move focus after Enter (\"down\") or Tab (\"right\"). */\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n className?: string;\n}\n\nconst NULL_TOKEN = (\n <span className=\"italic text-muted-foreground/60 select-none\">NULL</span>\n);\n\nexport function EditableCell({\n column,\n kind,\n value,\n dirty,\n editable = true,\n active,\n editing,\n onCommit,\n onStartEdit,\n onCancelEdit,\n onNavigate,\n className,\n}: EditableCellProps) {\n const display = formatCellValue(value, kind);\n\n // Boolean cells toggle in place rather than opening a text editor.\n if (kind === \"boolean\") {\n return (\n <BooleanCell\n value={value}\n dirty={dirty}\n editable={editable}\n active={active}\n onCommit={onCommit}\n onNavigate={onNavigate}\n className={className}\n />\n );\n }\n\n const baseCell = cn(\n \"relative h-full w-full px-2 py-1 text-xs truncate outline-none\",\n \"font-mono\",\n active && \"ring-1 ring-inset ring-ring\",\n dirty && \"bg-amber-500/10 ring-1 ring-inset ring-amber-500/50\",\n editable && \"cursor-text\",\n className,\n );\n\n if (editing && editable) {\n if (kind === \"enum\") {\n return (\n <EnumEditor\n column={column}\n value={value}\n onCommit={onCommit}\n onCancel={onCancelEdit}\n onNavigate={onNavigate}\n />\n );\n }\n if (kind === \"json\") {\n return (\n <JsonEditor value={value} onCommit={onCommit} onCancel={onCancelEdit} />\n );\n }\n return (\n <InlineTextEditor\n kind={kind}\n value={value}\n nullable={column.nullable}\n onCommit={onCommit}\n onCancel={onCancelEdit}\n onNavigate={onNavigate}\n />\n );\n }\n\n return (\n <div\n role=\"gridcell\"\n tabIndex={active ? 0 : -1}\n className={baseCell}\n onDoubleClick={() => editable && onStartEdit?.()}\n onKeyDown={(e) => {\n if (!editable) return;\n if (e.key === \"Enter\" || e.key === \"F2\") {\n e.preventDefault();\n onStartEdit?.();\n }\n }}\n title={display.isNull ? \"NULL\" : display.text}\n >\n <div className=\"flex items-center gap-1\">\n <span className=\"truncate\">\n {display.isNull ? NULL_TOKEN : display.text}\n </span>\n {editable && (kind === \"json\" || kind === \"text\") && (\n <button\n type=\"button\"\n tabIndex={-1}\n onClick={(e) => {\n e.stopPropagation();\n onStartEdit?.();\n }}\n className=\"ml-auto shrink-0 text-muted-foreground/50 opacity-0 hover:text-foreground group-hover:opacity-100\"\n aria-label=\"Expand editor\"\n >\n <IconMaximize className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n </div>\n );\n}\n\n// ─── Boolean (tri-state) ─────────────────────────────────────────────────────\n\nfunction BooleanCell({\n value,\n dirty,\n editable,\n active,\n onCommit,\n onNavigate,\n className,\n}: {\n value: unknown;\n dirty?: boolean;\n editable: boolean;\n active?: boolean;\n onCommit: (v: unknown) => void;\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n className?: string;\n}) {\n const label = value === true ? \"true\" : value === false ? \"false\" : null;\n return (\n <div\n role=\"gridcell\"\n tabIndex={active ? 0 : -1}\n className={cn(\n \"h-full w-full px-2 py-1 text-xs font-mono outline-none cursor-pointer select-none\",\n active && \"ring-1 ring-inset ring-ring\",\n dirty && \"bg-amber-500/10 ring-1 ring-inset ring-amber-500/50\",\n className,\n )}\n onClick={() => editable && onCommit(cycleTriStateBoolean(value))}\n onKeyDown={(e) => {\n if (!editable) return;\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n onCommit(cycleTriStateBoolean(value));\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n onNavigate?.(\"down\");\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n onNavigate?.(\"up\");\n }\n }}\n >\n {label === null ? NULL_TOKEN : label}\n </div>\n );\n}\n\n// ─── Inline text / number / timestamp / uuid editor ──────────────────────────\n\nfunction InlineTextEditor({\n kind,\n value,\n nullable,\n onCommit,\n onCancel,\n onNavigate,\n}: {\n kind: EditorKind;\n value: unknown;\n nullable: boolean;\n onCommit: (v: unknown) => void;\n onCancel?: () => void;\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n}) {\n const ref = useRef<HTMLInputElement>(null);\n const [text, setText] = useState(() => valueToEditString(value, kind));\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n ref.current?.focus();\n ref.current?.select();\n }, []);\n\n const commit = (nav?: \"down\" | \"right\") => {\n try {\n const parsed = parseEditValue(text, kind);\n setError(null);\n onCommit(parsed);\n if (nav) onNavigate?.(nav);\n } catch (err) {\n setError(err instanceof ParseError ? err.message : String(err));\n }\n };\n\n return (\n <div className=\"relative h-full w-full\">\n <input\n ref={ref}\n type=\"text\"\n inputMode={kind === \"number\" ? \"decimal\" : undefined}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onBlur={() => commit()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n commit(\"down\");\n } else if (e.key === \"Tab\") {\n e.preventDefault();\n commit(\"right\");\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n onCancel?.();\n }\n }}\n className={cn(\n \"h-full w-full bg-background px-2 py-1 text-xs font-mono outline-none\",\n \"ring-2 ring-inset ring-ring\",\n error && \"ring-destructive\",\n )}\n />\n {nullable && (\n <button\n type=\"button\"\n tabIndex={-1}\n title=\"Set NULL\"\n onMouseDown={(e) => {\n e.preventDefault();\n onCommit(null);\n }}\n className=\"absolute right-1 top-1/2 -translate-y-1/2 text-muted-foreground/50 hover:text-foreground\"\n >\n <IconCircleX className=\"h-3.5 w-3.5\" />\n </button>\n )}\n {error && (\n <div className=\"absolute left-0 top-full z-50 mt-0.5 rounded border border-destructive bg-popover px-2 py-1 text-[11px] text-destructive shadow-md\">\n {error}\n </div>\n )}\n </div>\n );\n}\n\n// ─── Enum (select) editor ────────────────────────────────────────────────────\n\nfunction EnumEditor({\n column,\n value,\n onCommit,\n onCancel,\n onNavigate,\n}: {\n column: DbAdminColumn;\n value: unknown;\n onCommit: (v: unknown) => void;\n onCancel?: () => void;\n onNavigate?: (dir: \"up\" | \"down\" | \"left\" | \"right\") => void;\n}) {\n const ref = useRef<HTMLSelectElement>(null);\n const options = inferEnumValues(column) ?? [];\n\n useEffect(() => {\n ref.current?.focus();\n }, []);\n\n return (\n <select\n ref={ref}\n defaultValue={value === null || value === undefined ? \"\" : String(value)}\n onChange={(e) => {\n const v = e.target.value;\n onCommit(v === \"\" ? null : v);\n onNavigate?.(\"down\");\n }}\n onBlur={() => onCancel?.()}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") onCancel?.();\n }}\n className=\"h-full w-full appearance-none bg-background px-2 py-1 text-xs font-mono outline-none ring-2 ring-inset ring-ring\"\n >\n {column.nullable && <option value=\"\">NULL</option>}\n {options.map((opt) => (\n <option key={opt} value={opt}>\n {opt}\n </option>\n ))}\n </select>\n );\n}\n\n// ─── JSON / long-text expanding editor ───────────────────────────────────────\n\nfunction JsonEditor({\n value,\n onCommit,\n onCancel,\n}: {\n value: unknown;\n onCommit: (v: unknown) => void;\n onCancel?: () => void;\n}) {\n const [open, setOpen] = useState(true);\n const [text, setText] = useState(() => formatJsonPretty(value));\n const [error, setError] = useState<string | null>(null);\n\n const commit = () => {\n if (text.trim() === \"\") {\n onCommit(null);\n setOpen(false);\n return;\n }\n try {\n const parsed = parseEditValue(text, \"json\");\n setError(null);\n onCommit(parsed);\n setOpen(false);\n } catch (err) {\n setError(err instanceof ParseError ? err.message : String(err));\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n if (!o) onCancel?.();\n setOpen(o);\n }}\n >\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"flex h-full w-full items-center gap-1 px-2 py-1 text-xs font-mono ring-2 ring-inset ring-ring outline-none\"\n >\n <span className=\"truncate\">{formatJsonPretty(value) || \"{}\"}</span>\n <IconChevronDown className=\"ml-auto h-3 w-3 shrink-0\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"w-[28rem] p-2\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <textarea\n autoFocus\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n commit();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n onCancel?.();\n }\n }}\n rows={10}\n spellCheck={false}\n className={cn(\n \"w-full resize-y rounded border border-border bg-background p-2 font-mono text-xs outline-none focus:ring-1 focus:ring-ring\",\n error && \"border-destructive\",\n )}\n />\n {error && (\n <div className=\"mt-1 text-[11px] text-destructive\">{error}</div>\n )}\n <div className=\"mt-2 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={() => {\n onCommit(null);\n setOpen(false);\n }}\n className=\"rounded px-2 py-1 text-[11px] text-muted-foreground hover:text-foreground\"\n >\n Set NULL\n </button>\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n onClick={() => onCancel?.()}\n className=\"rounded px-2 py-1 text-[11px] text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={commit}\n className=\"rounded bg-primary px-2 py-1 text-[11px] font-medium text-primary-foreground hover:bg-primary/90\"\n >\n Apply\n </button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* shipping with the keybinding active in prod is fine because nothing renders
|
|
12
12
|
* unless invoked.
|
|
13
13
|
*/
|
|
14
|
-
import { type ReactNode } from "react";
|
|
15
14
|
import "./builtins.js";
|
|
16
15
|
export interface DevOverlayProps {
|
|
17
16
|
/**
|
|
@@ -22,5 +21,4 @@ export interface DevOverlayProps {
|
|
|
22
21
|
onOpenChange?: (open: boolean) => void;
|
|
23
22
|
}
|
|
24
23
|
export declare function DevOverlay({ open, onOpenChange }?: DevOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
-
export type { ReactNode };
|
|
26
24
|
//# sourceMappingURL=DevOverlay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DevOverlay.d.ts","sourceRoot":"","sources":["../../../src/client/dev-overlay/DevOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"DevOverlay.d.ts","sourceRoot":"","sources":["../../../src/client/dev-overlay/DevOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA0BH,OAAO,eAAe,CAAC;AAUvB,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,GAAE,eAAoB,2CAqCtE"}
|
|
@@ -12,14 +12,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
* shipping with the keybinding active in prod is fine because nothing renders
|
|
13
13
|
* unless invoked.
|
|
14
14
|
*/
|
|
15
|
-
import { useCallback, useEffect, useState, useSyncExternalStore
|
|
15
|
+
import { useCallback, useEffect, useState, useSyncExternalStore } from "react";
|
|
16
16
|
import { IconChevronDown, IconChevronRight, IconLoader2, IconRefresh, IconTrash, IconX, } from "@tabler/icons-react";
|
|
17
17
|
import { listDevPanels, subscribeDevPanels } from "./registry.js";
|
|
18
18
|
import { clearAllDevOverlayStorage, useDevOption, DEV_OVERLAY_STORAGE_PREFIX, } from "./use-dev-option.js";
|
|
19
19
|
import { useDevOverlayShortcut } from "./use-dev-overlay-shortcut.js";
|
|
20
20
|
import "./builtins.js";
|
|
21
21
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
22
|
-
const PANEL_OPEN_KEY = `${DEV_OVERLAY_STORAGE_PREFIX}open`;
|
|
23
22
|
const COLLAPSED_KEY_PREFIX = `${DEV_OVERLAY_STORAGE_PREFIX}collapsed-`;
|
|
24
23
|
export function DevOverlay({ open, onOpenChange } = {}) {
|
|
25
24
|
const [internalOpen, setInternalOpen] = useState(false);
|