@agent-native/core 0.47.1 → 0.48.2
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/bin/agent-native.js +41 -0
- package/dist/a2a/handlers.js +2 -2
- package/dist/a2a/handlers.js.map +1 -1
- package/dist/a2a/server.js +2 -2
- package/dist/a2a/server.js.map +1 -1
- package/dist/action.d.ts +43 -2
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/context-xray/actions/context-evict.d.ts +7 -1
- package/dist/agent/context-xray/actions/context-evict.d.ts.map +1 -1
- package/dist/agent/context-xray/actions/context-manifest-get.d.ts +4 -1
- package/dist/agent/context-xray/actions/context-manifest-get.d.ts.map +1 -1
- package/dist/agent/context-xray/actions/context-pin.d.ts +7 -1
- package/dist/agent/context-xray/actions/context-pin.d.ts.map +1 -1
- package/dist/agent/context-xray/actions/context-report.d.ts +12 -1
- package/dist/agent/context-xray/actions/context-report.d.ts.map +1 -1
- package/dist/agent/context-xray/actions/context-restore.d.ts +7 -1
- package/dist/agent/context-xray/actions/context-restore.d.ts.map +1 -1
- package/dist/agent/context-xray/apply-directives.d.ts.map +1 -1
- package/dist/agent/context-xray/apply-directives.js.map +1 -1
- package/dist/agent/context-xray/schema.d.ts +10 -10
- package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
- package/dist/agent/engine/ai-sdk-engine.js +26 -3
- package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/builder-engine.js +47 -8
- package/dist/agent/engine/builder-engine.js.map +1 -1
- package/dist/agent/engine/builtin.js +1 -1
- package/dist/agent/engine/builtin.js.map +1 -1
- package/dist/agent/engine/output-tokens.d.ts +1 -1
- package/dist/agent/engine/output-tokens.d.ts.map +1 -1
- package/dist/agent/engine/output-tokens.js +6 -2
- package/dist/agent/engine/output-tokens.js.map +1 -1
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +7 -4
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/engine/types.d.ts +19 -0
- package/dist/agent/engine/types.d.ts.map +1 -1
- package/dist/agent/engine/types.js +6 -0
- package/dist/agent/engine/types.js.map +1 -1
- package/dist/agent/model-config.d.ts +22 -14
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +113 -8
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +19 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +253 -39
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +10 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-manager.d.ts +1 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +36 -9
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +47 -4
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +154 -4
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/thread-data-builder.d.ts.map +1 -1
- package/dist/agent/thread-data-builder.js +57 -2
- package/dist/agent/thread-data-builder.js.map +1 -1
- package/dist/agent/types.d.ts +3 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/agent-web/generator.d.ts +3 -3
- package/dist/appearance/actions/change-appearance.d.ts +6 -1
- package/dist/appearance/actions/change-appearance.d.ts.map +1 -1
- package/dist/application-state/handlers.d.ts +2 -2
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +17 -0
- package/dist/application-state/store.js.map +1 -1
- package/dist/catalog.json +2 -1
- package/dist/cli/code-agent-commands.d.ts.map +1 -1
- package/dist/cli/code-agent-commands.js +2 -0
- package/dist/cli/code-agent-commands.js.map +1 -1
- package/dist/cli/code-agent-connector.js +7 -13
- package/dist/cli/code-agent-connector.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts +54 -2
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +504 -48
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/code-agent-runs.d.ts +13 -0
- package/dist/cli/code-agent-runs.d.ts.map +1 -1
- package/dist/cli/code-agent-runs.js +36 -0
- package/dist/cli/code-agent-runs.js.map +1 -1
- package/dist/cli/code.js +59 -5
- package/dist/cli/code.js.map +1 -1
- package/dist/cli/connect.js +141 -3
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.js +476 -46
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.js +298 -179
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +29 -2
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AgentTaskCard.d.ts.map +1 -1
- package/dist/client/AgentTaskCard.js +17 -2
- package/dist/client/AgentTaskCard.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +310 -1732
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/CommandMenu.d.ts +1 -1
- package/dist/client/CommandMenu.d.ts.map +1 -1
- package/dist/client/CommandMenu.js +1 -1
- package/dist/client/CommandMenu.js.map +1 -1
- package/dist/client/HighlightedCodeBlock.d.ts +40 -0
- package/dist/client/HighlightedCodeBlock.d.ts.map +1 -0
- package/dist/client/HighlightedCodeBlock.js +110 -0
- package/dist/client/HighlightedCodeBlock.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +8 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/PoweredByBadge.d.ts +2 -2
- package/dist/client/PoweredByBadge.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.d.ts +1 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/StarfieldBackground.d.ts.map +1 -1
- package/dist/client/StarfieldBackground.js +10 -5
- package/dist/client/StarfieldBackground.js.map +1 -1
- package/dist/client/Turnstile.d.ts +1 -1
- package/dist/client/Turnstile.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts +3 -2
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +13 -9
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/app-providers.d.ts +99 -0
- package/dist/client/app-providers.d.ts.map +1 -0
- package/dist/client/app-providers.js +19 -0
- package/dist/client/app-providers.js.map +1 -0
- package/dist/client/assistant-ui-recovery.d.ts +1 -1
- package/dist/client/auth-redirect-url.d.ts +1 -1
- package/dist/client/auth-redirect-url.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts +0 -19
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +141 -55
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +1 -1
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.js +5 -3
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +5 -4
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +22 -3
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/blocks/library/diagram.js +1 -1
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/diff.config.d.ts +3 -2
- package/dist/client/blocks/library/diff.config.d.ts.map +1 -1
- package/dist/client/blocks/library/diff.config.js +4 -3
- package/dist/client/blocks/library/diff.config.js.map +1 -1
- package/dist/client/blocks/library/question-form.d.ts.map +1 -1
- package/dist/client/blocks/library/question-form.js +2 -1
- package/dist/client/blocks/library/question-form.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +1 -1
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/chat/attachment-adapters.d.ts +58 -0
- package/dist/client/chat/attachment-adapters.d.ts.map +1 -0
- package/dist/client/chat/attachment-adapters.js +331 -0
- package/dist/client/chat/attachment-adapters.js.map +1 -0
- package/dist/client/chat/index.d.ts +13 -0
- package/dist/client/chat/index.d.ts.map +1 -0
- package/dist/client/chat/index.js +13 -0
- package/dist/client/chat/index.js.map +1 -0
- package/dist/client/chat/markdown-renderer.d.ts +49 -0
- package/dist/client/chat/markdown-renderer.d.ts.map +1 -0
- package/dist/client/chat/markdown-renderer.js +391 -0
- package/dist/client/chat/markdown-renderer.js.map +1 -0
- package/dist/client/chat/message-components.d.ts +35 -0
- package/dist/client/chat/message-components.d.ts.map +1 -0
- package/dist/client/chat/message-components.js +452 -0
- package/dist/client/chat/message-components.js.map +1 -0
- package/dist/client/chat/repo-helpers.d.ts +41 -0
- package/dist/client/chat/repo-helpers.d.ts.map +1 -0
- package/dist/client/chat/repo-helpers.js +61 -0
- package/dist/client/chat/repo-helpers.js.map +1 -0
- package/dist/client/chat/run-recovery.d.ts +41 -0
- package/dist/client/chat/run-recovery.d.ts.map +1 -0
- package/dist/client/chat/run-recovery.js +348 -0
- package/dist/client/chat/run-recovery.js.map +1 -0
- package/dist/client/chat/tool-call-display.d.ts +34 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -0
- package/dist/client/chat/tool-call-display.js +284 -0
- package/dist/client/chat/tool-call-display.js.map +1 -0
- package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/code-agent-chat-adapter.js +20 -0
- package/dist/client/code-agent-chat-adapter.js.map +1 -1
- package/dist/client/collab/index.d.ts +10 -0
- package/dist/client/collab/index.d.ts.map +1 -0
- package/dist/client/collab/index.js +10 -0
- package/dist/client/collab/index.js.map +1 -0
- package/dist/client/components/AgentPresenceChip.d.ts +1 -1
- package/dist/client/components/AgentPresenceChip.d.ts.map +1 -1
- package/dist/client/components/ApiKeySettings.d.ts +1 -1
- package/dist/client/components/ApiKeySettings.d.ts.map +1 -1
- package/dist/client/components/CodeAgentIndicator.d.ts +1 -1
- package/dist/client/components/CodeAgentIndicator.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
- package/dist/client/components/LiveCursorOverlay.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts +1 -1
- package/dist/client/components/PresenceBar.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +6 -26
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +8 -2
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +21 -9
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts +2 -2
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/index.d.ts +1 -1
- package/dist/client/composer/index.d.ts.map +1 -1
- package/dist/client/composer/index.js +1 -1
- package/dist/client/composer/index.js.map +1 -1
- package/dist/client/composer/use-skills.d.ts +1 -1
- package/dist/client/context-xray/ContextMeter.d.ts +1 -1
- package/dist/client/context-xray/ContextMeter.d.ts.map +1 -1
- package/dist/client/context-xray/ContextMeter.js +3 -3
- package/dist/client/context-xray/ContextMeter.js.map +1 -1
- package/dist/client/context-xray/ContextXRayPanel.d.ts.map +1 -1
- package/dist/client/context-xray/ContextXRayPanel.js +4 -3
- package/dist/client/context-xray/ContextXRayPanel.js.map +1 -1
- package/dist/client/context-xray/format.d.ts +11 -0
- package/dist/client/context-xray/format.d.ts.map +1 -1
- package/dist/client/context-xray/format.js +16 -0
- package/dist/client/context-xray/format.js.map +1 -1
- package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/client/conversation/AgentConversation.js +8 -53
- package/dist/client/conversation/AgentConversation.js.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js +14 -1
- package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
- package/dist/client/create-query-client.d.ts +28 -0
- package/dist/client/create-query-client.d.ts.map +1 -0
- package/dist/client/create-query-client.js +78 -0
- package/dist/client/create-query-client.js.map +1 -0
- package/dist/client/db-admin/DevDatabaseLink.d.ts +1 -1
- package/dist/client/db-admin/DevDatabaseLink.d.ts.map +1 -1
- package/dist/client/db-admin/RowSidePanel.d.ts +1 -1
- package/dist/client/db-admin/RowSidePanel.d.ts.map +1 -1
- package/dist/client/db-admin/RowSidePanel.js +2 -2
- package/dist/client/db-admin/RowSidePanel.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts +1 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +1 -1
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/client/db-admin/cell-format.d.ts +1 -1
- package/dist/client/db-admin/cell-format.d.ts.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.d.ts +1 -1
- package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
- package/dist/client/editor/index.d.ts +2 -0
- package/dist/client/editor/index.d.ts.map +1 -0
- package/dist/client/editor/index.js +2 -0
- package/dist/client/editor/index.js.map +1 -0
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +4 -0
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts +1 -1
- package/dist/client/extensions/AgentNativeExtensionFrame.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionSlot.d.ts +1 -1
- package/dist/client/extensions/ExtensionSlot.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewerPage.d.ts +1 -1
- package/dist/client/extensions/ExtensionViewerPage.d.ts.map +1 -1
- package/dist/client/guided-questions.d.ts +6 -6
- package/dist/client/host-bridge.d.ts.map +1 -1
- package/dist/client/host-bridge.js +2 -0
- package/dist/client/host-bridge.js.map +1 -1
- package/dist/client/index.d.ts +7 -6
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +5 -3
- package/dist/client/index.js.map +1 -1
- package/dist/client/onboarding/OnboardingBanner.d.ts +1 -1
- package/dist/client/onboarding/OnboardingBanner.d.ts.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.d.ts +1 -1
- package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/client/onboarding/SetupButton.d.ts +1 -1
- package/dist/client/onboarding/SetupButton.d.ts.map +1 -1
- package/dist/client/org/InvitationBanner.d.ts +1 -1
- package/dist/client/org/InvitationBanner.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
- package/dist/client/org/hooks.d.ts +3 -3
- package/dist/client/org/hooks.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.d.ts +2 -2
- package/dist/client/progress/RunsTray.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.js +34 -9
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
- package/dist/client/resources/ResourceEditor.js +1 -1
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +2 -0
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/CodeBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/CodeBlockNode.js +2 -1
- package/dist/client/rich-markdown-editor/CodeBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/ImageExtension.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/ImageExtension.js +2 -1
- package/dist/client/rich-markdown-editor/ImageExtension.js.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +2 -3
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +1 -1
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +1 -1
- package/dist/client/route-state.d.ts +12 -2
- package/dist/client/route-state.d.ts.map +1 -1
- package/dist/client/route-state.js +1 -1
- package/dist/client/route-state.js.map +1 -1
- package/dist/client/route-warmup.d.ts +1 -1
- package/dist/client/route-warmup.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +2 -2
- package/dist/client/sharing/ShareDialog.d.ts +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sse-event-processor.d.ts +8 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +33 -10
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
- package/dist/client/terminal/AgentTerminal.js +4 -2
- package/dist/client/terminal/AgentTerminal.js.map +1 -1
- package/dist/client/tool-cells/BashCell.d.ts +25 -0
- package/dist/client/tool-cells/BashCell.d.ts.map +1 -0
- package/dist/client/tool-cells/BashCell.js +49 -0
- package/dist/client/tool-cells/BashCell.js.map +1 -0
- package/dist/client/tool-cells/EditCell.d.ts +24 -0
- package/dist/client/tool-cells/EditCell.d.ts.map +1 -0
- package/dist/client/tool-cells/EditCell.js +126 -0
- package/dist/client/tool-cells/EditCell.js.map +1 -0
- package/dist/client/tool-cells/FilesChangedSummary.d.ts +13 -0
- package/dist/client/tool-cells/FilesChangedSummary.d.ts.map +1 -0
- package/dist/client/tool-cells/FilesChangedSummary.js +98 -0
- package/dist/client/tool-cells/FilesChangedSummary.js.map +1 -0
- package/dist/client/tool-cells/WriteCell.d.ts +17 -0
- package/dist/client/tool-cells/WriteCell.d.ts.map +1 -0
- package/dist/client/tool-cells/WriteCell.js +26 -0
- package/dist/client/tool-cells/WriteCell.js.map +1 -0
- package/dist/client/tool-cells/index.d.ts +8 -0
- package/dist/client/tool-cells/index.d.ts.map +1 -0
- package/dist/client/tool-cells/index.js +5 -0
- package/dist/client/tool-cells/index.js.map +1 -0
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts +1 -1
- package/dist/client/transcription/BuilderTranscriptionCta.d.ts.map +1 -1
- package/dist/client/use-chat-threads.d.ts +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +11 -8
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +2 -0
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +329 -302
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/code-agents/transcript-normalizer.d.ts +15 -1
- package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +47 -0
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/coding-tools/index.d.ts +75 -0
- package/dist/coding-tools/index.d.ts.map +1 -1
- package/dist/coding-tools/index.js +137 -10
- package/dist/coding-tools/index.js.map +1 -1
- package/dist/collab/client.d.ts +1 -1
- package/dist/collab/client.js +20 -14
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/ydoc-manager.d.ts +1 -1
- package/dist/collab/ydoc-manager.d.ts.map +1 -1
- package/dist/collab/ydoc-manager.js +1 -1
- package/dist/collab/ydoc-manager.js.map +1 -1
- package/dist/db/client.d.ts +9 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +204 -48
- package/dist/db/client.js.map +1 -1
- package/dist/db/create-get-db.d.ts +38 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +204 -4
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +159 -67
- package/dist/db/migrations.js.map +1 -1
- package/dist/demo/actions/toggle-demo-mode.d.ts +6 -1
- package/dist/demo/actions/toggle-demo-mode.d.ts.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +80 -39
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/workspace-deploy.js +20 -10
- package/dist/deploy/workspace-deploy.js.map +1 -1
- package/dist/extensions/schema.d.ts +51 -51
- package/dist/extensions/slots/schema.d.ts +13 -13
- package/dist/file-upload/actions/upload-image.d.ts +26 -1
- package/dist/file-upload/actions/upload-image.d.ts.map +1 -1
- package/dist/file-upload/index.d.ts +1 -1
- package/dist/file-upload/index.d.ts.map +1 -1
- package/dist/file-upload/index.js +1 -1
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/pre-upload-attachments.d.ts +37 -0
- package/dist/file-upload/pre-upload-attachments.d.ts.map +1 -1
- package/dist/file-upload/pre-upload-attachments.js +79 -19
- package/dist/file-upload/pre-upload-attachments.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapters/slack.js +1 -1
- package/dist/integrations/adapters/slack.js.map +1 -1
- package/dist/integrations/plugin.js +1 -1
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/jobs/scheduler.js +70 -21
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/mcp/actions/create-org-service-token.d.ts +14 -0
- package/dist/mcp/actions/create-org-service-token.d.ts.map +1 -0
- package/dist/mcp/actions/create-org-service-token.js +74 -0
- package/dist/mcp/actions/create-org-service-token.js.map +1 -0
- package/dist/mcp/actions/list-org-service-tokens.d.ts +17 -0
- package/dist/mcp/actions/list-org-service-tokens.d.ts.map +1 -0
- package/dist/mcp/actions/list-org-service-tokens.js +42 -0
- package/dist/mcp/actions/list-org-service-tokens.js.map +1 -0
- package/dist/mcp/actions/revoke-org-service-token.d.ts +7 -0
- package/dist/mcp/actions/revoke-org-service-token.d.ts.map +1 -0
- package/dist/mcp/actions/revoke-org-service-token.js +28 -0
- package/dist/mcp/actions/revoke-org-service-token.js.map +1 -0
- package/dist/mcp/actions/service-token-access.d.ts +24 -0
- package/dist/mcp/actions/service-token-access.d.ts.map +1 -0
- package/dist/mcp/actions/service-token-access.js +63 -0
- package/dist/mcp/actions/service-token-access.js.map +1 -0
- package/dist/mcp/build-server.d.ts +42 -11
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +53 -3
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/connect-route.d.ts +35 -0
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +57 -2
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/mcp/connect-store.d.ts +43 -0
- package/dist/mcp/connect-store.d.ts.map +1 -1
- package/dist/mcp/connect-store.js +129 -12
- package/dist/mcp/connect-store.js.map +1 -1
- package/dist/mcp/oauth-token.d.ts +10 -0
- package/dist/mcp/oauth-token.d.ts.map +1 -1
- package/dist/mcp/oauth-token.js +2 -0
- package/dist/mcp/oauth-token.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +3 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp-client/routes.js +1 -1
- package/dist/mcp-client/routes.js.map +1 -1
- package/dist/org/context.d.ts +4 -0
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +10 -0
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts +11 -7
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +0 -8
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/migrations.d.ts.map +1 -1
- package/dist/org/migrations.js +8 -0
- package/dist/org/migrations.js.map +1 -1
- package/dist/org/schema.d.ts +15 -15
- package/dist/progress/actions.d.ts.map +1 -1
- package/dist/progress/actions.js +13 -5
- package/dist/progress/actions.js.map +1 -1
- package/dist/provider-api/actions/delete-staged-dataset.d.ts +9 -0
- package/dist/provider-api/actions/delete-staged-dataset.d.ts.map +1 -0
- package/dist/provider-api/actions/delete-staged-dataset.js +35 -0
- package/dist/provider-api/actions/delete-staged-dataset.js.map +1 -0
- package/dist/provider-api/actions/list-staged-datasets.d.ts +15 -0
- package/dist/provider-api/actions/list-staged-datasets.d.ts.map +1 -0
- package/dist/provider-api/actions/list-staged-datasets.js +41 -0
- package/dist/provider-api/actions/list-staged-datasets.js.map +1 -0
- package/dist/provider-api/actions/query-staged-dataset.d.ts +29 -0
- package/dist/provider-api/actions/query-staged-dataset.d.ts.map +1 -0
- package/dist/provider-api/actions/query-staged-dataset.js +116 -0
- package/dist/provider-api/actions/query-staged-dataset.js.map +1 -0
- package/dist/provider-api/custom-registry.d.ts.map +1 -1
- package/dist/provider-api/custom-registry.js.map +1 -1
- package/dist/provider-api/index.d.ts +10 -10
- package/dist/provider-api/index.js +0 -5
- package/dist/provider-api/index.js.map +1 -1
- package/dist/provider-api/staged-datasets-aggregate.d.ts +46 -0
- package/dist/provider-api/staged-datasets-aggregate.d.ts.map +1 -0
- package/dist/provider-api/staged-datasets-aggregate.js +209 -0
- package/dist/provider-api/staged-datasets-aggregate.js.map +1 -0
- package/dist/provider-api/staged-datasets-store.d.ts +76 -0
- package/dist/provider-api/staged-datasets-store.d.ts.map +1 -0
- package/dist/provider-api/staged-datasets-store.js +319 -0
- package/dist/provider-api/staged-datasets-store.js.map +1 -0
- package/dist/provider-api/staging.d.ts +100 -0
- package/dist/provider-api/staging.d.ts.map +1 -0
- package/dist/provider-api/staging.js +281 -0
- package/dist/provider-api/staging.js.map +1 -0
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +13 -1
- package/dist/resources/handlers.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +1 -2
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/resources/migrate-learnings.d.ts +1 -1
- package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -1
- package/dist/scripts/resources/migrate-learnings.js +1 -1
- package/dist/scripts/resources/migrate-learnings.js.map +1 -1
- package/dist/secrets/schema.d.ts +7 -7
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +14 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +3 -2
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +33 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +251 -180
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +13 -16
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/agent-teams-run-queue.d.ts +31 -8
- package/dist/server/agent-teams-run-queue.d.ts.map +1 -1
- package/dist/server/agent-teams-run-queue.js +61 -18
- package/dist/server/agent-teams-run-queue.js.map +1 -1
- package/dist/server/agent-teams.d.ts +27 -1
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +214 -14
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/app-base-path.d.ts +20 -0
- package/dist/server/app-base-path.d.ts.map +1 -1
- package/dist/server/app-base-path.js +36 -0
- package/dist/server/app-base-path.js.map +1 -1
- package/dist/server/attachment-actions.d.ts +43 -0
- package/dist/server/attachment-actions.d.ts.map +1 -0
- package/dist/server/attachment-actions.js +214 -0
- package/dist/server/attachment-actions.js.map +1 -0
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/complete-text.d.ts +56 -0
- package/dist/server/complete-text.d.ts.map +1 -0
- package/dist/server/complete-text.js +147 -0
- package/dist/server/complete-text.js.map +1 -0
- package/dist/server/core-routes-plugin.d.ts +4 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +49 -29
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/cors-origins.d.ts.map +1 -1
- package/dist/server/cors-origins.js +6 -1
- package/dist/server/cors-origins.js.map +1 -1
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +2 -1
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/csrf.d.ts +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/email-actions.d.ts +19 -0
- package/dist/server/email-actions.d.ts.map +1 -0
- package/dist/server/email-actions.js +191 -0
- package/dist/server/email-actions.js.map +1 -0
- package/dist/server/embed-route.js +1 -1
- package/dist/server/embed-route.js.map +1 -1
- package/dist/server/embed-session.d.ts.map +1 -1
- package/dist/server/embed-session.js +5 -1
- package/dist/server/embed-session.js.map +1 -1
- package/dist/server/entry-server.d.ts +24 -0
- package/dist/server/entry-server.d.ts.map +1 -0
- package/dist/server/entry-server.js +54 -0
- package/dist/server/entry-server.js.map +1 -0
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +2 -10
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/google-oauth.d.ts.map +1 -1
- package/dist/server/google-oauth.js +2 -9
- package/dist/server/google-oauth.js.map +1 -1
- package/dist/server/google-realtime-session.d.ts.map +1 -1
- package/dist/server/google-realtime-session.js +6 -4
- package/dist/server/google-realtime-session.js.map +1 -1
- package/dist/server/h3-helpers.d.ts +39 -0
- package/dist/server/h3-helpers.d.ts.map +1 -1
- package/dist/server/h3-helpers.js +104 -1
- package/dist/server/h3-helpers.js.map +1 -1
- 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 +1 -8
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/open-route.d.ts.map +1 -1
- package/dist/server/open-route.js +1 -0
- package/dist/server/open-route.js.map +1 -1
- package/dist/server/prompts/framework-core-compact.d.ts +19 -0
- package/dist/server/prompts/framework-core-compact.d.ts.map +1 -0
- package/dist/server/prompts/framework-core-compact.js +69 -0
- package/dist/server/prompts/framework-core-compact.js.map +1 -0
- package/dist/server/prompts/framework-core.d.ts +26 -0
- package/dist/server/prompts/framework-core.d.ts.map +1 -0
- package/dist/server/prompts/framework-core.js +130 -0
- package/dist/server/prompts/framework-core.js.map +1 -0
- package/dist/server/prompts/index.d.ts +9 -0
- package/dist/server/prompts/index.d.ts.map +1 -0
- package/dist/server/prompts/index.js +9 -0
- package/dist/server/prompts/index.js.map +1 -0
- package/dist/server/prompts/model-overlays.d.ts +18 -0
- package/dist/server/prompts/model-overlays.d.ts.map +1 -0
- package/dist/server/prompts/model-overlays.js +46 -0
- package/dist/server/prompts/model-overlays.js.map +1 -0
- package/dist/server/prompts/shared-rules.d.ts +29 -0
- package/dist/server/prompts/shared-rules.d.ts.map +1 -0
- package/dist/server/prompts/shared-rules.js +54 -0
- package/dist/server/prompts/shared-rules.js.map +1 -0
- package/dist/server/security-headers.d.ts +7 -1
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +11 -0
- package/dist/server/security-headers.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +135 -46
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts.map +1 -1
- package/dist/server/transcribe-voice.js +7 -4
- package/dist/server/transcribe-voice.js.map +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +9 -0
- package/dist/settings/store.js.map +1 -1
- package/dist/shared/markdown-block-split.d.ts +39 -0
- package/dist/shared/markdown-block-split.d.ts.map +1 -0
- package/dist/shared/markdown-block-split.js +97 -0
- package/dist/shared/markdown-block-split.js.map +1 -0
- package/dist/shared/reasoning-effort.js +13 -1
- package/dist/shared/reasoning-effort.js.map +1 -1
- package/dist/shared/streaming-text-smoothing.d.ts +18 -0
- package/dist/shared/streaming-text-smoothing.d.ts.map +1 -1
- package/dist/shared/streaming-text-smoothing.js +70 -4
- package/dist/shared/streaming-text-smoothing.js.map +1 -1
- package/dist/sharing/actions/list-resource-shares.d.ts +24 -1
- package/dist/sharing/actions/list-resource-shares.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts +8 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts +12 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/unshare-resource.d.ts +8 -1
- package/dist/sharing/actions/unshare-resource.d.ts.map +1 -1
- package/dist/sharing/schema.d.ts +10 -10
- package/dist/styles/agent-conversation.css +239 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +50 -2
- package/dist/templates/default/AGENTS.md +1 -1
- package/dist/templates/default/DEVELOPING.md +19 -0
- package/dist/templates/default/app/entry.client.tsx +4 -1
- package/dist/templates/default/app/entry.server.tsx +4 -56
- package/dist/templates/default/app/global.css +3 -2
- package/dist/templates/default/app/root.tsx +8 -24
- package/dist/templates/default/app/routes/_index.tsx +0 -13
- package/dist/templates/default/package.json +6 -5
- package/dist/templates/default/tsconfig.json +2 -1
- package/dist/templates/starter-shell-sync.spec.ts +118 -0
- package/dist/templates/ui-primitives-sync.spec.ts +399 -0
- package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +50 -2
- package/dist/terminal/pty-server.js +1 -1
- package/dist/terminal/pty-server.js.map +1 -1
- package/dist/triggers/dispatcher.js +1 -1
- package/dist/triggers/dispatcher.js.map +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +60 -7
- package/dist/usage/store.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +44 -12
- package/dist/vite/client.js.map +1 -1
- package/dist/workspace-files/schema.d.ts +8 -8
- package/dist/workspace-files/tool.d.ts.map +1 -1
- package/dist/workspace-files/tool.js +0 -1
- package/dist/workspace-files/tool.js.map +1 -1
- package/docs/content/a2a-protocol.md +18 -12
- package/docs/content/actions.md +42 -10
- package/docs/content/agent-mentions.md +7 -8
- package/docs/content/agent-teams.md +23 -37
- package/docs/content/agent-web-surfaces.md +18 -9
- package/docs/content/authentication.md +6 -17
- package/docs/content/automations.md +43 -15
- package/docs/content/cli-adapters.md +25 -24
- package/docs/content/client.md +66 -17
- package/docs/content/cloneable-saas.md +19 -23
- package/docs/content/code-agents-ui.md +3 -31
- package/docs/content/components.md +308 -0
- package/docs/content/context-awareness.md +4 -0
- package/docs/content/creating-templates.md +4 -2
- package/docs/content/cross-app-sso.md +45 -19
- package/docs/content/database.md +26 -1
- package/docs/content/deployment.md +3 -1
- package/docs/content/dispatch.md +9 -37
- package/docs/content/drop-in-agent.md +123 -2
- package/docs/content/embedding-sdk.md +35 -0
- package/docs/content/extensions.md +2 -2
- package/docs/content/external-agents.md +86 -171
- package/docs/content/faq.md +6 -27
- package/docs/content/frames.md +9 -12
- package/docs/content/getting-started.md +80 -77
- package/docs/content/key-concepts.md +29 -19
- package/docs/content/mcp-apps.md +103 -0
- package/docs/content/mcp-clients.md +2 -2
- package/docs/content/mcp-protocol.md +40 -17
- package/docs/content/messaging.md +11 -4
- package/docs/content/migration-workbench.md +4 -47
- package/docs/content/multi-app-workspace.md +48 -17
- package/docs/content/multi-tenancy.md +1 -1
- package/docs/content/notifications.md +8 -6
- package/docs/content/observability.md +26 -15
- package/docs/content/onboarding.md +7 -1
- package/docs/content/pr-visual-recap.md +203 -23
- package/docs/content/progress.md +5 -5
- package/docs/content/pure-agent-apps.md +3 -1
- package/docs/content/real-time-collaboration.md +106 -0
- package/docs/content/recurring-jobs.md +17 -1
- package/docs/content/security.md +17 -3
- package/docs/content/server.md +39 -3
- package/docs/content/sharing.md +20 -1
- package/docs/content/skills-guide.md +151 -125
- package/docs/content/template-analytics.md +8 -0
- package/docs/content/template-assets.md +2 -0
- package/docs/content/template-brain.md +59 -3
- package/docs/content/template-calendar.md +8 -0
- package/docs/content/template-clips.md +11 -2
- package/docs/content/template-content.md +24 -4
- package/docs/content/template-design.md +19 -17
- package/docs/content/template-dispatch.md +2 -0
- package/docs/content/template-forms.md +28 -1
- package/docs/content/template-mail.md +17 -0
- package/docs/content/template-plan.md +177 -10
- package/docs/content/template-slides.md +51 -12
- package/docs/content/template-videos.md +17 -0
- package/docs/content/tracking.md +17 -13
- package/docs/content/using-your-agent.md +15 -5
- package/docs/content/voice-input.md +1 -1
- package/docs/content/what-is-agent-native.md +5 -6
- package/docs/content/workspace-connections.md +138 -424
- package/docs/content/workspace-management.md +12 -128
- package/docs/content/workspace.md +125 -199
- package/docs/content/writing-agent-instructions.md +17 -1
- package/package.json +25 -6
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +50 -2
- package/src/templates/default/AGENTS.md +1 -1
- package/src/templates/default/DEVELOPING.md +19 -0
- package/src/templates/default/app/entry.client.tsx +4 -1
- package/src/templates/default/app/entry.server.tsx +4 -56
- package/src/templates/default/app/global.css +3 -2
- package/src/templates/default/app/root.tsx +8 -24
- package/src/templates/default/app/routes/_index.tsx +0 -13
- package/src/templates/default/package.json +6 -5
- package/src/templates/default/tsconfig.json +2 -1
- package/src/templates/starter-shell-sync.spec.ts +118 -0
- package/src/templates/ui-primitives-sync.spec.ts +399 -0
- package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +50 -2
- package/tsconfig.base.json +2 -10
- package/dist/cli/app-skill.d.ts +0 -157
- package/dist/cli/app-skill.d.ts.map +0 -1
- package/dist/cli/audit-agent-web.d.ts +0 -2
- package/dist/cli/audit-agent-web.d.ts.map +0 -1
- package/dist/cli/code-agent-connector.d.ts +0 -17
- package/dist/cli/code-agent-connector.d.ts.map +0 -1
- package/dist/cli/code.d.ts +0 -66
- package/dist/cli/code.d.ts.map +0 -1
- package/dist/cli/connect.d.ts +0 -140
- package/dist/cli/connect.d.ts.map +0 -1
- package/dist/cli/context-xray-local.d.ts +0 -16
- package/dist/cli/context-xray-local.d.ts.map +0 -1
- package/dist/cli/create-workspace.d.ts +0 -8
- package/dist/cli/create-workspace.d.ts.map +0 -1
- package/dist/cli/index.d.ts +0 -3
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/info.d.ts +0 -2
- package/dist/cli/info.d.ts.map +0 -1
- package/dist/cli/mcp-config-writers.d.ts +0 -82
- package/dist/cli/mcp-config-writers.d.ts.map +0 -1
- package/dist/cli/mcp.d.ts +0 -16
- package/dist/cli/mcp.d.ts.map +0 -1
- package/dist/cli/migrate.d.ts +0 -38
- package/dist/cli/migrate.d.ts.map +0 -1
- package/dist/cli/plan-local.d.ts +0 -43
- package/dist/cli/plan-local.d.ts.map +0 -1
- package/dist/cli/plan-publish-store.d.ts +0 -62
- package/dist/cli/plan-publish-store.d.ts.map +0 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +0 -11
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +0 -1
- package/dist/cli/recap.d.ts +0 -297
- package/dist/cli/recap.d.ts.map +0 -1
- package/dist/cli/skills.d.ts +0 -162
- package/dist/cli/skills.d.ts.map +0 -1
- package/dist/cli/workspace-dev.d.ts +0 -96
- package/dist/cli/workspace-dev.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BubbleToolbar.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/BubbleToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C,4CAA4C;AAC5C,MAAM,MAAM,iBAAiB,GACzB;IACE,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,GACD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,IAAI,GACrB,iBAAiB,EAAE,CAyDrB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,IAAI,KAAK,iBAAiB,EAAE,CAAC;CAC9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAoC,GACrC,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"BubbleToolbar.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/BubbleToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAI5C,4CAA4C;AAC5C,MAAM,MAAM,iBAAiB,GACzB;IACE,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,GACD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,IAAI,GACrB,iBAAiB,EAAE,CAyDrB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,IAAI,KAAK,iBAAiB,EAAE,CAAC;CAC9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAoC,GACrC,EAAE,kBAAkB,kDAmJpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlockNode.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/CodeBlockNode.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAQvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAS/C;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iFAAiF;AACjF,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,EAkBtD,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAcD,MAAM,WAAW,0BAA0B;IACzC,kFAAkF;IAClF,QAAQ,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC5C,iFAAiF;IACjF,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACjC,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AA2HD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,SAAkC,EAClC,UAAU,GACX,EAAE,0BAA0B,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"CodeBlockNode.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/CodeBlockNode.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAQvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAS/C;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iFAAiF;AACjF,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,EAkBtD,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAcD,MAAM,WAAW,0BAA0B;IACzC,kFAAkF;IAClF,QAAQ,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC5C,iFAAiF;IACjF,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACjC,kFAAkF;IAClF,UAAU,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AA2HD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,SAAkC,EAClC,UAAU,GACX,EAAE,0BAA0B,GAAG,UAAU,CAkCzC"}
|
|
@@ -98,7 +98,8 @@ export function createCodeBlockNode({ lowlight, languages = DEFAULT_CODE_LANGUAG
|
|
|
98
98
|
return CodeBlockLowlight.extend({
|
|
99
99
|
addOptions() {
|
|
100
100
|
return {
|
|
101
|
-
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
102
|
+
...this.parent(),
|
|
102
103
|
languagePickerOptions: languages,
|
|
103
104
|
codeBlockClassNames: resolvedClassNames,
|
|
104
105
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlockNode.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/CodeBlockNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useState } from \"react\";\nimport type { Node as TiptapNode } from \"@tiptap/core\";\nimport {\n NodeViewContent,\n NodeViewWrapper,\n ReactNodeViewRenderer,\n type NodeViewProps,\n} from \"@tiptap/react\";\nimport { CodeBlockLowlight } from \"@tiptap/extension-code-block-lowlight\";\nimport type { createLowlight } from \"lowlight\";\nimport { IconCheck, IconChevronDown } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\n\n/**\n * A selectable language for the code-block picker. `value === null` is the\n * \"Auto\" sentinel: the block stores no language and the lowlight plugin\n * auto-detects (biased toward the editor's registered, web-leaning grammar\n * set). Keeping it first makes Auto the default, matching how plans skew toward\n * JS/TS/JSON without the author having to choose.\n */\nexport interface CodeLanguageOption {\n value: string | null;\n label: string;\n}\n\n/** Default picker list — Auto first, then the web-leaning grammars plans use. */\nexport const DEFAULT_CODE_LANGUAGES: CodeLanguageOption[] = [\n { value: null, label: \"Auto\" },\n { value: \"typescript\", label: \"TypeScript\" },\n { value: \"javascript\", label: \"JavaScript\" },\n { value: \"tsx\", label: \"TSX\" },\n { value: \"jsx\", label: \"JSX\" },\n { value: \"json\", label: \"JSON\" },\n { value: \"html\", label: \"HTML\" },\n { value: \"css\", label: \"CSS\" },\n { value: \"bash\", label: \"Bash\" },\n { value: \"python\", label: \"Python\" },\n { value: \"sql\", label: \"SQL\" },\n { value: \"yaml\", label: \"YAML\" },\n { value: \"markdown\", label: \"Markdown\" },\n { value: \"graphql\", label: \"GraphQL\" },\n { value: \"go\", label: \"Go\" },\n { value: \"rust\", label: \"Rust\" },\n { value: \"diff\", label: \"Diff\" },\n];\n\n/** Class hooks so each app themes the shared node with its own palette. */\nexport interface CodeBlockClassNames {\n wrapper: string;\n header: string;\n langButton: string;\n langButtonReadonly: string;\n picker: string;\n search: string;\n list: string;\n option: string;\n optionActive: string;\n}\n\nconst DEFAULT_CLASS_NAMES: CodeBlockClassNames = {\n wrapper: \"an-code-block\",\n header: \"an-code-block__header\",\n langButton: \"an-code-block__lang\",\n langButtonReadonly: \"an-code-block__lang--readonly\",\n picker: \"an-code-block__picker\",\n search: \"an-code-block__search\",\n list: \"an-code-block__list\",\n option: \"an-code-block__option\",\n optionActive: \"is-active\",\n};\n\nexport interface CreateCodeBlockNodeOptions {\n /** Lowlight instance backing syntax highlighting (same one the app registers). */\n lowlight: ReturnType<typeof createLowlight>;\n /** Picker languages. Defaults to {@link DEFAULT_CODE_LANGUAGES} (Auto first). */\n languages?: CodeLanguageOption[];\n /** Class hooks for per-app theming. Defaults to the shared `an-code-block__*`. */\n classNames?: Partial<CodeBlockClassNames>;\n}\n\nfunction optionLabel(\n language: string | null,\n languages: CodeLanguageOption[],\n): string {\n if (!language) return languages[0]?.label ?? \"Auto\";\n const match = languages.find((option) => option.value === language);\n return match?.label ?? language;\n}\n\ninterface CodeBlockNodeViewExtraOptions {\n languagePickerOptions: CodeLanguageOption[];\n codeBlockClassNames: CodeBlockClassNames;\n}\n\nfunction CodeBlockView({\n node,\n updateAttributes,\n editor,\n extension,\n}: NodeViewProps) {\n const options = extension.options as unknown as CodeBlockNodeViewExtraOptions;\n const languages = options.languagePickerOptions;\n const classNames = options.codeBlockClassNames;\n\n const [open, setOpen] = useState(false);\n const [filter, setFilter] = useState(\"\");\n const isEditable = editor.isEditable;\n\n const current = (node.attrs.language as string | null) || null;\n const label = optionLabel(current, languages);\n\n const filtered = useMemo(() => {\n const query = filter.trim().toLowerCase();\n if (!query) return languages;\n return languages.filter((option) =>\n option.label.toLowerCase().includes(query),\n );\n }, [filter, languages]);\n\n const select = (value: string | null) => {\n // Store `\"\"` for Auto so tiptap-markdown emits a bare fence (no language),\n // matching the auto-detect read path.\n updateAttributes({ language: value ?? \"\" });\n setFilter(\"\");\n setOpen(false);\n };\n\n return (\n <NodeViewWrapper className={classNames.wrapper}>\n <div className={classNames.header} contentEditable={false}>\n {isEditable ? (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setFilter(\"\");\n }}\n >\n <PopoverTrigger asChild>\n <button type=\"button\" className={classNames.langButton}>\n {label}\n <IconChevronDown className=\"size-3\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" side=\"bottom\" className=\"w-52 p-0\">\n <input\n autoFocus\n type=\"text\"\n value={filter}\n onChange={(event) => setFilter(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && filtered.length > 0) {\n event.preventDefault();\n select(filtered[0].value);\n }\n }}\n placeholder=\"Search languages…\"\n className={classNames.search}\n />\n <div className={classNames.list}>\n {filtered.map((option) => {\n const active =\n option.value === current || (!option.value && !current);\n return (\n <button\n key={option.value ?? \"auto\"}\n type=\"button\"\n className={cn(\n classNames.option,\n active && classNames.optionActive,\n )}\n onClick={() => select(option.value)}\n >\n {option.label}\n {active && <IconCheck className=\"size-3.5\" />}\n </button>\n );\n })}\n </div>\n </PopoverContent>\n </Popover>\n ) : (\n label && (\n <span\n className={cn(\n classNames.langButton,\n classNames.langButtonReadonly,\n )}\n >\n {label}\n </span>\n )\n )}\n </div>\n <pre>\n <NodeViewContent as={\"code\" as never} />\n </pre>\n </NodeViewWrapper>\n );\n}\n\n/**\n * The shared Notion-style code block: {@link CodeBlockLowlight} (so fenced\n * markdown round-trips byte-identically — the node name and `language` attr are\n * unchanged) plus a React node view that adds a language picker header instead\n * of a bare highlighted `<pre>`. \"Auto\" stores no language and the lowlight\n * plugin auto-detects.\n *\n * Lifted from the Content editor's bespoke code block so Plans (and any app\n * opting into `features.codeBlock`) share one implementation. Theming is fully\n * class-driven via {@link CreateCodeBlockNodeOptions.classNames}, so each app\n * maps the hooks onto its own palette.\n */\nexport function createCodeBlockNode({\n lowlight,\n languages = DEFAULT_CODE_LANGUAGES,\n classNames,\n}: CreateCodeBlockNodeOptions): TiptapNode {\n const resolvedClassNames: CodeBlockClassNames = {\n ...DEFAULT_CLASS_NAMES,\n ...(classNames ?? {}),\n };\n\n return CodeBlockLowlight.extend({\n addOptions() {\n return {\n ...this.parent?.(),\n languagePickerOptions: languages,\n codeBlockClassNames: resolvedClassNames,\n };\n },\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockView);\n },\n addKeyboardShortcuts() {\n return {\n ...this.parent?.(),\n Tab: ({ editor }) => {\n if (editor.isActive(this.name)) {\n editor.commands.insertContent(\"\\t\");\n return true;\n }\n return false;\n },\n };\n },\n }).configure({\n lowlight,\n defaultLanguage: null,\n }) as unknown as TiptapNode;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CodeBlockNode.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/CodeBlockNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useState } from \"react\";\nimport type { Node as TiptapNode } from \"@tiptap/core\";\nimport {\n NodeViewContent,\n NodeViewWrapper,\n ReactNodeViewRenderer,\n type NodeViewProps,\n} from \"@tiptap/react\";\nimport { CodeBlockLowlight } from \"@tiptap/extension-code-block-lowlight\";\nimport type { createLowlight } from \"lowlight\";\nimport { IconCheck, IconChevronDown } from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\n\n/**\n * A selectable language for the code-block picker. `value === null` is the\n * \"Auto\" sentinel: the block stores no language and the lowlight plugin\n * auto-detects (biased toward the editor's registered, web-leaning grammar\n * set). Keeping it first makes Auto the default, matching how plans skew toward\n * JS/TS/JSON without the author having to choose.\n */\nexport interface CodeLanguageOption {\n value: string | null;\n label: string;\n}\n\n/** Default picker list — Auto first, then the web-leaning grammars plans use. */\nexport const DEFAULT_CODE_LANGUAGES: CodeLanguageOption[] = [\n { value: null, label: \"Auto\" },\n { value: \"typescript\", label: \"TypeScript\" },\n { value: \"javascript\", label: \"JavaScript\" },\n { value: \"tsx\", label: \"TSX\" },\n { value: \"jsx\", label: \"JSX\" },\n { value: \"json\", label: \"JSON\" },\n { value: \"html\", label: \"HTML\" },\n { value: \"css\", label: \"CSS\" },\n { value: \"bash\", label: \"Bash\" },\n { value: \"python\", label: \"Python\" },\n { value: \"sql\", label: \"SQL\" },\n { value: \"yaml\", label: \"YAML\" },\n { value: \"markdown\", label: \"Markdown\" },\n { value: \"graphql\", label: \"GraphQL\" },\n { value: \"go\", label: \"Go\" },\n { value: \"rust\", label: \"Rust\" },\n { value: \"diff\", label: \"Diff\" },\n];\n\n/** Class hooks so each app themes the shared node with its own palette. */\nexport interface CodeBlockClassNames {\n wrapper: string;\n header: string;\n langButton: string;\n langButtonReadonly: string;\n picker: string;\n search: string;\n list: string;\n option: string;\n optionActive: string;\n}\n\nconst DEFAULT_CLASS_NAMES: CodeBlockClassNames = {\n wrapper: \"an-code-block\",\n header: \"an-code-block__header\",\n langButton: \"an-code-block__lang\",\n langButtonReadonly: \"an-code-block__lang--readonly\",\n picker: \"an-code-block__picker\",\n search: \"an-code-block__search\",\n list: \"an-code-block__list\",\n option: \"an-code-block__option\",\n optionActive: \"is-active\",\n};\n\nexport interface CreateCodeBlockNodeOptions {\n /** Lowlight instance backing syntax highlighting (same one the app registers). */\n lowlight: ReturnType<typeof createLowlight>;\n /** Picker languages. Defaults to {@link DEFAULT_CODE_LANGUAGES} (Auto first). */\n languages?: CodeLanguageOption[];\n /** Class hooks for per-app theming. Defaults to the shared `an-code-block__*`. */\n classNames?: Partial<CodeBlockClassNames>;\n}\n\nfunction optionLabel(\n language: string | null,\n languages: CodeLanguageOption[],\n): string {\n if (!language) return languages[0]?.label ?? \"Auto\";\n const match = languages.find((option) => option.value === language);\n return match?.label ?? language;\n}\n\ninterface CodeBlockNodeViewExtraOptions {\n languagePickerOptions: CodeLanguageOption[];\n codeBlockClassNames: CodeBlockClassNames;\n}\n\nfunction CodeBlockView({\n node,\n updateAttributes,\n editor,\n extension,\n}: NodeViewProps) {\n const options = extension.options as unknown as CodeBlockNodeViewExtraOptions;\n const languages = options.languagePickerOptions;\n const classNames = options.codeBlockClassNames;\n\n const [open, setOpen] = useState(false);\n const [filter, setFilter] = useState(\"\");\n const isEditable = editor.isEditable;\n\n const current = (node.attrs.language as string | null) || null;\n const label = optionLabel(current, languages);\n\n const filtered = useMemo(() => {\n const query = filter.trim().toLowerCase();\n if (!query) return languages;\n return languages.filter((option) =>\n option.label.toLowerCase().includes(query),\n );\n }, [filter, languages]);\n\n const select = (value: string | null) => {\n // Store `\"\"` for Auto so tiptap-markdown emits a bare fence (no language),\n // matching the auto-detect read path.\n updateAttributes({ language: value ?? \"\" });\n setFilter(\"\");\n setOpen(false);\n };\n\n return (\n <NodeViewWrapper className={classNames.wrapper}>\n <div className={classNames.header} contentEditable={false}>\n {isEditable ? (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setFilter(\"\");\n }}\n >\n <PopoverTrigger asChild>\n <button type=\"button\" className={classNames.langButton}>\n {label}\n <IconChevronDown className=\"size-3\" />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" side=\"bottom\" className=\"w-52 p-0\">\n <input\n autoFocus\n type=\"text\"\n value={filter}\n onChange={(event) => setFilter(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && filtered.length > 0) {\n event.preventDefault();\n select(filtered[0].value);\n }\n }}\n placeholder=\"Search languages…\"\n className={classNames.search}\n />\n <div className={classNames.list}>\n {filtered.map((option) => {\n const active =\n option.value === current || (!option.value && !current);\n return (\n <button\n key={option.value ?? \"auto\"}\n type=\"button\"\n className={cn(\n classNames.option,\n active && classNames.optionActive,\n )}\n onClick={() => select(option.value)}\n >\n {option.label}\n {active && <IconCheck className=\"size-3.5\" />}\n </button>\n );\n })}\n </div>\n </PopoverContent>\n </Popover>\n ) : (\n label && (\n <span\n className={cn(\n classNames.langButton,\n classNames.langButtonReadonly,\n )}\n >\n {label}\n </span>\n )\n )}\n </div>\n <pre>\n <NodeViewContent as={\"code\" as never} />\n </pre>\n </NodeViewWrapper>\n );\n}\n\n/**\n * The shared Notion-style code block: {@link CodeBlockLowlight} (so fenced\n * markdown round-trips byte-identically — the node name and `language` attr are\n * unchanged) plus a React node view that adds a language picker header instead\n * of a bare highlighted `<pre>`. \"Auto\" stores no language and the lowlight\n * plugin auto-detects.\n *\n * Lifted from the Content editor's bespoke code block so Plans (and any app\n * opting into `features.codeBlock`) share one implementation. Theming is fully\n * class-driven via {@link CreateCodeBlockNodeOptions.classNames}, so each app\n * maps the hooks onto its own palette.\n */\nexport function createCodeBlockNode({\n lowlight,\n languages = DEFAULT_CODE_LANGUAGES,\n classNames,\n}: CreateCodeBlockNodeOptions): TiptapNode {\n const resolvedClassNames: CodeBlockClassNames = {\n ...DEFAULT_CLASS_NAMES,\n ...(classNames ?? {}),\n };\n\n return CodeBlockLowlight.extend({\n addOptions() {\n return {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n ...this.parent!(),\n languagePickerOptions: languages,\n codeBlockClassNames: resolvedClassNames,\n };\n },\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockView);\n },\n addKeyboardShortcuts() {\n return {\n ...this.parent?.(),\n Tab: ({ editor }) => {\n if (editor.isActive(this.name)) {\n editor.commands.insertContent(\"\\t\");\n return true;\n }\n return false;\n },\n };\n },\n }).configure({\n lowlight,\n defaultLanguage: null,\n }) as unknown as TiptapNode;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageExtension.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/ImageExtension.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,IAAI,EAAE,IAAI,KACP,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5C,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACtC;AAoHD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"ImageExtension.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/ImageExtension.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,IAAI,EAAE,IAAI,KACP,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5C,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACtC;AAoHD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,WAAW,sDAqGtB,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;CAAO,wDAMvD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,aAAa,GACpB,IAAI,CAgBN"}
|
|
@@ -127,7 +127,8 @@ export const SharedImage = Image.extend({
|
|
|
127
127
|
group: "block",
|
|
128
128
|
addOptions() {
|
|
129
129
|
return {
|
|
130
|
-
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
131
|
+
...this.parent(),
|
|
131
132
|
onImageUpload: null,
|
|
132
133
|
};
|
|
133
134
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageExtension.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/ImageExtension.ts"],"names":[],"mappings":"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","sourcesContent":["import Image, { type ImageOptions } from \"@tiptap/extension-image\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\n\n/**\n * The injectable async upload contract for the shared image block.\n *\n * An app provides this to turn a picked / pasted / dropped {@link File} into a\n * hosted image. It returns the final `src` (a hosted URL) plus an optional\n * `alt`. Plans wire it to the framework `upload-image` action; Content keeps its\n * own richer image block and does not use this contract.\n *\n * When NO upload function is supplied, the shared block still renders images and\n * round-trips `` markdown — it just cannot ingest local files (paste\n * of an image URL / markdown still works via the base node's input rules).\n */\nexport type ImageUploadFn = (\n file: File,\n) => Promise<{ src: string; alt?: string }>;\n\nexport interface SharedImageOptions extends ImageOptions {\n /**\n * App-injected uploader. When present, the shared block accepts pasted /\n * dropped image files and the `/image` slash command, uploading each file\n * through this function and patching the node's `src` on resolve.\n */\n onImageUpload?: ImageUploadFn | null;\n}\n\nconst sharedImageUploadPluginKey = new PluginKey(\"an-shared-image-upload\");\n\n/** A monotonically increasing id so concurrent uploads patch the right node. */\nlet uploadCounter = 0;\nfunction nextUploadId(): string {\n uploadCounter += 1;\n return `an-img-${Date.now()}-${uploadCounter}`;\n}\n\n/** Image files only — never ingest non-image clipboard/drop payloads. */\nfunction imageFilesFrom(data: DataTransfer | null | undefined): File[] {\n if (!data) return [];\n return Array.from(data.files ?? []).filter((file) =>\n file.type.startsWith(\"image/\"),\n );\n}\n\n/**\n * Insert a placeholder `image` node (empty `src`, transient `uploadId`) at\n * `pos` for every file, then resolve each upload and patch the matching node's\n * `src`. Mirrors Content's optimistic upload flow but is self-contained in the\n * shared extension so it works for ANY editor wrapper (the plan's\n * `SharedRichEditor` and Content's hand-rolled `useEditor` alike) without a new\n * `editorProps` seam.\n */\nfunction uploadAndInsertImages(\n view: EditorView,\n files: File[],\n pos: number,\n upload: ImageUploadFn,\n): void {\n if (files.length === 0) return;\n\n const pending: Array<{ uploadId: string; file: File }> = [];\n\n // Insert all placeholders first, top-down from `pos`, so multi-file\n // paste/drop keeps source order.\n let insertAt = pos;\n for (const file of files) {\n const uploadId = nextUploadId();\n const node = view.state.schema.nodes.image?.create({\n src: \"\",\n alt: \"\",\n uploadId,\n });\n if (!node) continue;\n const tr = view.state.tr.insert(insertAt, node);\n view.dispatch(tr);\n pending.push({ uploadId, file });\n // Advance past the inserted atom for the next placeholder.\n insertAt += node.nodeSize;\n }\n\n for (const item of pending) {\n void (async () => {\n try {\n const { src, alt } = await upload(item.file);\n if (!view.dom.isConnected || view.isDestroyed) return;\n patchUploadNode(view, item.uploadId, { src, alt: alt ?? \"\" });\n } catch (error) {\n console.error(\"Image upload failed:\", error);\n // Drop the placeholder so a failed upload does not leave an empty box.\n if (view.dom.isConnected && !view.isDestroyed) {\n removeUploadNode(view, item.uploadId);\n }\n }\n })();\n }\n}\n\n/** Find a placeholder node by its transient `uploadId` and return its position. */\nfunction findUploadNode(\n view: EditorView,\n uploadId: string,\n): { pos: number; nodeSize: number } | null {\n let found: { pos: number; nodeSize: number } | null = null;\n view.state.doc.descendants((node, pos) => {\n if (found) return false;\n if (node.type.name === \"image\" && node.attrs.uploadId === uploadId) {\n found = { pos, nodeSize: node.nodeSize };\n return false;\n }\n return true;\n });\n return found;\n}\n\n/** Patch the resolved `src`/`alt` onto the placeholder and clear `uploadId`. */\nfunction patchUploadNode(\n view: EditorView,\n uploadId: string,\n attrs: { src: string; alt: string },\n): void {\n const target = findUploadNode(view, uploadId);\n if (!target) return;\n const node = view.state.doc.nodeAt(target.pos);\n if (!node) return;\n const tr = view.state.tr.setNodeMarkup(target.pos, undefined, {\n ...node.attrs,\n src: attrs.src,\n alt: attrs.alt,\n uploadId: null,\n });\n view.dispatch(tr);\n}\n\n/** Remove a placeholder whose upload failed. */\nfunction removeUploadNode(view: EditorView, uploadId: string): void {\n const target = findUploadNode(view, uploadId);\n if (!target) return;\n const tr = view.state.tr.delete(target.pos, target.pos + target.nodeSize);\n view.dispatch(tr);\n}\n\n/**\n * The SHARED block-level image node. Built on `@tiptap/extension-image` (a\n * node named `image`), so:\n *\n * - **GFM serialization** emits pure `` markdown via a block-aware\n * `addStorage().markdown.serialize` (it calls `closeBlock` so a block image\n * keeps its blank-line separator, byte-stable). It emits NO `<img width>`\n * HTML, so plans stay source-syncable under the GFM `html:false` contract.\n * - **Paste / drop** of local image files is handled by a self-contained\n * ProseMirror plugin that calls the injected {@link ImageUploadFn}. Pasting\n * an image URL or `` markdown works through the base node's input\n * rules even when no uploader is supplied.\n *\n * The node adds one transient `uploadId` attribute (never parsed/rendered to\n * HTML, never serialized to markdown) used to track an in-flight upload.\n *\n * Content keeps its own richer `ImageNode` (Assets picker, AI alt-text, resize,\n * NFM `{color}` serialization) and does NOT use this shared node — both nodes\n * are named `image` but never coexist in the same editor because Content leaves\n * `features.image` off and injects its own via `extraExtensions`.\n */\nexport const SharedImage = Image.extend<SharedImageOptions>({\n // Block-level atom (Content's image is also a block atom). The base extension\n // is block when `inline:false`.\n inline: false,\n group: \"block\",\n\n addOptions() {\n return {\n ...this.parent?.(),\n onImageUpload: null,\n };\n },\n\n addAttributes() {\n return {\n ...this.parent?.(),\n // Transient: marks an in-flight upload so the plugin can patch `src` on\n // resolve. Never written to HTML or markdown.\n uploadId: {\n default: null,\n parseHTML: () => null,\n renderHTML: () => ({}),\n },\n };\n },\n\n addStorage() {\n return {\n ...this.parent?.(),\n // A BLOCK-aware markdown serializer. tiptap-markdown's built-in fallback\n // for the `image` node is prosemirror-markdown's INLINE image serializer,\n // which omits the trailing block separator — so an image immediately\n // followed by a paragraph loses its blank line on round-trip. This\n // node-level spec (merged OVER the fallback by tiptap-markdown's\n // `getMarkdownSpec`) emits the same pure `` markdown but calls\n // `closeBlock`, so a block image stays byte-stable and source-syncable.\n // No `<img width>` / HTML is emitted, so the GFM `html:false` contract and\n // the plan round-trip corpus are preserved.\n markdown: {\n serialize(\n state: {\n esc: (s: string) => string;\n write: (s: string) => void;\n closeBlock: (n: unknown) => void;\n },\n node: { attrs: { src?: string; alt?: string; title?: string } },\n ) {\n const src = node.attrs.src ?? \"\";\n const alt = node.attrs.alt ?? \"\";\n const title = node.attrs.title ?? \"\";\n const titleSuffix = title ? ` \"${title.replace(/\"/g, '\\\\\"')}\"` : \"\";\n state.write(`}${titleSuffix})`);\n state.closeBlock(node);\n },\n parse: {\n // Parsing `` is handled by markdown-it + the base node's\n // markdown input rule.\n },\n },\n };\n },\n\n addProseMirrorPlugins() {\n const upload = this.options.onImageUpload;\n const parentPlugins = this.parent?.() ?? [];\n if (!upload) return parentPlugins;\n\n return [\n ...parentPlugins,\n new Plugin({\n key: sharedImageUploadPluginKey,\n props: {\n handlePaste(view, event) {\n const files = imageFilesFrom(event.clipboardData);\n if (files.length === 0) return false;\n event.preventDefault();\n uploadAndInsertImages(\n view,\n files,\n view.state.selection.from,\n upload,\n );\n return true;\n },\n handleDrop(view, event) {\n const files = imageFilesFrom(event.dataTransfer);\n if (files.length === 0) return false;\n event.preventDefault();\n const coords = view.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n const pos = coords?.pos ?? view.state.selection.from;\n uploadAndInsertImages(view, files, pos, upload);\n return true;\n },\n },\n }),\n ];\n },\n});\n\n/**\n * Build the shared image extension, optionally wired with an app uploader.\n *\n * @example\n * createImageExtension({ onImageUpload: uploadEditorImage })\n */\nexport function createImageExtension(\n options: { onImageUpload?: ImageUploadFn | null } = {},\n) {\n return SharedImage.configure({\n onImageUpload: options.onImageUpload ?? null,\n HTMLAttributes: { class: \"an-rich-md-image\" },\n });\n}\n\n/**\n * Open a native file picker, then upload + insert the chosen image(s) through\n * the same flow as paste/drop. Used by the `/image` slash command.\n */\nexport function pickAndInsertImage(\n view: EditorView,\n upload: ImageUploadFn,\n): void {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = \"image/*\";\n input.multiple = true;\n input.style.display = \"none\";\n input.addEventListener(\"change\", () => {\n const files = Array.from(input.files ?? []).filter((file) =>\n file.type.startsWith(\"image/\"),\n );\n input.remove();\n if (files.length === 0) return;\n uploadAndInsertImages(view, files, view.state.selection.from, upload);\n });\n document.body.appendChild(input);\n input.click();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ImageExtension.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/ImageExtension.ts"],"names":[],"mappings":"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","sourcesContent":["import Image, { type ImageOptions } from \"@tiptap/extension-image\";\nimport { Plugin, PluginKey } from \"@tiptap/pm/state\";\nimport type { EditorView } from \"@tiptap/pm/view\";\n\n/**\n * The injectable async upload contract for the shared image block.\n *\n * An app provides this to turn a picked / pasted / dropped {@link File} into a\n * hosted image. It returns the final `src` (a hosted URL) plus an optional\n * `alt`. Plans wire it to the framework `upload-image` action; Content keeps its\n * own richer image block and does not use this contract.\n *\n * When NO upload function is supplied, the shared block still renders images and\n * round-trips `` markdown — it just cannot ingest local files (paste\n * of an image URL / markdown still works via the base node's input rules).\n */\nexport type ImageUploadFn = (\n file: File,\n) => Promise<{ src: string; alt?: string }>;\n\nexport interface SharedImageOptions extends ImageOptions {\n /**\n * App-injected uploader. When present, the shared block accepts pasted /\n * dropped image files and the `/image` slash command, uploading each file\n * through this function and patching the node's `src` on resolve.\n */\n onImageUpload?: ImageUploadFn | null;\n}\n\nconst sharedImageUploadPluginKey = new PluginKey(\"an-shared-image-upload\");\n\n/** A monotonically increasing id so concurrent uploads patch the right node. */\nlet uploadCounter = 0;\nfunction nextUploadId(): string {\n uploadCounter += 1;\n return `an-img-${Date.now()}-${uploadCounter}`;\n}\n\n/** Image files only — never ingest non-image clipboard/drop payloads. */\nfunction imageFilesFrom(data: DataTransfer | null | undefined): File[] {\n if (!data) return [];\n return Array.from(data.files ?? []).filter((file) =>\n file.type.startsWith(\"image/\"),\n );\n}\n\n/**\n * Insert a placeholder `image` node (empty `src`, transient `uploadId`) at\n * `pos` for every file, then resolve each upload and patch the matching node's\n * `src`. Mirrors Content's optimistic upload flow but is self-contained in the\n * shared extension so it works for ANY editor wrapper (the plan's\n * `SharedRichEditor` and Content's hand-rolled `useEditor` alike) without a new\n * `editorProps` seam.\n */\nfunction uploadAndInsertImages(\n view: EditorView,\n files: File[],\n pos: number,\n upload: ImageUploadFn,\n): void {\n if (files.length === 0) return;\n\n const pending: Array<{ uploadId: string; file: File }> = [];\n\n // Insert all placeholders first, top-down from `pos`, so multi-file\n // paste/drop keeps source order.\n let insertAt = pos;\n for (const file of files) {\n const uploadId = nextUploadId();\n const node = view.state.schema.nodes.image?.create({\n src: \"\",\n alt: \"\",\n uploadId,\n });\n if (!node) continue;\n const tr = view.state.tr.insert(insertAt, node);\n view.dispatch(tr);\n pending.push({ uploadId, file });\n // Advance past the inserted atom for the next placeholder.\n insertAt += node.nodeSize;\n }\n\n for (const item of pending) {\n void (async () => {\n try {\n const { src, alt } = await upload(item.file);\n if (!view.dom.isConnected || view.isDestroyed) return;\n patchUploadNode(view, item.uploadId, { src, alt: alt ?? \"\" });\n } catch (error) {\n console.error(\"Image upload failed:\", error);\n // Drop the placeholder so a failed upload does not leave an empty box.\n if (view.dom.isConnected && !view.isDestroyed) {\n removeUploadNode(view, item.uploadId);\n }\n }\n })();\n }\n}\n\n/** Find a placeholder node by its transient `uploadId` and return its position. */\nfunction findUploadNode(\n view: EditorView,\n uploadId: string,\n): { pos: number; nodeSize: number } | null {\n let found: { pos: number; nodeSize: number } | null = null;\n view.state.doc.descendants((node, pos) => {\n if (found) return false;\n if (node.type.name === \"image\" && node.attrs.uploadId === uploadId) {\n found = { pos, nodeSize: node.nodeSize };\n return false;\n }\n return true;\n });\n return found;\n}\n\n/** Patch the resolved `src`/`alt` onto the placeholder and clear `uploadId`. */\nfunction patchUploadNode(\n view: EditorView,\n uploadId: string,\n attrs: { src: string; alt: string },\n): void {\n const target = findUploadNode(view, uploadId);\n if (!target) return;\n const node = view.state.doc.nodeAt(target.pos);\n if (!node) return;\n const tr = view.state.tr.setNodeMarkup(target.pos, undefined, {\n ...node.attrs,\n src: attrs.src,\n alt: attrs.alt,\n uploadId: null,\n });\n view.dispatch(tr);\n}\n\n/** Remove a placeholder whose upload failed. */\nfunction removeUploadNode(view: EditorView, uploadId: string): void {\n const target = findUploadNode(view, uploadId);\n if (!target) return;\n const tr = view.state.tr.delete(target.pos, target.pos + target.nodeSize);\n view.dispatch(tr);\n}\n\n/**\n * The SHARED block-level image node. Built on `@tiptap/extension-image` (a\n * node named `image`), so:\n *\n * - **GFM serialization** emits pure `` markdown via a block-aware\n * `addStorage().markdown.serialize` (it calls `closeBlock` so a block image\n * keeps its blank-line separator, byte-stable). It emits NO `<img width>`\n * HTML, so plans stay source-syncable under the GFM `html:false` contract.\n * - **Paste / drop** of local image files is handled by a self-contained\n * ProseMirror plugin that calls the injected {@link ImageUploadFn}. Pasting\n * an image URL or `` markdown works through the base node's input\n * rules even when no uploader is supplied.\n *\n * The node adds one transient `uploadId` attribute (never parsed/rendered to\n * HTML, never serialized to markdown) used to track an in-flight upload.\n *\n * Content keeps its own richer `ImageNode` (Assets picker, AI alt-text, resize,\n * NFM `{color}` serialization) and does NOT use this shared node — both nodes\n * are named `image` but never coexist in the same editor because Content leaves\n * `features.image` off and injects its own via `extraExtensions`.\n */\nexport const SharedImage = Image.extend<SharedImageOptions>({\n // Block-level atom (Content's image is also a block atom). The base extension\n // is block when `inline:false`.\n inline: false,\n group: \"block\",\n\n addOptions() {\n return {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n ...this.parent!(),\n onImageUpload: null,\n };\n },\n\n addAttributes() {\n return {\n ...this.parent?.(),\n // Transient: marks an in-flight upload so the plugin can patch `src` on\n // resolve. Never written to HTML or markdown.\n uploadId: {\n default: null,\n parseHTML: () => null,\n renderHTML: () => ({}),\n },\n };\n },\n\n addStorage() {\n return {\n ...this.parent?.(),\n // A BLOCK-aware markdown serializer. tiptap-markdown's built-in fallback\n // for the `image` node is prosemirror-markdown's INLINE image serializer,\n // which omits the trailing block separator — so an image immediately\n // followed by a paragraph loses its blank line on round-trip. This\n // node-level spec (merged OVER the fallback by tiptap-markdown's\n // `getMarkdownSpec`) emits the same pure `` markdown but calls\n // `closeBlock`, so a block image stays byte-stable and source-syncable.\n // No `<img width>` / HTML is emitted, so the GFM `html:false` contract and\n // the plan round-trip corpus are preserved.\n markdown: {\n serialize(\n state: {\n esc: (s: string) => string;\n write: (s: string) => void;\n closeBlock: (n: unknown) => void;\n },\n node: { attrs: { src?: string; alt?: string; title?: string } },\n ) {\n const src = node.attrs.src ?? \"\";\n const alt = node.attrs.alt ?? \"\";\n const title = node.attrs.title ?? \"\";\n const titleSuffix = title ? ` \"${title.replace(/\"/g, '\\\\\"')}\"` : \"\";\n state.write(`}${titleSuffix})`);\n state.closeBlock(node);\n },\n parse: {\n // Parsing `` is handled by markdown-it + the base node's\n // markdown input rule.\n },\n },\n };\n },\n\n addProseMirrorPlugins() {\n const upload = this.options.onImageUpload;\n const parentPlugins = this.parent?.() ?? [];\n if (!upload) return parentPlugins;\n\n return [\n ...parentPlugins,\n new Plugin({\n key: sharedImageUploadPluginKey,\n props: {\n handlePaste(view, event) {\n const files = imageFilesFrom(event.clipboardData);\n if (files.length === 0) return false;\n event.preventDefault();\n uploadAndInsertImages(\n view,\n files,\n view.state.selection.from,\n upload,\n );\n return true;\n },\n handleDrop(view, event) {\n const files = imageFilesFrom(event.dataTransfer);\n if (files.length === 0) return false;\n event.preventDefault();\n const coords = view.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n const pos = coords?.pos ?? view.state.selection.from;\n uploadAndInsertImages(view, files, pos, upload);\n return true;\n },\n },\n }),\n ];\n },\n});\n\n/**\n * Build the shared image extension, optionally wired with an app uploader.\n *\n * @example\n * createImageExtension({ onImageUpload: uploadEditorImage })\n */\nexport function createImageExtension(\n options: { onImageUpload?: ImageUploadFn | null } = {},\n) {\n return SharedImage.configure({\n onImageUpload: options.onImageUpload ?? null,\n HTMLAttributes: { class: \"an-rich-md-image\" },\n });\n}\n\n/**\n * Open a native file picker, then upload + insert the chosen image(s) through\n * the same flow as paste/drop. Used by the `/image` slash command.\n */\nexport function pickAndInsertImage(\n view: EditorView,\n upload: ImageUploadFn,\n): void {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = \"image/*\";\n input.multiple = true;\n input.style.display = \"none\";\n input.addEventListener(\"change\", () => {\n const files = Array.from(input.files ?? []).filter((file) =>\n file.type.startsWith(\"image/\"),\n );\n input.remove();\n if (files.length === 0) return;\n uploadAndInsertImages(view, files, view.state.selection.from, upload);\n });\n document.body.appendChild(input);\n input.click();\n}\n"]}
|
|
@@ -89,7 +89,7 @@ export declare function LegacyJsonEditSurface({ block, open, onOpenChange, rende
|
|
|
89
89
|
* own `onChange`.
|
|
90
90
|
*/
|
|
91
91
|
customEditor?: ReactNode;
|
|
92
|
-
}): string | number | bigint | boolean |
|
|
92
|
+
}): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
93
93
|
/** Options for {@link createRegistryBlockNode}. */
|
|
94
94
|
export interface CreateRegistryBlockNodeOptions {
|
|
95
95
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegistryBlockNode.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/RegistryBlockNode.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,IAAI,EAIJ,KAAK,aAAa,EACnB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAsB5B,0EAA0E;AAC1E,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB,CACrC,MAAM,SAAS,yBAAyB,GAAG,yBAAyB;IAEpE,qEAAqE;IACrE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAClD,8DAA8D;IAC9D,iBAAiB,EAAE,CACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,EACjB,IAAI,CAAC,EAAE,mBAAmB,KACvB,IAAI,CAAC;IACV,8DAA8D;IAC9D,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,wBAAwB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1D;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,KAC1B,SAAS,CAAC;IACf;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;QAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE,KAC5C,SAAS,CAAC;IACf;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CACvD;AAKD,wBAAgB,yBAAyB,CACvC,MAAM,SAAS,yBAAyB,GAAG,yBAAyB,EACpE,EACA,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACtC,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAMA;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAClC,MAAM,SAAS,yBAAyB,GAAG,yBAAyB,KACjE,sBAAsB,CAAC,MAAM,CAAC,GAAG,IAAI,CAIzC;AAgCD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,2CAoPzD;AAED,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,YAAY,GACb,EAAE;IACD,KAAK,EAAE,yBAAyB,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;IAC5D,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;CAC1B,
|
|
1
|
+
{"version":3,"file":"RegistryBlockNode.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/RegistryBlockNode.tsx"],"names":[],"mappings":"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"}
|
|
@@ -166,7 +166,7 @@ export function RegistryBlockNodeView(props) {
|
|
|
166
166
|
// corner edit surface — the block owns a single, self-contained overlay.
|
|
167
167
|
const selfEdits = editable && Boolean(sideMap.legacyBlockSelfEdits?.(blockType));
|
|
168
168
|
body = sideMap.renderLegacyBlock(block, { editing: selfEdits });
|
|
169
|
-
if (editable &&
|
|
169
|
+
if (editable && !selfEdits) {
|
|
170
170
|
// Prefer a host-provided schema/custom editor (a real form) over the raw
|
|
171
171
|
// JSON fallback when the host knows how to edit this legacy block type.
|
|
172
172
|
const customEditor = sideMap.renderLegacyBlockEditor?.(block, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegistryBlockNode.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/RegistryBlockNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createContext,\n useEffect,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { IconPencil } from \"@tabler/icons-react\";\nimport {\n Node,\n NodeViewWrapper,\n ReactNodeViewRenderer,\n mergeAttributes,\n type NodeViewProps,\n} from \"@tiptap/react\";\nimport {\n NodeSelection,\n Plugin,\n PluginKey,\n type EditorState,\n} from \"@tiptap/pm/state\";\nimport {\n blockEditSurface,\n useOptionalBlockRegistry,\n type BlockDataChangeMeta,\n type BlockRenderContext,\n} from \"../blocks/index.js\";\nimport { SchemaBlockEditor } from \"../blocks/SchemaBlockEditor.js\";\n\n/* -------------------------------------------------------------------------- */\n/* The generic registry-block side-map + Tiptap NodeView, lifted into core. */\n/* */\n/* This is the app-agnostic NodeView that renders registered block specs */\n/* inside a `SharedRichEditor` document. Hosts mount the node produced by */\n/* {@link createRegistryBlockNode} as an extra extension and wrap the editor */\n/* in a {@link RegistryBlockDataProvider}, sourcing the typed block `data` */\n/* from their own authoritative store (for example, PlanContent.blocks). The */\n/* node itself carries only lightweight identity attrs (type/id/title/summary) */\n/* plus an optional `__raw` verbatim-MDX attr for byte-stable source */\n/* round-trips; the heavy typed `data` is threaded through the side-map */\n/* context, keeping the doc small and the block data the single source of */\n/* truth. */\n/* -------------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------------- */\n/* C. Block-data side-map context */\n/* -------------------------------------------------------------------------- */\n\n/** The minimal block shape the NodeView renders through `<BlockView>`. */\nexport interface RegistryBlockSideMapBlock {\n id: string;\n title?: string;\n summary?: string;\n data: unknown;\n}\n\n/**\n * The side-map an editor host supplies so the registry NodeView can resolve a\n * block's full typed `data` (and commit edits) by its stable id, without ever\n * storing that data in the ProseMirror doc.\n */\nexport interface RegistryBlockDataValue<\n TBlock extends RegistryBlockSideMapBlock = RegistryBlockSideMapBlock,\n> {\n /** Resolve a block's full record (incl. `data`) by its stable id. */\n getBlock: (blockId: string) => TBlock | undefined;\n /** Commit a new `data` value for a block (edit-mode only). */\n onBlockDataChange: (\n blockId: string,\n nextData: unknown,\n meta?: BlockDataChangeMeta,\n ) => void;\n /** Whether the document (and thus its blocks) is editable. */\n editable: boolean;\n /**\n * When true, blocks whose type has no Notion (NFM) analog are badged so the\n * author knows they won't sync. The host decides which types are incompatible\n * via {@link isNotionIncompatibleType}; this flag just toggles the badge on.\n */\n notionSync?: boolean;\n /**\n * Decide whether a block type is Notion-incompatible (no NFM analog). Only\n * consulted when {@link notionSync} is true. Injected by the host so the\n * single registry-level allowlist (plan's `isNotionCompatibleBlockType`, or\n * content's registry-derived gate) drives the badge — core stays policy-free.\n */\n isNotionIncompatibleType?: (blockType: string) => boolean;\n /**\n * Render a block whose type is NOT in the registry through the host's own\n * dispatcher (plan: `PlanBlockView` for decision / legacy visual-questions /\n * image; omitted in hosts with no legacy types), so every block type renders\n * in the document instead of a bare fallback.\n */\n renderLegacyBlock?: (\n block: TBlock,\n options: { editing: boolean },\n ) => ReactNode;\n /**\n * Optional: render a schema-driven (or otherwise custom) editor for a legacy\n * block in place of the raw-JSON fallback. Receives an `onChange` that commits\n * the block's new `data`. Return `null`/`undefined` to keep the JSON editor for\n * that block type. The returned editor is expected to autosave through\n * `onChange` (no Save button is shown), matching registered panel blocks.\n */\n renderLegacyBlockEditor?: (\n block: TBlock,\n args: { onChange: (nextData: unknown) => void },\n ) => ReactNode;\n /**\n * Return `true` for legacy block types that render their OWN edit affordance\n * inside `renderLegacyBlock` (e.g. an image block with its own hover toolbar).\n * For those types the node view renders the legacy block in edit mode and adds\n * NO separate corner edit surface (no pencil / JSON / form popover), so the\n * block owns a single, self-contained control overlay.\n */\n legacyBlockSelfEdits?: (blockType: string) => boolean;\n}\n\nconst RegistryBlockDataContext =\n createContext<RegistryBlockDataValue<any> | null>(null);\n\nexport function RegistryBlockDataProvider<\n TBlock extends RegistryBlockSideMapBlock = RegistryBlockSideMapBlock,\n>({\n value,\n children,\n}: {\n value: RegistryBlockDataValue<TBlock>;\n children: ReactNode;\n}) {\n return (\n <RegistryBlockDataContext.Provider value={value}>\n {children}\n </RegistryBlockDataContext.Provider>\n );\n}\n\n/** Read the registry block side-map. Returns `null` outside a provider. */\nexport function useRegistryBlockData<\n TBlock extends RegistryBlockSideMapBlock = RegistryBlockSideMapBlock,\n>(): RegistryBlockDataValue<TBlock> | null {\n return useContext(\n RegistryBlockDataContext,\n ) as RegistryBlockDataValue<TBlock> | null;\n}\n\nfunction clickedInteractiveChild(target: HTMLElement) {\n if (target.closest(\"button,input,textarea,select,a,[role='textbox']\")) {\n return true;\n }\n\n // The block drag-handle grip is a `role=\"button\"` div that lives in the editor\n // wrapper, and nested container blocks (columns/tabs) render their own inner\n // editors — each its own grip. A container block's `onMouseDownCapture`\n // selection handler runs in a SEPARATE React root (Tiptap mounts every node\n // view as its own root), so its `stopPropagation()` halts the NATIVE mousedown\n // right there, before it can reach an inner grip or inner editor. Treat the\n // grip and anything inside a nested editor region as interactive so the outer\n // container never hijacks a mousedown meant for inner machinery — this is what\n // makes dragging a block OUT of / BETWEEN columns (a nested grip) work at all.\n if (\n target.closest(\".drag-handle\") ||\n target.closest(\".plan-nested-document-editor-region\")\n ) {\n return true;\n }\n\n const blockNode = target.closest(\".plan-block-node\");\n const editable = target.closest(\"[contenteditable='true']\");\n return !!blockNode && !!editable && blockNode.contains(editable);\n}\n\n/* -------------------------------------------------------------------------- */\n/* B. RegistryBlockNodeView (React) */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Renders one registry-block atom. The block is non-editable as far as\n * ProseMirror is concerned (`contentEditable={false}`); all interaction happens\n * inside the registry-driven `<BlockView>`. Read vs edit is toggled by\n * `props.selected` (the node is \"selected\" in the editor) AND the document being\n * editable. `data-plan-interactive` keeps existing host click-guards from\n * treating clicks inside the block as document clicks.\n */\nexport function RegistryBlockNodeView(props: NodeViewProps) {\n const blockType = String(props.node.attrs.blockType ?? \"\");\n const blockId = String(props.node.attrs.blockId ?? \"\");\n const [panelOpen, setPanelOpen] = useState(false);\n const [shellHovered, setShellHovered] = useState(false);\n\n const registryValue = useOptionalBlockRegistry();\n const sideMap = useRegistryBlockData();\n\n // Optimistic edit override. `onBlockDataChange` commits into the host's own\n // store (a ref the side-map context can't observe), so an edit does NOT\n // re-render this node — the new data only reaches the view on the next full\n // document reconcile, which lands after the autosave round-trip (seconds\n // later) and is skipped entirely when the host treats the save as its own\n // echo. That left quick toggles like the callout tone buttons visually frozen\n // until reload. Holding the just-edited data locally re-renders this one node\n // immediately, then releases once the authoritative block catches up to (or\n // moves past) the value the edit was based on.\n const [pendingEdit, setPendingEdit] = useState<{\n data: unknown;\n base: unknown;\n } | null>(null);\n const liveBlock = sideMap?.getBlock(blockId);\n const liveData = liveBlock?.data;\n useEffect(() => {\n if (pendingEdit && !Object.is(liveData, pendingEdit.base)) {\n setPendingEdit(null);\n }\n }, [liveData, pendingEdit]);\n const block =\n liveBlock && pendingEdit && Object.is(liveData, pendingEdit.base)\n ? { ...liveBlock, data: pendingEdit.data }\n : liveBlock;\n const commitBlockData = (nextData: unknown, meta?: BlockDataChangeMeta) => {\n setPendingEdit({ data: nextData, base: liveData });\n sideMap?.onBlockDataChange(blockId, nextData, meta);\n };\n const editable = sideMap?.editable ?? false;\n // In Notion-sync mode, flag blocks that have no Notion (NFM) analog so the\n // author sees what won't push. Prose blocks aren't registry-block nodes, so\n // this only ever covers structured blocks.\n const incompatibleWithNotion =\n (sideMap?.notionSync ?? false) &&\n (sideMap?.isNotionIncompatibleType?.(blockType) ?? false);\n\n // The block data isn't in the side-map yet (e.g. a freshly inserted node whose\n // store entry hasn't been seeded). Render a graceful placeholder.\n if (!block) {\n return (\n <NodeViewWrapper className=\"plan-block-node\" data-block-id={blockId}>\n <div\n contentEditable={false}\n data-plan-interactive\n className=\"plan-block-node__placeholder rounded-md border border-dashed border-border px-3 py-2 text-sm text-muted-foreground\"\n >\n {blockType ? `Loading ${blockType} block…` : \"Loading block…\"}\n </div>\n </NodeViewWrapper>\n );\n }\n\n const spec = registryValue?.registry.get(blockType);\n const selectNode = (event: ReactMouseEvent<HTMLElement>) => {\n if (!editable) return;\n const target = event.target;\n if (target instanceof HTMLElement && clickedInteractiveChild(target))\n return;\n const pos = typeof props.getPos === \"function\" ? props.getPos() : null;\n if (typeof pos !== \"number\") return;\n try {\n event.preventDefault();\n event.stopPropagation();\n const { view } = props.editor;\n view.dispatch(\n view.state.tr.setSelection(NodeSelection.create(view.state.doc, pos)),\n );\n view.focus();\n } catch {\n // Ignore stale positions during React/ProseMirror reconciliation.\n }\n };\n const updateShellHover = (event: ReactMouseEvent<HTMLElement>) => {\n const target = event.target;\n setShellHovered(\n target instanceof HTMLElement &&\n target.closest(\".plan-block-node__shell\") === event.currentTarget,\n );\n };\n\n // Choose how to render the block body:\n // 1. Registered spec → read view by default; direct-manipulation specs\n // (`editSurface: \"inline\" | \"container\"`) render their editor in place,\n // while artifact/config specs (`\"panel\"`) keep the read view plus a\n // corner edit button.\n // 2. No spec, but the side-map provides `renderLegacyBlock` → delegate to the\n // host's dispatcher (decision, legacy visual-questions, image, and any\n // other type rendered by a bespoke component rather than the registry), so\n // EVERY block type renders in the document exactly as it does in the\n // per-block reader — never a bare title fallback.\n // 3. Neither → a small non-crashing fallback.\n let body: ReactNode;\n let editSurface: ReactNode = null;\n if (registryValue && spec) {\n const blockData = (block as { data: unknown }).data;\n const Read = spec.Read;\n const readNode = (\n <Read\n data={blockData}\n blockId={block.id}\n title={block.title}\n summary={block.summary}\n ctx={registryValue.ctx}\n />\n );\n body = readNode;\n const canEditBlock =\n editable &&\n spec.placement.includes(\"block\") &&\n !!sideMap?.onBlockDataChange;\n if (canEditBlock) {\n const Edit = spec.Edit;\n const editorNode = Edit ? (\n <Edit\n data={blockData}\n onChange={commitBlockData}\n editable\n blockId={block.id}\n title={block.title}\n summary={block.summary}\n ctx={registryValue.ctx}\n />\n ) : (\n <SchemaBlockEditor\n data={blockData}\n onChange={(nextData) => commitBlockData(nextData)}\n schema={spec.schema}\n editable\n blockId={block.id}\n ctx={registryValue.ctx}\n />\n );\n const surface = blockEditSurface(spec);\n if (surface === \"panel\" && registryValue.ctx.renderEditSurface) {\n editSurface = registryValue.ctx.renderEditSurface({\n title: spec.label,\n open: panelOpen,\n onOpenChange: setPanelOpen,\n blockId: block.id,\n blockType,\n blockTitle: block.title,\n blockSummary: block.summary,\n blockData,\n trigger: (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Edit ${spec.label}`}\n onClick={() => setPanelOpen(true)}\n className=\"an-block-edit-trigger flex size-7 items-center justify-center rounded-md border border-border bg-background/85 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-opacity hover:bg-muted hover:text-foreground focus-visible:opacity-100 data-[visible=true]:opacity-100\"\n data-visible={panelOpen || shellHovered}\n >\n <IconPencil className=\"size-4\" />\n </button>\n ),\n children: editorNode,\n });\n } else if (surface === \"panel\") {\n editSurface = props.selected ? (\n <div className=\"mt-3\">{editorNode}</div>\n ) : null;\n } else {\n body = editorNode;\n }\n }\n } else if (sideMap?.renderLegacyBlock) {\n // Self-editing legacy blocks (e.g. image) render their own edit affordance\n // inside their overlay, so render them in edit mode and add NO separate\n // corner edit surface — the block owns a single, self-contained overlay.\n const selfEdits =\n editable && Boolean(sideMap.legacyBlockSelfEdits?.(blockType));\n body = sideMap.renderLegacyBlock(block, { editing: selfEdits });\n if (editable && sideMap.onBlockDataChange && !selfEdits) {\n // Prefer a host-provided schema/custom editor (a real form) over the raw\n // JSON fallback when the host knows how to edit this legacy block type.\n const customEditor = sideMap.renderLegacyBlockEditor?.(block, {\n onChange: (nextData) => commitBlockData(nextData),\n });\n editSurface = (\n <LegacyJsonEditSurface\n block={block}\n open={panelOpen}\n onOpenChange={setPanelOpen}\n renderEditSurface={registryValue?.ctx.renderEditSurface}\n onChange={(nextBlock) => commitBlockData(nextBlock)}\n selected={shellHovered}\n customEditor={customEditor}\n />\n );\n }\n } else {\n body = (\n <div className=\"plan-block-node__fallback rounded-md border border-border px-3 py-2 text-sm text-muted-foreground\">\n {block.title || blockType || \"Unsupported block\"}\n </div>\n );\n }\n\n return (\n <NodeViewWrapper\n className=\"plan-block-node\"\n data-block-id={blockId}\n // Mirror the block type onto the wrapper so the document flow can detect a\n // RUN of consecutive blocks of the same type (e.g. api-endpoint) and\n // collapse the divider + gap between them, matching the read-only path.\n data-block-type={blockType || undefined}\n data-plan-block-selected={props.selected ? \"\" : undefined}\n data-notion-incompatible={incompatibleWithNotion ? \"\" : undefined}\n onMouseDownCapture={selectNode}\n >\n <div\n contentEditable={false}\n data-plan-interactive\n className=\"plan-block-node__shell relative\"\n onMouseEnter={updateShellHover}\n onMouseMove={updateShellHover}\n onMouseLeave={() => setShellHovered(false)}\n >\n {incompatibleWithNotion && (\n <span\n className=\"plan-block-notion-badge\"\n title=\"This block type has no Notion equivalent and won't sync to Notion.\"\n >\n Won't sync to Notion\n </span>\n )}\n {body}\n {editSurface && (\n <div className=\"plan-block-node__edit absolute right-2 top-2 z-20\">\n {editSurface}\n </div>\n )}\n </div>\n </NodeViewWrapper>\n );\n}\n\nexport function LegacyJsonEditSurface({\n block,\n open,\n onOpenChange,\n renderEditSurface,\n onChange,\n selected,\n customEditor,\n}: {\n block: RegistryBlockSideMapBlock;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n renderEditSurface?: BlockRenderContext[\"renderEditSurface\"];\n onChange: (nextData: unknown) => void;\n selected: boolean;\n /**\n * A host-provided form editor (e.g. {@link SchemaBlockEditor}). When present it\n * replaces the raw-JSON textarea + Save button; the form autosaves through its\n * own `onChange`.\n */\n customEditor?: ReactNode;\n}) {\n const serializedBlockData = useMemo(\n () => JSON.stringify(block.data, null, 2),\n [block.data],\n );\n const [draft, setDraft] = useState(serializedBlockData);\n const [parseError, setParseError] = useState<string | null>(null);\n\n useEffect(() => {\n setDraft(serializedBlockData);\n setParseError(null);\n }, [block.id, serializedBlockData]);\n\n const saveDraft = () => {\n try {\n const nextData = JSON.parse(draft) as unknown;\n setParseError(null);\n onChange(nextData);\n onOpenChange(false);\n } catch (error) {\n setParseError(\n error instanceof Error ? error.message : \"Invalid JSON data.\",\n );\n }\n };\n\n const trigger = (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Edit ${block.title ?? \"block\"}`}\n onClick={() => onOpenChange(true)}\n className=\"an-block-edit-trigger flex size-7 items-center justify-center rounded-md border border-border bg-background/85 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-opacity hover:bg-muted hover:text-foreground focus-visible:opacity-100 data-[visible=true]:opacity-100\"\n data-visible={selected || open}\n >\n <IconPencil className=\"size-4\" />\n </button>\n );\n const jsonEditor = (\n <div className=\"grid gap-3\">\n <textarea\n data-plan-interactive\n className=\"min-h-64 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={draft}\n aria-invalid={parseError ? true : undefined}\n onChange={(event) => {\n setDraft(event.target.value);\n if (parseError) setParseError(null);\n }}\n />\n {parseError ? (\n <p className=\"text-xs text-destructive\" role=\"alert\">\n Invalid JSON: {parseError}\n </p>\n ) : null}\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n data-plan-interactive\n className=\"inline-flex h-8 items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground\"\n onClick={saveDraft}\n >\n Save\n </button>\n </div>\n </div>\n );\n const editor = customEditor ?? jsonEditor;\n if (!renderEditSurface) return open ? editor : trigger;\n return renderEditSurface({\n title: block.title ?? \"Block\",\n open,\n onOpenChange,\n blockId: block.id,\n blockType:\n typeof (block as { type?: unknown }).type === \"string\"\n ? ((block as unknown as { type: string }).type ?? \"\")\n : \"legacy\",\n blockTitle: block.title,\n blockSummary: block.summary,\n blockData: block.data,\n trigger,\n children: editor,\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* A. registry-block Tiptap node factory */\n/* -------------------------------------------------------------------------- */\n\n/** Options for {@link createRegistryBlockNode}. */\nexport interface CreateRegistryBlockNodeOptions {\n /**\n * The Tiptap node name (e.g. `\"planBlock\"`). Hosts that serialize the doc by\n * node name (plan's `plan-doc.ts` keys off `\"planBlock\"`) must pass the exact\n * name their serializer expects.\n */\n nodeName: string;\n /**\n * The HTML data-attribute that marks a serialized registry block on copy/paste\n * round-trip (e.g. `\"data-plan-block\"`).\n */\n dataTag: string;\n /**\n * Mint a fresh, unique block id for a given block type. Used by the dedupe\n * plugin to re-mint duplicate / missing ids (paste/duplicate). Plan passes\n * `createPlanBlockId`.\n */\n mintId: (blockType: string) => string;\n /** Node group (default `\"block\"`). */\n group?: string;\n}\n\n/**\n * Build the generic registry-block Tiptap atom node. Returns a Tiptap `Node`\n * that:\n * - carries identity attrs `blockType` / `blockId` / `title` / `summary`, a\n * `sourceBlockId` (set when a duplicate is re-minted, so the host can copy the\n * original block's data), and an optional `__raw` verbatim-MDX attr for\n * byte-stable source round-trips;\n * - is an atom + isolating + draggable block that renders through\n * {@link RegistryBlockNodeView} (via `ReactNodeViewRenderer`);\n * - installs a dedupe `appendTransaction` plugin that re-mints any duplicate or\n * empty `blockId` (the classic paste/duplicate case), preserving the original\n * block's id + side-map data and tagging its own transaction so it never\n * loops.\n */\nexport function createRegistryBlockNode(\n options: CreateRegistryBlockNodeOptions,\n) {\n const { nodeName, dataTag, mintId, group = \"block\" } = options;\n const dedupeKey = new PluginKey(`${nodeName}DedupeIds`);\n const keyboardGuardKey = new PluginKey(`${nodeName}KeyboardGuard`);\n\n /**\n * Collect every `blockId` currently present on this node type in a doc, with\n * the position of each node, so duplicate ids (from paste/duplicate) can be\n * detected and re-minted.\n */\n function collectEntries(state: EditorState): Array<{\n pos: number;\n blockType: string;\n blockId: string;\n sourceBlockId?: string;\n }> {\n const found: Array<{\n pos: number;\n blockType: string;\n blockId: string;\n sourceBlockId?: string;\n }> = [];\n state.doc.descendants((node, pos) => {\n if (node.type.name === nodeName) {\n found.push({\n pos,\n blockType: String(node.attrs.blockType ?? \"\"),\n blockId: String(node.attrs.blockId ?? \"\"),\n sourceBlockId:\n typeof node.attrs.sourceBlockId === \"string\"\n ? node.attrs.sourceBlockId\n : undefined,\n });\n }\n return true;\n });\n return found;\n }\n\n /**\n * Build a transaction that re-mints any duplicate / missing ids in `state`, or\n * `null` when nothing needs changing. Only the *later* duplicate (and any node\n * with an empty id) is re-minted, so the original keeps its id and side-map\n * data.\n */\n function buildDedupeTransaction(state: EditorState) {\n const entries = collectEntries(state);\n if (entries.length === 0) return null;\n\n const seen = new Set<string>();\n let tr = state.tr;\n let changed = false;\n\n for (const entry of entries) {\n const needsNewId = !entry.blockId || seen.has(entry.blockId);\n if (needsNewId) {\n const freshId = mintId(entry.blockType || \"block\");\n const node = state.doc.nodeAt(entry.pos);\n if (node) {\n tr = tr.setNodeMarkup(entry.pos, undefined, {\n ...node.attrs,\n blockId: freshId,\n sourceBlockId: entry.sourceBlockId || entry.blockId || null,\n });\n changed = true;\n }\n seen.add(freshId);\n } else {\n seen.add(entry.blockId);\n }\n }\n\n return changed ? tr.setMeta(dedupeKey, true) : null;\n }\n\n const selectedRegistryBlock = (state: EditorState) =>\n state.selection instanceof NodeSelection &&\n state.selection.node.type.name === nodeName;\n\n const isMutatingKey = (event: KeyboardEvent) => {\n if (event.altKey || event.ctrlKey || event.metaKey) return false;\n if (event.key === \"Enter\") return true;\n return event.key.length === 1;\n };\n\n return Node.create({\n name: nodeName,\n group,\n atom: true,\n draggable: true,\n selectable: true,\n isolating: true,\n\n addAttributes() {\n return {\n blockType: { default: \"\" },\n blockId: { default: \"\" },\n title: { default: null },\n summary: { default: null },\n sourceBlockId: { default: null },\n // Optional verbatim source for hosts that need byte-identical\n // source-format round-trips without React (server pull, hashing). Plan\n // never sets this.\n __raw: { default: null, rendered: false },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: `div[${dataTag}]`,\n getAttrs: (element) => {\n const node = element as HTMLElement;\n return {\n blockType: node.getAttribute(\"data-block-type\") || \"\",\n blockId: node.getAttribute(\"data-block-id\") || \"\",\n title: node.getAttribute(\"data-title\") || null,\n summary: node.getAttribute(\"data-summary\") || null,\n sourceBlockId: node.getAttribute(\"data-source-block-id\") || null,\n };\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n [dataTag]: \"\",\n \"data-block-type\": HTMLAttributes.blockType ?? \"\",\n \"data-block-id\": HTMLAttributes.blockId ?? \"\",\n \"data-title\": HTMLAttributes.title ?? undefined,\n \"data-summary\": HTMLAttributes.summary ?? undefined,\n \"data-source-block-id\": HTMLAttributes.sourceBlockId ?? undefined,\n }),\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(RegistryBlockNodeView);\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: dedupeKey,\n appendTransaction(transactions, _oldState, newState) {\n // Ignore our own re-mint, and skip when nothing changed the doc.\n if (\n transactions.some((transaction) =>\n transaction.getMeta(dedupeKey),\n ) ||\n !transactions.some((transaction) => transaction.docChanged)\n ) {\n return null;\n }\n return buildDedupeTransaction(newState);\n },\n }),\n new Plugin({\n key: keyboardGuardKey,\n props: {\n handleClickOn(view, _pos, node, nodePos, event, direct) {\n if (node.type.name !== nodeName || !direct) return false;\n if (\n event.target instanceof HTMLElement &&\n clickedInteractiveChild(event.target)\n ) {\n return false;\n }\n event.preventDefault();\n view.dispatch(\n view.state.tr.setSelection(\n NodeSelection.create(view.state.doc, nodePos),\n ),\n );\n view.focus();\n return true;\n },\n handleKeyDown(view, event) {\n if (!selectedRegistryBlock(view.state) || !isMutatingKey(event))\n return false;\n event.preventDefault();\n return true;\n },\n handleTextInput(view) {\n return selectedRegistryBlock(view.state);\n },\n handlePaste(view, event) {\n if (!selectedRegistryBlock(view.state)) return false;\n event.preventDefault();\n return true;\n },\n handleDOMEvents: {\n beforeinput(view, event) {\n if (!selectedRegistryBlock(view.state)) return false;\n const inputEvent = event as InputEvent;\n if (\n !inputEvent.inputType ||\n (!inputEvent.inputType.startsWith(\"insert\") &&\n inputEvent.inputType !== \"formatSetBlockTextDirection\")\n ) {\n return false;\n }\n event.preventDefault();\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"RegistryBlockNode.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/RegistryBlockNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n createContext,\n useEffect,\n useContext,\n useMemo,\n useState,\n type ReactNode,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { IconPencil } from \"@tabler/icons-react\";\nimport {\n Node,\n NodeViewWrapper,\n ReactNodeViewRenderer,\n mergeAttributes,\n type NodeViewProps,\n} from \"@tiptap/react\";\nimport {\n NodeSelection,\n Plugin,\n PluginKey,\n type EditorState,\n} from \"@tiptap/pm/state\";\nimport {\n blockEditSurface,\n useOptionalBlockRegistry,\n type BlockDataChangeMeta,\n type BlockRenderContext,\n} from \"../blocks/index.js\";\nimport { SchemaBlockEditor } from \"../blocks/SchemaBlockEditor.js\";\n\n/* -------------------------------------------------------------------------- */\n/* The generic registry-block side-map + Tiptap NodeView, lifted into core. */\n/* */\n/* This is the app-agnostic NodeView that renders registered block specs */\n/* inside a `SharedRichEditor` document. Hosts mount the node produced by */\n/* {@link createRegistryBlockNode} as an extra extension and wrap the editor */\n/* in a {@link RegistryBlockDataProvider}, sourcing the typed block `data` */\n/* from their own authoritative store (for example, PlanContent.blocks). The */\n/* node itself carries only lightweight identity attrs (type/id/title/summary) */\n/* plus an optional `__raw` verbatim-MDX attr for byte-stable source */\n/* round-trips; the heavy typed `data` is threaded through the side-map */\n/* context, keeping the doc small and the block data the single source of */\n/* truth. */\n/* -------------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------------- */\n/* C. Block-data side-map context */\n/* -------------------------------------------------------------------------- */\n\n/** The minimal block shape the NodeView renders through `<BlockView>`. */\nexport interface RegistryBlockSideMapBlock {\n id: string;\n title?: string;\n summary?: string;\n data: unknown;\n}\n\n/**\n * The side-map an editor host supplies so the registry NodeView can resolve a\n * block's full typed `data` (and commit edits) by its stable id, without ever\n * storing that data in the ProseMirror doc.\n */\nexport interface RegistryBlockDataValue<\n TBlock extends RegistryBlockSideMapBlock = RegistryBlockSideMapBlock,\n> {\n /** Resolve a block's full record (incl. `data`) by its stable id. */\n getBlock: (blockId: string) => TBlock | undefined;\n /** Commit a new `data` value for a block (edit-mode only). */\n onBlockDataChange: (\n blockId: string,\n nextData: unknown,\n meta?: BlockDataChangeMeta,\n ) => void;\n /** Whether the document (and thus its blocks) is editable. */\n editable: boolean;\n /**\n * When true, blocks whose type has no Notion (NFM) analog are badged so the\n * author knows they won't sync. The host decides which types are incompatible\n * via {@link isNotionIncompatibleType}; this flag just toggles the badge on.\n */\n notionSync?: boolean;\n /**\n * Decide whether a block type is Notion-incompatible (no NFM analog). Only\n * consulted when {@link notionSync} is true. Injected by the host so the\n * single registry-level allowlist (plan's `isNotionCompatibleBlockType`, or\n * content's registry-derived gate) drives the badge — core stays policy-free.\n */\n isNotionIncompatibleType?: (blockType: string) => boolean;\n /**\n * Render a block whose type is NOT in the registry through the host's own\n * dispatcher (plan: `PlanBlockView` for decision / legacy visual-questions /\n * image; omitted in hosts with no legacy types), so every block type renders\n * in the document instead of a bare fallback.\n */\n renderLegacyBlock?: (\n block: TBlock,\n options: { editing: boolean },\n ) => ReactNode;\n /**\n * Optional: render a schema-driven (or otherwise custom) editor for a legacy\n * block in place of the raw-JSON fallback. Receives an `onChange` that commits\n * the block's new `data`. Return `null`/`undefined` to keep the JSON editor for\n * that block type. The returned editor is expected to autosave through\n * `onChange` (no Save button is shown), matching registered panel blocks.\n */\n renderLegacyBlockEditor?: (\n block: TBlock,\n args: { onChange: (nextData: unknown) => void },\n ) => ReactNode;\n /**\n * Return `true` for legacy block types that render their OWN edit affordance\n * inside `renderLegacyBlock` (e.g. an image block with its own hover toolbar).\n * For those types the node view renders the legacy block in edit mode and adds\n * NO separate corner edit surface (no pencil / JSON / form popover), so the\n * block owns a single, self-contained control overlay.\n */\n legacyBlockSelfEdits?: (blockType: string) => boolean;\n}\n\nconst RegistryBlockDataContext =\n createContext<RegistryBlockDataValue<any> | null>(null);\n\nexport function RegistryBlockDataProvider<\n TBlock extends RegistryBlockSideMapBlock = RegistryBlockSideMapBlock,\n>({\n value,\n children,\n}: {\n value: RegistryBlockDataValue<TBlock>;\n children: ReactNode;\n}) {\n return (\n <RegistryBlockDataContext.Provider value={value}>\n {children}\n </RegistryBlockDataContext.Provider>\n );\n}\n\n/** Read the registry block side-map. Returns `null` outside a provider. */\nexport function useRegistryBlockData<\n TBlock extends RegistryBlockSideMapBlock = RegistryBlockSideMapBlock,\n>(): RegistryBlockDataValue<TBlock> | null {\n return useContext(\n RegistryBlockDataContext,\n ) as RegistryBlockDataValue<TBlock> | null;\n}\n\nfunction clickedInteractiveChild(target: HTMLElement) {\n if (target.closest(\"button,input,textarea,select,a,[role='textbox']\")) {\n return true;\n }\n\n // The block drag-handle grip is a `role=\"button\"` div that lives in the editor\n // wrapper, and nested container blocks (columns/tabs) render their own inner\n // editors — each its own grip. A container block's `onMouseDownCapture`\n // selection handler runs in a SEPARATE React root (Tiptap mounts every node\n // view as its own root), so its `stopPropagation()` halts the NATIVE mousedown\n // right there, before it can reach an inner grip or inner editor. Treat the\n // grip and anything inside a nested editor region as interactive so the outer\n // container never hijacks a mousedown meant for inner machinery — this is what\n // makes dragging a block OUT of / BETWEEN columns (a nested grip) work at all.\n if (\n target.closest(\".drag-handle\") ||\n target.closest(\".plan-nested-document-editor-region\")\n ) {\n return true;\n }\n\n const blockNode = target.closest(\".plan-block-node\");\n const editable = target.closest(\"[contenteditable='true']\");\n return !!blockNode && !!editable && blockNode.contains(editable);\n}\n\n/* -------------------------------------------------------------------------- */\n/* B. RegistryBlockNodeView (React) */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Renders one registry-block atom. The block is non-editable as far as\n * ProseMirror is concerned (`contentEditable={false}`); all interaction happens\n * inside the registry-driven `<BlockView>`. Read vs edit is toggled by\n * `props.selected` (the node is \"selected\" in the editor) AND the document being\n * editable. `data-plan-interactive` keeps existing host click-guards from\n * treating clicks inside the block as document clicks.\n */\nexport function RegistryBlockNodeView(props: NodeViewProps) {\n const blockType = String(props.node.attrs.blockType ?? \"\");\n const blockId = String(props.node.attrs.blockId ?? \"\");\n const [panelOpen, setPanelOpen] = useState(false);\n const [shellHovered, setShellHovered] = useState(false);\n\n const registryValue = useOptionalBlockRegistry();\n const sideMap = useRegistryBlockData();\n\n // Optimistic edit override. `onBlockDataChange` commits into the host's own\n // store (a ref the side-map context can't observe), so an edit does NOT\n // re-render this node — the new data only reaches the view on the next full\n // document reconcile, which lands after the autosave round-trip (seconds\n // later) and is skipped entirely when the host treats the save as its own\n // echo. That left quick toggles like the callout tone buttons visually frozen\n // until reload. Holding the just-edited data locally re-renders this one node\n // immediately, then releases once the authoritative block catches up to (or\n // moves past) the value the edit was based on.\n const [pendingEdit, setPendingEdit] = useState<{\n data: unknown;\n base: unknown;\n } | null>(null);\n const liveBlock = sideMap?.getBlock(blockId);\n const liveData = liveBlock?.data;\n useEffect(() => {\n if (pendingEdit && !Object.is(liveData, pendingEdit.base)) {\n setPendingEdit(null);\n }\n }, [liveData, pendingEdit]);\n const block =\n liveBlock && pendingEdit && Object.is(liveData, pendingEdit.base)\n ? { ...liveBlock, data: pendingEdit.data }\n : liveBlock;\n const commitBlockData = (nextData: unknown, meta?: BlockDataChangeMeta) => {\n setPendingEdit({ data: nextData, base: liveData });\n sideMap?.onBlockDataChange(blockId, nextData, meta);\n };\n const editable = sideMap?.editable ?? false;\n // In Notion-sync mode, flag blocks that have no Notion (NFM) analog so the\n // author sees what won't push. Prose blocks aren't registry-block nodes, so\n // this only ever covers structured blocks.\n const incompatibleWithNotion =\n (sideMap?.notionSync ?? false) &&\n (sideMap?.isNotionIncompatibleType?.(blockType) ?? false);\n\n // The block data isn't in the side-map yet (e.g. a freshly inserted node whose\n // store entry hasn't been seeded). Render a graceful placeholder.\n if (!block) {\n return (\n <NodeViewWrapper className=\"plan-block-node\" data-block-id={blockId}>\n <div\n contentEditable={false}\n data-plan-interactive\n className=\"plan-block-node__placeholder rounded-md border border-dashed border-border px-3 py-2 text-sm text-muted-foreground\"\n >\n {blockType ? `Loading ${blockType} block…` : \"Loading block…\"}\n </div>\n </NodeViewWrapper>\n );\n }\n\n const spec = registryValue?.registry.get(blockType);\n const selectNode = (event: ReactMouseEvent<HTMLElement>) => {\n if (!editable) return;\n const target = event.target;\n if (target instanceof HTMLElement && clickedInteractiveChild(target))\n return;\n const pos = typeof props.getPos === \"function\" ? props.getPos() : null;\n if (typeof pos !== \"number\") return;\n try {\n event.preventDefault();\n event.stopPropagation();\n const { view } = props.editor;\n view.dispatch(\n view.state.tr.setSelection(NodeSelection.create(view.state.doc, pos)),\n );\n view.focus();\n } catch {\n // Ignore stale positions during React/ProseMirror reconciliation.\n }\n };\n const updateShellHover = (event: ReactMouseEvent<HTMLElement>) => {\n const target = event.target;\n setShellHovered(\n target instanceof HTMLElement &&\n target.closest(\".plan-block-node__shell\") === event.currentTarget,\n );\n };\n\n // Choose how to render the block body:\n // 1. Registered spec → read view by default; direct-manipulation specs\n // (`editSurface: \"inline\" | \"container\"`) render their editor in place,\n // while artifact/config specs (`\"panel\"`) keep the read view plus a\n // corner edit button.\n // 2. No spec, but the side-map provides `renderLegacyBlock` → delegate to the\n // host's dispatcher (decision, legacy visual-questions, image, and any\n // other type rendered by a bespoke component rather than the registry), so\n // EVERY block type renders in the document exactly as it does in the\n // per-block reader — never a bare title fallback.\n // 3. Neither → a small non-crashing fallback.\n let body: ReactNode;\n let editSurface: ReactNode = null;\n if (registryValue && spec) {\n const blockData = (block as { data: unknown }).data;\n const Read = spec.Read;\n const readNode = (\n <Read\n data={blockData}\n blockId={block.id}\n title={block.title}\n summary={block.summary}\n ctx={registryValue.ctx}\n />\n );\n body = readNode;\n const canEditBlock =\n editable &&\n spec.placement.includes(\"block\") &&\n !!sideMap?.onBlockDataChange;\n if (canEditBlock) {\n const Edit = spec.Edit;\n const editorNode = Edit ? (\n <Edit\n data={blockData}\n onChange={commitBlockData}\n editable\n blockId={block.id}\n title={block.title}\n summary={block.summary}\n ctx={registryValue.ctx}\n />\n ) : (\n <SchemaBlockEditor\n data={blockData}\n onChange={(nextData) => commitBlockData(nextData)}\n schema={spec.schema}\n editable\n blockId={block.id}\n ctx={registryValue.ctx}\n />\n );\n const surface = blockEditSurface(spec);\n if (surface === \"panel\" && registryValue.ctx.renderEditSurface) {\n editSurface = registryValue.ctx.renderEditSurface({\n title: spec.label,\n open: panelOpen,\n onOpenChange: setPanelOpen,\n blockId: block.id,\n blockType,\n blockTitle: block.title,\n blockSummary: block.summary,\n blockData,\n trigger: (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Edit ${spec.label}`}\n onClick={() => setPanelOpen(true)}\n className=\"an-block-edit-trigger flex size-7 items-center justify-center rounded-md border border-border bg-background/85 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-opacity hover:bg-muted hover:text-foreground focus-visible:opacity-100 data-[visible=true]:opacity-100\"\n data-visible={panelOpen || shellHovered}\n >\n <IconPencil className=\"size-4\" />\n </button>\n ),\n children: editorNode,\n });\n } else if (surface === \"panel\") {\n editSurface = props.selected ? (\n <div className=\"mt-3\">{editorNode}</div>\n ) : null;\n } else {\n body = editorNode;\n }\n }\n } else if (sideMap?.renderLegacyBlock) {\n // Self-editing legacy blocks (e.g. image) render their own edit affordance\n // inside their overlay, so render them in edit mode and add NO separate\n // corner edit surface — the block owns a single, self-contained overlay.\n const selfEdits =\n editable && Boolean(sideMap.legacyBlockSelfEdits?.(blockType));\n body = sideMap.renderLegacyBlock(block, { editing: selfEdits });\n if (editable && !selfEdits) {\n // Prefer a host-provided schema/custom editor (a real form) over the raw\n // JSON fallback when the host knows how to edit this legacy block type.\n const customEditor = sideMap.renderLegacyBlockEditor?.(block, {\n onChange: (nextData) => commitBlockData(nextData),\n });\n editSurface = (\n <LegacyJsonEditSurface\n block={block}\n open={panelOpen}\n onOpenChange={setPanelOpen}\n renderEditSurface={registryValue?.ctx.renderEditSurface}\n onChange={(nextBlock) => commitBlockData(nextBlock)}\n selected={shellHovered}\n customEditor={customEditor}\n />\n );\n }\n } else {\n body = (\n <div className=\"plan-block-node__fallback rounded-md border border-border px-3 py-2 text-sm text-muted-foreground\">\n {block.title || blockType || \"Unsupported block\"}\n </div>\n );\n }\n\n return (\n <NodeViewWrapper\n className=\"plan-block-node\"\n data-block-id={blockId}\n // Mirror the block type onto the wrapper so the document flow can detect a\n // RUN of consecutive blocks of the same type (e.g. api-endpoint) and\n // collapse the divider + gap between them, matching the read-only path.\n data-block-type={blockType || undefined}\n data-plan-block-selected={props.selected ? \"\" : undefined}\n data-notion-incompatible={incompatibleWithNotion ? \"\" : undefined}\n onMouseDownCapture={selectNode}\n >\n <div\n contentEditable={false}\n data-plan-interactive\n className=\"plan-block-node__shell relative\"\n onMouseEnter={updateShellHover}\n onMouseMove={updateShellHover}\n onMouseLeave={() => setShellHovered(false)}\n >\n {incompatibleWithNotion && (\n <span\n className=\"plan-block-notion-badge\"\n title=\"This block type has no Notion equivalent and won't sync to Notion.\"\n >\n Won't sync to Notion\n </span>\n )}\n {body}\n {editSurface && (\n <div className=\"plan-block-node__edit absolute right-2 top-2 z-20\">\n {editSurface}\n </div>\n )}\n </div>\n </NodeViewWrapper>\n );\n}\n\nexport function LegacyJsonEditSurface({\n block,\n open,\n onOpenChange,\n renderEditSurface,\n onChange,\n selected,\n customEditor,\n}: {\n block: RegistryBlockSideMapBlock;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n renderEditSurface?: BlockRenderContext[\"renderEditSurface\"];\n onChange: (nextData: unknown) => void;\n selected: boolean;\n /**\n * A host-provided form editor (e.g. {@link SchemaBlockEditor}). When present it\n * replaces the raw-JSON textarea + Save button; the form autosaves through its\n * own `onChange`.\n */\n customEditor?: ReactNode;\n}) {\n const serializedBlockData = useMemo(\n () => JSON.stringify(block.data, null, 2),\n [block.data],\n );\n const [draft, setDraft] = useState(serializedBlockData);\n const [parseError, setParseError] = useState<string | null>(null);\n\n useEffect(() => {\n setDraft(serializedBlockData);\n setParseError(null);\n }, [block.id, serializedBlockData]);\n\n const saveDraft = () => {\n try {\n const nextData = JSON.parse(draft) as unknown;\n setParseError(null);\n onChange(nextData);\n onOpenChange(false);\n } catch (error) {\n setParseError(\n error instanceof Error ? error.message : \"Invalid JSON data.\",\n );\n }\n };\n\n const trigger = (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Edit ${block.title ?? \"block\"}`}\n onClick={() => onOpenChange(true)}\n className=\"an-block-edit-trigger flex size-7 items-center justify-center rounded-md border border-border bg-background/85 text-muted-foreground opacity-0 shadow-sm backdrop-blur transition-opacity hover:bg-muted hover:text-foreground focus-visible:opacity-100 data-[visible=true]:opacity-100\"\n data-visible={selected || open}\n >\n <IconPencil className=\"size-4\" />\n </button>\n );\n const jsonEditor = (\n <div className=\"grid gap-3\">\n <textarea\n data-plan-interactive\n className=\"min-h-64 w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-xs leading-5 text-foreground shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n value={draft}\n aria-invalid={parseError ? true : undefined}\n onChange={(event) => {\n setDraft(event.target.value);\n if (parseError) setParseError(null);\n }}\n />\n {parseError ? (\n <p className=\"text-xs text-destructive\" role=\"alert\">\n Invalid JSON: {parseError}\n </p>\n ) : null}\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n data-plan-interactive\n className=\"inline-flex h-8 items-center justify-center rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground\"\n onClick={saveDraft}\n >\n Save\n </button>\n </div>\n </div>\n );\n const editor = customEditor ?? jsonEditor;\n if (!renderEditSurface) return open ? editor : trigger;\n return renderEditSurface({\n title: block.title ?? \"Block\",\n open,\n onOpenChange,\n blockId: block.id,\n blockType:\n typeof (block as { type?: unknown }).type === \"string\"\n ? ((block as unknown as { type: string }).type ?? \"\")\n : \"legacy\",\n blockTitle: block.title,\n blockSummary: block.summary,\n blockData: block.data,\n trigger,\n children: editor,\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* A. registry-block Tiptap node factory */\n/* -------------------------------------------------------------------------- */\n\n/** Options for {@link createRegistryBlockNode}. */\nexport interface CreateRegistryBlockNodeOptions {\n /**\n * The Tiptap node name (e.g. `\"planBlock\"`). Hosts that serialize the doc by\n * node name (plan's `plan-doc.ts` keys off `\"planBlock\"`) must pass the exact\n * name their serializer expects.\n */\n nodeName: string;\n /**\n * The HTML data-attribute that marks a serialized registry block on copy/paste\n * round-trip (e.g. `\"data-plan-block\"`).\n */\n dataTag: string;\n /**\n * Mint a fresh, unique block id for a given block type. Used by the dedupe\n * plugin to re-mint duplicate / missing ids (paste/duplicate). Plan passes\n * `createPlanBlockId`.\n */\n mintId: (blockType: string) => string;\n /** Node group (default `\"block\"`). */\n group?: string;\n}\n\n/**\n * Build the generic registry-block Tiptap atom node. Returns a Tiptap `Node`\n * that:\n * - carries identity attrs `blockType` / `blockId` / `title` / `summary`, a\n * `sourceBlockId` (set when a duplicate is re-minted, so the host can copy the\n * original block's data), and an optional `__raw` verbatim-MDX attr for\n * byte-stable source round-trips;\n * - is an atom + isolating + draggable block that renders through\n * {@link RegistryBlockNodeView} (via `ReactNodeViewRenderer`);\n * - installs a dedupe `appendTransaction` plugin that re-mints any duplicate or\n * empty `blockId` (the classic paste/duplicate case), preserving the original\n * block's id + side-map data and tagging its own transaction so it never\n * loops.\n */\nexport function createRegistryBlockNode(\n options: CreateRegistryBlockNodeOptions,\n) {\n const { nodeName, dataTag, mintId, group = \"block\" } = options;\n const dedupeKey = new PluginKey(`${nodeName}DedupeIds`);\n const keyboardGuardKey = new PluginKey(`${nodeName}KeyboardGuard`);\n\n /**\n * Collect every `blockId` currently present on this node type in a doc, with\n * the position of each node, so duplicate ids (from paste/duplicate) can be\n * detected and re-minted.\n */\n function collectEntries(state: EditorState): Array<{\n pos: number;\n blockType: string;\n blockId: string;\n sourceBlockId?: string;\n }> {\n const found: Array<{\n pos: number;\n blockType: string;\n blockId: string;\n sourceBlockId?: string;\n }> = [];\n state.doc.descendants((node, pos) => {\n if (node.type.name === nodeName) {\n found.push({\n pos,\n blockType: String(node.attrs.blockType ?? \"\"),\n blockId: String(node.attrs.blockId ?? \"\"),\n sourceBlockId:\n typeof node.attrs.sourceBlockId === \"string\"\n ? node.attrs.sourceBlockId\n : undefined,\n });\n }\n return true;\n });\n return found;\n }\n\n /**\n * Build a transaction that re-mints any duplicate / missing ids in `state`, or\n * `null` when nothing needs changing. Only the *later* duplicate (and any node\n * with an empty id) is re-minted, so the original keeps its id and side-map\n * data.\n */\n function buildDedupeTransaction(state: EditorState) {\n const entries = collectEntries(state);\n if (entries.length === 0) return null;\n\n const seen = new Set<string>();\n let tr = state.tr;\n let changed = false;\n\n for (const entry of entries) {\n const needsNewId = !entry.blockId || seen.has(entry.blockId);\n if (needsNewId) {\n const freshId = mintId(entry.blockType || \"block\");\n const node = state.doc.nodeAt(entry.pos);\n if (node) {\n tr = tr.setNodeMarkup(entry.pos, undefined, {\n ...node.attrs,\n blockId: freshId,\n sourceBlockId: entry.sourceBlockId || entry.blockId || null,\n });\n changed = true;\n }\n seen.add(freshId);\n } else {\n seen.add(entry.blockId);\n }\n }\n\n return changed ? tr.setMeta(dedupeKey, true) : null;\n }\n\n const selectedRegistryBlock = (state: EditorState) =>\n state.selection instanceof NodeSelection &&\n state.selection.node.type.name === nodeName;\n\n const isMutatingKey = (event: KeyboardEvent) => {\n if (event.altKey || event.ctrlKey || event.metaKey) return false;\n if (event.key === \"Enter\") return true;\n return event.key.length === 1;\n };\n\n return Node.create({\n name: nodeName,\n group,\n atom: true,\n draggable: true,\n selectable: true,\n isolating: true,\n\n addAttributes() {\n return {\n blockType: { default: \"\" },\n blockId: { default: \"\" },\n title: { default: null },\n summary: { default: null },\n sourceBlockId: { default: null },\n // Optional verbatim source for hosts that need byte-identical\n // source-format round-trips without React (server pull, hashing). Plan\n // never sets this.\n __raw: { default: null, rendered: false },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: `div[${dataTag}]`,\n getAttrs: (element) => {\n const node = element as HTMLElement;\n return {\n blockType: node.getAttribute(\"data-block-type\") || \"\",\n blockId: node.getAttribute(\"data-block-id\") || \"\",\n title: node.getAttribute(\"data-title\") || null,\n summary: node.getAttribute(\"data-summary\") || null,\n sourceBlockId: node.getAttribute(\"data-source-block-id\") || null,\n };\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n [dataTag]: \"\",\n \"data-block-type\": HTMLAttributes.blockType ?? \"\",\n \"data-block-id\": HTMLAttributes.blockId ?? \"\",\n \"data-title\": HTMLAttributes.title ?? undefined,\n \"data-summary\": HTMLAttributes.summary ?? undefined,\n \"data-source-block-id\": HTMLAttributes.sourceBlockId ?? undefined,\n }),\n ];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(RegistryBlockNodeView);\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: dedupeKey,\n appendTransaction(transactions, _oldState, newState) {\n // Ignore our own re-mint, and skip when nothing changed the doc.\n if (\n transactions.some((transaction) =>\n transaction.getMeta(dedupeKey),\n ) ||\n !transactions.some((transaction) => transaction.docChanged)\n ) {\n return null;\n }\n return buildDedupeTransaction(newState);\n },\n }),\n new Plugin({\n key: keyboardGuardKey,\n props: {\n handleClickOn(view, _pos, node, nodePos, event, direct) {\n if (node.type.name !== nodeName || !direct) return false;\n if (\n event.target instanceof HTMLElement &&\n clickedInteractiveChild(event.target)\n ) {\n return false;\n }\n event.preventDefault();\n view.dispatch(\n view.state.tr.setSelection(\n NodeSelection.create(view.state.doc, nodePos),\n ),\n );\n view.focus();\n return true;\n },\n handleKeyDown(view, event) {\n if (!selectedRegistryBlock(view.state) || !isMutatingKey(event))\n return false;\n event.preventDefault();\n return true;\n },\n handleTextInput(view) {\n return selectedRegistryBlock(view.state);\n },\n handlePaste(view, event) {\n if (!selectedRegistryBlock(view.state)) return false;\n event.preventDefault();\n return true;\n },\n handleDOMEvents: {\n beforeinput(view, event) {\n if (!selectedRegistryBlock(view.state)) return false;\n const inputEvent = event as InputEvent;\n if (\n !inputEvent.inputType ||\n (!inputEvent.inputType.startsWith(\"insert\") &&\n inputEvent.inputType !== \"formatSetBlockTextDirection\")\n ) {\n return false;\n }\n event.preventDefault();\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n}\n"]}
|
|
@@ -38,7 +38,7 @@ export interface CreateRichMarkdownExtensionsOptions {
|
|
|
38
38
|
* shared factory expects. The round-trip and collab specs build their `Editor`
|
|
39
39
|
* from this, so its output must stay byte-stable.
|
|
40
40
|
*/
|
|
41
|
-
export declare function createRichMarkdownExtensions({ dialect, placeholder, ydoc, awareness, user, }?: CreateRichMarkdownExtensionsOptions): (import("@tiptap/core").Node<any, any> | import("@tiptap/core").
|
|
41
|
+
export declare function createRichMarkdownExtensions({ dialect, placeholder, ydoc, awareness, user, }?: CreateRichMarkdownExtensionsOptions): (import("@tiptap/core").Node<any, any> | import("@tiptap/core").Extension<any, any> | import("@tiptap/core").Mark<any, any>)[];
|
|
42
42
|
/** @deprecated Prefer {@link SharedRichEditorProps}. */
|
|
43
43
|
export type RichMarkdownEditorProps = SharedRichEditorProps;
|
|
44
44
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SharedRichEditor.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/SharedRichEditor.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SharedRichEditor.d.ts","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/SharedRichEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -70,13 +70,12 @@ export function SharedRichEditor({ value, onChange, onBlur, contentUpdatedAt, ed
|
|
|
70
70
|
// With a custom `setContent` the reconcile seeds the editor too (the raw
|
|
71
71
|
// `value` is not directly settable content — e.g. the plan's blocks JSON),
|
|
72
72
|
// so only the plain markdown path seeds from `value` here.
|
|
73
|
-
content: collab || setContent ?
|
|
73
|
+
content: collab || setContent ? null : value,
|
|
74
74
|
editable,
|
|
75
75
|
editorProps: {
|
|
76
76
|
attributes: {
|
|
77
77
|
class: cn("an-rich-md-prose", editorClassName),
|
|
78
|
-
|
|
79
|
-
"aria-label": ariaLabel,
|
|
78
|
+
...(ariaLabel ? { role: "textbox", "aria-label": ariaLabel } : {}),
|
|
80
79
|
},
|
|
81
80
|
},
|
|
82
81
|
onUpdate: ({ editor, transaction }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SharedRichEditor.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/SharedRichEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useRef } from \"react\";\nimport { EditorContent, useEditor } from \"@tiptap/react\";\nimport type { Extension, Node, Mark } from \"@tiptap/core\";\nimport type { Doc as YDoc } from \"yjs\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport { cn } from \"../utils.js\";\nimport {\n createSharedEditorExtensions,\n type RichMarkdownDialect,\n type RichMarkdownEditorPreset,\n type RichMarkdownCollabUser,\n type SharedEditorFeatures,\n} from \"./extensions.js\";\nimport type { ImageUploadFn } from \"./ImageExtension.js\";\nimport {\n useCollabReconcile,\n getEditorMarkdown,\n type UseCollabReconcileResult,\n} from \"./useCollabReconcile.js\";\nimport { SlashCommandMenu, type SlashCommandItem } from \"./SlashCommandMenu.js\";\nimport { BubbleToolbar, type BubbleToolbarItem } from \"./BubbleToolbar.js\";\n\nexport interface SharedRichEditorProps {\n value: string;\n onChange: (markdown: string) => void;\n onBlur?: () => void;\n contentUpdatedAt?: string | null;\n editable?: boolean;\n dialect?: RichMarkdownDialect;\n preset?: RichMarkdownEditorPreset;\n /** Toggle individual base extensions (tables/tasks/link/codeBlock/image). */\n features?: SharedEditorFeatures;\n /**\n * Injectable image uploader for the shared image block. Used only when\n * `features.image` is on. Pass `uploadEditorImage` (the framework\n * `upload-image` action) for a real uploading image block.\n */\n onImageUpload?: ImageUploadFn | null;\n /**\n * App-specific extensions (Notion nodes, media, drag handles, comment\n * anchors, …) appended after the shared base schema.\n */\n extraExtensions?: Array<Extension | Node | Mark>;\n placeholder?: string;\n className?: string;\n editorClassName?: string;\n ariaLabel?: string;\n interactive?: boolean;\n /**\n * Yjs document for real-time multi-user editing. When provided, prose is\n * authored against the shared Y.Doc and mirrored back to `value` as markdown\n * (still the source of truth). When omitted, the editor is a plain controlled\n * `value`/`onChange` editor — the existing, non-collaborative behavior.\n */\n ydoc?: YDoc | null;\n /** Shared awareness instance for live cursors/presence. */\n awareness?: Awareness | null;\n /** Current user info for the collaborative cursor label. */\n user?: RichMarkdownCollabUser | null;\n /**\n * Disable StarterKit's built-in undo/redo for a controlled (non-collab)\n * editor whose host owns its own undo authority (see\n * {@link CreateSharedEditorExtensionsOptions.disableHistory}). Ignored when a\n * `ydoc` is present (Yjs always owns history then). Default `false`, so every\n * existing embedder is unchanged.\n */\n disableHistory?: boolean;\n /** Override the slash-menu block command list. */\n slashItems?: SlashCommandItem[];\n /** Override the bubble-toolbar item builder. */\n buildBubbleItems?: (\n editor: import(\"@tiptap/react\").Editor,\n toggleLink: () => void,\n ) => BubbleToolbarItem[];\n /**\n * Override how the editor's content is read into the canonical `value`.\n * Defaults to the tiptap-markdown storage reader. Apps with a custom on-disk\n * format (Content's NFM, the plan's `blocks[]` JSON) pass their serializer so\n * seed/reconcile/onChange all speak the same value space.\n */\n getMarkdown?: (editor: import(\"@tiptap/react\").Editor) => string;\n /** Override how the canonical `value` is applied into the editor (seed + reconcile). */\n setContent?: (\n editor: import(\"@tiptap/react\").Editor,\n value: string,\n options: { emitUpdate?: boolean; addToHistory?: boolean },\n ) => void;\n /** Canonicalize `value` for the echo / already-in-sync equality checks. */\n normalizeValue?: (value: string) => string;\n /** Override the empty-doc seed predicate (see {@link useCollabReconcile}). */\n shouldSeed?: (info: {\n value: string;\n currentMarkdown: string;\n fragmentLength: number;\n }) => boolean;\n /** Initial \"applied\" watermark (see {@link useCollabReconcile}). */\n initialAppliedUpdatedAt?: string | null;\n /** Extra class on the editor wrapper (e.g. a drag-handle `wrapperSelector` hook). */\n wrapperClassName?: string;\n /**\n * Fires once the editor instance exists. Lets a host capture the root\n * `editor.view` — e.g. to repaint the WHOLE document after a structural block\n * move (a column emptied and its container dissolved) that a surgical\n * per-region patch can't express, since the change is in the root doc itself.\n */\n onEditorReady?: (editor: import(\"@tiptap/react\").Editor) => void;\n}\n\n/**\n * The single shared rich markdown editor surface. Combines\n * {@link createSharedEditorExtensions} (schema + dialect-keyed markdown +\n * optional collab + app extras), {@link useCollabReconcile} (seed / reconcile /\n * lead-client logic), and the shared {@link SlashCommandMenu} +\n * {@link BubbleToolbar}.\n *\n * With no `ydoc` it is a controlled `value`/`onChange` single-user editor.\n * With a `ydoc` it binds the framework collaboration stack; markdown stays the\n * canonical saved representation while the Y.Doc is transient live state.\n */\nexport function SharedRichEditor({\n value,\n onChange,\n onBlur,\n contentUpdatedAt,\n editable = true,\n dialect = \"gfm\",\n preset = \"plan\",\n features,\n onImageUpload = null,\n extraExtensions,\n placeholder = \"Type '/' for commands...\",\n className,\n editorClassName,\n ariaLabel,\n interactive = editable,\n ydoc = null,\n awareness = null,\n user = null,\n disableHistory = false,\n slashItems,\n buildBubbleItems,\n getMarkdown,\n setContent,\n normalizeValue,\n shouldSeed,\n initialAppliedUpdatedAt,\n wrapperClassName,\n onEditorReady,\n}: SharedRichEditorProps) {\n const readMarkdown = getMarkdown ?? getEditorMarkdown;\n const onChangeRef = useRef(onChange);\n const onBlurRef = useRef(onBlur);\n onChangeRef.current = onChange;\n onBlurRef.current = onBlur;\n\n const extensions = useMemo(\n () =>\n createSharedEditorExtensions({\n dialect,\n preset,\n placeholder,\n features,\n extraExtensions,\n onImageUpload,\n collab: ydoc ? { ydoc, awareness, user } : null,\n disableHistory,\n }),\n // `preset` is retained in the dependency list so future preset-specific\n // schema branches re-create the editor; it is currently schema-neutral. The\n // collab inputs are identity-stable per block (one Y.Doc per docId), so they\n // only change on a genuine doc switch — exactly when the editor must\n // re-create to rebind Collaboration.\n [\n dialect,\n placeholder,\n preset,\n features,\n extraExtensions,\n onImageUpload,\n ydoc,\n awareness,\n user?.name,\n user?.email,\n user?.color,\n disableHistory,\n ],\n );\n\n const collab = !!ydoc;\n\n // The collab hook needs the editor, but useEditor's `onUpdate` needs the\n // hook's guards. Break the cycle with a ref: `onUpdate` reads the guards\n // through `guardsRef`, which is populated right after the hook runs below.\n // `onUpdate` only ever fires after the editor exists, by which point the ref\n // holds the real guards.\n const guardsRef = useRef<UseCollabReconcileResult | null>(null);\n\n const editor = useEditor({\n extensions,\n // With Collaboration active the prose is owned by the shared Y.XmlFragment.\n // Seeding `content` here too would make the editor initialize from BOTH the\n // prop and the Y.Doc, firing a spurious initial update that could autosave a\n // stale value over newer SQL. The lead-client seed effect populates an empty\n // doc instead. Non-collab editors keep initializing from `value`.\n // With Collaboration the Y.Doc owns the prose (seeded by the lead client).\n // With a custom `setContent` the reconcile seeds the editor too (the raw\n // `value` is not directly settable content — e.g. the plan's blocks JSON),\n // so only the plain markdown path seeds from `value` here.\n content: collab || setContent ? undefined : value,\n editable,\n editorProps: {\n attributes: {\n class: cn(\"an-rich-md-prose\", editorClassName),\n role: ariaLabel ? \"textbox\" : undefined,\n \"aria-label\": ariaLabel,\n },\n },\n onUpdate: ({ editor, transaction }) => {\n const guards = guardsRef.current;\n if (!guards || guards.shouldIgnoreUpdate(transaction)) return;\n try {\n const markdown = readMarkdown(editor);\n if (!guards.registerEmitted(markdown)) return;\n queueMicrotask(() => onChangeRef.current(markdown));\n } catch (error) {\n console.error(\"Markdown serialization error:\", error);\n }\n },\n onBlur: () => {\n onBlurRef.current?.();\n },\n });\n\n const collabState = useCollabReconcile({\n editor,\n ydoc,\n awareness,\n value,\n contentUpdatedAt,\n editable,\n getMarkdown: readMarkdown,\n setContent,\n normalizeValue,\n shouldSeed,\n initialAppliedUpdatedAt,\n });\n guardsRef.current = collabState;\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n editor.setEditable(editable);\n }, [editable, editor]);\n\n useEffect(() => {\n if (editor) onEditorReady?.(editor);\n }, [editor, onEditorReady]);\n\n useEffect(() => () => editor?.destroy(), [editor]);\n\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!editable || !editor || editor.isDestroyed) return;\n const target = event.target as HTMLElement;\n if (\n target.classList.contains(\"an-rich-md-wrapper\") ||\n target.classList.contains(\"an-rich-md-clickable\")\n ) {\n editor.chain().focus(\"end\").run();\n }\n };\n\n if (!editor) {\n return (\n <div\n className={cn(\"an-rich-md-wrapper an-rich-md-loading\", className)}\n data-plan-interactive={interactive ? true : undefined}\n />\n );\n }\n\n return (\n <div\n className={cn(\n \"an-rich-md-wrapper an-rich-md-clickable\",\n !editable && \"an-rich-md-wrapper--readonly\",\n wrapperClassName,\n className,\n )}\n onClick={handleWrapperClick}\n data-plan-interactive={interactive ? true : undefined}\n >\n {editable ? (\n <BubbleToolbar editor={editor} buildItems={buildBubbleItems} />\n ) : null}\n {editable ? (\n <SlashCommandMenu editor={editor} items={slashItems} />\n ) : null}\n <EditorContent editor={editor} />\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SharedRichEditor.js","sourceRoot":"","sources":["../../../src/client/rich-markdown-editor/SharedRichEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useRef } from \"react\";\nimport { EditorContent, useEditor } from \"@tiptap/react\";\nimport type { Extension, Node, Mark } from \"@tiptap/core\";\nimport type { Doc as YDoc } from \"yjs\";\nimport type { Awareness } from \"y-protocols/awareness\";\nimport { cn } from \"../utils.js\";\nimport {\n createSharedEditorExtensions,\n type RichMarkdownDialect,\n type RichMarkdownEditorPreset,\n type RichMarkdownCollabUser,\n type SharedEditorFeatures,\n} from \"./extensions.js\";\nimport type { ImageUploadFn } from \"./ImageExtension.js\";\nimport {\n useCollabReconcile,\n getEditorMarkdown,\n type UseCollabReconcileResult,\n} from \"./useCollabReconcile.js\";\nimport { SlashCommandMenu, type SlashCommandItem } from \"./SlashCommandMenu.js\";\nimport { BubbleToolbar, type BubbleToolbarItem } from \"./BubbleToolbar.js\";\n\nexport interface SharedRichEditorProps {\n value: string;\n onChange: (markdown: string) => void;\n onBlur?: () => void;\n contentUpdatedAt?: string | null;\n editable?: boolean;\n dialect?: RichMarkdownDialect;\n preset?: RichMarkdownEditorPreset;\n /** Toggle individual base extensions (tables/tasks/link/codeBlock/image). */\n features?: SharedEditorFeatures;\n /**\n * Injectable image uploader for the shared image block. Used only when\n * `features.image` is on. Pass `uploadEditorImage` (the framework\n * `upload-image` action) for a real uploading image block.\n */\n onImageUpload?: ImageUploadFn | null;\n /**\n * App-specific extensions (Notion nodes, media, drag handles, comment\n * anchors, …) appended after the shared base schema.\n */\n extraExtensions?: Array<Extension | Node | Mark>;\n placeholder?: string;\n className?: string;\n editorClassName?: string;\n ariaLabel?: string;\n interactive?: boolean;\n /**\n * Yjs document for real-time multi-user editing. When provided, prose is\n * authored against the shared Y.Doc and mirrored back to `value` as markdown\n * (still the source of truth). When omitted, the editor is a plain controlled\n * `value`/`onChange` editor — the existing, non-collaborative behavior.\n */\n ydoc?: YDoc | null;\n /** Shared awareness instance for live cursors/presence. */\n awareness?: Awareness | null;\n /** Current user info for the collaborative cursor label. */\n user?: RichMarkdownCollabUser | null;\n /**\n * Disable StarterKit's built-in undo/redo for a controlled (non-collab)\n * editor whose host owns its own undo authority (see\n * {@link CreateSharedEditorExtensionsOptions.disableHistory}). Ignored when a\n * `ydoc` is present (Yjs always owns history then). Default `false`, so every\n * existing embedder is unchanged.\n */\n disableHistory?: boolean;\n /** Override the slash-menu block command list. */\n slashItems?: SlashCommandItem[];\n /** Override the bubble-toolbar item builder. */\n buildBubbleItems?: (\n editor: import(\"@tiptap/react\").Editor,\n toggleLink: () => void,\n ) => BubbleToolbarItem[];\n /**\n * Override how the editor's content is read into the canonical `value`.\n * Defaults to the tiptap-markdown storage reader. Apps with a custom on-disk\n * format (Content's NFM, the plan's `blocks[]` JSON) pass their serializer so\n * seed/reconcile/onChange all speak the same value space.\n */\n getMarkdown?: (editor: import(\"@tiptap/react\").Editor) => string;\n /** Override how the canonical `value` is applied into the editor (seed + reconcile). */\n setContent?: (\n editor: import(\"@tiptap/react\").Editor,\n value: string,\n options: { emitUpdate?: boolean; addToHistory?: boolean },\n ) => void;\n /** Canonicalize `value` for the echo / already-in-sync equality checks. */\n normalizeValue?: (value: string) => string;\n /** Override the empty-doc seed predicate (see {@link useCollabReconcile}). */\n shouldSeed?: (info: {\n value: string;\n currentMarkdown: string;\n fragmentLength: number;\n }) => boolean;\n /** Initial \"applied\" watermark (see {@link useCollabReconcile}). */\n initialAppliedUpdatedAt?: string | null;\n /** Extra class on the editor wrapper (e.g. a drag-handle `wrapperSelector` hook). */\n wrapperClassName?: string;\n /**\n * Fires once the editor instance exists. Lets a host capture the root\n * `editor.view` — e.g. to repaint the WHOLE document after a structural block\n * move (a column emptied and its container dissolved) that a surgical\n * per-region patch can't express, since the change is in the root doc itself.\n */\n onEditorReady?: (editor: import(\"@tiptap/react\").Editor) => void;\n}\n\n/**\n * The single shared rich markdown editor surface. Combines\n * {@link createSharedEditorExtensions} (schema + dialect-keyed markdown +\n * optional collab + app extras), {@link useCollabReconcile} (seed / reconcile /\n * lead-client logic), and the shared {@link SlashCommandMenu} +\n * {@link BubbleToolbar}.\n *\n * With no `ydoc` it is a controlled `value`/`onChange` single-user editor.\n * With a `ydoc` it binds the framework collaboration stack; markdown stays the\n * canonical saved representation while the Y.Doc is transient live state.\n */\nexport function SharedRichEditor({\n value,\n onChange,\n onBlur,\n contentUpdatedAt,\n editable = true,\n dialect = \"gfm\",\n preset = \"plan\",\n features,\n onImageUpload = null,\n extraExtensions,\n placeholder = \"Type '/' for commands...\",\n className,\n editorClassName,\n ariaLabel,\n interactive = editable,\n ydoc = null,\n awareness = null,\n user = null,\n disableHistory = false,\n slashItems,\n buildBubbleItems,\n getMarkdown,\n setContent,\n normalizeValue,\n shouldSeed,\n initialAppliedUpdatedAt,\n wrapperClassName,\n onEditorReady,\n}: SharedRichEditorProps) {\n const readMarkdown = getMarkdown ?? getEditorMarkdown;\n const onChangeRef = useRef(onChange);\n const onBlurRef = useRef(onBlur);\n onChangeRef.current = onChange;\n onBlurRef.current = onBlur;\n\n const extensions = useMemo(\n () =>\n createSharedEditorExtensions({\n dialect,\n preset,\n placeholder,\n features,\n extraExtensions,\n onImageUpload,\n collab: ydoc ? { ydoc, awareness, user } : null,\n disableHistory,\n }),\n // `preset` is retained in the dependency list so future preset-specific\n // schema branches re-create the editor; it is currently schema-neutral. The\n // collab inputs are identity-stable per block (one Y.Doc per docId), so they\n // only change on a genuine doc switch — exactly when the editor must\n // re-create to rebind Collaboration.\n [\n dialect,\n placeholder,\n preset,\n features,\n extraExtensions,\n onImageUpload,\n ydoc,\n awareness,\n user?.name,\n user?.email,\n user?.color,\n disableHistory,\n ],\n );\n\n const collab = !!ydoc;\n\n // The collab hook needs the editor, but useEditor's `onUpdate` needs the\n // hook's guards. Break the cycle with a ref: `onUpdate` reads the guards\n // through `guardsRef`, which is populated right after the hook runs below.\n // `onUpdate` only ever fires after the editor exists, by which point the ref\n // holds the real guards.\n const guardsRef = useRef<UseCollabReconcileResult | null>(null);\n\n const editor = useEditor({\n extensions,\n // With Collaboration active the prose is owned by the shared Y.XmlFragment.\n // Seeding `content` here too would make the editor initialize from BOTH the\n // prop and the Y.Doc, firing a spurious initial update that could autosave a\n // stale value over newer SQL. The lead-client seed effect populates an empty\n // doc instead. Non-collab editors keep initializing from `value`.\n // With Collaboration the Y.Doc owns the prose (seeded by the lead client).\n // With a custom `setContent` the reconcile seeds the editor too (the raw\n // `value` is not directly settable content — e.g. the plan's blocks JSON),\n // so only the plain markdown path seeds from `value` here.\n content: collab || setContent ? null : value,\n editable,\n editorProps: {\n attributes: {\n class: cn(\"an-rich-md-prose\", editorClassName),\n ...(ariaLabel ? { role: \"textbox\", \"aria-label\": ariaLabel } : {}),\n },\n },\n onUpdate: ({ editor, transaction }) => {\n const guards = guardsRef.current;\n if (!guards || guards.shouldIgnoreUpdate(transaction)) return;\n try {\n const markdown = readMarkdown(editor);\n if (!guards.registerEmitted(markdown)) return;\n queueMicrotask(() => onChangeRef.current(markdown));\n } catch (error) {\n console.error(\"Markdown serialization error:\", error);\n }\n },\n onBlur: () => {\n onBlurRef.current?.();\n },\n });\n\n const collabState = useCollabReconcile({\n editor,\n ydoc,\n awareness,\n value,\n contentUpdatedAt,\n editable,\n getMarkdown: readMarkdown,\n setContent,\n normalizeValue,\n shouldSeed,\n initialAppliedUpdatedAt,\n });\n guardsRef.current = collabState;\n\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n editor.setEditable(editable);\n }, [editable, editor]);\n\n useEffect(() => {\n if (editor) onEditorReady?.(editor);\n }, [editor, onEditorReady]);\n\n useEffect(() => () => editor?.destroy(), [editor]);\n\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement>) => {\n if (!editable || !editor || editor.isDestroyed) return;\n const target = event.target as HTMLElement;\n if (\n target.classList.contains(\"an-rich-md-wrapper\") ||\n target.classList.contains(\"an-rich-md-clickable\")\n ) {\n editor.chain().focus(\"end\").run();\n }\n };\n\n if (!editor) {\n return (\n <div\n className={cn(\"an-rich-md-wrapper an-rich-md-loading\", className)}\n data-plan-interactive={interactive ? true : undefined}\n />\n );\n }\n\n return (\n <div\n className={cn(\n \"an-rich-md-wrapper an-rich-md-clickable\",\n !editable && \"an-rich-md-wrapper--readonly\",\n wrapperClassName,\n className,\n )}\n onClick={handleWrapperClick}\n data-plan-interactive={interactive ? true : undefined}\n >\n {editable ? (\n <BubbleToolbar editor={editor} buildItems={buildBubbleItems} />\n ) : null}\n {editable ? (\n <SlashCommandMenu editor={editor} items={slashItems} />\n ) : null}\n <EditorContent editor={editor} />\n </div>\n );\n}\n"]}
|