your personal website on atproto - mirror
blento.app
1<script lang="ts">
2 import { marked } from 'marked';
3 import { user, login } from '$lib/atproto';
4 import { Button } from '@foxui/core';
5 import { BlueskyLogin } from '@foxui/social';
6 import { env } from '$env/dynamic/public';
7 import type { WebsiteData } from '$lib/types';
8 import { getDescription, getImage, getName, getProfilePosition } from '$lib/helper';
9 import { page } from '$app/state';
10 import type { ActorIdentifier } from '@atcute/lexicons';
11 import { qrOverlay } from '$lib/components/qr/qrOverlay.svelte';
12 import MadeWithBlento from './MadeWithBlento.svelte';
13
14 let {
15 data,
16 showEditButton = false
17 }: {
18 data: WebsiteData;
19 showEditButton?: boolean;
20 } = $props();
21
22 const renderer = new marked.Renderer();
23 renderer.link = ({ href, title, text }) =>
24 `<a target="_blank" href="${href}" title="${title}">${text}</a>`;
25
26 const profileUrl = $derived(`${page.url.origin}/${data.handle}`);
27 const profilePosition = $derived(getProfilePosition(data));
28</script>
29
30<!-- lg:fixed lg:h-screen lg:w-1/4 lg:max-w-none lg:px-12 lg:pt-24 xl:w-1/3 -->
31<div
32 class={[
33 'mx-auto flex max-w-lg flex-col justify-between px-8',
34 profilePosition === 'side'
35 ? '@5xl/wrapper:fixed @5xl/wrapper:h-screen @5xl/wrapper:w-1/4 @5xl/wrapper:max-w-none @5xl/wrapper:px-12'
36 : '@5xl/wrapper:max-w-4xl @5xl/wrapper:px-12'
37 ]}
38>
39 <div
40 class={[
41 'flex flex-col gap-4 pt-16 pb-8',
42 profilePosition === 'side' && '@5xl/wrapper:h-screen @5xl/wrapper:pt-24'
43 ]}
44 >
45 <a
46 href={profileUrl}
47 class="w-fit"
48 use:qrOverlay={{
49 context: {
50 title: getName(data) + "'s blento"
51 }
52 }}
53 >
54 {#if data.publication?.icon || data.profile.avatar}
55 <img
56 class={[
57 'border-base-400 dark:border-base-800 size-32 shrink-0 rounded-full border object-cover',
58 profilePosition === 'side' && '@5xl/wrapper:size-44'
59 ]}
60 src={getImage(data.publication, data.did, 'icon') || data.profile.avatar}
61 alt=""
62 />
63 {:else}
64 <div
65 class={[
66 'bg-base-300 dark:bg-base-700 size-32 shrink-0 rounded-full',
67 profilePosition === 'side' && '@5xl/wrapper:size-44'
68 ]}
69 ></div>
70 {/if}
71 </a>
72
73 <div class="text-4xl font-bold wrap-anywhere">
74 {getName(data)}
75 </div>
76
77 <div class="scrollbar -mx-4 grow overflow-x-hidden overflow-y-scroll px-4">
78 <div
79 class="text-base-600 dark:text-base-400 prose dark:prose-invert prose-a:text-accent-500 prose-a:no-underline"
80 >
81 {@html marked.parse(getDescription(data), {
82 renderer
83 })}
84 </div>
85 </div>
86
87 {#if showEditButton && user.isLoggedIn && user.profile?.did === data.did}
88 <div>
89 <Button href="{page.url}/edit" class="mt-2">
90 <svg
91 xmlns="http://www.w3.org/2000/svg"
92 fill="none"
93 viewBox="0 0 24 24"
94 stroke-width="1.5"
95 stroke="currentColor"
96 >
97 <path
98 stroke-linecap="round"
99 stroke-linejoin="round"
100 d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"
101 />
102 </svg>
103
104 Edit Your Website</Button
105 >
106 </div>
107 {:else}
108 <div class={['h-10.5 w-1', profilePosition === 'side' && '@5xl/wrapper:hidden']}></div>
109 {/if}
110
111 {#if !env.PUBLIC_IS_SELFHOSTED && data.handle === 'blento.app' && user.profile?.handle !== data.handle}
112 {#if !user.isInitializing && !user.isLoggedIn}
113 <div>
114 <div class="my-4 text-sm">
115 To create your own blento, sign in with your bluesky account
116 </div>
117 <BlueskyLogin
118 login={async (handle) => {
119 await login(handle as ActorIdentifier);
120 return true;
121 }}
122 />
123 </div>
124 {:else if user.isLoggedIn}
125 <div>
126 <Button href="/{env.PUBLIC_IS_SELFHOSTED ? '' : user.profile?.handle}/edit" class="mt-2">
127 <svg
128 xmlns="http://www.w3.org/2000/svg"
129 fill="none"
130 viewBox="0 0 24 24"
131 stroke-width="1.5"
132 stroke="currentColor"
133 >
134 <path
135 stroke-linecap="round"
136 stroke-linejoin="round"
137 d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25"
138 />
139 </svg>
140
141 Edit Your Blento</Button
142 >
143 </div>
144 {/if}
145 {/if}
146 <MadeWithBlento class="hidden {profilePosition === 'side' && '@5xl/wrapper:block'}" />
147 </div>
148</div>