<svelte:options runes={true} /> <script lang="ts"> import { OpenInNewWindow } from 'radix-icons-svelte'; import { quintInOut } from 'svelte/easing'; import { slide } from 'svelte/transition'; import { IconType, type Service } from '$lib/types/data-types'; import { Skeleton } from '$lib/components/ui/skeleton'; import type { Heartbeat } from '$lib/types/uptime-kuma-types'; let { service, icons, monitor } = $props<{ service: Service; icons: Array<string>; monitor: Heartbeat; }>(); let status = $state(4); let hover = $state({ title: false, link: false, ext: false }); let img_source: string = $state(''); function checkForImage(service: Service) { const rootSplit = service.icon.split('/'); const root = rootSplit[rootSplit.length - 1]; if (icons.includes(`${root}.${service.iconType}`)) { img_source = `${service.icon}.${service.iconType}`; } else { img_source = ''; } } $effect(() => { if (typeof monitor !== 'undefined') { status = monitor.status; } if (icons.length != 0) { const rootSplit = service.icon.split('/'); const root = rootSplit[rootSplit.length - 1]; if (service.iconType === IconType.SVG) { checkForImage(service); } else { if (icons.includes(`${root}-36.${service.iconType}`)) { img_source = `${service.icon}-36.${service.iconType}`; } else { checkForImage(service); } } } }); </script> <div class="z-0 flex h-48 w-[28rem] flex-col gap-y-3 rounded-xl border-t-4 border-secondary bg-black/55 p-4 backdrop-blur-sm" > <div class="flex flex-row justify-between"> <div class="flex flex-row items-center gap-1" on:mouseover={() => (hover.title = true)} on:mouseleave={() => (hover.title = false)} > {#if service.icon} {#if img_source != ''} <img width="24px" class="h-6 w-6 cursor-pointer" src={img_source} alt="{service.name} Logo" /> {:else} <Skeleton class="h-6 w-6 rounded-full" /> {/if} {:else}{/if} <a href={service.href} class="font-bold {!hover.title || 'text-secondary'}">{service.name}</a> {#if hover.title} <div transition:slide={{ delay: 100, duration: 200, easing: quintInOut, axis: 'x' }} class="grid items-center" > <OpenInNewWindow color={hover.title ? 'hsl(var(--secondary))' : 'hsl(var(--primary)'} class="self-center" /> </div> {/if} </div> </div> <p class="text-wrap text-center text-sm">{service.desc}</p> <p class="text-center text-sm font-bold text-destructive">{service.warn}</p> <div class="grid {service.extLink ? 'grid-cols-2' : 'grid-cols-1'} mt-auto justify-items-center"> <a class="flex flex-row rounded-md border-x-2 px-2 text-sm hover:border-secondary hover:text-secondary" href={service.href} on:mouseover={() => (hover.link = true)} on:mouseleave={() => (hover.link = false)} > Open {#if hover.link} <div transition:slide={{ delay: 100, duration: 200, easing: quintInOut, axis: 'x' }} class="grid items-center pl-1 pr-0" > <OpenInNewWindow color={hover.link ? 'hsl(var(--secondary))' : 'hsl(var(--primary)'} class="self-center" /> </div> {/if} </a> {#if service.extLink} <a class="flex flex-row rounded-md border-x-2 px-2 text-sm hover:border-secondary hover:text-secondary" href={service.extLink} on:mouseover={() => (hover.ext = true)} on:mouseleave={() => (hover.ext = false)} > Official Site {#if hover.ext} <div transition:slide={{ delay: 100, duration: 200, easing: quintInOut, axis: 'x' }} class="grid items-center pl-1 pr-0" > <OpenInNewWindow color={hover.ext ? 'hsl(var(--secondary))' : 'hsl(var(--primary)'} class="self-center" /> </div> {/if} </a> {/if} </div> </div>