<script module lang="ts">
import { tv, type VariantProps } from "tailwind-variants";
import type { AvatarSize } from "#lib/components/ui/Avatar.svelte";
export const user = tv({
slots: {
root: "inline-flex min-w-0 items-center",
handle: "min-w-0 truncate"
},
variants: {
size: {
header: {
root: "gap-xs",
handle: "typography-heading-4"
},
large: {
root: "gap-1.5",
handle: "typography-paragraph-large"
},
regular: {
root: "gap-1.5",
handle: "typography-paragraph-regular"
},
small: {
root: "gap-1.5",
handle: "typography-paragraph-small"
},
mini: {
root: "gap-2xs",
handle: "typography-paragraph-mini"
}
},
link: {
true: {
root: "text-foreground-default hover:underline"
}
}
},
defaultVariants: {
size: "regular",
link: false
}
});
export type UserVariants = VariantProps<typeof user>;
const avatarSize = {
header: "large",
large: "large",
regular: "regular",
small: "small",
mini: "mini"
} satisfies Record<NonNullable<UserVariants["size"]>, AvatarSize>;
</script>
<script lang="ts">
import { isDid, isHandle } from "@atcute/lexicons/syntax";
import { profileIdentifier } from "#lib/api/identity.ts";
import { resolve } from "$app/paths";
import Avatar from "#lib/components/ui/Avatar.svelte";
import VouchAvatar from "#lib/components/profile/VouchAvatar.svelte";
interface Props {
handle?: string;
did?: string;
avatarCid?: string | null;
size?: UserVariants["size"];
showImage?: boolean;
showText?: boolean;
class?: string;
avatarClass?: string;
handleClass?: string;
link?: boolean;
email?: string;
vouchBadge?: boolean;
loading?: "lazy" | "eager";
}
let {
handle,
did,
avatarCid,
size = "regular",
showImage = true,
showText = true,
class: className,
avatarClass,
handleClass,
link = false,
email,
vouchBadge = false,
loading
}: Props = $props();
const identified = $derived(isDid(did) ? did : undefined);
const actor = $derived(
identified ? profileIdentifier(isHandle(handle) ? handle : undefined, identified) : handle
);
const linked = $derived(link && actor !== undefined);
const slots = $derived(user({ size, link: linked }));
</script>
{#snippet body()}
{#if showImage}
{#if vouchBadge && did}
<VouchAvatar
{did}
{avatarCid}
{handle}
size={avatarSize[size]}
{loading}
class={avatarClass}
/>
{:else}
<Avatar
{did}
{avatarCid}
{handle}
size={avatarSize[size]}
{loading}
class={avatarClass}
/>
{/if}
{/if}
{#if showText && handle}
<span class={slots.handle({ class: handleClass })} title={actor}>{actor}</span>
{/if}
{/snippet}
{#if linked}
{#if email}
<a href="mailto:{email}" class={slots.root({ class: className })}>
{@render body()}
</a>
{:else}
<a href={resolve(`/${actor}` as "/")} class={slots.root({ class: className })}>
{@render body()}
</a>
{/if}
{:else}
<span class={slots.root({ class: className })}>
{@render body()}
</span>
{/if}