File size: 3,131 Bytes
502cb81 ca3d512 4b8b411 5c869f5 4b8b411 60216ec 502cb81 0ffe6c3 0bcf467 ce92b65 1cd3833 502cb81 25a5986 eb79b3d 502cb81 5c869f5 de2ec19 5c869f5 de2ec19 cd2e1ea de2ec19 cd2e1ea de2ec19 502cb81 25a5986 502cb81 5213b80 f2e5687 de2ec19 25a5986 502cb81 25a5986 5c869f5 502cb81 5213b80 60c7941 502cb81 1cd3833 92f7aa1 d5e14b5 5213b80 25a5986 502cb81 5213b80 f2e5687 5213b80 25a5986 de2ec19 60216ec b34b73b 5213b80 502cb81 eeca96c 60216ec 5213b80 502cb81 5213b80 a979074 5213b80 502cb81 5213b80 8709c70 5213b80 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
<script lang="ts">
import type { Conversation } from "$lib/components/InferencePlayground/types";
import { createEventDispatcher, tick } from "svelte";
import CodeSnippets from "./InferencePlaygroundCodeSnippets.svelte";
import Message from "./InferencePlaygroundMessage.svelte";
import IconPlus from "../Icons/IconPlus.svelte";
export let conversation: Conversation;
export let loading: boolean;
export let viewCode: boolean;
export let hfToken: string;
export let compareActive: boolean;
let shouldScrollToBottom = true;
let isProgrammaticScroll = true;
let conversationLength = conversation.messages.length;
const dispatch = createEventDispatcher<{
addMessage: void;
deleteMessage: number;
}>();
let messageContainer: HTMLDivElement | null = null;
async function resizeMessageTextAreas() {
// ideally we would use CSS "field-sizing:content". However, it is currently only supported on Chrome.
await tick();
if (messageContainer) {
const containerScrollTop = messageContainer.scrollTop;
const textareaEls = messageContainer.querySelectorAll("textarea");
for (const textarea of textareaEls) {
textarea.style.height = "0px";
textarea.style.height = textarea.scrollHeight + "px";
}
messageContainer.scrollTop = containerScrollTop;
}
}
function scrollToBottom() {
if (messageContainer) {
isProgrammaticScroll = true;
messageContainer.scrollTop = messageContainer.scrollHeight;
}
}
$: {
if (conversation.messages.at(-1)) {
resizeMessageTextAreas();
if (shouldScrollToBottom) {
scrollToBottom();
}
}
}
$: if (conversation.messages.length !== conversationLength) {
// enable automatic scrolling when new message was added
conversationLength = conversation.messages.length;
shouldScrollToBottom = true;
}
$: viewCode, resizeMessageTextAreas();
</script>
<svelte:window on:resize={resizeMessageTextAreas} />
<div
class="flex flex-col overflow-y-auto overflow-x-hidden @container {compareActive
? 'max-h-[calc(100dvh-5.8rem-2.5rem-75px)] md:max-h-[calc(100dvh-5.8rem-2.5rem)]'
: 'max-h-[calc(100dvh-5.8rem-2.5rem-75px)] md:max-h-[calc(100dvh-5.8rem)]'}"
class:animate-pulse={loading && !conversation.streaming}
bind:this={messageContainer}
on:scroll={() => {
// disable automatic scrolling is user initiates scroll
if (!isProgrammaticScroll) {
shouldScrollToBottom = false;
}
isProgrammaticScroll = false;
}}
>
{#if !viewCode}
{#each conversation.messages as message, messageIdx}
<Message
class="border-b"
{message}
{loading}
on:input={resizeMessageTextAreas}
on:delete={() => dispatch("deleteMessage", messageIdx)}
autofocus={!loading && messageIdx === conversation.messages.length - 1}
/>
{/each}
<button
class="flex px-3.5 py-6 hover:bg-gray-50 md:px-6 dark:hover:bg-gray-800/50"
on:click={() => dispatch("addMessage")}
disabled={loading}
>
<div class="flex items-center gap-2 !p-0 text-sm font-semibold">
<IconPlus classNames="text-lg" /> Add message
</div>
</button>
{:else}
<CodeSnippets {conversation} {hfToken} on:closeCode />
{/if}
</div>
|