062832a1e3
$state runes only work in .svelte and .svelte.ts files. The toasts and theme stores used $state in plain .ts files, which compiled in dev but crashed in production SSR. Renamed and updated all imports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
56 lines
2.5 KiB
Svelte
56 lines
2.5 KiB
Svelte
<script lang="ts">
|
|
import { fly } from 'svelte/transition';
|
|
import { getToasts, removeToast, type ToastType } from '$lib/stores/toasts.svelte.js';
|
|
|
|
const toasts = $derived(getToasts());
|
|
|
|
function typeClasses(type: ToastType): string {
|
|
switch (type) {
|
|
case 'success':
|
|
return 'bg-green-600 text-white';
|
|
case 'error':
|
|
return 'bg-red-600 text-white';
|
|
case 'warning':
|
|
return 'bg-yellow-500 text-white';
|
|
case 'info':
|
|
return 'bg-blue-600 text-white';
|
|
}
|
|
}
|
|
|
|
function typeIcon(type: ToastType): string {
|
|
switch (type) {
|
|
case 'success':
|
|
return 'M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z';
|
|
case 'error':
|
|
return 'M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z';
|
|
case 'warning':
|
|
return 'M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z';
|
|
case 'info':
|
|
return 'M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z';
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="fixed bottom-4 right-4 z-[100] flex flex-col gap-2 pointer-events-none">
|
|
{#each toasts as t (t.id)}
|
|
<div
|
|
class="pointer-events-auto flex items-center gap-2 rounded-lg px-4 py-3 shadow-lg text-sm font-medium min-w-[280px] max-w-sm {typeClasses(t.type)}"
|
|
transition:fly={{ x: 100, duration: 300 }}
|
|
>
|
|
<svg class="w-4 h-4 flex-shrink-0" viewBox="0 0 20 20" fill="currentColor">
|
|
<path fill-rule="evenodd" d={typeIcon(t.type)} clip-rule="evenodd" />
|
|
</svg>
|
|
<span class="flex-1">{t.message}</span>
|
|
<button
|
|
onclick={() => removeToast(t.id)}
|
|
class="flex-shrink-0 opacity-70 hover:opacity-100 transition"
|
|
aria-label="Dismiss"
|
|
>
|
|
<svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
|
|
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
{/each}
|
|
</div>
|