mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 21:46:35 +00:00
fix: separate preview tile component
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { toDataUrl } from "$lib/core/io";
|
import { toDataUrl } from "$lib/core/io";
|
||||||
import type { PixelImage } from "$lib/core/types";
|
import type { PixelImage } from "$lib/core/types";
|
||||||
import type { FileResult } from "$lib/registry";
|
import type { FileResult, ResultKind } from "$lib/registry";
|
||||||
import { Check, RefreshCw } from "@lucide/svelte";
|
import { Check } from "@lucide/svelte";
|
||||||
import SchemaTextResult from "./SchemaTextResult.svelte";
|
import SchemaTextResult from "./SchemaTextResult.svelte";
|
||||||
|
import PreviewTile from "./layout/PreviewTile.svelte";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
resultKind?: "image" | "text" | "verdict" | "files";
|
resultKind?: ResultKind;
|
||||||
result: PixelImage | null;
|
result: PixelImage | null;
|
||||||
fileResult?: FileResult | null;
|
fileResult?: FileResult | null;
|
||||||
textResult?: string | null;
|
textResult?: string | null;
|
||||||
@@ -33,20 +34,13 @@
|
|||||||
}))
|
}))
|
||||||
: [],
|
: [],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let parts = $derived(
|
||||||
|
resultKind === "files" && fileResult ? fileResult.files.length : undefined,
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<figure class="tile">
|
<PreviewTile label="RESULT" viewMode={resultKind} loading={running} {parts}>
|
||||||
<figcaption>
|
|
||||||
<span>
|
|
||||||
RESULT
|
|
||||||
{#if resultKind === "files" && fileResult}
|
|
||||||
<span class="count">{fileResult.files.length} parts</span>
|
|
||||||
{/if}
|
|
||||||
{#if running}
|
|
||||||
<RefreshCw class="rotating" size="16" />
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
</figcaption>
|
|
||||||
<div class="canvas" class:checker={resultKind === "image"}>
|
<div class="canvas" class:checker={resultKind === "image"}>
|
||||||
{#if resultKind === "text" && textResult}
|
{#if resultKind === "text" && textResult}
|
||||||
<div class="text-result-wrap">
|
<div class="text-result-wrap">
|
||||||
@@ -83,20 +77,9 @@
|
|||||||
<span class="empty">no result yet</span>
|
<span class="empty">no result yet</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
</PreviewTile>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tile figcaption {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--space-m);
|
|
||||||
margin-bottom: var(--space-m);
|
|
||||||
font: var(--font-size-s) var(--font-mono);
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
& :global(.rotating) {
|
|
||||||
animation: rotate var(--duration-l) linear infinite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.canvas {
|
.canvas {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -109,8 +92,10 @@
|
|||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
.canvas img {
|
.canvas img {
|
||||||
width: 100%;
|
width: auto;
|
||||||
height: 100%;
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
max-height: 100vh;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -124,10 +109,6 @@
|
|||||||
.empty {
|
.empty {
|
||||||
font: var(--font-size-s) var(--font-mono);
|
font: var(--font-size-s) var(--font-mono);
|
||||||
}
|
}
|
||||||
.count {
|
|
||||||
margin-left: var(--space-m);
|
|
||||||
color: var(--color-main);
|
|
||||||
}
|
|
||||||
.parts-grid {
|
.parts-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(
|
grid-template-columns: repeat(
|
||||||
@@ -170,13 +151,4 @@
|
|||||||
padding: var(--space-l);
|
padding: var(--space-l);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rotate {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { toDataUrl } from "$lib/core/io";
|
import { toDataUrl } from "$lib/core/io";
|
||||||
import type { PixelImage } from "$lib/core/types";
|
import type { PixelImage } from "$lib/core/types";
|
||||||
import type { InputMode } from "$lib/registry";
|
import type { InputMode } from "$lib/registry";
|
||||||
|
import PreviewTile from "./layout/PreviewTile.svelte";
|
||||||
import SchemaTextSource from "./SchemaTextSource.svelte";
|
import SchemaTextSource from "./SchemaTextSource.svelte";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -24,61 +25,26 @@
|
|||||||
const sourceUrl = $derived(source ? toDataUrl(source) : null);
|
const sourceUrl = $derived(source ? toDataUrl(source) : null);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<figure class="tile">
|
<PreviewTile label="SOURCE" viewMode={mode}>
|
||||||
<figcaption><span>SOURCE</span></figcaption>
|
{#if mode === "text"}
|
||||||
<div class="canvas" class:checker={mode === "image"}>
|
<div class="text-source-wrap">
|
||||||
{#if mode === "text"}
|
<SchemaTextSource
|
||||||
<div class="text-source-wrap">
|
value={textSource}
|
||||||
<SchemaTextSource
|
disabled={running}
|
||||||
value={textSource}
|
oninput={ontextinput ?? (() => {})}
|
||||||
disabled={running}
|
onrender={onrendertext ?? (() => {})}
|
||||||
oninput={ontextinput ?? (() => {})}
|
/>
|
||||||
onrender={onrendertext ?? (() => {})}
|
</div>
|
||||||
/>
|
{:else if mode === "image" && sourceUrl}
|
||||||
</div>
|
<img src={sourceUrl} alt="source" />
|
||||||
{:else if mode === "image" && sourceUrl}
|
{:else if mode === "image"}
|
||||||
<img src={sourceUrl} alt="source" />
|
<span class="empty">choose an image</span>
|
||||||
{:else if mode === "image"}
|
{:else}
|
||||||
<span class="empty">choose an image</span>
|
<span class="empty">no source — configure the parameters</span>
|
||||||
{:else}
|
{/if}
|
||||||
<span class="empty">no source — configure the parameters</span>
|
</PreviewTile>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tile figcaption {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--space-m);
|
|
||||||
margin-bottom: var(--space-m);
|
|
||||||
font: var(--font-size-s) var(--font-mono);
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
}
|
|
||||||
.canvas {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: clamp(var(--space-brand), 30vh, 60vh);
|
|
||||||
border: var(--size-border) solid var(--color-border);
|
|
||||||
border-radius: var(--radius-s);
|
|
||||||
overflow: hidden;
|
|
||||||
background: var(--color-background-muted);
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
}
|
|
||||||
.canvas img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.canvas.checker {
|
|
||||||
background: repeating-conic-gradient(
|
|
||||||
var(--color-checker-main) 0 25%,
|
|
||||||
var(--color-checker-alt) 0 50%
|
|
||||||
)
|
|
||||||
50% / 28px 28px;
|
|
||||||
}
|
|
||||||
.empty {
|
.empty {
|
||||||
font: var(--font-size-s) var(--font-mono);
|
font: var(--font-size-s) var(--font-mono);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { InputMode, ResultKind } from "$lib/registry";
|
||||||
|
import { RefreshCw } from "@lucide/svelte";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
label: string;
|
||||||
|
viewMode: InputMode | ResultKind;
|
||||||
|
children: Snippet;
|
||||||
|
loading?: boolean;
|
||||||
|
parts?: number;
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
label,
|
||||||
|
viewMode: mode,
|
||||||
|
children,
|
||||||
|
loading = false,
|
||||||
|
parts = undefined,
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
// TODO: make canvas aspect ratio auto, from 16:9 to 9:16 max
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<figure class="tile">
|
||||||
|
<figcaption>
|
||||||
|
<span>
|
||||||
|
{label}
|
||||||
|
{#if parts !== undefined}
|
||||||
|
<span class="count">{parts} parts</span>
|
||||||
|
{/if}
|
||||||
|
{#if loading}
|
||||||
|
<RefreshCw class="rotating" size="12" />
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</figcaption>
|
||||||
|
<div class="canvas" class:checker={mode === "image"}>
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.tile figcaption {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-m);
|
||||||
|
margin-bottom: var(--space-m);
|
||||||
|
font: var(--font-size-s) var(--font-mono);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
& :global(.rotating) {
|
||||||
|
animation: rotate var(--duration-l) linear infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.count {
|
||||||
|
margin-left: var(--space-m);
|
||||||
|
color: var(--color-main);
|
||||||
|
}
|
||||||
|
.canvas {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: clamp(var(--space-brand), 30vh, 60vh);
|
||||||
|
border: var(--size-border) solid var(--color-border);
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--color-background-muted);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
.canvas :global(img) {
|
||||||
|
width: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
max-height: 100vh;
|
||||||
|
object-fit: contain;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.canvas.checker {
|
||||||
|
background: repeating-conic-gradient(
|
||||||
|
var(--color-checker-main) 0 25%,
|
||||||
|
var(--color-checker-alt) 0 50%
|
||||||
|
)
|
||||||
|
50% / 28px 28px;
|
||||||
|
}
|
||||||
|
@keyframes rotate {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user