({
allowMultiple,
imagesOnly,
}: {
allowMultiple: boolean;
imagesOnly?: boolean;
})
| 16 | }; |
| 17 | |
| 18 | function openBrowserFilePicker({ |
| 19 | allowMultiple, |
| 20 | imagesOnly, |
| 21 | }: { |
| 22 | allowMultiple: boolean; |
| 23 | imagesOnly?: boolean; |
| 24 | }): Promise<File[]> { |
| 25 | return new Promise((resolve, reject) => { |
| 26 | const input = document.createElement("input"); |
| 27 | let settled = false; |
| 28 | |
| 29 | function cleanup(): void { |
| 30 | input.removeEventListener("cancel", handleCancel); |
| 31 | input.removeEventListener("change", handleChange); |
| 32 | input.remove(); |
| 33 | } |
| 34 | |
| 35 | function finish(files: File[]): void { |
| 36 | if (settled) { |
| 37 | return; |
| 38 | } |
| 39 | settled = true; |
| 40 | cleanup(); |
| 41 | resolve(files); |
| 42 | } |
| 43 | |
| 44 | function fail(error: unknown): void { |
| 45 | if (settled) { |
| 46 | return; |
| 47 | } |
| 48 | settled = true; |
| 49 | cleanup(); |
| 50 | reject(error); |
| 51 | } |
| 52 | |
| 53 | function handleCancel(): void { |
| 54 | finish([]); |
| 55 | } |
| 56 | |
| 57 | function handleChange(): void { |
| 58 | finish(Array.from(input.files ?? [])); |
| 59 | } |
| 60 | |
| 61 | input.type = "file"; |
| 62 | input.multiple = allowMultiple; |
| 63 | if (imagesOnly) { |
| 64 | input.accept = "image/*"; |
| 65 | } |
| 66 | Object.assign(input.style, { |
| 67 | height: "1px", |
| 68 | left: "-9999px", |
| 69 | opacity: "0", |
| 70 | position: "fixed", |
| 71 | top: "0", |
| 72 | width: "1px", |
| 73 | }); |
| 74 | input.addEventListener("cancel", handleCancel); |
| 75 | input.addEventListener("change", handleChange); |
no test coverage detected