Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nwaughachukwuma committed Nov 7, 2024
1 parent eea5481 commit 4b64f1d
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 27 deletions.
19 changes: 0 additions & 19 deletions app/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,6 @@
text-decoration: none;
}
}
span,
div,
.data-training-status {
&[data-training-status] {
@apply opacity-80;
}
&[data-training-status='queued'] {
@apply text-blue-500;
}
&[data-training-status='processing'] {
@apply text-yellow-500;
}
&[data-training-status='completed'] {
@apply text-green-500;
}
&[data-training-status='failed'] {
@apply text-red-500;
}
}
.gradient-gray-to-emerald {
@apply bg-gradient-to-r from-gray-400 to-emerald-200 bg-clip-text text-transparent;
}
Expand Down
118 changes: 118 additions & 0 deletions app/src/lib/components/ChatBox.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<script lang="ts" context="module">
import { debounce } from 'throttle-debounce';
export const updateCursor = debounce(200, (field: HTMLElement, autofocus = false) => {
const sel = window.getSelection();
if (!sel || !field.childNodes.length) return;
const range = document.createRange();
range.setStart(field.childNodes[0], field.innerText.length);
range.setEnd(field.childNodes[0], field.innerText.length);
sel.removeAllRanges();
sel.addRange(range);
if (autofocus) field.focus();
});
</script>

<script lang="ts">
import { createEventDispatcher, tick } from 'svelte';
import cs from 'clsx';
export let searchTerm = '';
export let autofocus = true;
export let showIcon = true;
export let placeholder = '';
export let disabled = false;
export let iconPosition: 'left' | 'right' = 'right';
export let submitOnBlur = false;
export function hasFocus() {
return document.activeElement === inputEl;
}
export function setFocus() {
tick().then(() => inputEl?.focus());
}
const dispatch = createEventDispatcher<{ keypress: void }>();
let inputEl: HTMLDivElement | undefined;
$: autofocus && setFocus();
$: placeholder = searchTerm ? '' : placeholder;
$: if (inputEl && searchTerm) {
inputEl.removeAttribute('data-placeholder');
} else if (inputEl) {
inputEl.setAttribute('data-placeholder', placeholder);
}
$: inputEl && updateCursor(inputEl, autofocus);
function handleKeyPress(ev: KeyboardEvent) {
if (ev.key === 'Enter' && !ev.shiftKey && searchTerm) {
ev.preventDefault();
dispatch('keypress');
}
}
function onInput() {
if (!inputEl) return;
if (inputEl.innerHTML.trim() === '<br>') {
inputEl.innerHTML = '';
}
}
</script>

<div
class="relative flex min-h-14 w-full gap-x-2 rounded-md border-2 border-zinc-500 p-1 pl-2.5 focus-within:border-emerald-600"
>
{#if showIcon && iconPosition === 'left'}
<slot name="icon-left" {disabled} />
{/if}

<div class="flex w-[90%] overflow-y-auto overflow-x-hidden pl-0.5 pr-0 pt-2 outline-none">
<div
id="contentDiv"
role="textbox"
tabindex="0"
contenteditable
class={cs(
'peer block h-full w-full break-words border-none bg-transparent text-left text-[16px] outline-none',
{ 'pointer-events-none': disabled }
)}
data-placeholder={placeholder}
spellcheck={false}
bind:this={inputEl}
bind:textContent={searchTerm}
on:keypress={handleKeyPress}
on:blur={() => submitOnBlur && dispatch('keypress')}
on:input={onInput}
/>
</div>
<div class:hidden={!$$slots['icon-right']} class="absolute bottom-0 right-0 flex h-full pr-2">
{#if showIcon && iconPosition === 'right'}
<span class="self-end">
<slot name="icon-right" {disabled} />
</span>
{/if}
</div>
</div>

<style lang="postcss">
#contentDiv[data-placeholder]::before {
content: attr(data-placeholder);
color: rgba(var(--fg));
opacity: 0.6;
font-size: 16px;
pointer-events: none;
display: inline-block;
}
#contentDiv[data-placeholder]::before {
@apply bg-gradient-to-r from-gray-400 to-emerald-200 bg-clip-text text-transparent;
}
</style>
44 changes: 44 additions & 0 deletions app/src/lib/components/ChatBoxIcon.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script lang="ts">
import { SearchIcon, SendIcon } from 'lucide-svelte';
import cs from 'clsx';
import Spinner from './Spinner.svelte';
export let loading = false;
export let disabled = false;
export let searchTerm = '';
export let iconType: 'search' | 'send' = 'search';
</script>

<button
class={cs(
'my-2 flex h-8 w-8 items-center justify-center rounded-md outline-none transition duration-200 ease-in-out hover:scale-[1.02] active:translate-y-1',
{
'p-1': iconType === 'search',
'p-2': iconType === 'send',
'bg-gray-600': (searchTerm || loading) && iconType === 'send'
}
)}
disabled={disabled || !searchTerm}
on:click
>
{#if loading}
<span class:text-white={iconType === 'send'}>
<Spinner small />
</span>
{:else if iconType === 'send'}
<svg
class="h-6 w-6 fill-gray-600 transition-colors duration-200"
class:opacity-50={!searchTerm}
class:text-white={searchTerm}
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path fill="currentColor" d="m2 21l21-9L2 3v7l15 2l-15 2v7Z" />
</svg>
{:else}
<SendIcon
class="h-full w-full rounded-sm opacity-70 transition-colors duration-200 hover:bg-gray-400/40"
/>
{/if}
</button>
6 changes: 3 additions & 3 deletions app/src/lib/components/ChatContainer.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="relative overflow-hidden w-full flex flex-col h-full">
<div class="overflow-auto px-10 w-full block h-[calc(85%-2.5rem)]">
<div class="overflow-auto px-10 w-full block h-[calc(86%-2.5rem)]">
<div class="flex flex-col gap-y-2">
<h1 class="text-5xl font-bold">🎧 Audiora</h1>
<h2 class="text-lg">Listen to anything, anytime.</h2>
Expand All @@ -8,7 +8,7 @@
<slot name="content"></slot>
</div>

<div class="h-[16%] fixed w-[calc(100%-24.5rem)] bottom-0 shrink-0">
<slot name="chat_input"></slot>
<div class="h-[14%] fixed px-10 w-[calc(100%-24.5rem)] bottom-0 shrink-0">
<slot name="chat_box"></slot>
</div>
</div>
19 changes: 19 additions & 0 deletions app/src/lib/components/Spinner.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script>
import cs from 'clsx';
export let small = false;
</script>

<spinner>
<svg
class={cs('animate-spin', {
'h-4 w-4': small,
'h-6 w-6': !small
})}
viewBox="0 0 256 256"
>
<path
fill="currentColor"
d="M140 32v32a12 12 0 0 1-24 0V32a12 12 0 0 1 24 0Zm33.25 62.75a12 12 0 0 0 8.49-3.52l22.63-22.63a12 12 0 0 0-17-17l-22.6 22.66a12 12 0 0 0 8.48 20.49ZM224 116h-32a12 12 0 0 0 0 24h32a12 12 0 0 0 0-24Zm-42.26 48.77a12 12 0 1 0-17 17l22.63 22.63a12 12 0 0 0 17-17ZM128 180a12 12 0 0 0-12 12v32a12 12 0 0 0 24 0v-32a12 12 0 0 0-12-12Zm-53.74-15.23L51.63 187.4a12 12 0 0 0 17 17l22.63-22.63a12 12 0 1 0-17-17ZM76 128a12 12 0 0 0-12-12H32a12 12 0 0 0 0 24h32a12 12 0 0 0 12-12Zm-7.4-76.37a12 12 0 1 0-17 17l22.66 22.6a12 12 0 0 0 17-17Z"
/>
</svg>
</spinner>
19 changes: 17 additions & 2 deletions app/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
<script lang="ts">
import RenderExamples from '@/components/RenderExamples.svelte';
import ChatContainer from '@/components/ChatContainer.svelte';
import ChatBox from '@/components/ChatBox.svelte';
import ChatBoxIcon from '@/components/ChatBoxIcon.svelte';
export let data;
let searchTerm = '';
$: sessionId = data.sessionId;
function handleSearch() {
if (searchTerm) {
console.log(searchTerm);
}
}
</script>

<svelte:head>
Expand All @@ -12,7 +23,11 @@
<ChatContainer>
<RenderExamples slot="content" {sessionId} />

<div slot="chat_input" class="h-[16%] fixed w-[calc(100%-24.5rem)] bottom-0 shrink-0">
Chat Input Section
<div slot="chat_box">
<ChatBox bind:searchTerm placeholder="What would you like to listen to?">
<svelte:fragment slot="icon-right">
<ChatBoxIcon iconType="send" {searchTerm} on:click={handleSearch} />
</svelte:fragment>
</ChatBox>
</div>
</ChatContainer>
9 changes: 6 additions & 3 deletions app/src/routes/[sessionId=sessionId]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<script>
import ChatContainer from '@/components/ChatContainer.svelte';
export let data;
import ChatBox from '@/components/ChatBox.svelte';
export let data;
$: category = data.category;
$: sessionId = data.sessionId;
let searchTerm = '';
</script>

<ChatContainer>
<div slot="content">
{sessionId}: {category}
</div>

<div slot="chat_input" class="h-[16%] fixed w-[calc(100%-24.5rem)] bottom-0 shrink-0">
Chat Input Section
<div slot="chat_box">
<ChatBox bind:searchTerm placeholder="What would you like to listen to?" />
</div>
</ChatContainer>

0 comments on commit 4b64f1d

Please sign in to comment.