diff --git a/client/src/components/Artifacts/Artifacts.tsx b/client/src/components/Artifacts/Artifacts.tsx index 2818bb4d72..2f3e3ff2c9 100644 --- a/client/src/components/Artifacts/Artifacts.tsx +++ b/client/src/components/Artifacts/Artifacts.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useEffect, useRef } from 'react'; +import React, { useMemo, useState, useEffect, useRef, memo } from 'react'; import * as Tabs from '@radix-ui/react-tabs'; import { Sandpack } from '@codesandbox/sandpack-react'; import { removeNullishValues } from 'librechat-data-provider'; @@ -8,6 +8,7 @@ import type { Artifact } from '~/common'; import { sharedFiles, sharedProps, + getTemplate, sharedOptions, getFileExtension, getArtifactFilename, @@ -17,7 +18,7 @@ import { useChatContext } from '~/Providers'; import { cn } from '~/utils'; import store from '~/store'; -export function ArtifactPreview({ +const ArtifactPreview = memo(function ({ showEditor = false, artifact, }: { @@ -28,6 +29,11 @@ export function ArtifactPreview({ return removeNullishValues({ [getArtifactFilename(artifact.type ?? '')]: artifact.content }); }, [artifact.type, artifact.content]); + const template = useMemo( + () => getTemplate(artifact.type ?? '', artifact.language), + [artifact.type, artifact.language], + ); + if (Object.keys(files).length === 0) { return null; } @@ -45,6 +51,7 @@ export function ArtifactPreview({ ...sharedFiles, }} {...sharedProps} + template={template} /> ) : ( ); -} +}); export default function Artifacts() { const { isSubmitting, latestMessage, conversation } = useChatContext(); diff --git a/client/src/utils/artifacts.ts b/client/src/utils/artifacts.ts index 197919ff60..b635cada5a 100644 --- a/client/src/utils/artifacts.ts +++ b/client/src/utils/artifacts.ts @@ -1,4 +1,8 @@ import dedent from 'dedent'; +import type { + SandpackProviderProps, + SandpackPredefinedTemplate, +} from '@codesandbox/sandpack-react'; // import * as shadcnComponents from '~/utils/shadcn'; const artifactFilename = { @@ -11,6 +15,17 @@ const artifactFilename = { // 'tsx': 'tsx', }; +const artifactTemplate: Record = { + 'text/html': 'static', + 'application/vnd.react': 'react-ts', + 'application/vnd.code-html': 'static', + // 'css': 'css', + // 'javascript': 'js', + // 'typescript': 'ts', + // 'jsx': 'jsx', + // 'tsx': 'tsx', +}; + export function getArtifactFilename(type: string): string { return artifactFilename[type] ?? 'App.tsx'; } @@ -34,8 +49,13 @@ export function getFileExtension(language?: string): string { } } -export const sharedProps = { - template: 'react-ts', +export function getTemplate(type: string, language?: string): SandpackPredefinedTemplate { + return ( + artifactTemplate[`${type}${(language?.length ?? 0) > 0 ? `-${language}` : ''}`] ?? 'react-ts' + ); +} + +export const sharedProps: Partial = { customSetup: { dependencies: { 'lucide-react': '^0.394.0', @@ -78,7 +98,7 @@ export const sharedProps = { }, } as const; -export const sharedOptions = { +export const sharedOptions: SandpackProviderProps['options'] = { externalResources: ['https://unpkg.com/@tailwindcss/ui/dist/tailwind-ui.min.css'], };