@flanksource/clicky-ui 0.3.44 → 0.3.46
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/README.md +24 -0
- package/dist/ai.cjs +4 -2
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +3 -1
- package/dist/components/MdxEditorField.cjs +40 -22
- package/dist/components/MdxEditorField.cjs.map +1 -1
- package/dist/components/MdxEditorField.d.ts.map +1 -1
- package/dist/components/MdxEditorField.js +41 -23
- package/dist/components/MdxEditorField.js.map +1 -1
- package/dist/components/json-schema-form-item-summary.cjs +6 -1
- package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
- package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
- package/dist/components/json-schema-form-item-summary.js +6 -1
- package/dist/components/json-schema-form-item-summary.js.map +1 -1
- package/dist/data/AccessMark.cjs +23 -0
- package/dist/data/AccessMark.cjs.map +1 -0
- package/dist/data/AccessMark.d.ts +11 -0
- package/dist/data/AccessMark.d.ts.map +1 -0
- package/dist/data/AccessMark.js +23 -0
- package/dist/data/AccessMark.js.map +1 -0
- package/dist/data/CodeBlock.cjs +3 -2
- package/dist/data/CodeBlock.cjs.map +1 -1
- package/dist/data/CodeBlock.d.ts +3 -1
- package/dist/data/CodeBlock.d.ts.map +1 -1
- package/dist/data/CodeBlock.js +3 -2
- package/dist/data/CodeBlock.js.map +1 -1
- package/dist/data/CodeDiff.cjs +116 -23
- package/dist/data/CodeDiff.cjs.map +1 -1
- package/dist/data/CodeDiff.d.ts +26 -0
- package/dist/data/CodeDiff.d.ts.map +1 -1
- package/dist/data/CodeDiff.js +116 -23
- package/dist/data/CodeDiff.js.map +1 -1
- package/dist/data/GraphDiagram.cjs +75 -11
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +17 -2
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +76 -12
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramGroups.cjs +100 -0
- package/dist/data/GraphDiagramGroups.cjs.map +1 -0
- package/dist/data/GraphDiagramGroups.d.ts +24 -0
- package/dist/data/GraphDiagramGroups.d.ts.map +1 -0
- package/dist/data/GraphDiagramGroups.js +100 -0
- package/dist/data/GraphDiagramGroups.js.map +1 -0
- package/dist/data/GraphDiagramNodes.cjs +46 -51
- package/dist/data/GraphDiagramNodes.cjs.map +1 -1
- package/dist/data/GraphDiagramNodes.d.ts +8 -9
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -1
- package/dist/data/GraphDiagramNodes.js +46 -51
- package/dist/data/GraphDiagramNodes.js.map +1 -1
- package/dist/data/JsonView.cjs +118 -49
- package/dist/data/JsonView.cjs.map +1 -1
- package/dist/data/JsonView.d.ts +13 -10
- package/dist/data/JsonView.d.ts.map +1 -1
- package/dist/data/JsonView.js +118 -49
- package/dist/data/JsonView.js.map +1 -1
- package/dist/data/MarkdownEditor.cjs +2 -2
- package/dist/data/MarkdownEditor.cjs.map +1 -1
- package/dist/data/MarkdownEditor.js +2 -2
- package/dist/data/MarkdownEditor.js.map +1 -1
- package/dist/data/TreeNode.cjs +1 -1
- package/dist/data/TreeNode.cjs.map +1 -1
- package/dist/data/TreeNode.d.ts.map +1 -1
- package/dist/data/TreeNode.js +1 -1
- package/dist/data/TreeNode.js.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.cjs +90 -249
- package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.d.ts +2 -5
- package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
- package/dist/data/ai/AdvancedChatConfig.js +91 -250
- package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
- package/dist/data/ai/ChatButton.cjs +2 -0
- package/dist/data/ai/ChatButton.cjs.map +1 -1
- package/dist/data/ai/ChatButton.d.ts +1 -1
- package/dist/data/ai/ChatButton.d.ts.map +1 -1
- package/dist/data/ai/ChatButton.js +2 -0
- package/dist/data/ai/ChatButton.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +5 -1
- package/dist/data/ai/ChatFab.cjs.map +1 -1
- package/dist/data/ai/ChatFab.d.ts +5 -1
- package/dist/data/ai/ChatFab.d.ts.map +1 -1
- package/dist/data/ai/ChatFab.js +5 -1
- package/dist/data/ai/ChatFab.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +2 -8
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +2 -8
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.cjs +0 -5
- package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.d.ts +0 -2
- package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.runtime.js +0 -5
- package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +2 -2
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.js +2 -2
- package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +3 -6
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +3 -6
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +13 -4
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +5 -1
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.header.cjs +1 -1
- package/dist/data/ai/SessionViewer.header.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.header.js +1 -1
- package/dist/data/ai/SessionViewer.header.js.map +1 -1
- package/dist/data/ai/SessionViewer.js +13 -4
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs +2 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +2 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +41 -27
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +4 -2
- package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +41 -27
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SessionViewer.tokens.cjs +35 -0
- package/dist/data/ai/SessionViewer.tokens.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.tokens.d.ts +5 -0
- package/dist/data/ai/SessionViewer.tokens.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.tokens.js +35 -0
- package/dist/data/ai/SessionViewer.tokens.js.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.cjs +128 -0
- package/dist/data/ai/SessionViewer.tool-cost.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.d.ts +6 -0
- package/dist/data/ai/SessionViewer.tool-cost.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.tool-cost.js +128 -0
- package/dist/data/ai/SessionViewer.tool-cost.js.map +1 -0
- package/dist/data/ai/SessionViewer.tool-details.cjs +3 -1
- package/dist/data/ai/SessionViewer.tool-details.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-details.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-details.js +3 -1
- package/dist/data/ai/SessionViewer.tool-details.js.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.cjs +55 -35
- package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts +2 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.js +55 -35
- package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.cjs +18 -1
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
- package/dist/data/ai/SessionViewerMenu.d.ts +6 -1
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.js +18 -1
- package/dist/data/ai/SessionViewerMenu.js.map +1 -1
- package/dist/data/ai/ToolPreferences.cjs +149 -143
- package/dist/data/ai/ToolPreferences.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.d.ts +20 -6
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.js +151 -146
- package/dist/data/ai/ToolPreferences.js.map +1 -1
- package/dist/data/ai/ToolPreferences.model.cjs +14 -10
- package/dist/data/ai/ToolPreferences.model.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.model.d.ts +1 -0
- package/dist/data/ai/ToolPreferences.model.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.model.js +15 -11
- package/dist/data/ai/ToolPreferences.model.js.map +1 -1
- package/dist/data/ai/ToolPreferencesList.cjs +1 -0
- package/dist/data/ai/ToolPreferencesList.cjs.map +1 -1
- package/dist/data/ai/ToolPreferencesList.d.ts +4 -1
- package/dist/data/ai/ToolPreferencesList.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferencesList.js +2 -1
- package/dist/data/ai/ToolPreferencesList.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.cjs +52 -53
- package/dist/data/ai/ToolSchemaBrowser.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.d.ts +6 -3
- package/dist/data/ai/ToolSchemaBrowser.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs +9 -13
- package/dist/data/ai/ToolSchemaBrowser.directory-header.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts +5 -2
- package/dist/data/ai/ToolSchemaBrowser.directory-header.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.directory-header.js +9 -13
- package/dist/data/ai/ToolSchemaBrowser.directory-header.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.js +53 -54
- package/dist/data/ai/ToolSchemaBrowser.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.cjs +19 -27
- package/dist/data/ai/ToolSchemaBrowser.model.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.d.ts +9 -6
- package/dist/data/ai/ToolSchemaBrowser.model.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.model.js +20 -28
- package/dist/data/ai/ToolSchemaBrowser.model.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs +12 -213
- package/dist/data/ai/ToolSchemaBrowser.sidebar.cjs.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts +1 -3
- package/dist/data/ai/ToolSchemaBrowser.sidebar.d.ts.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.sidebar.js +13 -214
- package/dist/data/ai/ToolSchemaBrowser.sidebar.js.map +1 -1
- package/dist/data/ai/ToolSchemaBrowser.strategies.cjs +54 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.cjs.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts +9 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.d.ts.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.js +54 -0
- package/dist/data/ai/ToolSchemaBrowser.strategies.js.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.cjs +179 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.cjs.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.d.ts +20 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.d.ts.map +1 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.js +179 -0
- package/dist/data/ai/ToolSchemaBrowser.tree.js.map +1 -0
- package/dist/data/ai/index.d.ts +2 -2
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +8 -28
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -1
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +9 -29
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -1
- package/dist/data/ai/session-token-sizing.d.ts +32 -0
- package/dist/data/ai/session-token-sizing.d.ts.map +1 -0
- package/dist/data/ai/use-session-token-sizing.cjs +73 -0
- package/dist/data/ai/use-session-token-sizing.cjs.map +1 -0
- package/dist/data/ai/use-session-token-sizing.d.ts +21 -0
- package/dist/data/ai/use-session-token-sizing.d.ts.map +1 -0
- package/dist/data/ai/use-session-token-sizing.js +73 -0
- package/dist/data/ai/use-session-token-sizing.js.map +1 -0
- package/dist/data/call-graph/CallGraph.cjs +269 -0
- package/dist/data/call-graph/CallGraph.cjs.map +1 -0
- package/dist/data/call-graph/CallGraph.d.ts +78 -0
- package/dist/data/call-graph/CallGraph.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraph.js +269 -0
- package/dist/data/call-graph/CallGraph.js.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.cjs +39 -0
- package/dist/data/call-graph/CallGraphGlyphs.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.d.ts +19 -0
- package/dist/data/call-graph/CallGraphGlyphs.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphGlyphs.js +39 -0
- package/dist/data/call-graph/CallGraphGlyphs.js.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.cjs +51 -0
- package/dist/data/call-graph/CallGraphMembers.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.d.ts +22 -0
- package/dist/data/call-graph/CallGraphMembers.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphMembers.js +51 -0
- package/dist/data/call-graph/CallGraphMembers.js.map +1 -0
- package/dist/data/call-graph/CallGraphParts.cjs +204 -0
- package/dist/data/call-graph/CallGraphParts.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphParts.d.ts +44 -0
- package/dist/data/call-graph/CallGraphParts.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphParts.js +204 -0
- package/dist/data/call-graph/CallGraphParts.js.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.cjs +198 -0
- package/dist/data/call-graph/CallGraphToolbar.cjs.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts +55 -0
- package/dist/data/call-graph/CallGraphToolbar.d.ts.map +1 -0
- package/dist/data/call-graph/CallGraphToolbar.js +198 -0
- package/dist/data/call-graph/CallGraphToolbar.js.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.cjs +75 -0
- package/dist/data/call-graph/call-graph-exclude.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.d.ts +31 -0
- package/dist/data/call-graph/call-graph-exclude.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-exclude.js +75 -0
- package/dist/data/call-graph/call-graph-exclude.js.map +1 -0
- package/dist/data/call-graph/call-graph-labels.cjs +96 -0
- package/dist/data/call-graph/call-graph-labels.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-labels.d.ts +53 -0
- package/dist/data/call-graph/call-graph-labels.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-labels.js +96 -0
- package/dist/data/call-graph/call-graph-labels.js.map +1 -0
- package/dist/data/call-graph/call-graph-model.cjs +312 -0
- package/dist/data/call-graph/call-graph-model.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-model.d.ts +138 -0
- package/dist/data/call-graph/call-graph-model.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-model.js +312 -0
- package/dist/data/call-graph/call-graph-model.js.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.cjs +195 -0
- package/dist/data/call-graph/call-graph-vocabulary.cjs.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts +76 -0
- package/dist/data/call-graph/call-graph-vocabulary.d.ts.map +1 -0
- package/dist/data/call-graph/call-graph-vocabulary.js +195 -0
- package/dist/data/call-graph/call-graph-vocabulary.js.map +1 -0
- package/dist/data/call-graph/call-graph.fixtures.d.ts +63 -0
- package/dist/data/call-graph/call-graph.fixtures.d.ts.map +1 -0
- package/dist/data/call-graph/index.d.ts +7 -0
- package/dist/data/call-graph/index.d.ts.map +1 -0
- package/dist/data/call-graph/types.cjs +5 -0
- package/dist/data/call-graph/types.cjs.map +1 -0
- package/dist/data/call-graph/types.d.ts +140 -0
- package/dist/data/call-graph/types.d.ts.map +1 -0
- package/dist/data/call-graph/types.js +5 -0
- package/dist/data/call-graph/types.js.map +1 -0
- package/dist/data/call-graph/use-call-graph.cjs +93 -0
- package/dist/data/call-graph/use-call-graph.cjs.map +1 -0
- package/dist/data/call-graph/use-call-graph.d.ts +24 -0
- package/dist/data/call-graph/use-call-graph.d.ts.map +1 -0
- package/dist/data/call-graph/use-call-graph.js +93 -0
- package/dist/data/call-graph/use-call-graph.js.map +1 -0
- package/dist/data/chat/Chat.cjs +39 -15
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.fixtures.cjs +2 -2
- package/dist/data/chat/Chat.fixtures.cjs.map +1 -1
- package/dist/data/chat/Chat.fixtures.js +2 -2
- package/dist/data/chat/Chat.fixtures.js.map +1 -1
- package/dist/data/chat/Chat.js +40 -16
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.cjs +3 -6
- package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
- package/dist/data/chat/ChatRuntimeToolbar.js +3 -6
- package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
- package/dist/data/chat/ContextMeter.bar.cjs +5 -8
- package/dist/data/chat/ContextMeter.bar.cjs.map +1 -1
- package/dist/data/chat/ContextMeter.bar.d.ts +1 -1
- package/dist/data/chat/ContextMeter.bar.d.ts.map +1 -1
- package/dist/data/chat/ContextMeter.bar.js +5 -8
- package/dist/data/chat/ContextMeter.bar.js.map +1 -1
- package/dist/data/chat/ContextMeter.cjs +18 -19
- package/dist/data/chat/ContextMeter.cjs.map +1 -1
- package/dist/data/chat/ContextMeter.d.ts +1 -1
- package/dist/data/chat/ContextMeter.d.ts.map +1 -1
- package/dist/data/chat/ContextMeter.js +18 -19
- package/dist/data/chat/ContextMeter.js.map +1 -1
- package/dist/data/chat/Conversation.cjs +2 -1
- package/dist/data/chat/Conversation.cjs.map +1 -1
- package/dist/data/chat/Conversation.d.ts +4 -1
- package/dist/data/chat/Conversation.d.ts.map +1 -1
- package/dist/data/chat/Conversation.js +2 -1
- package/dist/data/chat/Conversation.js.map +1 -1
- package/dist/data/chat/Message.cjs +39 -12
- package/dist/data/chat/Message.cjs.map +1 -1
- package/dist/data/chat/Message.d.ts +1 -1
- package/dist/data/chat/Message.d.ts.map +1 -1
- package/dist/data/chat/Message.js +40 -13
- package/dist/data/chat/Message.js.map +1 -1
- package/dist/data/chat/ToolCall.cjs +60 -5
- package/dist/data/chat/ToolCall.cjs.map +1 -1
- package/dist/data/chat/ToolCall.d.ts +7 -2
- package/dist/data/chat/ToolCall.d.ts.map +1 -1
- package/dist/data/chat/ToolCall.js +60 -5
- package/dist/data/chat/ToolCall.js.map +1 -1
- package/dist/data/chat/approval.cjs.map +1 -1
- package/dist/data/chat/approval.d.ts +2 -2
- package/dist/data/chat/approval.d.ts.map +1 -1
- package/dist/data/chat/approval.js.map +1 -1
- package/dist/data/chat/tool-policy.cjs +59 -2
- package/dist/data/chat/tool-policy.cjs.map +1 -1
- package/dist/data/chat/tool-policy.d.ts +9 -0
- package/dist/data/chat/tool-policy.d.ts.map +1 -1
- package/dist/data/chat/tool-policy.js +59 -2
- package/dist/data/chat/tool-policy.js.map +1 -1
- package/dist/data/chat/types.cjs +6 -0
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +13 -4
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js +7 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/chat/usage-snapshot.cjs +11 -6
- package/dist/data/chat/usage-snapshot.cjs.map +1 -1
- package/dist/data/chat/usage-snapshot.d.ts +0 -1
- package/dist/data/chat/usage-snapshot.d.ts.map +1 -1
- package/dist/data/chat/usage-snapshot.js +11 -6
- package/dist/data/chat/usage-snapshot.js.map +1 -1
- package/dist/data/data-access.cjs +8 -0
- package/dist/data/data-access.cjs.map +1 -0
- package/dist/data/data-access.d.ts +5 -0
- package/dist/data/data-access.d.ts.map +1 -0
- package/dist/data/data-access.js +8 -0
- package/dist/data/data-access.js.map +1 -0
- package/dist/data/diagnostics/StackFrameRow.cjs +3 -3
- package/dist/data/diagnostics/StackFrameRow.cjs.map +1 -1
- package/dist/data/diagnostics/StackFrameRow.js +3 -3
- package/dist/data/diagnostics/StackFrameRow.js.map +1 -1
- package/dist/data/git/GitChangeList.cjs +6 -2
- package/dist/data/git/GitChangeList.cjs.map +1 -1
- package/dist/data/git/GitChangeList.d.ts +6 -1
- package/dist/data/git/GitChangeList.d.ts.map +1 -1
- package/dist/data/git/GitChangeList.js +6 -2
- package/dist/data/git/GitChangeList.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +61 -14
- package/dist/data/graph-columns-layout.cjs.map +1 -1
- package/dist/data/graph-columns-layout.d.ts +42 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -1
- package/dist/data/graph-columns-layout.js +61 -14
- package/dist/data/graph-columns-layout.js.map +1 -1
- package/dist/data/graph-diagram-model.cjs +5 -0
- package/dist/data/graph-diagram-model.cjs.map +1 -1
- package/dist/data/graph-diagram-model.d.ts +24 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -1
- package/dist/data/graph-diagram-model.js +5 -0
- package/dist/data/graph-diagram-model.js.map +1 -1
- package/dist/data/graph-edge-routing.cjs +9 -3
- package/dist/data/graph-edge-routing.cjs.map +1 -1
- package/dist/data/graph-edge-routing.d.ts +2 -0
- package/dist/data/graph-edge-routing.d.ts.map +1 -1
- package/dist/data/graph-edge-routing.js +9 -3
- package/dist/data/graph-edge-routing.js.map +1 -1
- package/dist/data/graph-group-window.cjs +60 -0
- package/dist/data/graph-group-window.cjs.map +1 -0
- package/dist/data/graph-group-window.d.ts +33 -0
- package/dist/data/graph-group-window.d.ts.map +1 -0
- package/dist/data/graph-group-window.js +60 -0
- package/dist/data/graph-group-window.js.map +1 -0
- package/dist/data/json-view/JsonSource.cjs +84 -0
- package/dist/data/json-view/JsonSource.cjs.map +1 -0
- package/dist/data/json-view/JsonSource.d.ts +7 -0
- package/dist/data/json-view/JsonSource.d.ts.map +1 -0
- package/dist/data/json-view/JsonSource.js +84 -0
- package/dist/data/json-view/JsonSource.js.map +1 -0
- package/dist/data/json-view/parse-prefix.cjs +132 -0
- package/dist/data/json-view/parse-prefix.cjs.map +1 -0
- package/dist/data/json-view/parse-prefix.d.ts +11 -0
- package/dist/data/json-view/parse-prefix.d.ts.map +1 -0
- package/dist/data/json-view/parse-prefix.js +132 -0
- package/dist/data/json-view/parse-prefix.js.map +1 -0
- package/dist/data/json-view/parse-source.cjs +62 -0
- package/dist/data/json-view/parse-source.cjs.map +1 -0
- package/dist/data/json-view/parse-source.d.ts +16 -0
- package/dist/data/json-view/parse-source.d.ts.map +1 -0
- package/dist/data/json-view/parse-source.js +62 -0
- package/dist/data/json-view/parse-source.js.map +1 -0
- package/dist/data/json-view/story-fixtures.d.ts +6 -0
- package/dist/data/json-view/story-fixtures.d.ts.map +1 -0
- package/dist/data/json-view/types.d.ts +14 -0
- package/dist/data/json-view/types.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.cjs +2 -5
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts +2 -4
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.cjs +2 -2
- package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.js +2 -2
- package/dist/data/runtime/RuntimeBar.fields.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.js +2 -5
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs +4 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.js +5 -2
- package/dist/data/runtime/RuntimeBar.selection.js.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.cjs +1 -5
- package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.js +1 -5
- package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.cjs +6 -14
- package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.d.ts +0 -1
- package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.js +6 -14
- package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.cjs +8 -27
- package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarLayout.js +8 -27
- package/dist/data/runtime/RuntimeBarLayout.js.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.cjs +1 -5
- package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.js +1 -5
- package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.cjs +4 -10
- package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts +1 -2
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -1
- package/dist/data/runtime/use-runtime-bar-overflow.js +4 -10
- package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -1
- package/dist/data/test-runner/TestRunner.fixtures.d.ts +0 -20
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.large-fixtures.d.ts +22 -0
- package/dist/data/test-runner/TestRunner.large-fixtures.d.ts.map +1 -0
- package/dist/data/use-group-windows.cjs +50 -0
- package/dist/data/use-group-windows.cjs.map +1 -0
- package/dist/data/use-group-windows.d.ts +27 -0
- package/dist/data/use-group-windows.d.ts.map +1 -0
- package/dist/data/use-group-windows.js +50 -0
- package/dist/data/use-group-windows.js.map +1 -0
- package/dist/data/use-pan-zoom.cjs +23 -10
- package/dist/data/use-pan-zoom.cjs.map +1 -1
- package/dist/data/use-pan-zoom.d.ts +16 -2
- package/dist/data/use-pan-zoom.d.ts.map +1 -1
- package/dist/data/use-pan-zoom.js +23 -10
- package/dist/data/use-pan-zoom.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +36 -2
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +5 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +35 -1
- package/dist/data.js.map +1 -1
- package/dist/hooks/event-hub.cjs +229 -0
- package/dist/hooks/event-hub.cjs.map +1 -0
- package/dist/hooks/event-hub.d.ts +26 -0
- package/dist/hooks/event-hub.d.ts.map +1 -0
- package/dist/hooks/event-hub.js +229 -0
- package/dist/hooks/event-hub.js.map +1 -0
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +40 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +37 -1
- package/dist/index.js.map +1 -1
- package/dist/layout/Workspace.cjs +13 -4
- package/dist/layout/Workspace.cjs.map +1 -1
- package/dist/layout/Workspace.d.ts +7 -2
- package/dist/layout/Workspace.d.ts.map +1 -1
- package/dist/layout/Workspace.js +13 -4
- package/dist/layout/Workspace.js.map +1 -1
- package/dist/lib/permission-strategies.cjs +71 -11
- package/dist/lib/permission-strategies.cjs.map +1 -1
- package/dist/lib/permission-strategies.d.ts +3 -0
- package/dist/lib/permission-strategies.d.ts.map +1 -1
- package/dist/lib/permission-strategies.js +71 -11
- package/dist/lib/permission-strategies.js.map +1 -1
- package/dist/overlay/modalStack.cjs +13 -6
- package/dist/overlay/modalStack.cjs.map +1 -1
- package/dist/overlay/modalStack.d.ts.map +1 -1
- package/dist/overlay/modalStack.js +13 -6
- package/dist/overlay/modalStack.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -3
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs +0 -57
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.cjs.map +0 -1
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts +0 -7
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.d.ts.map +0 -1
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js +0 -57
- package/dist/data/ai/ToolSchemaBrowser.selection-toolbar.js.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.cjs +0 -8
- package/dist/data/runtime/RuntimeBar.context.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.d.ts +0 -2
- package/dist/data/runtime/RuntimeBar.context.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBar.context.js +0 -8
- package/dist/data/runtime/RuntimeBar.context.js.map +0 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DataAccess } from './data-access.js';
|
|
2
|
+
export interface AccessMarkProps {
|
|
3
|
+
access: DataAccess;
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* How a name is accessed, as the read and write icons the call graph draws its edges with: one icon for
|
|
8
|
+
* a read or a write, both side by side for a name that is read and written. Its words are its title.
|
|
9
|
+
*/
|
|
10
|
+
export declare function AccessMark({ access, className }: AccessMarkProps): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=AccessMark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessMark.d.ts","sourceRoot":"","sources":["../../src/data/AccessMark.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,eAAe,+BAWhE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useResolvedTheme } from "../hooks/use-theme.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { UiWriteAccessDark, UiWriteAccess } from "../icons/components/UiWriteAccess.js";
|
|
5
|
+
import { UiReadAccessDark, UiReadAccess } from "../icons/components/UiReadAccess.js";
|
|
6
|
+
const WORDS = { read: "Read", write: "Written", readwrite: "Read and written" };
|
|
7
|
+
const ICONS = {
|
|
8
|
+
read: { light: UiReadAccess, dark: UiReadAccessDark },
|
|
9
|
+
write: { light: UiWriteAccess, dark: UiWriteAccessDark }
|
|
10
|
+
};
|
|
11
|
+
const KINDS = { read: ["read"], write: ["write"], readwrite: ["read", "write"] };
|
|
12
|
+
function AccessMark({ access, className }) {
|
|
13
|
+
const dark = useResolvedTheme() === "dark";
|
|
14
|
+
const words = WORDS[access];
|
|
15
|
+
return /* @__PURE__ */ jsx("span", { role: "img", "aria-label": words, title: words, "data-access": access, className: cn("inline-flex shrink-0 items-center gap-px text-sm leading-none", className), children: KINDS[access].map((kind) => {
|
|
16
|
+
const Icon = dark ? ICONS[kind].dark : ICONS[kind].light;
|
|
17
|
+
return /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, "data-access-icon": kind }, kind);
|
|
18
|
+
}) });
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
AccessMark
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=AccessMark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessMark.js","sources":["../../src/data/AccessMark.tsx"],"sourcesContent":["import { useResolvedTheme } from \"../hooks/use-theme\";\nimport { UiReadAccess, UiReadAccessDark, UiWriteAccess, UiWriteAccessDark, type IconComponent } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { DataAccess } from \"./data-access\";\n\nexport interface AccessMarkProps {\n access: DataAccess;\n className?: string;\n}\n\nconst WORDS: Record<DataAccess, string> = { read: \"Read\", write: \"Written\", readwrite: \"Read and written\" };\n\nconst ICONS: Record<\"read\" | \"write\", { light: IconComponent; dark: IconComponent }> = {\n read: { light: UiReadAccess, dark: UiReadAccessDark },\n write: { light: UiWriteAccess, dark: UiWriteAccessDark },\n};\n\nconst KINDS: Record<DataAccess, (\"read\" | \"write\")[]> = { read: [\"read\"], write: [\"write\"], readwrite: [\"read\", \"write\"] };\n\n/**\n * How a name is accessed, as the read and write icons the call graph draws its edges with: one icon for\n * a read or a write, both side by side for a name that is read and written. Its words are its title.\n */\nexport function AccessMark({ access, className }: AccessMarkProps) {\n const dark = useResolvedTheme() === \"dark\";\n const words = WORDS[access];\n return (\n <span role=\"img\" aria-label={words} title={words} data-access={access} className={cn(\"inline-flex shrink-0 items-center gap-px text-sm leading-none\", className)}>\n {KINDS[access].map((kind) => {\n const Icon = dark ? ICONS[kind].dark : ICONS[kind].light;\n return <Icon key={kind} aria-hidden data-access-icon={kind} />;\n })}\n </span>\n );\n}\n"],"names":[],"mappings":";;;;;AAUA,MAAM,QAAoC,EAAE,MAAM,QAAQ,OAAO,WAAW,WAAW,mBAAA;AAEvF,MAAM,QAAiF;AAAA,EACrF,MAAM,EAAE,OAAO,cAAc,MAAM,iBAAA;AAAA,EACnC,OAAO,EAAE,OAAO,eAAe,MAAM,kBAAA;AACvC;AAEA,MAAM,QAAkD,EAAE,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,WAAW,CAAC,QAAQ,OAAO,EAAA;AAMhH,SAAS,WAAW,EAAE,QAAQ,aAA8B;AACjE,QAAM,OAAO,uBAAuB;AACpC,QAAM,QAAQ,MAAM,MAAM;AAC1B,SACE,oBAAC,UAAK,MAAK,OAAM,cAAY,OAAO,OAAO,OAAO,eAAa,QAAQ,WAAW,GAAG,iEAAiE,SAAS,GAC5J,UAAA,MAAM,MAAM,EAAE,IAAI,CAAC,SAAS;AAC3B,UAAM,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,MAAM,IAAI,EAAE;AACnD,+BAAQ,MAAA,EAAgB,eAAW,MAAC,oBAAkB,QAApC,IAA0C;AAAA,EAC9D,CAAC,EAAA,CACH;AAEJ;"}
|
package/dist/data/CodeBlock.cjs
CHANGED
|
@@ -17,6 +17,7 @@ function CodeBlock({
|
|
|
17
17
|
highlightedHtml,
|
|
18
18
|
className,
|
|
19
19
|
jsonDefaultOpenDepth = 2,
|
|
20
|
+
jsonFormat = "json",
|
|
20
21
|
bare = false,
|
|
21
22
|
copyable = false,
|
|
22
23
|
downloadable = false,
|
|
@@ -98,7 +99,7 @@ function CodeBlock({
|
|
|
98
99
|
);
|
|
99
100
|
}
|
|
100
101
|
if (parsedJson !== JSON_PARSE_FAILED) {
|
|
101
|
-
const tree = /* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { data: parsedJson, defaultOpenDepth: jsonDefaultOpenDepth });
|
|
102
|
+
const tree = /* @__PURE__ */ jsxRuntime.jsx(JsonView.JsonView, { data: parsedJson, format: jsonFormat, defaultOpenDepth: jsonDefaultOpenDepth });
|
|
102
103
|
if (bare) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils.cn("overflow-auto text-xs", className), children: tree });
|
|
103
104
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
104
105
|
"div",
|
|
@@ -106,7 +107,7 @@ function CodeBlock({
|
|
|
106
107
|
className: utils.cn("overflow-hidden rounded-md border border-border bg-muted/40", className),
|
|
107
108
|
...overrideAttrs,
|
|
108
109
|
children: [
|
|
109
|
-
/* @__PURE__ */ jsxRuntime.jsx(CodeBlockHeader, { label:
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsx(CodeBlockHeader, { label: jsonFormat, actions: headerActions }),
|
|
110
111
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto p-3 text-xs", children: tree })
|
|
111
112
|
]
|
|
112
113
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlock.cjs","sources":["../../src/data/CodeBlock.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useResolvedTheme, type ResolvedTheme } from \"../hooks/use-theme\";\nimport { CodeBlockActions } from \"./code-block-actions\";\nimport { CodeDiff } from \"./CodeDiff\";\nimport { JsonView } from \"./JsonView\";\nimport { highlightCode } from \"./code-highlight\";\nimport { sanitizeHtml } from \"./html-utils\";\n\nexport type CodeBlockProps = {\n /** Language label and highlighter hint, e.g. `json`, `tsx`, or `bash`. */\n language?: string | undefined;\n /** Raw source code to render or highlight. */\n source?: string | undefined;\n /** Trusted server-rendered highlighted HTML, sanitized before rendering. */\n highlightedHtml?: string | undefined;\n /** Classes applied to the code block shell. */\n className?: string | undefined;\n /** Default expansion depth when rendering JSON as a tree. */\n jsonDefaultOpenDepth?: number | undefined;\n /** Render only the code — no border, background, or language header. */\n bare?: boolean | undefined;\n /** Show a copy-to-clipboard button in the header (ignored when `bare`). */\n copyable?: boolean | undefined;\n /** Show a download button in the header (ignored when `bare`). */\n downloadable?: boolean | undefined;\n /** Name of the downloaded file. Defaults to `snippet.<extension of language>`. */\n downloadFilename?: string | undefined;\n /** Show a per-block light/dark theme toggle in the header (ignored when `bare`). */\n themeToggle?: boolean | undefined;\n /** Render a language-aware diff instead of highlighting `source`. */\n diff?: { original: string; modified: string } | { unified: string } | undefined;\n /** Diff layout when `diff` is set. Defaults to `unified`. */\n diffView?: \"unified\" | \"split\" | undefined;\n /**\n * Render as a single truncated line for a table cell: no border, header, or\n * wrap, whitespace collapsed to one line, syntax-colored when highlighting\n * is available, with the collapsed source (up to 2,000 chars) in a title\n * tooltip. Only the leading 500 chars are rendered and highlighted — the\n * cell clips long before that. The full block is what a row-detail dialog\n * should show instead.\n */\n inline?: boolean | undefined;\n};\n\n// A captured SQL statement can run to tens of thousands of characters on one\n// line; highlighting all of it for a one-line cell cost ~220 ms a statement.\nconst INLINE_RENDER_CHARS = 500;\nconst INLINE_TITLE_CHARS = 2000;\n\nexport function CodeBlock({\n language: languageProp,\n source = \"\",\n highlightedHtml,\n className,\n jsonDefaultOpenDepth = 2,\n bare = false,\n copyable = false,\n downloadable = false,\n downloadFilename,\n themeToggle = false,\n diff,\n diffView,\n inline = false,\n}: CodeBlockProps) {\n const language = (languageProp ?? \"\").toLowerCase().replace(/^\\.+/, \"\");\n const chromaHtml = highlightedHtml ? sanitizeHtml(highlightedHtml) : \"\";\n const parsedJson = useMemo(\n () => (language === \"json\" ? tryParseJson(source) : JSON_PARSE_FAILED),\n [language, source],\n );\n // The block follows the global app theme by default; a per-block override\n // (set by the header toggle) wins over it and re-highlights just this block.\n const globalTheme = useResolvedTheme();\n const [themeOverride, setThemeOverride] = useState<ResolvedTheme | null>(null);\n const effectiveTheme = themeOverride ?? globalTheme;\n const [shikiHtml, setShikiHtml] = useState<string | null>(null);\n const wantsClientHighlight =\n parsedJson === JSON_PARSE_FAILED && !chromaHtml && !!language && !!source;\n const singleLine = useMemo(\n () => (inline ? source.replace(/\\s+/g, \" \").trim() : \"\"),\n [inline, source],\n );\n const highlightSource = inline ? singleLine.slice(0, INLINE_RENDER_CHARS) : source;\n\n useEffect(() => {\n if (!wantsClientHighlight) {\n setShikiHtml(null);\n return;\n }\n\n let cancelled = false;\n const theme = effectiveTheme === \"dark\" ? \"github-dark\" : \"github-light\";\n highlightCode(highlightSource, { lang: language, theme }).then((out) => {\n if (!cancelled) setShikiHtml(out);\n });\n\n return () => {\n cancelled = true;\n };\n }, [wantsClientHighlight, language, highlightSource, effectiveTheme]);\n\n const headerActions = (\n <CodeBlockActions\n source={source}\n language={languageProp}\n copyable={copyable}\n downloadable={downloadable}\n downloadFilename={downloadFilename}\n theme={effectiveTheme}\n {...(themeToggle\n ? { onToggleTheme: () => setThemeOverride(effectiveTheme === \"dark\" ? \"light\" : \"dark\") }\n : {})}\n />\n );\n // Re-scope theme tokens (shell background/border/label) to the override so an\n // overridden block stays visually coherent with its re-highlighted code.\n const overrideAttrs = themeOverride ? { \"data-theme\": themeOverride } : {};\n\n if (inline) {\n const html = chromaHtml || shikiHtml;\n const title =\n singleLine.length > INLINE_TITLE_CHARS\n ? `${singleLine.slice(0, INLINE_TITLE_CHARS)}…`\n : singleLine;\n return (\n <code\n className={cn(\n \"block max-w-full truncate font-mono text-xs text-foreground\",\n className,\n html && \"[&_pre]:inline [&_pre]:whitespace-pre [&_.chroma]:bg-transparent\",\n )}\n title={title}\n >\n {html ? <span dangerouslySetInnerHTML={{ __html: html }} /> : highlightSource}\n </code>\n );\n }\n\n if (diff) {\n return (\n <CodeDiff\n language={languageProp}\n view={diffView}\n bare={bare}\n className={className}\n {...diff}\n />\n );\n }\n\n if (parsedJson !== JSON_PARSE_FAILED) {\n const tree = <JsonView data={parsedJson} defaultOpenDepth={jsonDefaultOpenDepth} />;\n if (bare) return <div className={cn(\"overflow-auto text-xs\", className)}>{tree}</div>;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label=\"json\" actions={headerActions} />\n <div className=\"overflow-auto p-3 text-xs\">{tree}</div>\n </div>\n );\n }\n\n const xmlClasses =\n language === \"xml\" || language === \"xslt\" || language === \"html\"\n ? \" [&_.chroma_.nt]:text-pink-700 [&_.chroma_.nt]:dark:text-pink-300 [&_.chroma_.nt]:font-semibold\" +\n \" [&_.chroma_.na]:text-amber-700 [&_.chroma_.na]:dark:text-amber-300\" +\n \" [&_.chroma_.s]:text-emerald-700 [&_.chroma_.s]:dark:text-emerald-300\" +\n \" [&_.chroma_.c]:text-slate-500 [&_.chroma_.c]:italic\" +\n \" [&_.chroma_.cp]:text-slate-500 [&_.chroma_.cp]:italic\" +\n \" [&_pre]:leading-relaxed\"\n : \"\";\n\n const pad = bare ? undefined : \"p-3\";\n const body = chromaHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_.chroma]:bg-transparent [&_pre]:m-0 [&_pre]:whitespace-pre-wrap [&_pre]:bg-transparent\" +\n xmlClasses,\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: chromaHtml }}\n />\n ) : shikiHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_pre]:m-0 [&_pre.shiki]:!bg-transparent [&_pre]:whitespace-pre-wrap\",\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: shikiHtml }}\n />\n ) : (\n <pre\n className={cn(\n \"overflow-auto whitespace-pre-wrap break-words text-xs font-mono text-foreground\",\n pad,\n bare && className,\n )}\n >\n {source}\n </pre>\n );\n\n if (bare) return body;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label={languageProp || \"text\"} actions={headerActions} />\n {body}\n </div>\n );\n}\n\nfunction CodeBlockHeader({ label, actions }: { label: string; actions: ReactNode }) {\n return (\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1.5\">\n <span className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">{label}</span>\n {actions}\n </div>\n );\n}\n\nconst JSON_PARSE_FAILED: unique symbol = Symbol(\"json-parse-failed\");\n\nfunction tryParseJson(source: string): unknown | typeof JSON_PARSE_FAILED {\n const trimmed = source.trim();\n if (!trimmed) return JSON_PARSE_FAILED;\n try {\n return JSON.parse(trimmed);\n } catch {\n return JSON_PARSE_FAILED;\n }\n}\n"],"names":["sanitizeHtml","useMemo","useResolvedTheme","useState","useEffect","highlightCode","jsx","CodeBlockActions","cn","CodeDiff","JsonView","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeBlock.cjs","sources":["../../src/data/CodeBlock.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useResolvedTheme, type ResolvedTheme } from \"../hooks/use-theme\";\nimport { CodeBlockActions } from \"./code-block-actions\";\nimport { CodeDiff } from \"./CodeDiff\";\nimport { JsonView } from \"./JsonView\";\nimport { highlightCode } from \"./code-highlight\";\nimport { sanitizeHtml } from \"./html-utils\";\n\nexport type CodeBlockProps = {\n /** Language label and highlighter hint, e.g. `json`, `tsx`, or `bash`. */\n language?: string | undefined;\n /** Raw source code to render or highlight. */\n source?: string | undefined;\n /** Trusted server-rendered highlighted HTML, sanitized before rendering. */\n highlightedHtml?: string | undefined;\n /** Classes applied to the code block shell. */\n className?: string | undefined;\n /** Default expansion depth when rendering JSON as a tree. */\n jsonDefaultOpenDepth?: number | undefined;\n /** Display format for parsed JSON values. */\n jsonFormat?: \"json\" | \"yaml\" | undefined;\n /** Render only the code — no border, background, or language header. */\n bare?: boolean | undefined;\n /** Show a copy-to-clipboard button in the header (ignored when `bare`). */\n copyable?: boolean | undefined;\n /** Show a download button in the header (ignored when `bare`). */\n downloadable?: boolean | undefined;\n /** Name of the downloaded file. Defaults to `snippet.<extension of language>`. */\n downloadFilename?: string | undefined;\n /** Show a per-block light/dark theme toggle in the header (ignored when `bare`). */\n themeToggle?: boolean | undefined;\n /** Render a language-aware diff instead of highlighting `source`. */\n diff?: { original: string; modified: string } | { unified: string } | undefined;\n /** Diff layout when `diff` is set. Defaults to `unified`. */\n diffView?: \"unified\" | \"split\" | undefined;\n /**\n * Render as a single truncated line for a table cell: no border, header, or\n * wrap, whitespace collapsed to one line, syntax-colored when highlighting\n * is available, with the collapsed source (up to 2,000 chars) in a title\n * tooltip. Only the leading 500 chars are rendered and highlighted — the\n * cell clips long before that. The full block is what a row-detail dialog\n * should show instead.\n */\n inline?: boolean | undefined;\n};\n\n// A captured SQL statement can run to tens of thousands of characters on one\n// line; highlighting all of it for a one-line cell cost ~220 ms a statement.\nconst INLINE_RENDER_CHARS = 500;\nconst INLINE_TITLE_CHARS = 2000;\n\nexport function CodeBlock({\n language: languageProp,\n source = \"\",\n highlightedHtml,\n className,\n jsonDefaultOpenDepth = 2,\n jsonFormat = \"json\",\n bare = false,\n copyable = false,\n downloadable = false,\n downloadFilename,\n themeToggle = false,\n diff,\n diffView,\n inline = false,\n}: CodeBlockProps) {\n const language = (languageProp ?? \"\").toLowerCase().replace(/^\\.+/, \"\");\n const chromaHtml = highlightedHtml ? sanitizeHtml(highlightedHtml) : \"\";\n const parsedJson = useMemo(\n () => (language === \"json\" ? tryParseJson(source) : JSON_PARSE_FAILED),\n [language, source],\n );\n // The block follows the global app theme by default; a per-block override\n // (set by the header toggle) wins over it and re-highlights just this block.\n const globalTheme = useResolvedTheme();\n const [themeOverride, setThemeOverride] = useState<ResolvedTheme | null>(null);\n const effectiveTheme = themeOverride ?? globalTheme;\n const [shikiHtml, setShikiHtml] = useState<string | null>(null);\n const wantsClientHighlight =\n parsedJson === JSON_PARSE_FAILED && !chromaHtml && !!language && !!source;\n const singleLine = useMemo(\n () => (inline ? source.replace(/\\s+/g, \" \").trim() : \"\"),\n [inline, source],\n );\n const highlightSource = inline ? singleLine.slice(0, INLINE_RENDER_CHARS) : source;\n\n useEffect(() => {\n if (!wantsClientHighlight) {\n setShikiHtml(null);\n return;\n }\n\n let cancelled = false;\n const theme = effectiveTheme === \"dark\" ? \"github-dark\" : \"github-light\";\n highlightCode(highlightSource, { lang: language, theme }).then((out) => {\n if (!cancelled) setShikiHtml(out);\n });\n\n return () => {\n cancelled = true;\n };\n }, [wantsClientHighlight, language, highlightSource, effectiveTheme]);\n\n const headerActions = (\n <CodeBlockActions\n source={source}\n language={languageProp}\n copyable={copyable}\n downloadable={downloadable}\n downloadFilename={downloadFilename}\n theme={effectiveTheme}\n {...(themeToggle\n ? { onToggleTheme: () => setThemeOverride(effectiveTheme === \"dark\" ? \"light\" : \"dark\") }\n : {})}\n />\n );\n // Re-scope theme tokens (shell background/border/label) to the override so an\n // overridden block stays visually coherent with its re-highlighted code.\n const overrideAttrs = themeOverride ? { \"data-theme\": themeOverride } : {};\n\n if (inline) {\n const html = chromaHtml || shikiHtml;\n const title =\n singleLine.length > INLINE_TITLE_CHARS\n ? `${singleLine.slice(0, INLINE_TITLE_CHARS)}…`\n : singleLine;\n return (\n <code\n className={cn(\n \"block max-w-full truncate font-mono text-xs text-foreground\",\n className,\n html && \"[&_pre]:inline [&_pre]:whitespace-pre [&_.chroma]:bg-transparent\",\n )}\n title={title}\n >\n {html ? <span dangerouslySetInnerHTML={{ __html: html }} /> : highlightSource}\n </code>\n );\n }\n\n if (diff) {\n return (\n <CodeDiff\n language={languageProp}\n view={diffView}\n bare={bare}\n className={className}\n {...diff}\n />\n );\n }\n\n if (parsedJson !== JSON_PARSE_FAILED) {\n const tree = <JsonView data={parsedJson} format={jsonFormat} defaultOpenDepth={jsonDefaultOpenDepth} />;\n if (bare) return <div className={cn(\"overflow-auto text-xs\", className)}>{tree}</div>;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label={jsonFormat} actions={headerActions} />\n <div className=\"overflow-auto p-3 text-xs\">{tree}</div>\n </div>\n );\n }\n\n const xmlClasses =\n language === \"xml\" || language === \"xslt\" || language === \"html\"\n ? \" [&_.chroma_.nt]:text-pink-700 [&_.chroma_.nt]:dark:text-pink-300 [&_.chroma_.nt]:font-semibold\" +\n \" [&_.chroma_.na]:text-amber-700 [&_.chroma_.na]:dark:text-amber-300\" +\n \" [&_.chroma_.s]:text-emerald-700 [&_.chroma_.s]:dark:text-emerald-300\" +\n \" [&_.chroma_.c]:text-slate-500 [&_.chroma_.c]:italic\" +\n \" [&_.chroma_.cp]:text-slate-500 [&_.chroma_.cp]:italic\" +\n \" [&_pre]:leading-relaxed\"\n : \"\";\n\n const pad = bare ? undefined : \"p-3\";\n const body = chromaHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_.chroma]:bg-transparent [&_pre]:m-0 [&_pre]:whitespace-pre-wrap [&_pre]:bg-transparent\" +\n xmlClasses,\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: chromaHtml }}\n />\n ) : shikiHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_pre]:m-0 [&_pre.shiki]:!bg-transparent [&_pre]:whitespace-pre-wrap\",\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: shikiHtml }}\n />\n ) : (\n <pre\n className={cn(\n \"overflow-auto whitespace-pre-wrap break-words text-xs font-mono text-foreground\",\n pad,\n bare && className,\n )}\n >\n {source}\n </pre>\n );\n\n if (bare) return body;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label={languageProp || \"text\"} actions={headerActions} />\n {body}\n </div>\n );\n}\n\nfunction CodeBlockHeader({ label, actions }: { label: string; actions: ReactNode }) {\n return (\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1.5\">\n <span className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">{label}</span>\n {actions}\n </div>\n );\n}\n\nconst JSON_PARSE_FAILED: unique symbol = Symbol(\"json-parse-failed\");\n\nfunction tryParseJson(source: string): unknown | typeof JSON_PARSE_FAILED {\n const trimmed = source.trim();\n if (!trimmed) return JSON_PARSE_FAILED;\n try {\n return JSON.parse(trimmed);\n } catch {\n return JSON_PARSE_FAILED;\n }\n}\n"],"names":["sanitizeHtml","useMemo","useResolvedTheme","useState","useEffect","highlightCode","jsx","CodeBlockActions","cn","CodeDiff","JsonView","jsxs"],"mappings":"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"}
|
package/dist/data/CodeBlock.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export type CodeBlockProps = {
|
|
|
9
9
|
className?: string | undefined;
|
|
10
10
|
/** Default expansion depth when rendering JSON as a tree. */
|
|
11
11
|
jsonDefaultOpenDepth?: number | undefined;
|
|
12
|
+
/** Display format for parsed JSON values. */
|
|
13
|
+
jsonFormat?: "json" | "yaml" | undefined;
|
|
12
14
|
/** Render only the code — no border, background, or language header. */
|
|
13
15
|
bare?: boolean | undefined;
|
|
14
16
|
/** Show a copy-to-clipboard button in the header (ignored when `bare`). */
|
|
@@ -38,5 +40,5 @@ export type CodeBlockProps = {
|
|
|
38
40
|
*/
|
|
39
41
|
inline?: boolean | undefined;
|
|
40
42
|
};
|
|
41
|
-
export declare function CodeBlock({ language: languageProp, source, highlightedHtml, className, jsonDefaultOpenDepth, bare, copyable, downloadable, downloadFilename, themeToggle, diff, diffView, inline, }: CodeBlockProps): import("react").JSX.Element;
|
|
43
|
+
export declare function CodeBlock({ language: languageProp, source, highlightedHtml, className, jsonDefaultOpenDepth, jsonFormat, bare, copyable, downloadable, downloadFilename, themeToggle, diff, diffView, inline, }: CodeBlockProps): import("react").JSX.Element;
|
|
42
44
|
//# sourceMappingURL=CodeBlock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../src/data/CodeBlock.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,6DAA6D;IAC7D,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oFAAoF;IACpF,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,qEAAqE;IACrE,IAAI,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAChF,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAC3C;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B,CAAC;AAOF,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EAAE,YAAY,EACtB,MAAW,EACX,eAAe,EACf,SAAS,EACT,oBAAwB,EACxB,IAAY,EACZ,QAAgB,EAChB,YAAoB,EACpB,gBAAgB,EAChB,WAAmB,EACnB,IAAI,EACJ,QAAQ,EACR,MAAc,GACf,EAAE,cAAc,+BAyJhB"}
|
|
1
|
+
{"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../src/data/CodeBlock.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,6DAA6D;IAC7D,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzC,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oFAAoF;IACpF,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,qEAAqE;IACrE,IAAI,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAChF,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IAC3C;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B,CAAC;AAOF,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EAAE,YAAY,EACtB,MAAW,EACX,eAAe,EACf,SAAS,EACT,oBAAwB,EACxB,UAAmB,EACnB,IAAY,EACZ,QAAgB,EAChB,YAAoB,EACpB,gBAAgB,EAChB,WAAmB,EACnB,IAAI,EACJ,QAAQ,EACR,MAAc,GACf,EAAE,cAAc,+BAyJhB"}
|
package/dist/data/CodeBlock.js
CHANGED
|
@@ -15,6 +15,7 @@ function CodeBlock({
|
|
|
15
15
|
highlightedHtml,
|
|
16
16
|
className,
|
|
17
17
|
jsonDefaultOpenDepth = 2,
|
|
18
|
+
jsonFormat = "json",
|
|
18
19
|
bare = false,
|
|
19
20
|
copyable = false,
|
|
20
21
|
downloadable = false,
|
|
@@ -96,7 +97,7 @@ function CodeBlock({
|
|
|
96
97
|
);
|
|
97
98
|
}
|
|
98
99
|
if (parsedJson !== JSON_PARSE_FAILED) {
|
|
99
|
-
const tree = /* @__PURE__ */ jsx(JsonView, { data: parsedJson, defaultOpenDepth: jsonDefaultOpenDepth });
|
|
100
|
+
const tree = /* @__PURE__ */ jsx(JsonView, { data: parsedJson, format: jsonFormat, defaultOpenDepth: jsonDefaultOpenDepth });
|
|
100
101
|
if (bare) return /* @__PURE__ */ jsx("div", { className: cn("overflow-auto text-xs", className), children: tree });
|
|
101
102
|
return /* @__PURE__ */ jsxs(
|
|
102
103
|
"div",
|
|
@@ -104,7 +105,7 @@ function CodeBlock({
|
|
|
104
105
|
className: cn("overflow-hidden rounded-md border border-border bg-muted/40", className),
|
|
105
106
|
...overrideAttrs,
|
|
106
107
|
children: [
|
|
107
|
-
/* @__PURE__ */ jsx(CodeBlockHeader, { label:
|
|
108
|
+
/* @__PURE__ */ jsx(CodeBlockHeader, { label: jsonFormat, actions: headerActions }),
|
|
108
109
|
/* @__PURE__ */ jsx("div", { className: "overflow-auto p-3 text-xs", children: tree })
|
|
109
110
|
]
|
|
110
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlock.js","sources":["../../src/data/CodeBlock.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useResolvedTheme, type ResolvedTheme } from \"../hooks/use-theme\";\nimport { CodeBlockActions } from \"./code-block-actions\";\nimport { CodeDiff } from \"./CodeDiff\";\nimport { JsonView } from \"./JsonView\";\nimport { highlightCode } from \"./code-highlight\";\nimport { sanitizeHtml } from \"./html-utils\";\n\nexport type CodeBlockProps = {\n /** Language label and highlighter hint, e.g. `json`, `tsx`, or `bash`. */\n language?: string | undefined;\n /** Raw source code to render or highlight. */\n source?: string | undefined;\n /** Trusted server-rendered highlighted HTML, sanitized before rendering. */\n highlightedHtml?: string | undefined;\n /** Classes applied to the code block shell. */\n className?: string | undefined;\n /** Default expansion depth when rendering JSON as a tree. */\n jsonDefaultOpenDepth?: number | undefined;\n /** Render only the code — no border, background, or language header. */\n bare?: boolean | undefined;\n /** Show a copy-to-clipboard button in the header (ignored when `bare`). */\n copyable?: boolean | undefined;\n /** Show a download button in the header (ignored when `bare`). */\n downloadable?: boolean | undefined;\n /** Name of the downloaded file. Defaults to `snippet.<extension of language>`. */\n downloadFilename?: string | undefined;\n /** Show a per-block light/dark theme toggle in the header (ignored when `bare`). */\n themeToggle?: boolean | undefined;\n /** Render a language-aware diff instead of highlighting `source`. */\n diff?: { original: string; modified: string } | { unified: string } | undefined;\n /** Diff layout when `diff` is set. Defaults to `unified`. */\n diffView?: \"unified\" | \"split\" | undefined;\n /**\n * Render as a single truncated line for a table cell: no border, header, or\n * wrap, whitespace collapsed to one line, syntax-colored when highlighting\n * is available, with the collapsed source (up to 2,000 chars) in a title\n * tooltip. Only the leading 500 chars are rendered and highlighted — the\n * cell clips long before that. The full block is what a row-detail dialog\n * should show instead.\n */\n inline?: boolean | undefined;\n};\n\n// A captured SQL statement can run to tens of thousands of characters on one\n// line; highlighting all of it for a one-line cell cost ~220 ms a statement.\nconst INLINE_RENDER_CHARS = 500;\nconst INLINE_TITLE_CHARS = 2000;\n\nexport function CodeBlock({\n language: languageProp,\n source = \"\",\n highlightedHtml,\n className,\n jsonDefaultOpenDepth = 2,\n bare = false,\n copyable = false,\n downloadable = false,\n downloadFilename,\n themeToggle = false,\n diff,\n diffView,\n inline = false,\n}: CodeBlockProps) {\n const language = (languageProp ?? \"\").toLowerCase().replace(/^\\.+/, \"\");\n const chromaHtml = highlightedHtml ? sanitizeHtml(highlightedHtml) : \"\";\n const parsedJson = useMemo(\n () => (language === \"json\" ? tryParseJson(source) : JSON_PARSE_FAILED),\n [language, source],\n );\n // The block follows the global app theme by default; a per-block override\n // (set by the header toggle) wins over it and re-highlights just this block.\n const globalTheme = useResolvedTheme();\n const [themeOverride, setThemeOverride] = useState<ResolvedTheme | null>(null);\n const effectiveTheme = themeOverride ?? globalTheme;\n const [shikiHtml, setShikiHtml] = useState<string | null>(null);\n const wantsClientHighlight =\n parsedJson === JSON_PARSE_FAILED && !chromaHtml && !!language && !!source;\n const singleLine = useMemo(\n () => (inline ? source.replace(/\\s+/g, \" \").trim() : \"\"),\n [inline, source],\n );\n const highlightSource = inline ? singleLine.slice(0, INLINE_RENDER_CHARS) : source;\n\n useEffect(() => {\n if (!wantsClientHighlight) {\n setShikiHtml(null);\n return;\n }\n\n let cancelled = false;\n const theme = effectiveTheme === \"dark\" ? \"github-dark\" : \"github-light\";\n highlightCode(highlightSource, { lang: language, theme }).then((out) => {\n if (!cancelled) setShikiHtml(out);\n });\n\n return () => {\n cancelled = true;\n };\n }, [wantsClientHighlight, language, highlightSource, effectiveTheme]);\n\n const headerActions = (\n <CodeBlockActions\n source={source}\n language={languageProp}\n copyable={copyable}\n downloadable={downloadable}\n downloadFilename={downloadFilename}\n theme={effectiveTheme}\n {...(themeToggle\n ? { onToggleTheme: () => setThemeOverride(effectiveTheme === \"dark\" ? \"light\" : \"dark\") }\n : {})}\n />\n );\n // Re-scope theme tokens (shell background/border/label) to the override so an\n // overridden block stays visually coherent with its re-highlighted code.\n const overrideAttrs = themeOverride ? { \"data-theme\": themeOverride } : {};\n\n if (inline) {\n const html = chromaHtml || shikiHtml;\n const title =\n singleLine.length > INLINE_TITLE_CHARS\n ? `${singleLine.slice(0, INLINE_TITLE_CHARS)}…`\n : singleLine;\n return (\n <code\n className={cn(\n \"block max-w-full truncate font-mono text-xs text-foreground\",\n className,\n html && \"[&_pre]:inline [&_pre]:whitespace-pre [&_.chroma]:bg-transparent\",\n )}\n title={title}\n >\n {html ? <span dangerouslySetInnerHTML={{ __html: html }} /> : highlightSource}\n </code>\n );\n }\n\n if (diff) {\n return (\n <CodeDiff\n language={languageProp}\n view={diffView}\n bare={bare}\n className={className}\n {...diff}\n />\n );\n }\n\n if (parsedJson !== JSON_PARSE_FAILED) {\n const tree = <JsonView data={parsedJson} defaultOpenDepth={jsonDefaultOpenDepth} />;\n if (bare) return <div className={cn(\"overflow-auto text-xs\", className)}>{tree}</div>;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label=\"json\" actions={headerActions} />\n <div className=\"overflow-auto p-3 text-xs\">{tree}</div>\n </div>\n );\n }\n\n const xmlClasses =\n language === \"xml\" || language === \"xslt\" || language === \"html\"\n ? \" [&_.chroma_.nt]:text-pink-700 [&_.chroma_.nt]:dark:text-pink-300 [&_.chroma_.nt]:font-semibold\" +\n \" [&_.chroma_.na]:text-amber-700 [&_.chroma_.na]:dark:text-amber-300\" +\n \" [&_.chroma_.s]:text-emerald-700 [&_.chroma_.s]:dark:text-emerald-300\" +\n \" [&_.chroma_.c]:text-slate-500 [&_.chroma_.c]:italic\" +\n \" [&_.chroma_.cp]:text-slate-500 [&_.chroma_.cp]:italic\" +\n \" [&_pre]:leading-relaxed\"\n : \"\";\n\n const pad = bare ? undefined : \"p-3\";\n const body = chromaHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_.chroma]:bg-transparent [&_pre]:m-0 [&_pre]:whitespace-pre-wrap [&_pre]:bg-transparent\" +\n xmlClasses,\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: chromaHtml }}\n />\n ) : shikiHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_pre]:m-0 [&_pre.shiki]:!bg-transparent [&_pre]:whitespace-pre-wrap\",\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: shikiHtml }}\n />\n ) : (\n <pre\n className={cn(\n \"overflow-auto whitespace-pre-wrap break-words text-xs font-mono text-foreground\",\n pad,\n bare && className,\n )}\n >\n {source}\n </pre>\n );\n\n if (bare) return body;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label={languageProp || \"text\"} actions={headerActions} />\n {body}\n </div>\n );\n}\n\nfunction CodeBlockHeader({ label, actions }: { label: string; actions: ReactNode }) {\n return (\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1.5\">\n <span className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">{label}</span>\n {actions}\n </div>\n );\n}\n\nconst JSON_PARSE_FAILED: unique symbol = Symbol(\"json-parse-failed\");\n\nfunction tryParseJson(source: string): unknown | typeof JSON_PARSE_FAILED {\n const trimmed = source.trim();\n if (!trimmed) return JSON_PARSE_FAILED;\n try {\n return JSON.parse(trimmed);\n } catch {\n return JSON_PARSE_FAILED;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeBlock.js","sources":["../../src/data/CodeBlock.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useResolvedTheme, type ResolvedTheme } from \"../hooks/use-theme\";\nimport { CodeBlockActions } from \"./code-block-actions\";\nimport { CodeDiff } from \"./CodeDiff\";\nimport { JsonView } from \"./JsonView\";\nimport { highlightCode } from \"./code-highlight\";\nimport { sanitizeHtml } from \"./html-utils\";\n\nexport type CodeBlockProps = {\n /** Language label and highlighter hint, e.g. `json`, `tsx`, or `bash`. */\n language?: string | undefined;\n /** Raw source code to render or highlight. */\n source?: string | undefined;\n /** Trusted server-rendered highlighted HTML, sanitized before rendering. */\n highlightedHtml?: string | undefined;\n /** Classes applied to the code block shell. */\n className?: string | undefined;\n /** Default expansion depth when rendering JSON as a tree. */\n jsonDefaultOpenDepth?: number | undefined;\n /** Display format for parsed JSON values. */\n jsonFormat?: \"json\" | \"yaml\" | undefined;\n /** Render only the code — no border, background, or language header. */\n bare?: boolean | undefined;\n /** Show a copy-to-clipboard button in the header (ignored when `bare`). */\n copyable?: boolean | undefined;\n /** Show a download button in the header (ignored when `bare`). */\n downloadable?: boolean | undefined;\n /** Name of the downloaded file. Defaults to `snippet.<extension of language>`. */\n downloadFilename?: string | undefined;\n /** Show a per-block light/dark theme toggle in the header (ignored when `bare`). */\n themeToggle?: boolean | undefined;\n /** Render a language-aware diff instead of highlighting `source`. */\n diff?: { original: string; modified: string } | { unified: string } | undefined;\n /** Diff layout when `diff` is set. Defaults to `unified`. */\n diffView?: \"unified\" | \"split\" | undefined;\n /**\n * Render as a single truncated line for a table cell: no border, header, or\n * wrap, whitespace collapsed to one line, syntax-colored when highlighting\n * is available, with the collapsed source (up to 2,000 chars) in a title\n * tooltip. Only the leading 500 chars are rendered and highlighted — the\n * cell clips long before that. The full block is what a row-detail dialog\n * should show instead.\n */\n inline?: boolean | undefined;\n};\n\n// A captured SQL statement can run to tens of thousands of characters on one\n// line; highlighting all of it for a one-line cell cost ~220 ms a statement.\nconst INLINE_RENDER_CHARS = 500;\nconst INLINE_TITLE_CHARS = 2000;\n\nexport function CodeBlock({\n language: languageProp,\n source = \"\",\n highlightedHtml,\n className,\n jsonDefaultOpenDepth = 2,\n jsonFormat = \"json\",\n bare = false,\n copyable = false,\n downloadable = false,\n downloadFilename,\n themeToggle = false,\n diff,\n diffView,\n inline = false,\n}: CodeBlockProps) {\n const language = (languageProp ?? \"\").toLowerCase().replace(/^\\.+/, \"\");\n const chromaHtml = highlightedHtml ? sanitizeHtml(highlightedHtml) : \"\";\n const parsedJson = useMemo(\n () => (language === \"json\" ? tryParseJson(source) : JSON_PARSE_FAILED),\n [language, source],\n );\n // The block follows the global app theme by default; a per-block override\n // (set by the header toggle) wins over it and re-highlights just this block.\n const globalTheme = useResolvedTheme();\n const [themeOverride, setThemeOverride] = useState<ResolvedTheme | null>(null);\n const effectiveTheme = themeOverride ?? globalTheme;\n const [shikiHtml, setShikiHtml] = useState<string | null>(null);\n const wantsClientHighlight =\n parsedJson === JSON_PARSE_FAILED && !chromaHtml && !!language && !!source;\n const singleLine = useMemo(\n () => (inline ? source.replace(/\\s+/g, \" \").trim() : \"\"),\n [inline, source],\n );\n const highlightSource = inline ? singleLine.slice(0, INLINE_RENDER_CHARS) : source;\n\n useEffect(() => {\n if (!wantsClientHighlight) {\n setShikiHtml(null);\n return;\n }\n\n let cancelled = false;\n const theme = effectiveTheme === \"dark\" ? \"github-dark\" : \"github-light\";\n highlightCode(highlightSource, { lang: language, theme }).then((out) => {\n if (!cancelled) setShikiHtml(out);\n });\n\n return () => {\n cancelled = true;\n };\n }, [wantsClientHighlight, language, highlightSource, effectiveTheme]);\n\n const headerActions = (\n <CodeBlockActions\n source={source}\n language={languageProp}\n copyable={copyable}\n downloadable={downloadable}\n downloadFilename={downloadFilename}\n theme={effectiveTheme}\n {...(themeToggle\n ? { onToggleTheme: () => setThemeOverride(effectiveTheme === \"dark\" ? \"light\" : \"dark\") }\n : {})}\n />\n );\n // Re-scope theme tokens (shell background/border/label) to the override so an\n // overridden block stays visually coherent with its re-highlighted code.\n const overrideAttrs = themeOverride ? { \"data-theme\": themeOverride } : {};\n\n if (inline) {\n const html = chromaHtml || shikiHtml;\n const title =\n singleLine.length > INLINE_TITLE_CHARS\n ? `${singleLine.slice(0, INLINE_TITLE_CHARS)}…`\n : singleLine;\n return (\n <code\n className={cn(\n \"block max-w-full truncate font-mono text-xs text-foreground\",\n className,\n html && \"[&_pre]:inline [&_pre]:whitespace-pre [&_.chroma]:bg-transparent\",\n )}\n title={title}\n >\n {html ? <span dangerouslySetInnerHTML={{ __html: html }} /> : highlightSource}\n </code>\n );\n }\n\n if (diff) {\n return (\n <CodeDiff\n language={languageProp}\n view={diffView}\n bare={bare}\n className={className}\n {...diff}\n />\n );\n }\n\n if (parsedJson !== JSON_PARSE_FAILED) {\n const tree = <JsonView data={parsedJson} format={jsonFormat} defaultOpenDepth={jsonDefaultOpenDepth} />;\n if (bare) return <div className={cn(\"overflow-auto text-xs\", className)}>{tree}</div>;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label={jsonFormat} actions={headerActions} />\n <div className=\"overflow-auto p-3 text-xs\">{tree}</div>\n </div>\n );\n }\n\n const xmlClasses =\n language === \"xml\" || language === \"xslt\" || language === \"html\"\n ? \" [&_.chroma_.nt]:text-pink-700 [&_.chroma_.nt]:dark:text-pink-300 [&_.chroma_.nt]:font-semibold\" +\n \" [&_.chroma_.na]:text-amber-700 [&_.chroma_.na]:dark:text-amber-300\" +\n \" [&_.chroma_.s]:text-emerald-700 [&_.chroma_.s]:dark:text-emerald-300\" +\n \" [&_.chroma_.c]:text-slate-500 [&_.chroma_.c]:italic\" +\n \" [&_.chroma_.cp]:text-slate-500 [&_.chroma_.cp]:italic\" +\n \" [&_pre]:leading-relaxed\"\n : \"\";\n\n const pad = bare ? undefined : \"p-3\";\n const body = chromaHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_.chroma]:bg-transparent [&_pre]:m-0 [&_pre]:whitespace-pre-wrap [&_pre]:bg-transparent\" +\n xmlClasses,\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: chromaHtml }}\n />\n ) : shikiHtml ? (\n <div\n className={cn(\n \"overflow-auto text-xs font-mono [&_pre]:m-0 [&_pre.shiki]:!bg-transparent [&_pre]:whitespace-pre-wrap\",\n pad,\n bare && className,\n )}\n dangerouslySetInnerHTML={{ __html: shikiHtml }}\n />\n ) : (\n <pre\n className={cn(\n \"overflow-auto whitespace-pre-wrap break-words text-xs font-mono text-foreground\",\n pad,\n bare && className,\n )}\n >\n {source}\n </pre>\n );\n\n if (bare) return body;\n return (\n <div\n className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}\n {...overrideAttrs}\n >\n <CodeBlockHeader label={languageProp || \"text\"} actions={headerActions} />\n {body}\n </div>\n );\n}\n\nfunction CodeBlockHeader({ label, actions }: { label: string; actions: ReactNode }) {\n return (\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1.5\">\n <span className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">{label}</span>\n {actions}\n </div>\n );\n}\n\nconst JSON_PARSE_FAILED: unique symbol = Symbol(\"json-parse-failed\");\n\nfunction tryParseJson(source: string): unknown | typeof JSON_PARSE_FAILED {\n const trimmed = source.trim();\n if (!trimmed) return JSON_PARSE_FAILED;\n try {\n return JSON.parse(trimmed);\n } catch {\n return JSON_PARSE_FAILED;\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/data/CodeDiff.cjs
CHANGED
|
@@ -10,6 +10,7 @@ const HighlightedTokens = require("./HighlightedTokens.cjs");
|
|
|
10
10
|
const UiRows = require("../icons/components/UiRows.cjs");
|
|
11
11
|
const UiColumns = require("../icons/components/UiColumns.cjs");
|
|
12
12
|
const UiFile = require("../icons/components/UiFile.cjs");
|
|
13
|
+
const UiAdd = require("../icons/components/UiAdd.cjs");
|
|
13
14
|
const DIFF_VIEW_OPTIONS = [
|
|
14
15
|
{ id: "unified", label: "Unified", icon: UiRows.UiRows, title: "Unified view" },
|
|
15
16
|
{ id: "split", label: "Split", icon: UiColumns.UiColumns, title: "Split view" }
|
|
@@ -27,7 +28,8 @@ const MARKER_TONE = {
|
|
|
27
28
|
const MARKER = { context: "", add: "+", remove: "-" };
|
|
28
29
|
function CodeDiff(props) {
|
|
29
30
|
const { language, view: viewProp = "unified", showLineNumbers = true, bare = false, className } = props;
|
|
30
|
-
const { unified, original, modified } = props;
|
|
31
|
+
const { unified, original, modified, onLineAction, lineWidgets } = props;
|
|
32
|
+
const annotations = { onLineAction, lineWidgets };
|
|
31
33
|
const [view, setView] = react.useState(viewProp);
|
|
32
34
|
const hunks = react.useMemo(
|
|
33
35
|
() => unified !== void 0 ? codeDiff.parseUnifiedDiff(unified) : codeDiff.computeLineDiff(original ?? "", modified ?? ""),
|
|
@@ -62,7 +64,7 @@ function CodeDiff(props) {
|
|
|
62
64
|
lastPath = hunk.path;
|
|
63
65
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
64
66
|
filePath && /* @__PURE__ */ jsxRuntime.jsx(FileHeader, { path: filePath }),
|
|
65
|
-
view === "split" ? /* @__PURE__ */ jsxRuntime.jsx(SplitHunk, { hunk, showLineNumbers }) : /* @__PURE__ */ jsxRuntime.jsx(UnifiedHunk, { hunk, showLineNumbers })
|
|
67
|
+
view === "split" ? /* @__PURE__ */ jsxRuntime.jsx(SplitHunk, { hunk, showLineNumbers, annotations }) : /* @__PURE__ */ jsxRuntime.jsx(UnifiedHunk, { hunk, showLineNumbers, annotations })
|
|
66
68
|
] }, index);
|
|
67
69
|
});
|
|
68
70
|
if (bare) {
|
|
@@ -114,32 +116,96 @@ function resolveHunks(hunks, oldTokens, newTokens) {
|
|
|
114
116
|
})
|
|
115
117
|
}));
|
|
116
118
|
}
|
|
117
|
-
function
|
|
119
|
+
function lineHasPosition(line, side, number) {
|
|
120
|
+
if (side === "old") return line.type !== "add" && line.oldNumber === number;
|
|
121
|
+
return line.type !== "remove" && line.newNumber === number;
|
|
122
|
+
}
|
|
123
|
+
function WidgetRows({ widgets }) {
|
|
124
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: widgets.map((widget) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
125
|
+
"div",
|
|
126
|
+
{
|
|
127
|
+
"data-diff-widget": widget.key,
|
|
128
|
+
className: "whitespace-normal border-y border-border bg-background px-3 py-2 font-sans text-sm leading-normal text-foreground",
|
|
129
|
+
children: widget.node
|
|
130
|
+
},
|
|
131
|
+
widget.key
|
|
132
|
+
)) });
|
|
133
|
+
}
|
|
134
|
+
function UnifiedHunk({ hunk, showLineNumbers, annotations }) {
|
|
135
|
+
const { onLineAction, lineWidgets } = annotations;
|
|
118
136
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
119
137
|
hunk.header && /* @__PURE__ */ jsxRuntime.jsx(HunkHeader, { header: hunk.header }),
|
|
120
138
|
hunk.lines.map((resolved, index) => {
|
|
121
139
|
const { line } = resolved;
|
|
122
140
|
const tokens = line.type === "remove" ? resolved.oldTokens : resolved.newTokens;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
141
|
+
const actionSide = line.type === "remove" ? "old" : "new";
|
|
142
|
+
const widgets = lineWidgets == null ? void 0 : lineWidgets.filter((w) => lineHasPosition(line, w.side, w.line));
|
|
143
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
144
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("group flex", ROW_TINT[line.type]), "data-diff-line": line.type, children: [
|
|
145
|
+
showLineNumbers && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
146
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
147
|
+
Gutter,
|
|
148
|
+
{
|
|
149
|
+
value: line.oldNumber,
|
|
150
|
+
line,
|
|
151
|
+
side: "old",
|
|
152
|
+
actionSide,
|
|
153
|
+
onLineAction
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
157
|
+
Gutter,
|
|
158
|
+
{
|
|
159
|
+
value: line.newNumber,
|
|
160
|
+
line,
|
|
161
|
+
side: "new",
|
|
162
|
+
actionSide,
|
|
163
|
+
onLineAction
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
] }),
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx(Marker, { type: line.type }),
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "whitespace-pre pl-1 pr-3", children: /* @__PURE__ */ jsxRuntime.jsx(HighlightedTokens.HighlightedTokens, { tokens, content: line.content }) })
|
|
127
169
|
] }),
|
|
128
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
129
|
-
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "whitespace-pre pl-1 pr-3", children: /* @__PURE__ */ jsxRuntime.jsx(HighlightedTokens.HighlightedTokens, { tokens, content: line.content }) })
|
|
170
|
+
widgets && /* @__PURE__ */ jsxRuntime.jsx(WidgetRows, { widgets })
|
|
130
171
|
] }, index);
|
|
131
172
|
})
|
|
132
173
|
] });
|
|
133
174
|
}
|
|
134
|
-
function SplitHunk({ hunk, showLineNumbers }) {
|
|
175
|
+
function SplitHunk({ hunk, showLineNumbers, annotations }) {
|
|
135
176
|
const pairs = react.useMemo(() => pairLines(hunk.lines), [hunk.lines]);
|
|
177
|
+
const { onLineAction, lineWidgets } = annotations;
|
|
136
178
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
137
179
|
hunk.header && /* @__PURE__ */ jsxRuntime.jsx(HunkHeader, { header: hunk.header }),
|
|
138
|
-
pairs.map((pair, index) =>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
180
|
+
pairs.map((pair, index) => {
|
|
181
|
+
const widgets = lineWidgets == null ? void 0 : lineWidgets.filter(
|
|
182
|
+
(w) => pair.left !== void 0 && lineHasPosition(pair.left.line, w.side, w.line) && w.side === "old" || pair.right !== void 0 && lineHasPosition(pair.right.line, w.side, w.line) && w.side === "new"
|
|
183
|
+
);
|
|
184
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex", children: [
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
187
|
+
SplitCell,
|
|
188
|
+
{
|
|
189
|
+
resolved: pair.left,
|
|
190
|
+
side: "old",
|
|
191
|
+
showLineNumbers,
|
|
192
|
+
onLineAction
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "w-px shrink-0 bg-border" }),
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
197
|
+
SplitCell,
|
|
198
|
+
{
|
|
199
|
+
resolved: pair.right,
|
|
200
|
+
side: "new",
|
|
201
|
+
showLineNumbers,
|
|
202
|
+
onLineAction
|
|
203
|
+
}
|
|
204
|
+
)
|
|
205
|
+
] }),
|
|
206
|
+
widgets && /* @__PURE__ */ jsxRuntime.jsx(WidgetRows, { widgets })
|
|
207
|
+
] }, index);
|
|
208
|
+
})
|
|
143
209
|
] });
|
|
144
210
|
}
|
|
145
211
|
function pairLines(lines) {
|
|
@@ -166,7 +232,8 @@ function pairLines(lines) {
|
|
|
166
232
|
function SplitCell({
|
|
167
233
|
resolved,
|
|
168
234
|
side,
|
|
169
|
-
showLineNumbers
|
|
235
|
+
showLineNumbers,
|
|
236
|
+
onLineAction
|
|
170
237
|
}) {
|
|
171
238
|
if (!resolved) return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1" });
|
|
172
239
|
const { line } = resolved;
|
|
@@ -174,11 +241,18 @@ function SplitCell({
|
|
|
174
241
|
const type = active ? line.type : "context";
|
|
175
242
|
const number = side === "old" ? line.oldNumber : line.newNumber;
|
|
176
243
|
const tokens = side === "old" ? resolved.oldTokens : resolved.newTokens;
|
|
177
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
244
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
245
|
+
"div",
|
|
246
|
+
{
|
|
247
|
+
className: utils.cn("group flex min-w-0 flex-1", active && ROW_TINT[line.type]),
|
|
248
|
+
"data-diff-line": type,
|
|
249
|
+
children: [
|
|
250
|
+
showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx(Gutter, { value: number, line, side, actionSide: side, onLineAction }),
|
|
251
|
+
/* @__PURE__ */ jsxRuntime.jsx(Marker, { type }),
|
|
252
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { className: "min-w-0 whitespace-pre pl-1 pr-3", children: /* @__PURE__ */ jsxRuntime.jsx(HighlightedTokens.HighlightedTokens, { tokens, content: line.content }) })
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
);
|
|
182
256
|
}
|
|
183
257
|
function FileHeader({ path }) {
|
|
184
258
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -196,8 +270,27 @@ function FileHeader({ path }) {
|
|
|
196
270
|
function HunkHeader({ header }) {
|
|
197
271
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "select-none bg-muted/60 px-2 py-0.5 text-muted-foreground", children: header });
|
|
198
272
|
}
|
|
199
|
-
function Gutter({
|
|
200
|
-
|
|
273
|
+
function Gutter({
|
|
274
|
+
value,
|
|
275
|
+
line,
|
|
276
|
+
side,
|
|
277
|
+
actionSide,
|
|
278
|
+
onLineAction
|
|
279
|
+
}) {
|
|
280
|
+
const showAction = onLineAction !== void 0 && value !== void 0 && side === actionSide;
|
|
281
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative w-10 shrink-0 select-none px-2 text-right tabular-nums text-muted-foreground", children: [
|
|
282
|
+
value ?? "",
|
|
283
|
+
showAction && /* @__PURE__ */ jsxRuntime.jsx(
|
|
284
|
+
"button",
|
|
285
|
+
{
|
|
286
|
+
type: "button",
|
|
287
|
+
"aria-label": `Comment on line ${value}`,
|
|
288
|
+
onClick: () => onLineAction({ side, line: value, content: line.content }),
|
|
289
|
+
className: "absolute inset-y-0 left-0.5 flex items-center rounded-sm bg-background text-primary opacity-0 hover:text-primary/80 focus-visible:opacity-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring group-hover:opacity-100",
|
|
290
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(UiAdd.UiAdd, { className: "size-3.5" })
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
] });
|
|
201
294
|
}
|
|
202
295
|
function Marker({ type }) {
|
|
203
296
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils.cn("w-4 shrink-0 select-none text-center", MARKER_TONE[type]), children: MARKER[type] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeDiff.cjs","sources":["../../src/data/CodeDiff.tsx"],"sourcesContent":["import { Fragment, useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { SegmentedControl, type SegmentedOption } from \"../components/SegmentedControl\";\nimport { UiColumns, UiFile, UiRows } from \"../icons\";\nimport {\n computeLineDiff,\n parseUnifiedDiff,\n type DiffHunk,\n type DiffLine,\n type DiffLineType,\n} from \"./code-diff\";\nimport { highlightToLines, type HighlightedLine } from \"./code-highlight\";\nimport { HighlightedTokens } from \"./HighlightedTokens\";\n\nexport type CodeDiffView = \"unified\" | \"split\";\n\n// Rows = stacked/unified; columns = side-by-side/split.\nconst DIFF_VIEW_OPTIONS: SegmentedOption<CodeDiffView>[] = [\n { id: \"unified\", label: \"Unified\", icon: UiRows, title: \"Unified view\" },\n { id: \"split\", label: \"Split\", icon: UiColumns, title: \"Split view\" },\n];\n\n// Either two blobs (diffed in-repo) or a ready unified-diff string (what\n// `GitDiffPanel` already receives). `never` on the absent keys keeps the shapes\n// mutually exclusive.\ntype CodeDiffInput =\n | { original: string; modified: string; unified?: never }\n | { unified: string; original?: never; modified?: never };\n\nexport type CodeDiffProps = CodeDiffInput & {\n /** Highlighter language hint, e.g. `typescript`, `go`, `python`. */\n language?: string | undefined;\n /** Unified (single column) or split (side-by-side). Defaults to `unified`. */\n view?: CodeDiffView | undefined;\n /** Show old/new line-number gutters. Defaults to `true`. */\n showLineNumbers?: boolean | undefined;\n /** Render only the rows — no border, background, or language header. */\n bare?: boolean | undefined;\n className?: string | undefined;\n};\n\ntype ResolvedLine = {\n line: DiffLine;\n oldTokens: HighlightedLine | undefined;\n newTokens: HighlightedLine | undefined;\n};\n\ntype ResolvedHunk = { header: string | undefined; path: string | undefined; lines: ResolvedLine[] };\n\n// Row background tint — theme-aware via `[[data-theme=dark]_&]` (plain `dark:`\n// compiles to prefers-color-scheme in the built dist and ignores `data-theme`).\nconst ROW_TINT: Record<DiffLineType, string | undefined> = {\n context: undefined,\n add: \"bg-emerald-500/10\",\n remove: \"bg-rose-500/10\",\n};\n\nconst MARKER_TONE: Record<DiffLineType, string> = {\n context: \"text-muted-foreground\",\n add: \"text-emerald-700 [[data-theme=dark]_&]:text-emerald-300\",\n remove: \"text-rose-700 [[data-theme=dark]_&]:text-rose-300\",\n};\n\nconst MARKER: Record<DiffLineType, string> = { context: \"\", add: \"+\", remove: \"-\" };\n\nexport function CodeDiff(props: CodeDiffProps) {\n const { language, view: viewProp = \"unified\", showLineNumbers = true, bare = false, className } = props;\n const { unified, original, modified } = props;\n\n // `view` prop seeds the default; the header toggle then owns it.\n const [view, setView] = useState<CodeDiffView>(viewProp);\n\n const hunks = useMemo<DiffHunk[]>(\n () =>\n unified !== undefined\n ? parseUnifiedDiff(unified)\n : computeLineDiff(original ?? \"\", modified ?? \"\"),\n [unified, original, modified],\n );\n\n const { oldSource, newSource } = useMemo(() => buildSides(hunks), [hunks]);\n\n // Raw first paint, highlighted tokens swap in — matches CodeBlock. `null`\n // means \"not highlighted\" (empty/unsupported/loading); rows fall back to plain\n // text token-by-token.\n const [tokens, setTokens] = useState<{\n old: HighlightedLine[] | null;\n mod: HighlightedLine[] | null;\n }>({ old: null, mod: null });\n\n useEffect(() => {\n if (!language) {\n setTokens({ old: null, mod: null });\n return;\n }\n let cancelled = false;\n Promise.all([\n highlightToLines(oldSource, { lang: language }),\n highlightToLines(newSource, { lang: language }),\n ]).then(([old, mod]) => {\n if (!cancelled) setTokens({ old, mod });\n });\n return () => {\n cancelled = true;\n };\n }, [language, oldSource, newSource]);\n\n const resolved = useMemo(\n () => resolveHunks(hunks, tokens.old, tokens.mod),\n [hunks, tokens],\n );\n\n // Only a diff that spans more than one file labels its hunks with the path —\n // a single-file diff's path is already known from its surrounding context.\n const multiFile =\n new Set(resolved.map((hunk) => hunk.path).filter((p) => p !== undefined)).size > 1;\n\n let lastPath: string | undefined;\n const rows = resolved.map((hunk, index) => {\n const filePath =\n multiFile && hunk.path !== undefined && hunk.path !== lastPath ? hunk.path : undefined;\n lastPath = hunk.path;\n return (\n <Fragment key={index}>\n {filePath && <FileHeader path={filePath} />}\n {view === \"split\" ? (\n <SplitHunk hunk={hunk} showLineNumbers={showLineNumbers} />\n ) : (\n <UnifiedHunk hunk={hunk} showLineNumbers={showLineNumbers} />\n )}\n </Fragment>\n );\n });\n\n if (bare) {\n return (\n <div className={cn(\"overflow-x-auto font-mono text-xs leading-relaxed\", className)}>\n {rows}\n </div>\n );\n }\n return (\n <div className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}>\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1.5\">\n <span className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">\n {language || \"diff\"}\n </span>\n <SegmentedControl\n size=\"sm\"\n aria-label=\"Diff view\"\n value={view}\n onChange={setView}\n options={DIFF_VIEW_OPTIONS}\n />\n </div>\n <div className=\"overflow-x-auto font-mono text-xs leading-relaxed\">{rows}</div>\n </div>\n );\n}\n\n// Reconstruct the full old side (context + remove) and new side (context + add)\n// as text — highlighting each side as a coherent blob so grammar state is intact.\nfunction buildSides(hunks: DiffHunk[]): { oldSource: string; newSource: string } {\n const oldLines: string[] = [];\n const newLines: string[] = [];\n for (const hunk of hunks) {\n for (const line of hunk.lines) {\n if (line.type !== \"add\") oldLines.push(line.content);\n if (line.type !== \"remove\") newLines.push(line.content);\n }\n }\n return { oldSource: oldLines.join(\"\\n\"), newSource: newLines.join(\"\\n\") };\n}\n\n// Map each diff line to its highlighted tokens via a sequential cursor per side\n// (not absolute line number, so unified-diff gaps between hunks stay aligned).\nfunction resolveHunks(\n hunks: DiffHunk[],\n oldTokens: HighlightedLine[] | null,\n newTokens: HighlightedLine[] | null,\n): ResolvedHunk[] {\n let oldCursor = 0;\n let newCursor = 0;\n return hunks.map((hunk) => ({\n header: hunk.header,\n path: hunk.path,\n lines: hunk.lines.map((line) => {\n const resolved: ResolvedLine = {\n line,\n oldTokens: line.type === \"add\" ? undefined : oldTokens?.[oldCursor],\n newTokens: line.type === \"remove\" ? undefined : newTokens?.[newCursor],\n };\n if (line.type !== \"add\") oldCursor += 1;\n if (line.type !== \"remove\") newCursor += 1;\n return resolved;\n }),\n }));\n}\n\nfunction UnifiedHunk({ hunk, showLineNumbers }: { hunk: ResolvedHunk; showLineNumbers: boolean }) {\n return (\n <>\n {hunk.header && <HunkHeader header={hunk.header} />}\n {hunk.lines.map((resolved, index) => {\n const { line } = resolved;\n const tokens = line.type === \"remove\" ? resolved.oldTokens : resolved.newTokens;\n return (\n <div key={index} className={cn(\"flex\", ROW_TINT[line.type])} data-diff-line={line.type}>\n {showLineNumbers && (\n <>\n <Gutter value={line.oldNumber} />\n <Gutter value={line.newNumber} />\n </>\n )}\n <Marker type={line.type} />\n <code className=\"whitespace-pre pl-1 pr-3\">\n <HighlightedTokens tokens={tokens} content={line.content} />\n </code>\n </div>\n );\n })}\n </>\n );\n}\n\nfunction SplitHunk({ hunk, showLineNumbers }: { hunk: ResolvedHunk; showLineNumbers: boolean }) {\n const pairs = useMemo(() => pairLines(hunk.lines), [hunk.lines]);\n return (\n <>\n {hunk.header && <HunkHeader header={hunk.header} />}\n {pairs.map((pair, index) => (\n <div key={index} className=\"flex\">\n <SplitCell resolved={pair.left} side=\"old\" showLineNumbers={showLineNumbers} />\n <span aria-hidden className=\"w-px shrink-0 bg-border\" />\n <SplitCell resolved={pair.right} side=\"new\" showLineNumbers={showLineNumbers} />\n </div>\n ))}\n </>\n );\n}\n\ntype SplitPair = { left: ResolvedLine | undefined; right: ResolvedLine | undefined };\n\n// Pair consecutive remove/add runs (remove[i] ↔ add[i]); leftovers get a blank\n// opposite cell. Context is one aligned row on both sides.\nfunction pairLines(lines: ResolvedLine[]): SplitPair[] {\n const pairs: SplitPair[] = [];\n let removes: ResolvedLine[] = [];\n let adds: ResolvedLine[] = [];\n const flush = () => {\n const max = Math.max(removes.length, adds.length);\n for (let i = 0; i < max; i++) pairs.push({ left: removes[i], right: adds[i] });\n removes = [];\n adds = [];\n };\n for (const resolved of lines) {\n if (resolved.line.type === \"remove\") removes.push(resolved);\n else if (resolved.line.type === \"add\") adds.push(resolved);\n else {\n flush();\n pairs.push({ left: resolved, right: resolved });\n }\n }\n flush();\n return pairs;\n}\n\nfunction SplitCell({\n resolved,\n side,\n showLineNumbers,\n}: {\n resolved: ResolvedLine | undefined;\n side: \"old\" | \"new\";\n showLineNumbers: boolean;\n}) {\n if (!resolved) return <div className=\"min-w-0 flex-1\" />;\n const { line } = resolved;\n const active =\n (side === \"old\" && line.type === \"remove\") || (side === \"new\" && line.type === \"add\");\n const type: DiffLineType = active ? line.type : \"context\";\n const number = side === \"old\" ? line.oldNumber : line.newNumber;\n const tokens = side === \"old\" ? resolved.oldTokens : resolved.newTokens;\n return (\n <div className={cn(\"flex min-w-0 flex-1\", active && ROW_TINT[line.type])} data-diff-line={type}>\n {showLineNumbers && <Gutter value={number} />}\n <Marker type={type} />\n <code className=\"min-w-0 whitespace-pre pl-1 pr-3\">\n <HighlightedTokens tokens={tokens} content={line.content} />\n </code>\n </div>\n );\n}\n\nfunction FileHeader({ path }: { path: string }) {\n return (\n <div\n data-diff-file={path}\n className=\"flex items-center gap-1.5 border-b border-border bg-muted px-2 py-1 font-medium text-foreground\"\n >\n <UiFile className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{path}</span>\n </div>\n );\n}\n\nfunction HunkHeader({ header }: { header: string }) {\n return (\n <div className=\"select-none bg-muted/60 px-2 py-0.5 text-muted-foreground\">{header}</div>\n );\n}\n\nfunction Gutter({ value }: { value: number | undefined }) {\n return (\n <span className=\"w-10 shrink-0 select-none px-2 text-right tabular-nums text-muted-foreground\">\n {value ?? \"\"}\n </span>\n );\n}\n\nfunction Marker({ type }: { type: DiffLineType }) {\n return (\n <span className={cn(\"w-4 shrink-0 select-none text-center\", MARKER_TONE[type])}>\n {MARKER[type]}\n </span>\n );\n}\n"],"names":["UiRows","UiColumns","useState","useMemo","parseUnifiedDiff","computeLineDiff","useEffect","highlightToLines","jsxs","Fragment","jsx","cn","SegmentedControl","HighlightedTokens","UiFile"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeDiff.cjs","sources":["../../src/data/CodeDiff.tsx"],"sourcesContent":["import { Fragment, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { SegmentedControl, type SegmentedOption } from \"../components/SegmentedControl\";\nimport { UiAdd, UiColumns, UiFile, UiRows } from \"../icons\";\nimport {\n computeLineDiff,\n parseUnifiedDiff,\n type DiffHunk,\n type DiffLine,\n type DiffLineType,\n} from \"./code-diff\";\nimport { highlightToLines, type HighlightedLine } from \"./code-highlight\";\nimport { HighlightedTokens } from \"./HighlightedTokens\";\n\nexport type CodeDiffView = \"unified\" | \"split\";\n\n// Rows = stacked/unified; columns = side-by-side/split.\nconst DIFF_VIEW_OPTIONS: SegmentedOption<CodeDiffView>[] = [\n { id: \"unified\", label: \"Unified\", icon: UiRows, title: \"Unified view\" },\n { id: \"split\", label: \"Split\", icon: UiColumns, title: \"Split view\" },\n];\n\n// Either two blobs (diffed in-repo) or a ready unified-diff string (what\n// `GitDiffPanel` already receives). `never` on the absent keys keeps the shapes\n// mutually exclusive.\ntype CodeDiffInput =\n | { original: string; modified: string; unified?: never }\n | { unified: string; original?: never; modified?: never };\n\nexport type DiffSide = \"old\" | \"new\";\n\n/** The diff line a gutter \"+\" button was clicked on. */\nexport interface DiffLineTarget {\n side: DiffSide;\n line: number;\n content: string;\n}\n\n/** A node rendered as a full-width row directly below the row at `(side, line)`. */\nexport interface DiffLineWidget {\n key: string;\n side: DiffSide;\n line: number;\n node: ReactNode;\n}\n\ntype LineAnnotations = {\n onLineAction: ((target: DiffLineTarget) => void) | undefined;\n lineWidgets: DiffLineWidget[] | undefined;\n};\n\nexport type CodeDiffProps = CodeDiffInput & {\n /**\n * When set, every numbered line shows a \"+\" button in its gutter (on row hover\n * or keyboard focus). Added/context lines report side `new`, deleted lines\n * `old`; in split view the left column is `old` and the right `new`.\n */\n onLineAction?: ((target: DiffLineTarget) => void) | undefined;\n /**\n * Rendered as a full-width row directly below the row matching `(side, line)`,\n * in array order. A context line matches both its `old` and `new` number.\n */\n lineWidgets?: DiffLineWidget[] | undefined;\n /** Highlighter language hint, e.g. `typescript`, `go`, `python`. */\n language?: string | undefined;\n /** Unified (single column) or split (side-by-side). Defaults to `unified`. */\n view?: CodeDiffView | undefined;\n /** Show old/new line-number gutters. Defaults to `true`. */\n showLineNumbers?: boolean | undefined;\n /** Render only the rows — no border, background, or language header. */\n bare?: boolean | undefined;\n className?: string | undefined;\n};\n\ntype ResolvedLine = {\n line: DiffLine;\n oldTokens: HighlightedLine | undefined;\n newTokens: HighlightedLine | undefined;\n};\n\ntype ResolvedHunk = { header: string | undefined; path: string | undefined; lines: ResolvedLine[] };\n\n// Row background tint — theme-aware via `[[data-theme=dark]_&]` (plain `dark:`\n// compiles to prefers-color-scheme in the built dist and ignores `data-theme`).\nconst ROW_TINT: Record<DiffLineType, string | undefined> = {\n context: undefined,\n add: \"bg-emerald-500/10\",\n remove: \"bg-rose-500/10\",\n};\n\nconst MARKER_TONE: Record<DiffLineType, string> = {\n context: \"text-muted-foreground\",\n add: \"text-emerald-700 [[data-theme=dark]_&]:text-emerald-300\",\n remove: \"text-rose-700 [[data-theme=dark]_&]:text-rose-300\",\n};\n\nconst MARKER: Record<DiffLineType, string> = { context: \"\", add: \"+\", remove: \"-\" };\n\nexport function CodeDiff(props: CodeDiffProps) {\n const { language, view: viewProp = \"unified\", showLineNumbers = true, bare = false, className } = props;\n const { unified, original, modified, onLineAction, lineWidgets } = props;\n const annotations: LineAnnotations = { onLineAction, lineWidgets };\n\n // `view` prop seeds the default; the header toggle then owns it.\n const [view, setView] = useState<CodeDiffView>(viewProp);\n\n const hunks = useMemo<DiffHunk[]>(\n () =>\n unified !== undefined\n ? parseUnifiedDiff(unified)\n : computeLineDiff(original ?? \"\", modified ?? \"\"),\n [unified, original, modified],\n );\n\n const { oldSource, newSource } = useMemo(() => buildSides(hunks), [hunks]);\n\n // Raw first paint, highlighted tokens swap in — matches CodeBlock. `null`\n // means \"not highlighted\" (empty/unsupported/loading); rows fall back to plain\n // text token-by-token.\n const [tokens, setTokens] = useState<{\n old: HighlightedLine[] | null;\n mod: HighlightedLine[] | null;\n }>({ old: null, mod: null });\n\n useEffect(() => {\n if (!language) {\n setTokens({ old: null, mod: null });\n return;\n }\n let cancelled = false;\n Promise.all([\n highlightToLines(oldSource, { lang: language }),\n highlightToLines(newSource, { lang: language }),\n ]).then(([old, mod]) => {\n if (!cancelled) setTokens({ old, mod });\n });\n return () => {\n cancelled = true;\n };\n }, [language, oldSource, newSource]);\n\n const resolved = useMemo(\n () => resolveHunks(hunks, tokens.old, tokens.mod),\n [hunks, tokens],\n );\n\n // Only a diff that spans more than one file labels its hunks with the path —\n // a single-file diff's path is already known from its surrounding context.\n const multiFile =\n new Set(resolved.map((hunk) => hunk.path).filter((p) => p !== undefined)).size > 1;\n\n let lastPath: string | undefined;\n const rows = resolved.map((hunk, index) => {\n const filePath =\n multiFile && hunk.path !== undefined && hunk.path !== lastPath ? hunk.path : undefined;\n lastPath = hunk.path;\n return (\n <Fragment key={index}>\n {filePath && <FileHeader path={filePath} />}\n {view === \"split\" ? (\n <SplitHunk hunk={hunk} showLineNumbers={showLineNumbers} annotations={annotations} />\n ) : (\n <UnifiedHunk hunk={hunk} showLineNumbers={showLineNumbers} annotations={annotations} />\n )}\n </Fragment>\n );\n });\n\n if (bare) {\n return (\n <div className={cn(\"overflow-x-auto font-mono text-xs leading-relaxed\", className)}>\n {rows}\n </div>\n );\n }\n return (\n <div className={cn(\"overflow-hidden rounded-md border border-border bg-muted/40\", className)}>\n <div className=\"flex items-center justify-between gap-2 border-b border-border px-3 py-1.5\">\n <span className=\"text-[11px] uppercase tracking-wide text-muted-foreground\">\n {language || \"diff\"}\n </span>\n <SegmentedControl\n size=\"sm\"\n aria-label=\"Diff view\"\n value={view}\n onChange={setView}\n options={DIFF_VIEW_OPTIONS}\n />\n </div>\n <div className=\"overflow-x-auto font-mono text-xs leading-relaxed\">{rows}</div>\n </div>\n );\n}\n\n// Reconstruct the full old side (context + remove) and new side (context + add)\n// as text — highlighting each side as a coherent blob so grammar state is intact.\nfunction buildSides(hunks: DiffHunk[]): { oldSource: string; newSource: string } {\n const oldLines: string[] = [];\n const newLines: string[] = [];\n for (const hunk of hunks) {\n for (const line of hunk.lines) {\n if (line.type !== \"add\") oldLines.push(line.content);\n if (line.type !== \"remove\") newLines.push(line.content);\n }\n }\n return { oldSource: oldLines.join(\"\\n\"), newSource: newLines.join(\"\\n\") };\n}\n\n// Map each diff line to its highlighted tokens via a sequential cursor per side\n// (not absolute line number, so unified-diff gaps between hunks stay aligned).\nfunction resolveHunks(\n hunks: DiffHunk[],\n oldTokens: HighlightedLine[] | null,\n newTokens: HighlightedLine[] | null,\n): ResolvedHunk[] {\n let oldCursor = 0;\n let newCursor = 0;\n return hunks.map((hunk) => ({\n header: hunk.header,\n path: hunk.path,\n lines: hunk.lines.map((line) => {\n const resolved: ResolvedLine = {\n line,\n oldTokens: line.type === \"add\" ? undefined : oldTokens?.[oldCursor],\n newTokens: line.type === \"remove\" ? undefined : newTokens?.[newCursor],\n };\n if (line.type !== \"add\") oldCursor += 1;\n if (line.type !== \"remove\") newCursor += 1;\n return resolved;\n }),\n }));\n}\n\ntype HunkProps = {\n hunk: ResolvedHunk;\n showLineNumbers: boolean;\n annotations: LineAnnotations;\n};\n\n// Which side of `line` a widget at (side, number) attaches to: context lines\n// carry both numbers, add lines only `new`, remove lines only `old`.\nfunction lineHasPosition(line: DiffLine, side: DiffSide, number: number): boolean {\n if (side === \"old\") return line.type !== \"add\" && line.oldNumber === number;\n return line.type !== \"remove\" && line.newNumber === number;\n}\n\nfunction WidgetRows({ widgets }: { widgets: DiffLineWidget[] }) {\n return (\n <>\n {widgets.map((widget) => (\n <div\n key={widget.key}\n data-diff-widget={widget.key}\n className=\"whitespace-normal border-y border-border bg-background px-3 py-2 font-sans text-sm leading-normal text-foreground\"\n >\n {widget.node}\n </div>\n ))}\n </>\n );\n}\n\nfunction UnifiedHunk({ hunk, showLineNumbers, annotations }: HunkProps) {\n const { onLineAction, lineWidgets } = annotations;\n return (\n <>\n {hunk.header && <HunkHeader header={hunk.header} />}\n {hunk.lines.map((resolved, index) => {\n const { line } = resolved;\n const tokens = line.type === \"remove\" ? resolved.oldTokens : resolved.newTokens;\n const actionSide: DiffSide = line.type === \"remove\" ? \"old\" : \"new\";\n const widgets = lineWidgets?.filter((w) => lineHasPosition(line, w.side, w.line));\n return (\n <Fragment key={index}>\n <div className={cn(\"group flex\", ROW_TINT[line.type])} data-diff-line={line.type}>\n {showLineNumbers && (\n <>\n <Gutter\n value={line.oldNumber}\n line={line}\n side=\"old\"\n actionSide={actionSide}\n onLineAction={onLineAction}\n />\n <Gutter\n value={line.newNumber}\n line={line}\n side=\"new\"\n actionSide={actionSide}\n onLineAction={onLineAction}\n />\n </>\n )}\n <Marker type={line.type} />\n <code className=\"whitespace-pre pl-1 pr-3\">\n <HighlightedTokens tokens={tokens} content={line.content} />\n </code>\n </div>\n {widgets && <WidgetRows widgets={widgets} />}\n </Fragment>\n );\n })}\n </>\n );\n}\n\nfunction SplitHunk({ hunk, showLineNumbers, annotations }: HunkProps) {\n const pairs = useMemo(() => pairLines(hunk.lines), [hunk.lines]);\n const { onLineAction, lineWidgets } = annotations;\n return (\n <>\n {hunk.header && <HunkHeader header={hunk.header} />}\n {pairs.map((pair, index) => {\n const widgets = lineWidgets?.filter(\n (w) =>\n (pair.left !== undefined && lineHasPosition(pair.left.line, w.side, w.line) && w.side === \"old\") ||\n (pair.right !== undefined && lineHasPosition(pair.right.line, w.side, w.line) && w.side === \"new\"),\n );\n return (\n <Fragment key={index}>\n <div className=\"flex\">\n <SplitCell\n resolved={pair.left}\n side=\"old\"\n showLineNumbers={showLineNumbers}\n onLineAction={onLineAction}\n />\n <span aria-hidden className=\"w-px shrink-0 bg-border\" />\n <SplitCell\n resolved={pair.right}\n side=\"new\"\n showLineNumbers={showLineNumbers}\n onLineAction={onLineAction}\n />\n </div>\n {widgets && <WidgetRows widgets={widgets} />}\n </Fragment>\n );\n })}\n </>\n );\n}\n\ntype SplitPair = { left: ResolvedLine | undefined; right: ResolvedLine | undefined };\n\n// Pair consecutive remove/add runs (remove[i] ↔ add[i]); leftovers get a blank\n// opposite cell. Context is one aligned row on both sides.\nfunction pairLines(lines: ResolvedLine[]): SplitPair[] {\n const pairs: SplitPair[] = [];\n let removes: ResolvedLine[] = [];\n let adds: ResolvedLine[] = [];\n const flush = () => {\n const max = Math.max(removes.length, adds.length);\n for (let i = 0; i < max; i++) pairs.push({ left: removes[i], right: adds[i] });\n removes = [];\n adds = [];\n };\n for (const resolved of lines) {\n if (resolved.line.type === \"remove\") removes.push(resolved);\n else if (resolved.line.type === \"add\") adds.push(resolved);\n else {\n flush();\n pairs.push({ left: resolved, right: resolved });\n }\n }\n flush();\n return pairs;\n}\n\nfunction SplitCell({\n resolved,\n side,\n showLineNumbers,\n onLineAction,\n}: {\n resolved: ResolvedLine | undefined;\n side: DiffSide;\n showLineNumbers: boolean;\n onLineAction: LineAnnotations[\"onLineAction\"];\n}) {\n if (!resolved) return <div className=\"min-w-0 flex-1\" />;\n const { line } = resolved;\n const active =\n (side === \"old\" && line.type === \"remove\") || (side === \"new\" && line.type === \"add\");\n const type: DiffLineType = active ? line.type : \"context\";\n const number = side === \"old\" ? line.oldNumber : line.newNumber;\n const tokens = side === \"old\" ? resolved.oldTokens : resolved.newTokens;\n return (\n <div\n className={cn(\"group flex min-w-0 flex-1\", active && ROW_TINT[line.type])}\n data-diff-line={type}\n >\n {showLineNumbers && (\n <Gutter value={number} line={line} side={side} actionSide={side} onLineAction={onLineAction} />\n )}\n <Marker type={type} />\n <code className=\"min-w-0 whitespace-pre pl-1 pr-3\">\n <HighlightedTokens tokens={tokens} content={line.content} />\n </code>\n </div>\n );\n}\n\nfunction FileHeader({ path }: { path: string }) {\n return (\n <div\n data-diff-file={path}\n className=\"flex items-center gap-1.5 border-b border-border bg-muted px-2 py-1 font-medium text-foreground\"\n >\n <UiFile className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{path}</span>\n </div>\n );\n}\n\nfunction HunkHeader({ header }: { header: string }) {\n return (\n <div className=\"select-none bg-muted/60 px-2 py-0.5 text-muted-foreground\">{header}</div>\n );\n}\n\n// `side` is the number this gutter shows; the \"+\" button only renders in the\n// `actionSide` gutter so a unified row (two gutters) exposes exactly one.\nfunction Gutter({\n value,\n line,\n side,\n actionSide,\n onLineAction,\n}: {\n value: number | undefined;\n line: DiffLine;\n side: DiffSide;\n actionSide: DiffSide;\n onLineAction: LineAnnotations[\"onLineAction\"];\n}) {\n const showAction = onLineAction !== undefined && value !== undefined && side === actionSide;\n return (\n <span className=\"relative w-10 shrink-0 select-none px-2 text-right tabular-nums text-muted-foreground\">\n {value ?? \"\"}\n {showAction && (\n <button\n type=\"button\"\n aria-label={`Comment on line ${value}`}\n onClick={() => onLineAction({ side, line: value, content: line.content })}\n className=\"absolute inset-y-0 left-0.5 flex items-center rounded-sm bg-background text-primary opacity-0 hover:text-primary/80 focus-visible:opacity-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring group-hover:opacity-100\"\n >\n <UiAdd className=\"size-3.5\" />\n </button>\n )}\n </span>\n );\n}\n\nfunction Marker({ type }: { type: DiffLineType }) {\n return (\n <span className={cn(\"w-4 shrink-0 select-none text-center\", MARKER_TONE[type])}>\n {MARKER[type]}\n </span>\n );\n}\n"],"names":["UiRows","UiColumns","useState","useMemo","parseUnifiedDiff","computeLineDiff","useEffect","highlightToLines","jsxs","Fragment","jsx","cn","SegmentedControl","HighlightedTokens","UiFile","UiAdd"],"mappings":";;;;;;;;;;;;;AAiBA,MAAM,oBAAqD;AAAA,EACzD,EAAE,IAAI,WAAW,OAAO,WAAW,MAAMA,OAAAA,QAAQ,OAAO,eAAA;AAAA,EACxD,EAAE,IAAI,SAAS,OAAO,SAAS,MAAMC,UAAAA,WAAW,OAAO,aAAA;AACzD;AAgEA,MAAM,WAAqD;AAAA,EACzD,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AACV;AAEA,MAAM,cAA4C;AAAA,EAChD,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AACV;AAEA,MAAM,SAAuC,EAAE,SAAS,IAAI,KAAK,KAAK,QAAQ,IAAA;AAEvE,SAAS,SAAS,OAAsB;AAC7C,QAAM,EAAE,UAAU,MAAM,WAAW,WAAW,kBAAkB,MAAM,OAAO,OAAO,UAAA,IAAc;AAClG,QAAM,EAAE,SAAS,UAAU,UAAU,cAAc,gBAAgB;AACnE,QAAM,cAA+B,EAAE,cAAc,YAAA;AAGrD,QAAM,CAAC,MAAM,OAAO,IAAIC,MAAAA,SAAuB,QAAQ;AAEvD,QAAM,QAAQC,MAAAA;AAAAA,IACZ,MACE,YAAY,SACRC,SAAAA,iBAAiB,OAAO,IACxBC,SAAAA,gBAAgB,YAAY,IAAI,YAAY,EAAE;AAAA,IACpD,CAAC,SAAS,UAAU,QAAQ;AAAA,EAAA;AAG9B,QAAM,EAAE,WAAW,UAAA,IAAcF,MAAAA,QAAQ,MAAM,WAAW,KAAK,GAAG,CAAC,KAAK,CAAC;AAKzE,QAAM,CAAC,QAAQ,SAAS,IAAID,MAAAA,SAGzB,EAAE,KAAK,MAAM,KAAK,MAAM;AAE3BI,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,UAAU;AACb,gBAAU,EAAE,KAAK,MAAM,KAAK,MAAM;AAClC;AAAA,IACF;AACA,QAAI,YAAY;AAChB,YAAQ,IAAI;AAAA,MACVC,cAAAA,iBAAiB,WAAW,EAAE,MAAM,UAAU;AAAA,MAC9CA,cAAAA,iBAAiB,WAAW,EAAE,MAAM,UAAU;AAAA,IAAA,CAC/C,EAAE,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM;AACtB,UAAI,CAAC,UAAW,WAAU,EAAE,KAAK,KAAK;AAAA,IACxC,CAAC;AACD,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,UAAU,WAAW,SAAS,CAAC;AAEnC,QAAM,WAAWJ,MAAAA;AAAAA,IACf,MAAM,aAAa,OAAO,OAAO,KAAK,OAAO,GAAG;AAAA,IAChD,CAAC,OAAO,MAAM;AAAA,EAAA;AAKhB,QAAM,YACJ,IAAI,IAAI,SAAS,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,OAAO,CAAC,MAAM,MAAM,MAAS,CAAC,EAAE,OAAO;AAEnF,MAAI;AACJ,QAAM,OAAO,SAAS,IAAI,CAAC,MAAM,UAAU;AACzC,UAAM,WACJ,aAAa,KAAK,SAAS,UAAa,KAAK,SAAS,WAAW,KAAK,OAAO;AAC/E,eAAW,KAAK;AAChB,WACEK,2BAAAA,KAACC,gBAAA,EACE,UAAA;AAAA,MAAA,YAAYC,2BAAAA,IAAC,YAAA,EAAW,MAAM,SAAA,CAAU;AAAA,MACxC,SAAS,UACRA,2BAAAA,IAAC,WAAA,EAAU,MAAY,iBAAkC,YAAA,CAA0B,IAEnFA,2BAAAA,IAAC,aAAA,EAAY,MAAY,iBAAkC,YAAA,CAA0B;AAAA,IAAA,EAAA,GAL1E,KAOf;AAAA,EAEJ,CAAC;AAED,MAAI,MAAM;AACR,0CACG,OAAA,EAAI,WAAWC,MAAAA,GAAG,qDAAqD,SAAS,GAC9E,UAAA,MACH;AAAA,EAEJ;AACA,yCACG,OAAA,EAAI,WAAWA,MAAAA,GAAG,+DAA+D,SAAS,GACzF,UAAA;AAAA,IAAAH,2BAAAA,KAAC,OAAA,EAAI,WAAU,8EACb,UAAA;AAAA,MAAAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,6DACb,UAAA,YAAY,QACf;AAAA,MACAA,2BAAAA;AAAAA,QAACE,iBAAAA;AAAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAW;AAAA,UACX,OAAO;AAAA,UACP,UAAU;AAAA,UACV,SAAS;AAAA,QAAA;AAAA,MAAA;AAAA,IACX,GACF;AAAA,IACAF,2BAAAA,IAAC,OAAA,EAAI,WAAU,qDAAqD,UAAA,KAAA,CAAK;AAAA,EAAA,GAC3E;AAEJ;AAIA,SAAS,WAAW,OAA6D;AAC/E,QAAM,WAAqB,CAAA;AAC3B,QAAM,WAAqB,CAAA;AAC3B,aAAW,QAAQ,OAAO;AACxB,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,SAAS,MAAO,UAAS,KAAK,KAAK,OAAO;AACnD,UAAI,KAAK,SAAS,SAAU,UAAS,KAAK,KAAK,OAAO;AAAA,IACxD;AAAA,EACF;AACA,SAAO,EAAE,WAAW,SAAS,KAAK,IAAI,GAAG,WAAW,SAAS,KAAK,IAAI,EAAA;AACxE;AAIA,SAAS,aACP,OACA,WACA,WACgB;AAChB,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,SAAO,MAAM,IAAI,CAAC,UAAU;AAAA,IAC1B,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,OAAO,KAAK,MAAM,IAAI,CAAC,SAAS;AAC9B,YAAM,WAAyB;AAAA,QAC7B;AAAA,QACA,WAAW,KAAK,SAAS,QAAQ,SAAY,uCAAY;AAAA,QACzD,WAAW,KAAK,SAAS,WAAW,SAAY,uCAAY;AAAA,MAAS;AAEvE,UAAI,KAAK,SAAS,MAAO,cAAa;AACtC,UAAI,KAAK,SAAS,SAAU,cAAa;AACzC,aAAO;AAAA,IACT,CAAC;AAAA,EAAA,EACD;AACJ;AAUA,SAAS,gBAAgB,MAAgB,MAAgB,QAAyB;AAChF,MAAI,SAAS,MAAO,QAAO,KAAK,SAAS,SAAS,KAAK,cAAc;AACrE,SAAO,KAAK,SAAS,YAAY,KAAK,cAAc;AACtD;AAEA,SAAS,WAAW,EAAE,WAA0C;AAC9D,SACEA,2BAAAA,IAAAD,WAAAA,UAAA,EACG,UAAA,QAAQ,IAAI,CAAC,WACZC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MAEC,oBAAkB,OAAO;AAAA,MACzB,WAAU;AAAA,MAET,UAAA,OAAO;AAAA,IAAA;AAAA,IAJH,OAAO;AAAA,EAAA,CAMf,GACH;AAEJ;AAEA,SAAS,YAAY,EAAE,MAAM,iBAAiB,eAA0B;AACtE,QAAM,EAAE,cAAc,YAAA,IAAgB;AACtC,SACEF,2BAAAA,KAAAC,qBAAA,EACG,UAAA;AAAA,IAAA,KAAK,UAAUC,+BAAC,YAAA,EAAW,QAAQ,KAAK,QAAQ;AAAA,IAChD,KAAK,MAAM,IAAI,CAAC,UAAU,UAAU;AACnC,YAAM,EAAE,SAAS;AACjB,YAAM,SAAS,KAAK,SAAS,WAAW,SAAS,YAAY,SAAS;AACtE,YAAM,aAAuB,KAAK,SAAS,WAAW,QAAQ;AAC9D,YAAM,UAAU,2CAAa,OAAO,CAAC,MAAM,gBAAgB,MAAM,EAAE,MAAM,EAAE,IAAI;AAC/E,aACEF,2BAAAA,KAACC,gBAAA,EACC,UAAA;AAAA,QAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAWG,MAAAA,GAAG,cAAc,SAAS,KAAK,IAAI,CAAC,GAAG,kBAAgB,KAAK,MACzE,UAAA;AAAA,UAAA,mBACCH,2BAAAA,KAAAC,qBAAA,EACE,UAAA;AAAA,YAAAC,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,KAAK;AAAA,gBACZ;AAAA,gBACA,MAAK;AAAA,gBACL;AAAA,gBACA;AAAA,cAAA;AAAA,YAAA;AAAA,YAEFA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,KAAK;AAAA,gBACZ;AAAA,gBACA,MAAK;AAAA,gBACL;AAAA,gBACA;AAAA,cAAA;AAAA,YAAA;AAAA,UACF,GACF;AAAA,UAEFA,2BAAAA,IAAC,QAAA,EAAO,MAAM,KAAK,KAAA,CAAM;AAAA,UACzBA,2BAAAA,IAAC,QAAA,EAAK,WAAU,4BACd,UAAAA,2BAAAA,IAACG,kBAAAA,qBAAkB,QAAgB,SAAS,KAAK,QAAA,CAAS,EAAA,CAC5D;AAAA,QAAA,GACF;AAAA,QACC,WAAWH,2BAAAA,IAAC,YAAA,EAAW,QAAA,CAAkB;AAAA,MAAA,EAAA,GAzB7B,KA0Bf;AAAA,IAEJ,CAAC;AAAA,EAAA,GACH;AAEJ;AAEA,SAAS,UAAU,EAAE,MAAM,iBAAiB,eAA0B;AACpE,QAAM,QAAQP,cAAQ,MAAM,UAAU,KAAK,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC;AAC/D,QAAM,EAAE,cAAc,YAAA,IAAgB;AACtC,SACEK,2BAAAA,KAAAC,qBAAA,EACG,UAAA;AAAA,IAAA,KAAK,UAAUC,+BAAC,YAAA,EAAW,QAAQ,KAAK,QAAQ;AAAA,IAChD,MAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,YAAM,UAAU,2CAAa;AAAA,QAC3B,CAAC,MACE,KAAK,SAAS,UAAa,gBAAgB,KAAK,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,SAAS,SACzF,KAAK,UAAU,UAAa,gBAAgB,KAAK,MAAM,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,SAAS;AAAA;AAEhG,aACEF,2BAAAA,KAACC,gBAAA,EACC,UAAA;AAAA,QAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,UAAAE,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,UAAU,KAAK;AAAA,cACf,MAAK;AAAA,cACL;AAAA,cACA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEFA,2BAAAA,IAAC,QAAA,EAAK,eAAW,MAAC,WAAU,2BAA0B;AAAA,UACtDA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,UAAU,KAAK;AAAA,cACf,MAAK;AAAA,cACL;AAAA,cACA;AAAA,YAAA;AAAA,UAAA;AAAA,QACF,GACF;AAAA,QACC,WAAWA,2BAAAA,IAAC,YAAA,EAAW,QAAA,CAAkB;AAAA,MAAA,EAAA,GAhB7B,KAiBf;AAAA,IAEJ,CAAC;AAAA,EAAA,GACH;AAEJ;AAMA,SAAS,UAAU,OAAoC;AACrD,QAAM,QAAqB,CAAA;AAC3B,MAAI,UAA0B,CAAA;AAC9B,MAAI,OAAuB,CAAA;AAC3B,QAAM,QAAQ,MAAM;AAClB,UAAM,MAAM,KAAK,IAAI,QAAQ,QAAQ,KAAK,MAAM;AAChD,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,KAAK,EAAE,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG;AAC7E,cAAU,CAAA;AACV,WAAO,CAAA;AAAA,EACT;AACA,aAAW,YAAY,OAAO;AAC5B,QAAI,SAAS,KAAK,SAAS,SAAU,SAAQ,KAAK,QAAQ;AAAA,aACjD,SAAS,KAAK,SAAS,MAAO,MAAK,KAAK,QAAQ;AAAA,SACpD;AACH,YAAA;AACA,YAAM,KAAK,EAAE,MAAM,UAAU,OAAO,UAAU;AAAA,IAChD;AAAA,EACF;AACA,QAAA;AACA,SAAO;AACT;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,MAAI,CAAC,SAAU,QAAOA,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBAAiB;AACtD,QAAM,EAAE,SAAS;AACjB,QAAM,SACH,SAAS,SAAS,KAAK,SAAS,YAAc,SAAS,SAAS,KAAK,SAAS;AACjF,QAAM,OAAqB,SAAS,KAAK,OAAO;AAChD,QAAM,SAAS,SAAS,QAAQ,KAAK,YAAY,KAAK;AACtD,QAAM,SAAS,SAAS,QAAQ,SAAS,YAAY,SAAS;AAC9D,SACEF,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWG,MAAAA,GAAG,6BAA6B,UAAU,SAAS,KAAK,IAAI,CAAC;AAAA,MACxE,kBAAgB;AAAA,MAEf,UAAA;AAAA,QAAA,mBACCD,2BAAAA,IAAC,UAAO,OAAO,QAAQ,MAAY,MAAY,YAAY,MAAM,aAAA,CAA4B;AAAA,QAE/FA,+BAAC,UAAO,MAAY;AAAA,QACpBA,2BAAAA,IAAC,QAAA,EAAK,WAAU,oCACd,UAAAA,2BAAAA,IAACG,kBAAAA,qBAAkB,QAAgB,SAAS,KAAK,QAAA,CAAS,EAAA,CAC5D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,WAAW,EAAE,QAA0B;AAC9C,SACEL,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,kBAAgB;AAAA,MAChB,WAAU;AAAA,MAEV,UAAA;AAAA,QAAAE,2BAAAA,IAACI,OAAAA,QAAA,EAAO,WAAU,0CAAA,CAA0C;AAAA,QAC5DJ,2BAAAA,IAAC,QAAA,EAAK,WAAU,YAAY,UAAA,KAAA,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGvC;AAEA,SAAS,WAAW,EAAE,UAA8B;AAClD,SACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,6DAA6D,UAAA,QAAO;AAEvF;AAIA,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,aAAa,iBAAiB,UAAa,UAAU,UAAa,SAAS;AACjF,SACEF,2BAAAA,KAAC,QAAA,EAAK,WAAU,yFACb,UAAA;AAAA,IAAA,SAAS;AAAA,IACT,cACCE,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,mBAAmB,KAAK;AAAA,QACpC,SAAS,MAAM,aAAa,EAAE,MAAM,MAAM,OAAO,SAAS,KAAK,SAAS;AAAA,QACxE,WAAU;AAAA,QAEV,UAAAA,2BAAAA,IAACK,MAAAA,OAAA,EAAM,WAAU,WAAA,CAAW;AAAA,MAAA;AAAA,IAAA;AAAA,EAC9B,GAEJ;AAEJ;AAEA,SAAS,OAAO,EAAE,QAAgC;AAChD,SACEL,2BAAAA,IAAC,QAAA,EAAK,WAAWC,MAAAA,GAAG,wCAAwC,YAAY,IAAI,CAAC,GAC1E,UAAA,OAAO,IAAI,EAAA,CACd;AAEJ;;"}
|
package/dist/data/CodeDiff.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
export type CodeDiffView = "unified" | "split";
|
|
2
3
|
type CodeDiffInput = {
|
|
3
4
|
original: string;
|
|
@@ -8,7 +9,32 @@ type CodeDiffInput = {
|
|
|
8
9
|
original?: never;
|
|
9
10
|
modified?: never;
|
|
10
11
|
};
|
|
12
|
+
export type DiffSide = "old" | "new";
|
|
13
|
+
/** The diff line a gutter "+" button was clicked on. */
|
|
14
|
+
export interface DiffLineTarget {
|
|
15
|
+
side: DiffSide;
|
|
16
|
+
line: number;
|
|
17
|
+
content: string;
|
|
18
|
+
}
|
|
19
|
+
/** A node rendered as a full-width row directly below the row at `(side, line)`. */
|
|
20
|
+
export interface DiffLineWidget {
|
|
21
|
+
key: string;
|
|
22
|
+
side: DiffSide;
|
|
23
|
+
line: number;
|
|
24
|
+
node: ReactNode;
|
|
25
|
+
}
|
|
11
26
|
export type CodeDiffProps = CodeDiffInput & {
|
|
27
|
+
/**
|
|
28
|
+
* When set, every numbered line shows a "+" button in its gutter (on row hover
|
|
29
|
+
* or keyboard focus). Added/context lines report side `new`, deleted lines
|
|
30
|
+
* `old`; in split view the left column is `old` and the right `new`.
|
|
31
|
+
*/
|
|
32
|
+
onLineAction?: ((target: DiffLineTarget) => void) | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Rendered as a full-width row directly below the row matching `(side, line)`,
|
|
35
|
+
* in array order. A context line matches both its `old` and `new` number.
|
|
36
|
+
*/
|
|
37
|
+
lineWidgets?: DiffLineWidget[] | undefined;
|
|
12
38
|
/** Highlighter language hint, e.g. `typescript`, `go`, `python`. */
|
|
13
39
|
language?: string | undefined;
|
|
14
40
|
/** Unified (single column) or split (side-by-side). Defaults to `unified`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeDiff.d.ts","sourceRoot":"","sources":["../../src/data/CodeDiff.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CodeDiff.d.ts","sourceRoot":"","sources":["../../src/data/CodeDiff.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAc/E,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAW/C,KAAK,aAAa,GACd;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAA;CAAE,GACvD;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE5D,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AAErC,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;CACjB;AAOD,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAC1C;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC9D;;;OAGG;IACH,WAAW,CAAC,EAAE,cAAc,EAAE,GAAG,SAAS,CAAC;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,8EAA8E;IAC9E,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAChC,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AA0BF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,+BA8F5C"}
|