Spaces:
Running
Running
| <script lang="ts"> | |
| import { clickoutside } from '@svelte-put/clickoutside'; | |
| import { goto } from "$app/navigation"; | |
| import { page } from "$app/stores"; | |
| import { get } from "svelte/store"; | |
| import Icon from "@iconify/svelte"; | |
| import { modelStore } from "$lib/stores/use-model"; | |
| import UserIsLogged from '$lib/components/UserIsLogged.svelte'; | |
| import Comments from '$lib/components/models/drawer/comments/Comments.svelte'; | |
| import { env } from '$env/dynamic/public'; | |
| import { browser } from '$app/environment'; | |
| let { open, model } = get(modelStore); | |
| modelStore.subscribe((value) => { | |
| open = value?.open; | |
| model = value?.model; | |
| }); | |
| const handleClose = () => { | |
| modelStore.update((value) => { | |
| return { | |
| ...value, | |
| open: false, | |
| }; | |
| }); | |
| $page.url.searchParams.delete('model'); | |
| goto(`?${$page.url.searchParams.toString()}`); | |
| }; | |
| const handleClickNext = () => { | |
| const element = document.getElementById('gallery_examples'); | |
| element?.scrollBy({ | |
| left: 300, | |
| behavior: 'smooth' | |
| }); | |
| } | |
| </script> | |
| <div | |
| class="w-full fixed top-0 left-0 h-full bg-black bg-opacity-50 z-0 backdrop-blur transition-all duration-100" | |
| class:opacity-0={!open} | |
| class:pointer-events-none={!open} | |
| class:!z-40={open} | |
| > | |
| {#if open} | |
| <div | |
| class="ml-auto w-full max-w-3xl bg-neutral-950 h-full border-l border-neutral-800 transition-all duration-200 flex flex-col justify-between" | |
| use:clickoutside on:clickoutside={handleClose} | |
| > | |
| <div class="p-8 overflow-auto"> | |
| <header class="flex w-full justify-between items-start mb-6 pr-6"> | |
| <div class="flex items-center justify-start gap-3 lg:gap-6"> | |
| <img src={model?.image} class="lg:w-16 lg:h-16 w-12 h-12 rounded-xl bg-neutral-800 object-cover" alt={model?.id} /> | |
| <div> | |
| <p class="text-white font-semibold text-lg lg:text-2xl mb-1 truncate"> | |
| {model?.title ?? model?.id} | |
| </p> | |
| <a href="https://huggingface.co/{model?.id}" target="_blank" class="text-neutral-400 underline hover:text-neutral-300 flex items-center justify-start gap-1"> | |
| <Icon icon="iconamoon:link-external-fill" class="w-4 h-4" /> | |
| View on HuggingFace | |
| </a> | |
| </div> | |
| </div> | |
| <button on:click={handleClose}> | |
| <Icon icon="carbon:close" class="w-6 h-6 text-white cursor-pointer" /> | |
| </button> | |
| </header> | |
| <main class="grid grid-cols-1 gap-6"> | |
| <div class="justify-start items-center gap-4 flex"> | |
| <div class="bg-red-500 bg-opacity-20 border border-red-500 md:px-4 md:py-2 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 md:gap-2 font-medium text-sm md:text-base"> | |
| <Icon icon="solar:heart-bold" class="lg:w-5 lg:h-5 w-4 h-4 text-red-500" /> | |
| {model?.likes ?? 0} | |
| </div> | |
| <a | |
| href="https://huggingface.co/{model?.id}/tree/main" | |
| class="bg-blue-500 bg-opacity-20 border border-blue-500 hover:bg-opacity-60 transition-all duration-200 md:px-4 md:py-2 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 md:gap-2 font-medium text-sm md:text-base" | |
| > | |
| <Icon icon="solar:download-square-bold" class="lg:w-5 lg:h-5 w-4 h-4 text-blue-500" /> | |
| View files | |
| </a> | |
| <a | |
| href="/generate?model={model?.id}" | |
| class="bg-pink-500 bg-opacity-20 hover:bg-opacity-60 transition-all duration-200 border border-pink-500 md:px-4 md:py-2 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 md:gap-2 font-medium text-sm md:text-base" | |
| > | |
| <Icon icon="fluent:glance-horizontal-sparkles-16-filled" class="lg:w-5 lg:h-5 w-4 h-4 text-pink-500" /> | |
| Generate | |
| </a> | |
| </div> | |
| {#if model?.gallery && model?.gallery?.length > 0} | |
| <div class="-mr-8 relative"> | |
| <p class="text-neutral-400 uppercase text-xs font-bold"> | |
| Generations made by the community | |
| </p> | |
| <div id="gallery_examples" class="w-full h-[300px] mt-2 flex flex-nowrap overflow-auto gap-5 relative"> | |
| {#each model?.gallery as example} | |
| <div class="w-[300px] min-w-[300px] h-full relative"> | |
| <img src="{env.PUBLIC_FILE_UPLOAD_DIR}/{example.image}" class="w-full h-full bg-center bg-cover rounded-lg object-cover object-center bg-neutral-800" alt={example.prompt} /> | |
| </div> | |
| {/each} | |
| </div> | |
| <div class="w-[100px] h-full absolute right-0 top-0 bg-gradient-to-r from-transparent to-neutral-950 flex items-center justify-end pr-4"> | |
| <button | |
| class="w-8 h-8 rounded-full bg-neutral-100/20 flex items-center justify-center text-neutral-100 hover:bg-neutral-100/40 transition-all duration-200" | |
| on:click={handleClickNext} | |
| > | |
| <Icon icon="tabler:arrow-narrow-right" class="w-5 h-5" /> | |
| </button> | |
| </div> | |
| </div> | |
| {:else} | |
| <div class="bg-neutral-900 rounded-lg p-8 text-center"> | |
| <p class="text-neutral-400 font-base">No generation examples available for this model</p> | |
| <a href="/generate?model={model?.id}" class="text-neutral-100 underline"> | |
| Generate the first one | |
| </a> | |
| </div> | |
| {/if} | |
| {#if model?.infos} | |
| <div class="bg-neutral-900/70 rounded-lg border border-neutral-800/20"> | |
| <div class="border-b border-neutral-800/80 px-4 py-3"> | |
| <p class="text-neutral-400 uppercase text-[10px]">license</p> | |
| <p class="text-neutral-100 font-medium text-xs mt-0.5">{model?.infos?.license ?? 'N/A'}</p> | |
| </div> | |
| <div class="border-b border-neutral-800/80 px-4 py-3"> | |
| <p class="text-neutral-400 uppercase text-[10px]">tags</p> | |
| <p class="text-neutral-100 font-medium text-xs mt-0.5">{model?.infos?.tags?.join(', ')}</p> | |
| </div> | |
| <div class="px-4 py-3"> | |
| <p class="text-neutral-400 uppercase text-[10px]">base_model</p> | |
| <p class="text-neutral-100 font-medium text-xs mt-0.5">{model?.infos?.base_model ?? 'N/A'}</p> | |
| </div> | |
| </div> | |
| {/if} | |
| </main> | |
| </div> | |
| <footer class="p-8 border-t border-neutral-900 bg-neutral-900/30"> | |
| <p class="font-semibold text-neutral-100 text-base lg:text-lg mb-6"> | |
| Commentaire{(model?.comments?.length ?? 0) > 1 ? 's' : ''} ({model?.comments?.length ?? 0}) | |
| </p> | |
| {#if model?.id} | |
| <UserIsLogged> | |
| <Comments comments={model?.comments} model={model} /> | |
| </UserIsLogged> | |
| {/if} | |
| </footer> | |
| </div> | |
| {/if} | |
| </div> |