xet-object-viewer / src /lib /components /FileUpload.svelte
assafvayner's picture
assafvayner HF Staff
updates
c9619ed
<script lang="ts">
const { fileSelected } = $props();
let xorbDragActive = $state(false);
let shardDragActive = $state(false);
let xorbFileInput: HTMLInputElement;
let shardFileInput: HTMLInputElement;
function handleDragOver(event: DragEvent, type: "xorb" | "shard") {
event.preventDefault();
if (type === "xorb") {
xorbDragActive = true;
} else {
shardDragActive = true;
}
}
function handleDragLeave(type: "xorb" | "shard") {
if (type === "xorb") {
xorbDragActive = false;
} else {
shardDragActive = false;
}
}
function handleDrop(event: DragEvent, type: "xorb" | "shard") {
event.preventDefault();
if (type === "xorb") {
xorbDragActive = false;
} else {
shardDragActive = false;
}
const files = event.dataTransfer?.files;
if (files && files.length > 0) {
handleFile(files[0], type);
}
}
function handleFileInput(event: Event, type: "xorb" | "shard") {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
handleFile(input.files[0], type);
}
}
function handleFile(file: File, type: "xorb" | "shard") {
fileSelected({ file, type });
}
function openFileDialog(type: "xorb" | "shard") {
if (type === "xorb") {
xorbFileInput.click();
} else {
shardFileInput.click();
}
}
</script>
<div class="upload-container">
<div class="upload-areas">
<!-- XORB Upload Area -->
<div class="upload-section">
<h3>πŸ“¦ Upload XORB File</h3>
<div
class="upload-area xorb-area"
class:drag-active={xorbDragActive}
ondragover={(e) => handleDragOver(e, "xorb")}
ondragleave={() => handleDragLeave("xorb")}
ondrop={(e) => handleDrop(e, "xorb")}
onclick={() => openFileDialog("xorb")}
onkeydown={(e) => e.key === "Enter" && openFileDialog("xorb")}
role="button"
tabindex="0"
>
<div class="upload-content">
<div class="upload-icon">πŸ“¦</div>
<h4>Drop XORB file here</h4>
<p>or click to browse</p>
<span class="format-tag xorb-tag">XORB</span>
</div>
</div>
</div>
<!-- Shard Upload Area -->
<div class="upload-section">
<h3>πŸ—‚οΈ Upload Shard File</h3>
<div
class="upload-area shard-area"
class:drag-active={shardDragActive}
ondragover={(e) => handleDragOver(e, "shard")}
ondragleave={() => handleDragLeave("shard")}
ondrop={(e) => handleDrop(e, "shard")}
onclick={() => openFileDialog("shard")}
onkeydown={(e) => e.key === "Enter" && openFileDialog("shard")}
role="button"
tabindex="0"
>
<div class="upload-content">
<div class="upload-icon">πŸ—‚οΈ</div>
<h4>Drop Shard file here</h4>
<p>or click to browse</p>
<span class="format-tag shard-tag">SHARD</span>
</div>
</div>
</div>
</div>
<input
bind:this={xorbFileInput}
type="file"
onchange={(e) => handleFileInput(e, "xorb")}
style="display: none;"
/>
<input
bind:this={shardFileInput}
type="file"
onchange={(e) => handleFileInput(e, "shard")}
style="display: none;"
/>
</div>
<style>
.upload-container {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.upload-areas {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.upload-section {
text-align: center;
}
.upload-section h3 {
margin: 0 0 20px 0;
color: #2c3e50;
font-size: 18px;
font-weight: 600;
}
.upload-area {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 30px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
background: #fafafa;
min-height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.xorb-area:hover {
border-color: #28a745;
background: #f0fff4;
}
.xorb-area.drag-active {
border-color: #28a745;
background: #e8f5e8;
transform: scale(1.02);
}
.shard-area:hover {
border-color: #007bff;
background: #f0f8ff;
}
.shard-area.drag-active {
border-color: #007bff;
background: #e3f2fd;
transform: scale(1.02);
}
.upload-content {
pointer-events: none;
}
.upload-icon {
font-size: 36px;
margin-bottom: 12px;
}
.upload-area h4 {
margin: 0 0 8px 0;
color: #333;
font-weight: 600;
font-size: 16px;
}
.upload-area p {
margin: 0 0 16px 0;
color: #666;
font-size: 14px;
}
.format-tag {
color: white;
padding: 4px 12px;
border-radius: 16px;
font-size: 12px;
font-weight: 600;
}
.xorb-tag {
background: #28a745;
}
.shard-tag {
background: #007bff;
}
@media (max-width: 768px) {
.upload-areas {
grid-template-columns: 1fr;
gap: 20px;
}
.upload-area {
padding: 20px 15px;
min-height: 150px;
}
.upload-icon {
font-size: 28px;
}
}
</style>