This commit is contained in:
1 parent
367f34229c
commit
57b38fe2c7
36 files changed
+1159
-328
No files matched your search
@@ -0,0 +1,62 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/ui/button.svelte';
|
||||
import type { ButtonVariant } from '$lib/components/ui/button.svelte';
|
||||
import { isAcceptedZipFile, ZIP_ACCEPT_TYPES } from '$lib/zip-selection';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
type Props = {
|
||||
/** Identifies the hidden input for tests, e.g. `replace-zip` or `append-zip`. */
|
||||
pickerId: string;
|
||||
ariaLabel: string;
|
||||
onFilesSelected: (files: File[]) => void;
|
||||
children: Snippet;
|
||||
multiple?: boolean;
|
||||
disabled?: boolean;
|
||||
variant?: ButtonVariant;
|
||||
class?: string;
|
||||
};
|
||||
|
||||
let {
|
||||
pickerId,
|
||||
ariaLabel,
|
||||
onFilesSelected,
|
||||
children,
|
||||
multiple = true,
|
||||
disabled = false,
|
||||
variant = 'primary',
|
||||
class: className = ''
|
||||
}: Props = $props();
|
||||
|
||||
let fileInput = $state<HTMLInputElement | null>(null);
|
||||
|
||||
const handleFileSelection = (event: Event) => {
|
||||
const input = event.currentTarget as HTMLInputElement;
|
||||
const files = Array.from(input.files ?? []).filter(isAcceptedZipFile);
|
||||
|
||||
// Reset first so selecting the same file again still fires `change`.
|
||||
input.value = '';
|
||||
|
||||
if (files.length === 0) return;
|
||||
onFilesSelected(multiple ? files : files.slice(0, 1));
|
||||
};
|
||||
</script>
|
||||
|
||||
<input
|
||||
bind:this={fileInput}
|
||||
class="hidden"
|
||||
type="file"
|
||||
accept={ZIP_ACCEPT_TYPES}
|
||||
{multiple}
|
||||
data-zip-picker={pickerId}
|
||||
onchange={handleFileSelection}
|
||||
/>
|
||||
|
||||
<Button
|
||||
{variant}
|
||||
{disabled}
|
||||
aria-label={ariaLabel}
|
||||
class={className}
|
||||
onclick={() => fileInput?.click()}
|
||||
>
|
||||
{@render children()}
|
||||
</Button>
|
||||
Reference in new issue
Block a user