your personal website on atproto - mirror blento.app
at profile-stuff 252 lines 6.3 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 13 showingMobileView = $bindable(), 14 isSaving = $bindable(), 15 16 save, 17 18 handleImageInputChange, 19 handleVideoInputChange 20 }: { 21 data: WebsiteData; 22 linkValue: string; 23 newCard: (type: string) => void; 24 addLink: (url: string) => void; 25 26 showingMobileView: boolean; 27 28 isSaving: boolean; 29 30 save: () => Promise<void>; 31 32 handleImageInputChange: (evt: Event) => void; 33 handleVideoInputChange: (evt: Event) => void; 34 } = $props(); 35 36 let linkPopoverOpen = $state(false); 37 38 let imageInputRef: HTMLInputElement | undefined = $state(); 39 let videoInputRef: HTMLInputElement | undefined = $state(); 40 41 let shareModalOpen = $state(false); 42</script> 43 44<input 45 type="file" 46 accept="image/*" 47 onchange={handleImageInputChange} 48 class="hidden" 49 multiple 50 bind:this={imageInputRef} 51/> 52 53<input 54 type="file" 55 accept="video/*" 56 onchange={handleVideoInputChange} 57 class="hidden" 58 multiple 59 bind:this={videoInputRef} 60/> 61 62<Modal bind:open={shareModalOpen}></Modal> 63 64{#if dev || (user.isLoggedIn && user.profile?.did === data.did)} 65 <Navbar 66 class={[ 67 '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', 68 !dev ? 'hidden' : '' 69 ]} 70 > 71 <div class="flex items-center gap-2"> 72 <Button 73 size="iconLg" 74 variant="ghost" 75 class="backdrop-blur-none" 76 onclick={() => { 77 newCard('section'); 78 }} 79 > 80 <svg 81 xmlns="http://www.w3.org/2000/svg" 82 viewBox="0 0 24 24" 83 fill="none" 84 stroke="currentColor" 85 stroke-width="2" 86 stroke-linecap="round" 87 stroke-linejoin="round" 88 ><path d="M6 12h12" /><path d="M6 20V4" /><path d="M18 20V4" /></svg 89 > 90 </Button> 91 92 <Button 93 size="iconLg" 94 variant="ghost" 95 class="backdrop-blur-none" 96 onclick={() => { 97 newCard('text'); 98 }} 99 > 100 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" 101 ><path 102 fill="none" 103 stroke="currentColor" 104 stroke-linecap="round" 105 stroke-linejoin="round" 106 stroke-width="2" 107 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" 108 /></svg 109 > 110 </Button> 111 112 <Popover sideOffset={16} bind:open={linkPopoverOpen} class="bg-base-100 dark:bg-base-900"> 113 {#snippet child({ props })} 114 <Button 115 size="iconLg" 116 variant="ghost" 117 class="backdrop-blur-none" 118 onclick={() => { 119 newCard('link'); 120 }} 121 {...props} 122 > 123 <svg 124 xmlns="http://www.w3.org/2000/svg" 125 fill="none" 126 viewBox="-2 -2 28 28" 127 stroke-width="2" 128 stroke="currentColor" 129 > 130 <path 131 stroke-linecap="round" 132 stroke-linejoin="round" 133 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" 134 /> 135 </svg> 136 </Button> 137 {/snippet} 138 <Input 139 spellcheck={false} 140 type="url" 141 bind:value={linkValue} 142 onkeydown={(event) => { 143 if (event.code === 'Enter') { 144 addLink(linkValue); 145 event.preventDefault(); 146 } 147 }} 148 placeholder="Enter link" 149 /> 150 <Button onclick={() => addLink(linkValue)} size="icon" 151 ><svg 152 xmlns="http://www.w3.org/2000/svg" 153 fill="none" 154 viewBox="0 0 24 24" 155 stroke-width="2" 156 stroke="currentColor" 157 class="size-6" 158 > 159 <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /> 160 </svg> 161 </Button> 162 </Popover> 163 164 <Button 165 size="iconLg" 166 variant="ghost" 167 class="backdrop-blur-none" 168 onclick={() => { 169 imageInputRef?.click(); 170 }} 171 > 172 <svg 173 xmlns="http://www.w3.org/2000/svg" 174 fill="none" 175 viewBox="0 0 24 24" 176 stroke-width="2" 177 stroke="currentColor" 178 > 179 <path 180 stroke-linecap="round" 181 stroke-linejoin="round" 182 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" 183 /> 184 </svg> 185 </Button> 186 187 {#if dev} 188 <Button 189 size="iconLg" 190 variant="ghost" 191 class="backdrop-blur-none" 192 onclick={() => { 193 videoInputRef?.click(); 194 }} 195 > 196 <svg 197 xmlns="http://www.w3.org/2000/svg" 198 fill="none" 199 viewBox="0 0 24 24" 200 stroke-width="1.5" 201 stroke="currentColor" 202 > 203 <path 204 stroke-linecap="round" 205 stroke-linejoin="round" 206 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" 207 /> 208 </svg> 209 </Button> 210 {/if} 211 212 <Button size="iconLg" variant="ghost" class="backdrop-blur-none" popovertarget="mobile-menu"> 213 <svg 214 xmlns="http://www.w3.org/2000/svg" 215 fill="none" 216 viewBox="0 0 24 24" 217 stroke-width="1.5" 218 stroke="currentColor" 219 > 220 <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> 221 </svg> 222 </Button> 223 </div> 224 <div class="flex items-center gap-2"> 225 <Toggle 226 class="hidden bg-transparent backdrop-blur-none lg:block dark:bg-transparent" 227 bind:pressed={showingMobileView} 228 > 229 <svg 230 xmlns="http://www.w3.org/2000/svg" 231 fill="none" 232 viewBox="0 0 24 24" 233 stroke-width="1.5" 234 stroke="currentColor" 235 class="size-6" 236 > 237 <path 238 stroke-linecap="round" 239 stroke-linejoin="round" 240 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" 241 /> 242 </svg> 243 </Toggle> 244 <Button 245 disabled={isSaving} 246 onclick={async () => { 247 save(); 248 }}>{isSaving ? 'Saving...' : 'Save'}</Button 249 > 250 </div> 251 </Navbar> 252{/if}