Our Personal Data Server from scratch! tranquil.farm
pds rust database fun oauth atproto
221
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 83 lines 2.1 kB view raw
1<script lang="ts"> 2 interface Props { 3 value: string 4 domains: string[] 5 selectedDomain: string 6 disabled?: boolean 7 placeholder?: string 8 id?: string 9 autocomplete?: HTMLInputElement['autocomplete'] 10 checkAvailability?: (fullHandle: string) => Promise<boolean> 11 available?: boolean | null 12 checking?: boolean 13 onInput: (value: string) => void 14 onDomainChange: (domain: string) => void 15 } 16 17 let { 18 value, 19 domains, 20 selectedDomain, 21 disabled = false, 22 placeholder = 'username', 23 id = 'handle', 24 autocomplete = 'off', 25 checkAvailability, 26 available = $bindable<boolean | null>(null), 27 checking = $bindable(false), 28 onInput, 29 onDomainChange, 30 }: Props = $props() 31 32 const showDomainSelect = $derived(domains.length > 1 && !value.includes('.')) 33 34 let checkTimeout: ReturnType<typeof setTimeout> | null = null 35 36 $effect(() => { 37 void value 38 void selectedDomain 39 if (!checkAvailability) return 40 if (checkTimeout) clearTimeout(checkTimeout) 41 available = null 42 if (value.trim().length >= 3 && !value.includes('.')) { 43 checkTimeout = setTimeout(() => runCheck(), 400) 44 } 45 }) 46 47 async function runCheck() { 48 if (!checkAvailability) return 49 const fullHandle = value.includes('.') 50 ? value.trim() 51 : `${value.trim()}.${selectedDomain}` 52 checking = true 53 try { 54 available = await checkAvailability(fullHandle) 55 } catch { 56 available = null 57 } finally { 58 checking = false 59 } 60 } 61</script> 62 63<div class="handle-input-group"> 64 <input 65 {id} 66 type="text" 67 value={value} 68 {placeholder} 69 {disabled} 70 autocomplete={autocomplete} 71 required 72 oninput={(e) => onInput((e.target as HTMLInputElement).value)} 73 /> 74 {#if showDomainSelect} 75 <select value={selectedDomain} onchange={(e) => onDomainChange((e.target as HTMLSelectElement).value)}> 76 {#each domains as domain} 77 <option value={domain}>.{domain}</option> 78 {/each} 79 </select> 80 {:else if domains.length === 1 && !value.includes('.')} 81 <span class="domain-suffix">.{domains[0]}</span> 82 {/if} 83</div>