Spaces:
Runtime error
Runtime error
File size: 4,071 Bytes
9e93b10 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | <script lang="ts">
import { getContext } from "svelte";
import { models } from "$lib/stores";
import { REXPRO_API_BASE_URL } from "$lib/constants";
import Dropdown from "$lib/components/common/Dropdown.svelte";
import Search from "$lib/components/icons/Search.svelte";
const i18n = getContext("i18n");
export let model_id = "";
export let side: "top" | "bottom" = "top";
export let align: "start" | "end" = "start";
/** Optional callback when selection changes */
export let onChange: () => void = () => {};
let showDropdown = false;
let modelSearch = "";
$: modelLabel = model_id
? $models.find((m) => m.id === model_id)?.name || model_id
: $i18n.t("Select model");
$: filteredModels = (
modelSearch
? $models.filter(
(m) =>
m.name
.toLowerCase()
.includes(modelSearch.toLowerCase()) ||
m.id.toLowerCase().includes(modelSearch.toLowerCase()),
)
: $models
).filter((m) => !(m?.info?.meta?.hidden ?? false));
</script>
<Dropdown bind:show={showDropdown} {side} {align}>
<button
type="button"
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
text-gray-600 dark:text-gray-400 hover:bg-black/5 dark:hover:bg-white/5"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-3.5 shrink-0"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 0 0-2.455 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z"
/>
</svg>
<span class="whitespace-nowrap max-w-32 truncate">{modelLabel}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
class="size-2.5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m19.5 8.25-7.5 7.5-7.5-7.5"
/>
</svg>
</button>
<div
slot="content"
class="rounded-2xl shadow-lg border border-gray-200 dark:border-gray-800 flex flex-col bg-white dark:bg-gray-850 w-72 p-1"
>
<div class="flex items-center gap-2 px-2.5 py-1.5">
<Search className="size-3.5" strokeWidth="2.5" />
<input
bind:value={modelSearch}
class="w-full text-sm bg-transparent outline-hidden"
placeholder={$i18n.t("Search a model")}
autocomplete="off"
on:click={(e) => e.stopPropagation()}
/>
</div>
<div class="overflow-y-auto scrollbar-thin max-h-60">
<div class="px-2 text-xs text-gray-500 py-1">
{$i18n.t("Models")}
</div>
{#each filteredModels as model (model.id)}
<button
class="px-2.5 py-1.5 rounded-xl w-full text-left text-sm {model_id ===
model.id
? 'bg-gray-50 dark:bg-gray-800'
: ''}"
type="button"
on:click={() => {
model_id = model.id;
showDropdown = false;
modelSearch = "";
onChange();
}}
>
<div
class="flex text-black dark:text-gray-100 line-clamp-1"
>
<img
src={`${REXPRO_API_BASE_URL}/models/model/profile/image?id=${encodeURIComponent(model.id)}`}
alt={model?.name ?? model.id}
class="rounded-md size-5 items-center mr-2"
loading="lazy"
on:error={(e) => {
e.currentTarget.src = "/favicon.png";
}}
/>
<div class="truncate">
{model.name}
</div>
</div>
</button>
{:else}
<div
class="block px-3 py-2 text-sm text-gray-700 dark:text-gray-100"
>
{$i18n.t("No results found")}
</div>
{/each}
</div>
</div>
</Dropdown>
|