your personal website on atproto - mirror blento.app
at fix-formatting 282 lines 7.9 kB view raw
1<script lang="ts"> 2 import { dev } from '$app/environment'; 3 import { user } from '$lib/atproto'; 4 import type { WebsiteData } from '$lib/types'; 5 import { Button, Input, Modal, Navbar, Popover, Toggle } from '@foxui/core'; 6 7 let { 8 data, 9 linkValue = $bindable(), 10 newCard, 11 addLink, 12 showSettings = $bindable(), 13 14 showingMobileView = $bindable(), 15 isSaving = $bindable(), 16 17 save, 18 19 handleImageInputChange, 20 handleVideoInputChange 21 }: { 22 data: WebsiteData; 23 linkValue: string; 24 newCard: (type: string) => void; 25 addLink: (url: string) => void; 26 27 showSettings: boolean; 28 29 showingMobileView: boolean; 30 31 isSaving: boolean; 32 33 save: () => Promise<void>; 34 35 handleImageInputChange: (evt: Event) => void; 36 handleVideoInputChange: (evt: Event) => void; 37 } = $props(); 38 39 let linkPopoverOpen = $state(false); 40 41 let imageInputRef: HTMLInputElement | undefined = $state(); 42 let videoInputRef: HTMLInputElement | undefined = $state(); 43 44 let shareModalOpen = $state(false); 45</script> 46 47<input 48 type="file" 49 accept="image/*" 50 onchange={handleImageInputChange} 51 class="hidden" 52 multiple 53 bind:this={imageInputRef} 54/> 55 56<input 57 type="file" 58 accept="video/*" 59 onchange={handleVideoInputChange} 60 class="hidden" 61 multiple 62 bind:this={videoInputRef} 63/> 64 65<Modal bind:open={shareModalOpen}></Modal> 66 67{#if dev || (user.isLoggedIn && user.profile?.did === data.did)} 68 <Navbar 69 class={[ 70 'dark:bg-base-900 bg-base-100 top-auto bottom-2 mx-4 mt-3 max-w-3xl rounded-full px-4 md:mx-auto lg:inline-flex', 71 !dev ? 'hidden' : '' 72 ]} 73 > 74 <div class="flex items-center gap-2"> 75 <Button 76 size="iconLg" 77 variant="ghost" 78 class="backdrop-blur-none" 79 onclick={() => { 80 newCard('section'); 81 }} 82 > 83 <svg 84 xmlns="http://www.w3.org/2000/svg" 85 viewBox="0 0 24 24" 86 fill="none" 87 stroke="currentColor" 88 stroke-width="2" 89 stroke-linecap="round" 90 stroke-linejoin="round" 91 ><path d="M6 12h12" /><path d="M6 20V4" /><path d="M18 20V4" /></svg 92 > 93 </Button> 94 95 <Button 96 size="iconLg" 97 variant="ghost" 98 class="backdrop-blur-none" 99 onclick={() => { 100 newCard('text'); 101 }} 102 > 103 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" 104 ><path 105 fill="none" 106 stroke="currentColor" 107 stroke-linecap="round" 108 stroke-linejoin="round" 109 stroke-width="2" 110 d="m15 16l2.536-7.328a1.02 1.02 1 0 1 1.928 0L22 16m-6.303-2h5.606M2 16l4.039-9.69a.5.5 0 0 1 .923 0L11 16m-7.696-3h6.392" 111 /></svg 112 > 113 </Button> 114 115 <Popover sideOffset={16} bind:open={linkPopoverOpen} class="bg-base-100 dark:bg-base-900"> 116 {#snippet child({ props })} 117 <Button 118 size="iconLg" 119 variant="ghost" 120 class="backdrop-blur-none" 121 onclick={() => { 122 newCard('link'); 123 }} 124 {...props} 125 > 126 <svg 127 xmlns="http://www.w3.org/2000/svg" 128 fill="none" 129 viewBox="-2 -2 28 28" 130 stroke-width="2" 131 stroke="currentColor" 132 > 133 <path 134 stroke-linecap="round" 135 stroke-linejoin="round" 136 d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" 137 /> 138 </svg> 139 </Button> 140 {/snippet} 141 <Input 142 spellcheck={false} 143 type="url" 144 bind:value={linkValue} 145 onkeydown={(event) => { 146 if (event.code === 'Enter') { 147 addLink(linkValue); 148 event.preventDefault(); 149 } 150 }} 151 placeholder="Enter link" 152 /> 153 <Button onclick={() => addLink(linkValue)} size="icon" 154 ><svg 155 xmlns="http://www.w3.org/2000/svg" 156 fill="none" 157 viewBox="0 0 24 24" 158 stroke-width="2" 159 stroke="currentColor" 160 class="size-6" 161 > 162 <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /> 163 </svg> 164 </Button> 165 </Popover> 166 167 <Button 168 size="iconLg" 169 variant="ghost" 170 class="backdrop-blur-none" 171 onclick={() => { 172 imageInputRef?.click(); 173 }} 174 > 175 <svg 176 xmlns="http://www.w3.org/2000/svg" 177 fill="none" 178 viewBox="0 0 24 24" 179 stroke-width="2" 180 stroke="currentColor" 181 > 182 <path 183 stroke-linecap="round" 184 stroke-linejoin="round" 185 d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" 186 /> 187 </svg> 188 </Button> 189 190 {#if dev} 191 <Button 192 size="iconLg" 193 variant="ghost" 194 class="backdrop-blur-none" 195 onclick={() => { 196 videoInputRef?.click(); 197 }} 198 > 199 <svg 200 xmlns="http://www.w3.org/2000/svg" 201 fill="none" 202 viewBox="0 0 24 24" 203 stroke-width="1.5" 204 stroke="currentColor" 205 > 206 <path 207 stroke-linecap="round" 208 stroke-linejoin="round" 209 d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" 210 /> 211 </svg> 212 </Button> 213 {/if} 214 215 <Button size="iconLg" variant="ghost" class="backdrop-blur-none" popovertarget="mobile-menu"> 216 <svg 217 xmlns="http://www.w3.org/2000/svg" 218 fill="none" 219 viewBox="0 0 24 24" 220 stroke-width="1.5" 221 stroke="currentColor" 222 > 223 <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> 224 </svg> 225 </Button> 226 </div> 227 <div class="flex items-center gap-2"> 228 <Button 229 size="iconLg" 230 variant="ghost" 231 class="backdrop-blur-none" 232 onclick={() => { 233 showSettings = true; 234 }} 235 > 236 <svg 237 xmlns="http://www.w3.org/2000/svg" 238 fill="none" 239 viewBox="0 0 24 24" 240 stroke-width="1.5" 241 stroke="currentColor" 242 > 243 <path 244 stroke-linecap="round" 245 stroke-linejoin="round" 246 d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" 247 /> 248 <path 249 stroke-linecap="round" 250 stroke-linejoin="round" 251 d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" 252 /> 253 </svg> 254 </Button> 255 <Toggle 256 class="hidden bg-transparent backdrop-blur-none lg:block dark:bg-transparent" 257 bind:pressed={showingMobileView} 258 > 259 <svg 260 xmlns="http://www.w3.org/2000/svg" 261 fill="none" 262 viewBox="0 0 24 24" 263 stroke-width="1.5" 264 stroke="currentColor" 265 class="size-6" 266 > 267 <path 268 stroke-linecap="round" 269 stroke-linejoin="round" 270 d="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" 271 /> 272 </svg> 273 </Toggle> 274 <Button 275 disabled={isSaving} 276 onclick={async () => { 277 save(); 278 }}>{isSaving ? 'Saving...' : 'Save'}</Button 279 > 280 </div> 281 </Navbar> 282{/if}