enzostvs's picture
enzostvs HF Staff
can update previous message
822d5b9
<script lang="ts">
import { Check, PenLine, X } from '@lucide/svelte';
import SvelteMarkdown from 'svelte-markdown';
import type { ChatMessage } from '$lib/helpers/types';
import Paragraph from './markdown/Paragraph.svelte';
import Heading from './markdown/Heading.svelte';
import Code from './markdown/Code.svelte';
import Codespan from './markdown/Codespan.svelte';
import Blockquote from './markdown/Blockquote.svelte';
import List from './markdown/List.svelte';
import ListItem from './markdown/ListItem.svelte';
import Link from './markdown/Link.svelte';
import Hr from './markdown/Hr.svelte';
import Think from './markdown/Think.svelte';
import Button from '../ui/button/button.svelte';
let {
message,
nodeId,
onEdit
}: { message: ChatMessage; nodeId: string; onEdit?: (newContent: string) => void } = $props();
const renderers = {
paragraph: Paragraph,
heading: Heading,
code: Code,
codespan: Codespan,
blockquote: Blockquote,
list: List,
listitem: ListItem,
link: Link,
hr: Hr
};
let isEditing = $state(false);
let editContent = $state('');
function handleEdit() {
editContent = message.content as string;
isEditing = true;
}
function handleSubmitEdit() {
const trimmed = editContent.trim();
if (trimmed) {
onEdit?.(trimmed);
}
isEditing = false;
}
function handleCancelEdit() {
isEditing = false;
}
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSubmitEdit();
} else if (e.key === 'Escape') {
handleCancelEdit();
}
}
</script>
<main
class="group/message pointer-events-auto cursor-auto p-1 text-lg leading-relaxed text-accent-foreground select-text"
>
{#if message?.role === 'user'}
{#if isEditing}
<div class="w-full">
<p
contenteditable="true"
bind:textContent={editContent}
class="w-full rounded-lg bg-accent px-2 py-1 outline-none"
onkeydown={handleKeydown}
></p>
<div class="mt-1.5 flex items-center justify-end gap-1">
<Button variant="transparent" size="icon-2xs" onclick={handleCancelEdit}>
<X class="size-3" />
</Button>
<Button variant="transparent" size="icon-2xs" onclick={handleSubmitEdit}>
<Check class="size-3 text-primary" />
</Button>
</div>
</div>
{:else}
<p class="relative max-w-max pr-8">
{message.content}
<Button
variant="transparent"
size="icon-2xs"
class="absolute top-0.5 right-0 opacity-0 group-hover/message:opacity-100"
onclick={handleEdit}
>
<PenLine class="size-3" />
</Button>
</p>
{/if}
{:else}
{#if message.reasoning}
<Think
isThinking={!!message.content && (message.content as string)?.trim() !== ''}
content={message.reasoning as string}
/>
{/if}
<SvelteMarkdown source={message.content} renderers={renderers as any} />
{/if}
</main>