|
|
@@ -0,0 +1,45 @@
|
|
|
+<script generics="T" lang="ts">
|
|
|
+ import type { Snippet } from 'svelte';
|
|
|
+ import type { ClassValue } from 'svelte/elements';
|
|
|
+
|
|
|
+ import type { TestResponse } from '$lib/api/types';
|
|
|
+ import { Spinner } from '$lib/components/controls/spinner';
|
|
|
+
|
|
|
+ let {
|
|
|
+ class: className = '',
|
|
|
+ loading = false,
|
|
|
+ response,
|
|
|
+ error,
|
|
|
+ result,
|
|
|
+ }: {
|
|
|
+ class?: ClassValue;
|
|
|
+ loading?: boolean;
|
|
|
+ response?: TestResponse<T>;
|
|
|
+ error?: { type: string; message: string };
|
|
|
+ result: Snippet<[T | undefined]>;
|
|
|
+ } = $props();
|
|
|
+</script>
|
|
|
+
|
|
|
+<div class={['relative', className]}>
|
|
|
+ {#if error || response?.error}
|
|
|
+ <div class="flex h-48 flex-col items-center justify-center p-4">
|
|
|
+ <div class="text-sm font-medium text-red-500/50">
|
|
|
+ {error?.type || response?.error?.type}
|
|
|
+ </div>
|
|
|
+ <div class="text-sm text-white/50">{error?.message || response?.error?.message}</div>
|
|
|
+ </div>
|
|
|
+ {:else if response}
|
|
|
+ <div class={loading ? 'blur-[2px]' : ''}>
|
|
|
+ {@render result(response.response)}
|
|
|
+ </div>
|
|
|
+ {:else}
|
|
|
+ <div class="flex h-48 flex-col items-center justify-center">
|
|
|
+ <p class="text-sm text-white/50">No results yet</p>
|
|
|
+ </div>
|
|
|
+ {/if}
|
|
|
+ {#if loading}
|
|
|
+ <div class="absolute inset-0 z-10 flex items-center justify-center bg-black/25">
|
|
|
+ <Spinner class="size-6" />
|
|
|
+ </div>
|
|
|
+ {/if}
|
|
|
+</div>
|