embroidery-viewer/src/lib/components/CardList.svelte
2025-06-06 17:48:23 -03:00

162 lines
3.7 KiB
Svelte

<script>
import { t } from '$lib/translations';
import renderFileToCanvas from '$lib/file-renderer';
/**
* @type {ArrayLike<any>}
*/
export let files = [];
/**
* @type {HTMLElement}
*/
let errorMessageRef;
let canvasRefs = [];
let colorRefs = [];
let stitchesRefs = [];
let sizeRefs = [];
let localizedStrings = {
stitches: $t('viewer.stitches'),
dimensions: $t('viewer.dimensions'),
};
/**
* Downloads a given HTMLCanvasElement as a PNG image.
*
* @param {HTMLCanvasElement} canvas - The canvas element to export as an image.
* @param {string} filename - The desired name of the downloaded file (extension will be replaced with `.png`).
*/
const downloadCanvasAsImage = (canvas, filename) => {
const image = canvas
.toDataURL('image/png')
.replace('image/png', 'image/octet-stream');
const link = document.createElement('a');
link.download = `${filename.split('.').slice(0, -1).join('.')}.png`;
link.href = image;
link.click();
};
/**
* Cliks the button to render the files when user press enter.
*
* @param {KeyboardEvent} evt - The event that triggered the language switch.
*/
const onKeydown = (evt) => {
if (evt.key === 'Enter') {
const button = document.getElementById('download-button');
if (button) button.click();
}
};
</script>
{#if files.length !== 0}
<div id="container" style="width: 100%; heigth: 100vh;">
{#each Array.from(files) as file, i}
<div class="canvas-container">
<canvas bind:this={canvasRefs[i]} class="canvas"></canvas>
<p><strong>{file.name}</strong></p>
<div class="stitches-container" bind:this={stitchesRefs[i]}></div>
<div class="size-container" bind:this={sizeRefs[i]}></div>
<div class="colors-container" bind:this={colorRefs[i]}></div>
<div
id="download-button"
role="button"
tabindex="0"
onkeydown={onKeydown}
onclick={() => downloadCanvasAsImage(canvasRefs[i], file.name)}
>
{$t('viewer.download')}
</div>
</div>
{canvasRefs[i] &&
renderFileToCanvas(
file,
canvasRefs[i],
errorMessageRef,
colorRefs[i],
stitchesRefs[i],
sizeRefs[i],
localizedStrings,
)}
{/each}
<!-- svelte-ignore a11y-missing-content -->
<h1 bind:this={errorMessageRef}></h1>
</div>
{/if}
<style>
#container {
display: flex;
width: 100%;
justify-content: space-evenly;
flex-wrap: wrap;
margin-top: 50px;
}
.canvas-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 550px;
max-height: 1000px;
margin-bottom: 15px;
padding: 10px;
/* border: 2px solid black;*/
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
border-radius: 16px;
}
.canvas {
height: 70%;
width: 100%;
object-fit: contain;
}
.colors-container {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 5px;
row-gap: 5px;
padding-bottom: 15px;
}
.stitches-container {
padding: 10px 0;
}
div[role='button'] {
background-color: #05345f;
font-weight: bold;
color: white;
padding: 10px;
border-radius: 10px;
padding: 10px;
width: 50%;
text-align: center;
}
div[role='button']:hover {
cursor: pointer;
background-color: black;
color: white;
}
@media only screen and (max-device-width: 812px) {
.canvas-container {
width: 100%;
height: auto;
}
#container {
width: 100%;
}
div[role='button'] {
width: 100%;
padding: 15px;
}
}
</style>