handy online tools for AT Protocol boat.kelinci.net
atproto bluesky atcute typescript solidjs
at trunk 65 lines 1.5 kB view raw
1import type { JSX } from 'solid-js'; 2 3import { createDropZone, type CreateDropZoneOptions } from '~/lib/hooks/dropzone'; 4 5import Button from './inputs/button'; 6 7interface FileDropZoneProps { 8 accept?: string; 9 disabled?: boolean; 10 onFiles: (files: File[]) => void; 11 dataTypes?: CreateDropZoneOptions['dataTypes']; 12 multiple?: boolean; 13 children?: JSX.Element; 14} 15 16const FileDropZone = (props: FileDropZoneProps) => { 17 const { ref: dropRef, isDropping } = createDropZone({ 18 dataTypes: props.dataTypes, 19 multiple: props.multiple ?? false, 20 onDrop(files) { 21 if (files) { 22 props.onFiles(files); 23 } 24 }, 25 }); 26 27 const handleBrowse = () => { 28 const input = document.createElement('input'); 29 input.type = 'file'; 30 if (props.accept) { 31 input.accept = props.accept; 32 } 33 if (props.multiple) { 34 input.multiple = true; 35 } 36 input.oninput = () => { 37 const files = Array.from(input.files!); 38 if (files.length > 0) { 39 props.onFiles(files); 40 } 41 }; 42 input.click(); 43 }; 44 45 return ( 46 <fieldset 47 ref={dropRef} 48 disabled={props.disabled} 49 class={ 50 `relative grid place-items-center rounded border border-gray-300 px-6 py-12 disabled:opacity-50` + 51 (props.disabled || !isDropping() ? ` bg-gray-100` : ` bg-green-100`) 52 } 53 > 54 <div class="flex flex-col items-center gap-4"> 55 <Button variant="outline" onClick={handleBrowse}> 56 Browse files 57 </Button> 58 <p class="select-none font-medium text-gray-600">or drop your file here</p> 59 </div> 60 {props.children} 61 </fieldset> 62 ); 63}; 64 65export default FileDropZone;