| import type { Suggestion } from '@/lib/db/schema'; | |
| import type { UseChatHelpers } from '@ai-sdk/react'; | |
| import type { ComponentType, Dispatch, ReactNode, SetStateAction } from 'react'; | |
| import type { UIArtifact } from './artifact'; | |
| import type { ChatMessage, CustomUIDataTypes } from '@/lib/types'; | |
| import type { DataUIPart } from 'ai'; | |
| export type ArtifactActionContext<M = any> = { | |
| content: string; | |
| handleVersionChange: (type: 'next' | 'prev' | 'toggle' | 'latest') => void; | |
| currentVersionIndex: number; | |
| isCurrentVersion: boolean; | |
| mode: 'edit' | 'diff'; | |
| metadata: M; | |
| setMetadata: Dispatch<SetStateAction<M>>; | |
| }; | |
| type ArtifactAction<M = any> = { | |
| icon: ReactNode; | |
| label?: string; | |
| description: string; | |
| onClick: (context: ArtifactActionContext<M>) => Promise<void> | void; | |
| isDisabled?: (context: ArtifactActionContext<M>) => boolean; | |
| }; | |
| export type ArtifactToolbarContext = { | |
| sendMessage: UseChatHelpers<ChatMessage>['sendMessage']; | |
| }; | |
| export type ArtifactToolbarItem = { | |
| description: string; | |
| icon: ReactNode; | |
| onClick: (context: ArtifactToolbarContext) => void; | |
| }; | |
| interface ArtifactContent<M = any> { | |
| title: string; | |
| content: string; | |
| mode: 'edit' | 'diff'; | |
| isCurrentVersion: boolean; | |
| currentVersionIndex: number; | |
| status: 'streaming' | 'idle'; | |
| suggestions: Array<Suggestion>; | |
| onSaveContent: (updatedContent: string, debounce: boolean) => void; | |
| isInline: boolean; | |
| getDocumentContentById: (index: number) => string; | |
| isLoading: boolean; | |
| metadata: M; | |
| setMetadata: Dispatch<SetStateAction<M>>; | |
| } | |
| interface InitializeParameters<M = any> { | |
| documentId: string; | |
| setMetadata: Dispatch<SetStateAction<M>>; | |
| } | |
| type ArtifactConfig<T extends string, M = any> = { | |
| kind: T; | |
| description: string; | |
| content: ComponentType<ArtifactContent<M>>; | |
| actions: Array<ArtifactAction<M>>; | |
| toolbar: ArtifactToolbarItem[]; | |
| initialize?: (parameters: InitializeParameters<M>) => void; | |
| onStreamPart: (args: { | |
| setMetadata: Dispatch<SetStateAction<M>>; | |
| setArtifact: Dispatch<SetStateAction<UIArtifact>>; | |
| streamPart: DataUIPart<CustomUIDataTypes>; | |
| }) => void; | |
| }; | |
| export class Artifact<T extends string, M = any> { | |
| readonly kind: T; | |
| readonly description: string; | |
| readonly content: ComponentType<ArtifactContent<M>>; | |
| readonly actions: Array<ArtifactAction<M>>; | |
| readonly toolbar: ArtifactToolbarItem[]; | |
| readonly initialize?: (parameters: InitializeParameters) => void; | |
| readonly onStreamPart: (args: { | |
| setMetadata: Dispatch<SetStateAction<M>>; | |
| setArtifact: Dispatch<SetStateAction<UIArtifact>>; | |
| streamPart: DataUIPart<CustomUIDataTypes>; | |
| }) => void; | |
| constructor(config: ArtifactConfig<T, M>) { | |
| this.kind = config.kind; | |
| this.description = config.description; | |
| this.content = config.content; | |
| this.actions = config.actions || []; | |
| this.toolbar = config.toolbar || []; | |
| this.initialize = config.initialize || (async () => ({})); | |
| this.onStreamPart = config.onStreamPart; | |
| } | |
| } | |