<script lang="ts">
	const { onfiles = () => {}, accept = '*', multiple = false, children } = $props();

	let dragging = $state(false);
	let fileInputEl: HTMLInputElement; // Reference to the hidden file input

	function handleDrop(e: DragEvent) {
		e.preventDefault();
		dragging = false;
		const files = Array.from(e.dataTransfer?.files ?? []);
		if (files.length) {
			onfiles(files);
		}
	}

	function handleDragOver(e: DragEvent) {
		e.preventDefault();
		dragging = true;
	}

	function handleDragLeave(e: DragEvent) {
		e.preventDefault();
		dragging = false;
	}

	/** Handles file selection from the native dialog */
	function handleFileSelect(e: Event) {
		const input = e.target as HTMLInputElement;
		const files = Array.from(input.files ?? []);
		if (files.length) {
			onfiles(files);
		}
		// IMPORTANT: Reset the input value so the same file can be selected again
		input.value = '';
	}

	/** Programmatically clicks the hidden file input */
	function openFileSelect() {
		fileInputEl.click();
	}
</script>

<div
	role="button"
	aria-label="Drop files or click to upload"
	tabindex="0"
	ondragover={handleDragOver}
	ondragleave={handleDragLeave}
	ondrop={handleDrop}
	onclick={openFileSelect}
	onkeydown={(e) => {
		// Allow keyboard users to trigger the click with Enter or Space
		if (e.key === 'Enter' || e.key === ' ') {
			e.preventDefault();
			openFileSelect();
		}
	}}
	class="rounded-lg border-2 border-dashed p-6 text-center transition-colors
	{dragging ? 'border-primary bg-primary/5' : 'border-gray-300'}"
>
	<input
		type="file"
		bind:this={fileInputEl}
		{accept}
		{multiple}
		onchange={handleFileSelect}
		class="sr-only"
	/>

	{@render children?.()}
</div>
