diff --git a/package.json b/package.json index 0a7ce2c..ddd330e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pinchchat", - "version": "1.63.2", + "version": "1.63.4", "description": "A sleek, dark-themed webchat UI for OpenClaw — monitor sessions, stream responses, and inspect tool calls in real-time.", "type": "module", "repository": { diff --git a/src/components/CodeBlock.tsx b/src/components/CodeBlock.tsx index 9d7812a..5766ffa 100644 --- a/src/components/CodeBlock.tsx +++ b/src/components/CodeBlock.tsx @@ -1,5 +1,5 @@ import { useState, useCallback, type HTMLAttributes, type ReactElement } from 'react'; -import { Check, Copy, Hash, WrapText, AlignLeft } from 'lucide-react'; +import { Check, Copy, Hash, WrapText, AlignLeft, ChevronDown, ChevronUp } from 'lucide-react'; /** Extract the language from the nested element's className (e.g. "language-ts"). */ function extractLanguage(children: React.ReactNode): string | null { @@ -45,6 +45,8 @@ function formatLanguage(lang: string): string { const LINE_NUMBER_KEY = 'pinchchat-line-numbers'; const WRAP_KEY = 'pinchchat-code-wrap'; const LINE_THRESHOLD = 3; // Only show line numbers for blocks with more than this many lines +const COLLAPSE_THRESHOLD = 25; // Collapse code blocks longer than this +const COLLAPSE_PREVIEW_LINES = 10; // Lines to show when collapsed export function CodeBlock(props: HTMLAttributes) { const [copied, setCopied] = useState(false); @@ -56,11 +58,13 @@ export function CodeBlock(props: HTMLAttributes) { const stored = localStorage.getItem(WRAP_KEY); return stored === 'true'; }); + const [isCollapsed, setIsCollapsed] = useState(true); const language = extractLanguage(props.children); const code = (props.children as ReactElement<{ children?: string }> | undefined)?.props?.children; const lines = typeof code === 'string' ? code.replace(/\n$/, '').split('\n') : []; const hasEnoughLines = lines.length > LINE_THRESHOLD; + const isCollapsible = lines.length > COLLAPSE_THRESHOLD; const handleCopy = useCallback(() => { if (typeof code === 'string') { @@ -88,12 +92,15 @@ export function CodeBlock(props: HTMLAttributes) { }, []); const shouldShowNumbers = showLineNumbers && hasEnoughLines; + const collapsed = isCollapsible && isCollapsed; + const wrapStyle = wordWrap ? { whiteSpace: 'pre-wrap' as const, overflowWrap: 'break-word' as const, wordBreak: 'break-word' as const } : undefined; + const collapseStyle = collapsed ? { maxHeight: `${COLLAPSE_PREVIEW_LINES * 1.7142857}em`, overflow: 'hidden' as const } : undefined; return (
{language && (
- {formatLanguage(language)} + {formatLanguage(language)}{isCollapsible && ({lines.length} lines)}
)} - {shouldShowNumbers ? ( -
-