your personal website on atproto - mirror blento.app
at small-event-card-fixes 104 lines 2.7 kB view raw
1<script lang="ts"> 2 import { Alert, Button, Subheading } from '@foxui/core'; 3 import Modal from '$lib/components/modal/Modal.svelte'; 4 import type { CreationModalComponentProps } from '../../types'; 5 6 let { item = $bindable(), oncreate, oncancel }: CreationModalComponentProps = $props(); 7 8 let errorMessage = $state(''); 9 let fileInput = $state<HTMLInputElement | undefined>(undefined); 10 11 function handleFileSelect(event: Event) { 12 const input = event.target as HTMLInputElement; 13 const file = input.files?.[0]; 14 15 if (!file) return; 16 17 const extension = file.name.toLowerCase().split('.').pop(); 18 if (!['gltf', 'glb', 'stl', 'fbx'].includes(extension || '')) { 19 errorMessage = 'Please select a .gltf, .glb, .stl, or .fbx file'; 20 return; 21 } 22 23 errorMessage = ''; 24 item.cardData.modelFile = { 25 blob: file, 26 objectUrl: URL.createObjectURL(file), 27 name: file.name, 28 type: extension 29 }; 30 } 31 32 function clearFile() { 33 if (item.cardData.modelFile?.objectUrl) { 34 URL.revokeObjectURL(item.cardData.modelFile.objectUrl); 35 } 36 item.cardData.modelFile = undefined; 37 } 38 39 function canCreate() { 40 if (!item.cardData.modelFile) { 41 errorMessage = 'Please upload a file'; 42 return false; 43 } 44 return true; 45 } 46</script> 47 48<Modal open={true} closeButton={false}> 49 <Subheading>Add a 3D Model</Subheading> 50 51 <div> 52 <p class="text-base-600 dark:text-base-400 mb-2 text-sm"> 53 Upload a 3D model file (.glb, .stl, .fbx, or .gltf) 54 </p> 55 {#if item.cardData.modelFile} 56 <div 57 class="bg-base-100 dark:bg-base-800 flex items-center justify-between rounded-lg border p-3" 58 > 59 <span class="text-sm">{item.cardData.modelFile.name}</span> 60 <Button size="sm" variant="ghost" onclick={clearFile}>Remove</Button> 61 </div> 62 {:else} 63 <input 64 bind:this={fileInput} 65 type="file" 66 accept=".gltf,.glb,.stl,.fbx" 67 onchange={handleFileSelect} 68 class="hidden" 69 /> 70 <Button variant="secondary" onclick={() => fileInput?.click()} class="w-full"> 71 <svg 72 xmlns="http://www.w3.org/2000/svg" 73 fill="none" 74 viewBox="0 0 24 24" 75 stroke-width="1.5" 76 stroke="currentColor" 77 class="mr-2 size-5" 78 > 79 <path 80 stroke-linecap="round" 81 stroke-linejoin="round" 82 d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5" 83 /> 84 </svg> 85 Choose File 86 </Button> 87 {/if} 88 </div> 89 90 {#if errorMessage} 91 <Alert type="error" title="Error"><span>{errorMessage}</span></Alert> 92 {/if} 93 94 <div class="mt-4 flex justify-end gap-2"> 95 <Button onclick={oncancel} variant="ghost">Cancel</Button> 96 <Button 97 onclick={() => { 98 if (canCreate()) oncreate(); 99 }} 100 > 101 Create 102 </Button> 103 </div> 104</Modal>