Spaces:
Runtime error
Runtime error
File size: 3,877 Bytes
76a5c60 62ec7ad 76a5c60 62ec7ad 725337f 62ec7ad 76a5c60 725337f 62ec7ad 725337f 76a5c60 725337f 62ec7ad 725337f 62ec7ad 725337f 62ec7ad 725337f 62ec7ad 725337f 62ec7ad 725337f 62ec7ad 725337f 62ec7ad 725337f 62ec7ad 725337f 76a5c60 |
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 |
<script lang="ts">
import { goto } from "$app/navigation";
import { base } from "$app/paths";
import { useSettingsStore } from "$lib/stores/settings";
import CarbonUser from "~icons/carbon/user";
import CarbonSwitcher from "~icons/carbon/switcher";
import CarbonLocked from "~icons/carbon/locked";
interface Props {
lockedPersonaId?: string;
}
let { lockedPersonaId }: Props = $props();
const settings = useSettingsStore();
const availablePersonas = $derived($settings.personas.filter((persona) => !persona.archived));
// If locked, show only the locked persona; otherwise show active personas
let activePersonas = $derived(
lockedPersonaId
? availablePersonas.filter((persona) => persona.id === lockedPersonaId)
: $settings.activePersonas
.map((id) => availablePersonas.find((persona) => persona.id === id))
.filter(Boolean)
);
let displayText = $derived(() => {
if (activePersonas.length === 0) return "No active personas";
if (activePersonas.length === 1) return activePersonas[0]?.name ?? "Default";
return `${activePersonas.length} personas`;
});
let showDropdown = $state(false);
let hideTimeout: number | undefined = $state();
function handleMouseEnter() {
if (hideTimeout) {
clearTimeout(hideTimeout);
hideTimeout = undefined;
}
if (activePersonas.length > 1 && !lockedPersonaId) {
showDropdown = true;
}
}
function handleMouseLeave() {
hideTimeout = window.setTimeout(() => {
showDropdown = false;
}, 100);
}
</script>
<div class="relative">
<button
class="flex items-center gap-1.5 rounded-lg border border-gray-300 bg-gray-100 px-3 py-1.5 text-sm text-gray-400 shadow-sm dark:border-gray-600 dark:bg-gray-800 dark:text-gray-500 {lockedPersonaId ? 'cursor-not-allowed opacity-75' : 'hover:bg-gray-200 dark:hover:bg-gray-700'}"
onclick={() => {
if (!lockedPersonaId) {
const firstActive = $settings.activePersonas.find((id) =>
availablePersonas.some((persona) => persona.id === id)
);
const fallback = availablePersonas[0]?.id ?? "";
goto(`${base}/settings/personas/${firstActive ?? fallback}`);
}
}}
onmouseenter={handleMouseEnter}
onmouseleave={handleMouseLeave}
title={lockedPersonaId ? "Persona locked in branch" : (activePersonas.length === 1 ? 'Manage personas' : '')}
>
{#if lockedPersonaId}
<CarbonLocked class="text-xs" />
{:else}
<CarbonUser class="text-xs" />
{/if}
<span class="max-w-[150px] truncate">{displayText()}</span>
</button>
{#if showDropdown && activePersonas.length > 1}
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
<div
role="menu"
tabindex="-1"
class="absolute bottom-full left-0 mb-2 min-w-[200px] animate-in fade-in slide-in-from-bottom-2 duration-300 rounded-lg border border-gray-300 bg-gray-100 py-1.5 shadow-lg dark:border-gray-600 dark:bg-gray-800"
onmouseenter={handleMouseEnter}
onmouseleave={handleMouseLeave}
>
<div class="px-3 py-1.5 text-xs font-semibold text-gray-400 dark:text-gray-500">
Active Personas
</div>
{#each activePersonas as persona (persona?.id)}
<button
type="button"
class="group flex w-full items-center justify-between gap-2 px-3 py-1.5 text-left text-sm text-gray-400 transition-all duration-200 hover:bg-gray-200 hover:pl-4 hover:text-gray-600 dark:text-gray-500 dark:hover:bg-gray-700 dark:hover:text-gray-300"
onclick={() => goto(`${base}/settings/personas/${persona?.id || ''}`)}
>
<div class="flex items-center gap-2 truncate">
<div class="size-1.5 flex-shrink-0 rounded-full bg-gray-400 dark:bg-gray-500"></div>
<span class="truncate">{persona?.name ?? "Unknown"}</span>
</div>
<CarbonSwitcher class="size-3.5 flex-shrink-0 text-gray-400 opacity-0 transition-opacity duration-200 group-hover:opacity-100 dark:text-gray-500" />
</button>
{/each}
</div>
{/if}
</div>
|