your personal website on atproto - mirror blento.app
at small-improvements 143 lines 3.8 kB view raw
1<script lang="ts"> 2 import type { WebsiteData, PronounSet } from '$lib/types'; 3 import { Badge, Button, Input, Switch, Label } from '@foxui/core'; 4 import Modal from '$lib/components/modal/Modal.svelte'; 5 6 let { 7 data = $bindable(), 8 editing = false 9 }: { 10 data: WebsiteData; 11 editing?: boolean; 12 } = $props(); 13 14 let modalOpen = $state(false); 15 let editSets: PronounSet[] = $state([]); 16 let editDisplayMode: 'all' | 'firstOnly' = $state('all'); 17 18 function openModal() { 19 if (data.pronounsRecord?.value?.sets?.length) { 20 editSets = JSON.parse(JSON.stringify(data.pronounsRecord.value.sets)); 21 editDisplayMode = data.pronounsRecord.value.displayMode === 'firstOnly' ? 'firstOnly' : 'all'; 22 } else { 23 editSets = [{ forms: [''] }]; 24 editDisplayMode = 'all'; 25 } 26 modalOpen = true; 27 } 28 29 function save() { 30 const validSets = editSets.filter((set) => set.forms.some((form) => form.length > 0)); 31 if (validSets.length > 0) { 32 data.pronounsRecord = { 33 value: { 34 sets: validSets, 35 displayMode: editDisplayMode 36 } 37 }; 38 } else { 39 data.pronounsRecord = undefined; 40 } 41 data = { ...data }; 42 modalOpen = false; 43 } 44 45 function addSet() { 46 editSets = [...editSets, { forms: [''] }]; 47 } 48 49 function removeSet(index: number) { 50 editSets = editSets.filter((_, i) => i !== index); 51 } 52 53 function updateSetInput(index: number, value: string) { 54 editSets[index] = { forms: value.split('/').map((s) => s.trim()) }; 55 } 56 57 let allSets = $derived(data.pronounsRecord?.value?.sets ?? []); 58 let sets = $derived( 59 data.pronounsRecord?.value?.displayMode === 'firstOnly' ? allSets.slice(0, 1) : allSets 60 ); 61</script> 62 63{#if sets.length} 64 <div class="flex flex-wrap gap-1"> 65 {#each sets as set, i (i)} 66 <Badge>{set.forms.join('/')}</Badge> 67 {/each} 68 </div> 69{/if} 70 71{#if editing} 72 <Button size="sm" onclick={openModal}> 73 <svg 74 xmlns="http://www.w3.org/2000/svg" 75 fill="none" 76 viewBox="0 0 24 24" 77 stroke-width="1.5" 78 stroke="currentColor" 79 class="size-3" 80 > 81 <path 82 stroke-linecap="round" 83 stroke-linejoin="round" 84 d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" 85 /> 86 </svg> 87 {sets.length ? 'edit' : 'add'} pronouns 88 </Button> 89 90 <Modal open={modalOpen} onOpenChange={(v) => (modalOpen = v)} closeButton> 91 <div class="flex flex-col gap-4"> 92 <h3 class="text-base-900 dark:text-base-100 text-lg font-semibold">Edit pronouns</h3> 93 94 <div class="flex flex-col gap-2"> 95 {#each editSets as set, i (i)} 96 <div class="flex items-center gap-2"> 97 <Input 98 value={set.forms.join('/')} 99 oninput={(e) => updateSetInput(i, e.currentTarget.value)} 100 placeholder="e.g. she/her" 101 variant="secondary" 102 sizeVariant="sm" 103 class="grow" 104 /> 105 {#if editSets.length > 1} 106 <Button size="iconSm" variant="ghost" onclick={() => removeSet(i)}>&times;</Button> 107 {/if} 108 </div> 109 {/each} 110 </div> 111 112 {#if editSets.length < 10} 113 <Button 114 size="sm" 115 variant="secondary" 116 onclick={addSet} 117 disabled={!editSets.at(-1)?.forms.some((f) => f.length > 0)} 118 class="w-fit" 119 > 120 + add more pronouns 121 </Button> 122 {/if} 123 124 {#if editSets.length > 1} 125 <div class="flex items-center gap-1.5"> 126 <Switch 127 id="pronouns-display-mode" 128 checked={editDisplayMode === 'firstOnly'} 129 onCheckedChange={(checked) => { 130 editDisplayMode = checked ? 'firstOnly' : 'all'; 131 }} 132 /> 133 <Label for="pronouns-display-mode">show first only</Label> 134 </div> 135 {/if} 136 137 <div class="flex justify-end gap-2"> 138 <Button variant="secondary" onclick={() => (modalOpen = false)}>Cancel</Button> 139 <Button onclick={save}>Save</Button> 140 </div> 141 </div> 142 </Modal> 143{/if}