handy online tools for AT Protocol
boat.kelinci.net
atproto
bluesky
atcute
typescript
solidjs
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;