From 8754bbada9ef20f125c04b3481bcbf7e2186ae0a Mon Sep 17 00:00:00 2001 From: Enrico Ros Date: Fri, 4 Oct 2024 11:22:13 -0700 Subject: [PATCH] Will be replaced. --- src/modules/aifn/agicodefixup/agiFixupCode.ts | 20 -- src/modules/blocks/AutoBlocksRenderer.tsx | 7 +- src/modules/blocks/code/RenderCode.tsx | 80 ++----- .../code/code-buttons/useOpenInWebEditors.tsx | 3 - .../blocks/code/code-highlight/codePrism.ts | 3 - .../code/code-renderers/RenderCodeChartJS.tsx | 203 ------------------ .../code/code-renderers/useDynamicChartJS.ts | 197 ----------------- .../enhanced-code/EnhancedRenderCode.tsx | 15 +- 8 files changed, 22 insertions(+), 506 deletions(-) delete mode 100644 src/modules/blocks/code/code-renderers/RenderCodeChartJS.tsx delete mode 100644 src/modules/blocks/code/code-renderers/useDynamicChartJS.ts diff --git a/src/modules/aifn/agicodefixup/agiFixupCode.ts b/src/modules/aifn/agicodefixup/agiFixupCode.ts index ef1db2106..44163edfe 100644 --- a/src/modules/aifn/agicodefixup/agiFixupCode.ts +++ b/src/modules/aifn/agicodefixup/agiFixupCode.ts @@ -22,26 +22,6 @@ interface CodeFix { const CodeFixes: Record = { - // See `RenderCodeChartJS` - 'chartjs-issue': { - description: 'Provides the corrected Chart.js configuration code.', - systemMessage: `You are an AI assistant that fixes invalid Chart.js configuration JSON. -When provided with invalid Chart.js code, you analyze it, identify errors, especially remove all functions if any, and output a corrected version in valid JSON format. -Respond first with a very brief analysis of where the error is and exactly what to change, and then call the \`{{functionName}}\` function.`, - userInstructionTemplate: `The following Chart.js ChartOptions JSON is invalid and cannot be parsed: -\`\`\`json -{{codeToFix}} -\`\`\` - -{{errorMessageSection}} -Please analyze the JSON, correct any errors (REMOVE FUNCTIONS!!!), and provide a valid JSON-only ChartOptions that can be parsed by Chart.js.`, - functionName: 'provide_corrected_chartjs_code', - functionPolicy: 'think-then-invoke', - outputSchema: z.object({ - corrected_code: z.string().describe('The corrected Chart.js ChartOptions in valid JSON format.'), - }), - }, - }; diff --git a/src/modules/blocks/AutoBlocksRenderer.tsx b/src/modules/blocks/AutoBlocksRenderer.tsx index 0100c4eed..c23bc4f71 100644 --- a/src/modules/blocks/AutoBlocksRenderer.tsx +++ b/src/modules/blocks/AutoBlocksRenderer.tsx @@ -4,7 +4,6 @@ import type { Diff as SanityTextDiff } from '@sanity/diff-match-patch'; import type { ContentScaling } from '~/common/app.theme'; import type { DMessageRole } from '~/common/stores/chat/chat.message'; -import { BLOCK_CODE_VND_AGI_CHARTJS, renderCodeMemoOrNot } from './code/RenderCode'; import { BlocksContainer } from './BlocksContainers'; import { EnhancedRenderCode } from './enhanced-code/EnhancedRenderCode'; import { RenderDangerousHtml } from './danger-html/RenderDangerousHtml'; @@ -13,6 +12,7 @@ import { RenderMarkdown, RenderMarkdownMemo } from './markdown/RenderMarkdown'; import { RenderPlainText } from './plaintext/RenderPlainText'; import { RenderTextDiff } from './textdiff/RenderTextDiff'; import { ToggleExpansionButton } from './ToggleExpansionButton'; +import { renderCodeMemoOrNot } from './code/RenderCode'; import { useAutoBlocksMemoSemiStable, useTextCollapser } from './blocks.hooks'; import { useScaledCodeSx, useScaledImageSx, useScaledTypographySx, useToggleExpansionButtonSx } from './blocks.styles'; @@ -146,11 +146,6 @@ export function AutoBlocksRenderer(props: { // Custom handling for some of our blocks let disableEnhancedRender = bkInput.isPartial; let enhancedStartCollapsed = false; - if (bkInput.title === BLOCK_CODE_VND_AGI_CHARTJS) { - disableEnhancedRender = false; - // For Chart.js charts, at the moment, we use the 'unwanted' refresh at the end of the message to start (that block) without collapse - enhancedStartCollapsed = bkInput.isPartial; - } return (props.codeRenderVariant === 'enhanced' && !disableEnhancedRender) ? ( (null); - const chartJSRef = React.useRef(null); // external state const { isFullscreen, enterFullscreen, exitFullscreen } = useFullscreenElement(fullScreenElementRef); @@ -155,24 +147,6 @@ function RenderCodeImpl(props: RenderCodeBaseProps & { copyToClipboard(code, 'Code'); }, [code]); - const handleChartCopyToClipboard = React.useCallback(async (e: React.MouseEvent) => { - e.stopPropagation(); - copyBlobPromiseToClipboard('image/png', new Promise(async (resolve, reject) => { - const blob = await chartJSRef.current?.getChartPNG(e.shiftKey); - if (blob) resolve(blob); - else if (blob === undefined) reject('Chart not ready yet.') - else reject('Failed to generate chart image.'); - }), `Chart Image${e.shiftKey ? ' with transparent background' : ''}`); - }, []); - - const handleChartDownload = React.useCallback(async (e: React.MouseEvent) => { - e.stopPropagation(); - chartJSRef.current?.getChartPNG(e.shiftKey).then((blob) => { - if (blob) return downloadBlob(blob, `chart_${prettyTimestampForFilenames()}.png`); - alert('Chart not ready yet.'); - }); - }, []); - // heuristics for specialized rendering @@ -193,11 +167,8 @@ function RenderCodeImpl(props: RenderCodeBaseProps & { const renderSVG = isSVGCode && showSVG; const canScaleSVG = renderSVG && code.includes('viewBox="'); - const isChartJSCode = lcBlockTitle === BLOCK_CODE_VND_AGI_CHARTJS && !blockIsPartial; - const renderChartJS = isChartJSCode && showChartJS; - - const renderSyntaxHighlight = !renderHTML && !renderMermaid && !renderPlantUML && !renderSVG && !renderChartJS; - const cannotRenderLineNumbers = !renderSyntaxHighlight || showSoftWrap || renderChartJS; + const renderSyntaxHighlight = !renderHTML && !renderMermaid && !renderPlantUML && !renderSVG; + const cannotRenderLineNumbers = !renderSyntaxHighlight || showSoftWrap; const renderLineNumbers = !cannotRenderLineNumbers && ((showLineNumbers && uiComplexityMode === 'extra') || isFullscreen); @@ -263,7 +234,7 @@ function RenderCodeImpl(props: RenderCodeBaseProps & { ref={fullScreenElementRef} component='code' className={`language-${inferredCodeLanguage || 'unknown'}${renderLineNumbers ? ' line-numbers' : ''}`} - sx={!isFullscreen ? codeSx : {...codeSx, backgroundColor: 'background.surface' }} + sx={!isFullscreen ? codeSx : { ...codeSx, backgroundColor: 'background.surface' }} > {/* Markdown Title (File/Type) */} @@ -281,8 +252,7 @@ function RenderCodeImpl(props: RenderCodeBaseProps & { : renderMermaid ? : renderSVG ? : (renderPlantUML && (plantUmlSvgData || plantUmlError)) ? - : renderChartJS ? - : } + : } @@ -300,28 +270,25 @@ function RenderCodeImpl(props: RenderCodeBaseProps & { )} - {/* SVG, Chart.js, Mermaid, PlantUML -- including a max-out button */} - {(isSVGCode || isChartJSCode || isMermaidCode || isPlantUMLCode) && ( + {/* SVG, Mermaid, PlantUML -- including a max-out button */} + {(isSVGCode || isMermaidCode || isPlantUMLCode) && ( {/* Toggle rendering */} { if (isSVGCode) setShowSVG(on => !on); - if (isChartJSCode) setShowChartJS(on => !on); if (isMermaidCode) setShowMermaid(on => !on); if (isPlantUMLCode) setShowPlantUML(on => !on); }}> - {isSVGCode ? : isChartJSCode ? : } + {isSVGCode ? : } {/* Fit-Content */} @@ -376,30 +343,13 @@ function RenderCodeImpl(props: RenderCodeBaseProps & { )} {/* Copy */} - {props.noCopyButton !== true && !renderChartJS && ( + {props.noCopyButton !== true && ( )} - {/* Special Group: ChartJS */} - {props.noCopyButton !== true && renderChartJS && ( - - - {/* Download Chart PNG */} - Download PNGhold ⇧ for transparent} onClick={handleChartDownload}> - - - - {/* Copy Chart PNG */} - Copy PNGhold ⇧ for transparent} onClick={handleChartCopyToClipboard}> - - - - - )} - {/* DISABLED: Converted to a Dropdown */} diff --git a/src/modules/blocks/code/code-buttons/useOpenInWebEditors.tsx b/src/modules/blocks/code/code-buttons/useOpenInWebEditors.tsx index 6dd68bca9..b6b252f9e 100644 --- a/src/modules/blocks/code/code-buttons/useOpenInWebEditors.tsx +++ b/src/modules/blocks/code/code-buttons/useOpenInWebEditors.tsx @@ -7,7 +7,6 @@ import { GoogleColabIcon } from '~/common/components/icons/3rdparty/GoogleColabI import { JSFiddleIcon } from '~/common/components/icons/3rdparty/JSFiddleIcon'; import { StackBlitzIcon } from '~/common/components/icons/3rdparty/StackBlitzIcon'; -import { BLOCK_CODE_VND_AGI_CHARTJS } from '../RenderCode'; import { isCodePenSupported, openInCodePen } from './openInCodePen'; import { isGoogleColabSupported, openInGoogleColab } from './openInGoogleColab'; import { isJSFiddleSupported, openInJsFiddle } from './openInJsFiddle'; @@ -25,8 +24,6 @@ export function useOpenInWebEditors( return React.useMemo(() => { if (blockIsPartial) return stableNoButtons; - if (blockTitle === BLOCK_CODE_VND_AGI_CHARTJS) return stableNoButtons; - const mayExternal = code?.indexOf('\n') > 0; if (!mayExternal) return stableNoButtons; diff --git a/src/modules/blocks/code/code-highlight/codePrism.ts b/src/modules/blocks/code/code-highlight/codePrism.ts index 305066c3d..0ea1808e2 100644 --- a/src/modules/blocks/code/code-highlight/codePrism.ts +++ b/src/modules/blocks/code/code-highlight/codePrism.ts @@ -36,9 +36,6 @@ export function inferCodeLanguage(blockTitle: string, code: string): string | nu // if we have a block title, use it to infer the language if (blockTitle) { - // vnd.agi - we tell how to format these blocks, so we know what's the language inside - if (blockTitle.trim().toLowerCase() === 'chartjs') - return 'json'; // {{RenderChartJS}} // single word: assume it's the syntax highlight language if (!blockTitle.includes('.')) diff --git a/src/modules/blocks/code/code-renderers/RenderCodeChartJS.tsx b/src/modules/blocks/code/code-renderers/RenderCodeChartJS.tsx deleted file mode 100644 index b108b9bd4..000000000 --- a/src/modules/blocks/code/code-renderers/RenderCodeChartJS.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import * as React from 'react'; - -import type { SxProps } from '@mui/joy/styles/types'; -import { Box, Button, Typography, useColorScheme } from '@mui/joy'; -import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; - -import { useAgiFixupCode } from '~/modules/aifn/agicodefixup/useAgiFixupCode'; - -import { asyncCanvasToBlob } from '~/common/util/canvasUtils'; -import { themeFontFamilyCss } from '~/common/app.theme'; - -import { ChartConfiguration, ChartInstanceType, chartJSApplyTheme, chartJSFixupGeneratedObject, chartJSPixelRatio, useDynamicChartJS } from './useDynamicChartJS'; - - -const chartContainerSx: SxProps = { - // required by Chart.js - position: 'relative', - - // to try to regain the chart size after shrinking - width: '100%', - // to better get resized when fullscreen - flex: 1, - - // limit height of the canvas or it can too large easily - '& canvas': { - // width: '100% !important', - // height: '100%', - // minHeight: '320px', - maxHeight: '640px', - }, -}; - - -// Exposed API -export type RenderCodeChartJSHandle = { - getChartPNG: (transparentBackground: boolean) => Promise; -}; - - -export const RenderCodeChartJS = React.forwardRef(function RenderCodeChartJS(props: { - chartJSCode: string; - onReplaceInCode?: (search: string, replace: string) => boolean; -}, ref: React.Ref) { - - // state - const [renderError, setRenderError] = React.useState(null); - const [fixupError, setFixupError] = React.useState(null); - const canvasRef = React.useRef(null); - const chartInstanceRef = React.useRef(null); - - // external state - const isDarkMode = useColorScheme().mode === 'dark'; - const { chartJS, loadingError, isLoading: isLibraryLoading } = useDynamicChartJS(); - - // immediate parsing (note, this could be done with useEffect and state, but we save a render cycle) - const parseResult = React.useMemo(() => { - try { - const config = JSON.parse(props.chartJSCode) as ChartConfiguration; - chartJSFixupGeneratedObject(config); - return { chartConfig: config, parseError: null }; - } catch (error: any) { - return { chartConfig: null, parseError: error.message as string || 'Unknown error.' }; - } - }, [props.chartJSCode]); - - // AI functions - const { isFetching, refetch } = useAgiFixupCode('chartjs-issue', false, props.chartJSCode, parseResult.parseError); - - - // Rendering - React.useEffect(() => { - if (!chartJS || !parseResult.chartConfig || !canvasRef.current) return; - - try { - // Destroy previous chart instance if it exists - chartInstanceRef.current?.destroy(); - - // React to the theme - chartJSApplyTheme(chartJS, isDarkMode); - - // Create new chart instance - chartInstanceRef.current = new chartJS(canvasRef.current, parseResult.chartConfig); - setRenderError(null); - - } catch (error: any) { - setRenderError('Error rendering chart: ' + (error.message || 'Unknown error.')); - } - - // Cleanup on unmount - return () => { - chartInstanceRef.current?.destroy(); - chartInstanceRef.current = null; - }; - }, [chartJS, parseResult.chartConfig, isDarkMode]); - - - // Expose control methods - React.useImperativeHandle(ref, () => ({ - getChartPNG: async (transparentBackground: boolean) => { - const chartCanvas = canvasRef.current; - if (!chartCanvas) return null; - - // Create a new canvas - const pngCanvas = document.createElement('canvas'); - pngCanvas.width = chartCanvas.width; - pngCanvas.height = chartCanvas.height; - const ctx = pngCanvas.getContext('2d', { alpha: true }); - if (!ctx) - return await asyncCanvasToBlob(chartCanvas, 'image/png'); - - // Omit the background layer - if (!transparentBackground) { - // ctx.fillStyle = isDarkMode ? '#171A1C' : '#F0F4F8'; - ctx.fillStyle = isDarkMode ? '#000' : '#FFF'; - ctx.fillRect(0, 0, pngCanvas.width, pngCanvas.height); - } - - // Draw the chart - ctx.drawImage(chartCanvas, 0, 0); - - // Great work Big-AGI! - const pr = chartJSPixelRatio(); - ctx.font = `${10 * pr}px ${themeFontFamilyCss}`; - ctx.fillStyle = isDarkMode ? '#9FA6AD' : '#555E68'; - ctx.textAlign = 'left'; - ctx.textBaseline = 'bottom'; - ctx.fillText('Big-AGI.com', 7 * pr, pngCanvas.height - 6 * pr); - return await asyncCanvasToBlob(pngCanvas, 'image/png'); - }, - }), [isDarkMode]); - - - // handlers - - const { onReplaceInCode } = props; - - const handleChartRegenerate = React.useCallback(async () => { - if (!onReplaceInCode) return; - setFixupError(null); - refetch().then((result) => { - if (result.data) - onReplaceInCode(props.chartJSCode, result.data); - else if (result.error) - setFixupError(result.error.message || 'Unknown error.'); - else - setFixupError('Unknown Fixup error.'); - }); - }, [onReplaceInCode, props.chartJSCode, refetch]); - - - // Handle all the non-chart states - switch (true) { - case isLibraryLoading: - // DISABLED: reduce visual noise - // return Loading Chart.js...; - return null; - case !!loadingError: - return {loadingError}; - case !!parseResult.parseError || !!fixupError: - return ( - - {/* Here we play like if we won't get the callback, but we will */} - {/*{props.onReplaceInCode && (*/} - - {/*)}*/} - {fixupError ? ( - - Error fixing chart: {fixupError} - - ) : (parseResult.parseError && !isFetching) && ( - - Invalid Chart.js input: {parseResult.parseError} - - )} - - ); - case !!renderError: - return {renderError}; - } - - // Render the chart - return ( - - - - ); -}); \ No newline at end of file diff --git a/src/modules/blocks/code/code-renderers/useDynamicChartJS.ts b/src/modules/blocks/code/code-renderers/useDynamicChartJS.ts deleted file mode 100644 index 1dd2460d0..000000000 --- a/src/modules/blocks/code/code-renderers/useDynamicChartJS.ts +++ /dev/null @@ -1,197 +0,0 @@ -/** - * Copyright (c) 2024 Enrico Ros - * - * Hooks, state centralizer and utility functions to load Chart.js dynamically - * from CDN instead of bundling it with the app. - */ - -import * as React from 'react'; -import { create } from 'zustand'; - -import { themeFontFamilyCss } from '~/common/app.theme'; - - -// Configuration -const CHARTJS_VERSION = '4.4.4'; -const CHARTJS_CDN_URL = `https://cdn.jsdelivr.net/npm/chart.js@${CHARTJS_VERSION}/dist/chart.umd.js`; -const CHARTJS_SCRIPT_ID = 'chartjs-cdn'; - - -// Minimal type definitions for Chart.js - as of 4.4.4 - -interface ChartConstructorType { - defaults: ChartDefaults; - - new(context: CanvasRenderingContext2D | HTMLCanvasElement, config: ChartConfiguration): ChartInstanceType; -} - -interface ChartDefaults { - color?: string; - devicePixelRatio?: number; - font?: { - family: string; - size: number; - }; - maintainAspectRatio?: boolean; - responsive?: boolean; - plugins?: any, - - // [key: string]: any; -} - -export interface ChartConfiguration { - type?: string; - data?: any; - options?: ChartDefaults; - - // [key: string]: any; -} - -export interface ChartInstanceType { - destroy(): void; -} - - -// Code manipulation functions - -function _chartJSInitializeDefaults(Chart: ChartConstructorType): ChartConstructorType { - - // Use the application fonts - if (Chart.defaults.font) { - Chart.defaults.font.family = themeFontFamilyCss; - Chart.defaults.font.size = 13; - } - - // Responsive defaults, to autosize the chart while keeping the aspect ratios - Chart.defaults.maintainAspectRatio = true; // defaults to 1 for polar and so, 2 for bars and more - Chart.defaults.responsive = true; // re-draw on resize - - // Set devicePixelRatio to double, to enable downloading/zooming of charts - // FIXME: there's an issue here, by overriding the default (which invokes getDevicePixelRatio) we stop - // the re-render when a window is moved to a different screen with different DPI. In some sense - // we are anchoring the DPR to the first screen's x 2. - if (window.devicePixelRatio) - Chart.defaults.devicePixelRatio = chartJSPixelRatio(); - - // Change the default padding for the title - Chart.defaults.plugins.title.padding = { top: 8, bottom: 16 }; - - return Chart; -} - -export function chartJSPixelRatio() { - return 2 * (window.devicePixelRatio || 1); -} - -export function chartJSApplyTheme(Chart: ChartConstructorType, isDarkMode: boolean) { - // responsive color - Chart.defaults.color = isDarkMode ? '#CDD7E1' : '#32383E'; -} - -export function chartJSFixupGeneratedObject(chartConfig: ChartConfiguration): void { - // Do not remove Font, allow for override - // delete chartConfig?.options?.font; - // Remove responsive options - we handle this ourselves by default - delete chartConfig?.options?.responsive; - delete chartConfig?.options?.maintainAspectRatio; - delete chartConfig?.options?.devicePixelRatio; -} - - -// Singleton promise for loading Chart.js -let chartJSPromise: Promise | null = null; - -function loadCDNScript(): Promise { - // Resolve immediately if already loaded - if ((window as any).Chart) - return Promise.resolve(_chartJSInitializeDefaults((window as any).Chart)); - - // If loading has already started, return the existing promise - if (chartJSPromise) return chartJSPromise; - - // Ensure the API definitions from package.json match the CDN loaded version - // NOTE: Disabled because we are not using the package.json version anymore, we replaced the API - // if (devDependencies['chart.js'] !== CHARTJS_VERSION) - // return Promise.reject(new Error(`Chart.js version mismatch: loaded ${CHARTJS_VERSION}, expected ${devDependencies['chart.js']}.`)); - - chartJSPromise = new Promise((resolve, reject) => { - - // Create or reuse a script DOM element - const script = document.createElement('script'); - script.id = CHARTJS_SCRIPT_ID; - script.src = CHARTJS_CDN_URL; - script.async = true; - - script.onload = () => { - if ((window as any).Chart) resolve(_chartJSInitializeDefaults((window as any).Chart)); - else reject(new Error('Chart.js failed to load.')); - }; - - script.onerror = () => { - console.log(`[DEV] error loading Chart.js from: ${CHARTJS_CDN_URL}`); - reject(new Error('Failed to load Chart.js from CDN.')); - }; - - document.head.appendChild(script); - }); - - return chartJSPromise; -} - - -// Store: we share the state across multiple useChartJS hooks -interface ChartApiStore { - - // state - chartJS: ChartConstructorType | null; - loadingError: string | null; - isLoading: boolean; - - // actions - loadChartJS: () => void; - -} - -const useChartApiStore = create((set, get) => ({ - - // initial state - chartJS: null, - loadingError: null, - isLoading: false, - - // actions - loadChartJS: () => { - - // Prevent redundant calls - const { chartJS, loadingError, isLoading } = get(); - if (chartJS || loadingError || isLoading) return; - set({ isLoading: true }); - - // Load and save the constructor to the store - loadCDNScript() - .then((Chart) => - set({ chartJS: Chart, loadingError: null, isLoading: false }), - ) - .catch((error) => - set({ chartJS: null, loadingError: error.message, isLoading: false }), - ); - }, - -})); - - -/** - * Hook to load Chart.js and make it available to the component. - */ -export function useDynamicChartJS() { - const { chartJS, loadingError, isLoading } = useChartApiStore(); - - // Load the library upon first access - const needsLoading = !chartJS && !loadingError && !isLoading; - React.useEffect(() => { - if (needsLoading) - useChartApiStore.getState().loadChartJS(); - }, [needsLoading]); - - return { chartJS, loadingError, isLoading }; -} diff --git a/src/modules/blocks/enhanced-code/EnhancedRenderCode.tsx b/src/modules/blocks/enhanced-code/EnhancedRenderCode.tsx index 5fe26a718..ce6fe315c 100644 --- a/src/modules/blocks/enhanced-code/EnhancedRenderCode.tsx +++ b/src/modules/blocks/enhanced-code/EnhancedRenderCode.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import type { SxProps } from '@mui/joy/styles/types'; import { Box, ColorPaletteProp, IconButton, Typography } from '@mui/joy'; -import BarChartIcon from '@mui/icons-material/BarChart'; import CodeIcon from '@mui/icons-material/Code'; import MoreVertIcon from '@mui/icons-material/MoreVert'; @@ -10,8 +9,8 @@ import type { ContentScaling } from '~/common/app.theme'; import { ExpanderControlledBox } from '~/common/components/ExpanderControlledBox'; import { TooltipOutlined } from '~/common/components/TooltipOutlined'; -import { BLOCK_CODE_VND_AGI_CHARTJS, RenderCodeMemo } from '../code/RenderCode'; import { EnhancedRenderCodeMenu } from './EnhancedRenderCodeMenu'; +import { RenderCodeMemo } from '../code/RenderCode'; import { enhancedCodePanelTitleTooltipSx, RenderCodePanelFrame } from '../code/RenderCodePanelFrame'; import { getCodeCollapseManager } from './codeCollapseManager'; import { useLiveFilePatch } from './livefile-patch/useLiveFilePatch'; @@ -117,8 +116,7 @@ export function EnhancedRenderCode(props: { ), [props.code, props.semiStableId, props.title]); const headerRow = React.useMemo(() => { - const isChart = props.title === BLOCK_CODE_VND_AGI_CHARTJS; - const Icon = (isChart && !isCodeCollapsed) ? BarChartIcon : CodeIcon; + const Icon = CodeIcon; return <> {/* Icon and Title */} @@ -127,14 +125,13 @@ export function EnhancedRenderCode(props: { aria-hidden onClick={handleToggleCodeCollapse} sx={{ - transform: (isCodeCollapsed && !isChart) ? 'rotate(-90deg)' : 'none', + transform: isCodeCollapsed ? 'rotate(-90deg)' : 'none', transition: 'transform 0.2s cubic-bezier(.17,.84,.44,1)', cursor: 'pointer', }} /> - - {isChart ? 'Chart ' + (props.isPartial ? '.'.repeat(Math.round(props.code.length / 100) % 4) : '') - : props.title || 'Code'} + + {props.title || 'Code'} @@ -153,7 +150,7 @@ export function EnhancedRenderCode(props: { ; - }, [handleToggleCodeCollapse, handleToggleContextMenu, headerTooltipContents, isCodeCollapsed, liveFileButton, props.code.length, props.isPartial, props.title]); + }, [handleToggleCodeCollapse, handleToggleContextMenu, headerTooltipContents, isCodeCollapsed, liveFileButton, props.title]); // const toolbarRow = React.useMemo(() => <> // {props.onLiveFileCreate && (