Spaces:
Running
Running
| <script lang="ts"> | |
| import { slide } from 'svelte/transition'; | |
| import { Brain, ChevronDown } from '@lucide/svelte'; | |
| import SvelteMarkdown from 'svelte-markdown'; | |
| import Spinner from '$lib/components/loading/Spinner.svelte'; | |
| import Paragraph from './think/Paragraph.svelte'; | |
| import Heading from './think/Heading.svelte'; | |
| import Code from './think/Code.svelte'; | |
| import Codespan from './think/Codespan.svelte'; | |
| import Blockquote from './think/Blockquote.svelte'; | |
| import List from './think/List.svelte'; | |
| import ListItem from './think/ListItem.svelte'; | |
| import Link from './think/Link.svelte'; | |
| import Hr from './think/Hr.svelte'; | |
| let { isThinking, content }: { isThinking?: boolean; content?: string } = $props(); | |
| let isCollapsed = $state.raw<boolean>(false); | |
| let scrollRef = $state.raw<HTMLDivElement | null>(null); | |
| function toggleCollapse() { | |
| isCollapsed = !isCollapsed; | |
| } | |
| const renderers = { | |
| paragraph: Paragraph, | |
| heading: Heading, | |
| code: Code, | |
| codespan: Codespan, | |
| blockquote: Blockquote, | |
| list: List, | |
| listitem: ListItem, | |
| link: Link, | |
| hr: Hr | |
| }; | |
| $effect(() => { | |
| if (isThinking) { | |
| isCollapsed = true; | |
| } | |
| }); | |
| $effect(() => { | |
| if (content && scrollRef) { | |
| scrollRef.scrollTo({ top: scrollRef.scrollHeight, behavior: 'smooth' }); | |
| } | |
| }); | |
| </script> | |
| <div | |
| class="{!isCollapsed | |
| ? 'nowheel' | |
| : ''} mb-4 overflow-hidden rounded-xl border border-border bg-accent text-xs dark:bg-accent/30" | |
| > | |
| <button | |
| class="flex w-full cursor-pointer items-center gap-2.5 p-2 text-left transition-colors hover:bg-accent/80 dark:hover:bg-accent/30" | |
| onclick={toggleCollapse} | |
| > | |
| <div | |
| class="flex size-5 min-h-5 min-w-5 items-center justify-center rounded-lg bg-linear-to-br from-primary/20 to-primary/5 {!isThinking && | |
| 'animate-pulse'}" | |
| > | |
| <Brain class="size-3 text-muted-foreground" /> | |
| </div> | |
| {#if !isThinking} | |
| <Spinner className="text-muted-foreground text-[11px] font-medium">Thinking...</Spinner> | |
| {:else} | |
| <span class="text-[11px] font-medium text-muted-foreground">Thought process</span> | |
| {/if} | |
| <ChevronDown | |
| class="ml-auto size-3.5 text-muted-foreground/60 transition-transform duration-300 {isCollapsed | |
| ? '' | |
| : 'rotate-180'}" | |
| /> | |
| </button> | |
| {#if !isCollapsed} | |
| <div transition:slide={{ duration: 200 }}> | |
| <div | |
| bind:this={scrollRef} | |
| class="max-h-50 overflow-y-auto border-t border-border/60 px-4 py-3" | |
| > | |
| <SvelteMarkdown source={content?.trimStart()} renderers={renderers as any} /> | |
| </div> | |
| </div> | |
| {/if} | |
| </div> | |