mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 21:46:35 +00:00
fix: resolve always text input issue, separate to simple components
This commit is contained in:
@@ -0,0 +1,77 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import DownloadButton from "./ui/DownloadButton.svelte";
|
||||||
|
import { Sparkles, Upload } from "@lucide/svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
inputMode: "file" | "text" | "none";
|
||||||
|
canDownload: boolean;
|
||||||
|
running: boolean;
|
||||||
|
onupload: (file: File) => void;
|
||||||
|
ongenerate: () => void;
|
||||||
|
ondownload: () => void;
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
inputMode,
|
||||||
|
canDownload,
|
||||||
|
running,
|
||||||
|
onupload,
|
||||||
|
ongenerate,
|
||||||
|
ondownload,
|
||||||
|
}: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
{#if inputMode === "none"}
|
||||||
|
<button class="btn generate" onclick={ongenerate} disabled={running}>
|
||||||
|
<Sparkles size={14} />
|
||||||
|
{running ? "Generating…" : "Generate"}
|
||||||
|
</button>
|
||||||
|
{:else if inputMode === "file"}
|
||||||
|
<label class="btn upload">
|
||||||
|
<Upload size={14} /> Open image
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
onchange={(e) => {
|
||||||
|
const f = (e.target as HTMLInputElement).files?.[0];
|
||||||
|
if (f) onupload(f);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
{/if}
|
||||||
|
{#if canDownload}
|
||||||
|
<DownloadButton label="Download result" onclick={ondownload} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-l);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-m);
|
||||||
|
padding: var(--space-m) var(--space-l);
|
||||||
|
border: var(--size-border) solid var(--color-border);
|
||||||
|
border-radius: var(--radius-m);
|
||||||
|
font: var(--font-size-s) var(--font-mono);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.generate {
|
||||||
|
background: var(--color-main);
|
||||||
|
border-color: var(--color-main);
|
||||||
|
color: var(--color-background);
|
||||||
|
}
|
||||||
|
.generate:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.upload input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import MetaList from "$lib/components/kit/MetaList.svelte";
|
import MetaList from "$lib/components/kit/MetaList.svelte";
|
||||||
import DownloadButton from "$lib/components/kit/ui/DownloadButton.svelte";
|
import SchemaActions from "$lib/components/kit/SchemaActions.svelte";
|
||||||
import SchemaTextResult from "$lib/components/kit/SchemaTextResult.svelte";
|
import SchemaResultTile from "$lib/components/kit/SchemaResultTile.svelte";
|
||||||
import SchemaTextSource from "$lib/components/kit/SchemaTextSource.svelte";
|
import SchemaSourceTile from "$lib/components/kit/SchemaSourceTile.svelte";
|
||||||
import { toDataUrl } from "$lib/core/io";
|
|
||||||
import type { PixelImage } from "$lib/core/types";
|
import type { PixelImage } from "$lib/core/types";
|
||||||
import { Check, Sparkles, Upload } from "@lucide/svelte";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
inputMode?: "file" | "text" | "none";
|
||||||
|
resultKind?: "image" | "text" | "verdict";
|
||||||
source: PixelImage | null;
|
source: PixelImage | null;
|
||||||
result: PixelImage | null;
|
result: PixelImage | null;
|
||||||
textSource?: string;
|
textSource?: string;
|
||||||
textResult?: string | null;
|
textResult?: string | null;
|
||||||
resultKind?: "image" | "text" | "verdict";
|
running?: boolean;
|
||||||
running: boolean;
|
error?: string;
|
||||||
error: string;
|
|
||||||
isGenerator?: boolean;
|
|
||||||
onupload: (file: File) => void;
|
onupload: (file: File) => void;
|
||||||
ongenerate?: () => void;
|
ongenerate?: () => void;
|
||||||
ontextsource?: (text: string) => void;
|
ontextsource?: (text: string) => void;
|
||||||
@@ -25,14 +23,14 @@
|
|||||||
ondownload: () => void;
|
ondownload: () => void;
|
||||||
}
|
}
|
||||||
let {
|
let {
|
||||||
|
inputMode = "file",
|
||||||
|
resultKind = "image",
|
||||||
source,
|
source,
|
||||||
result,
|
result,
|
||||||
textSource = "",
|
textSource = "",
|
||||||
textResult = null,
|
textResult = null,
|
||||||
resultKind = "image",
|
running = false,
|
||||||
running,
|
error = "",
|
||||||
error,
|
|
||||||
isGenerator = false,
|
|
||||||
onupload,
|
onupload,
|
||||||
ongenerate,
|
ongenerate,
|
||||||
ontextsource,
|
ontextsource,
|
||||||
@@ -42,44 +40,39 @@
|
|||||||
ondownload,
|
ondownload,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
const isTextInput = $derived(ontextsource !== undefined && !isGenerator);
|
const isGenerator = $derived(inputMode === "none");
|
||||||
const isImageDownload = $derived(resultKind === "image" && Boolean(result));
|
const sourceValue = $derived(
|
||||||
|
isGenerator
|
||||||
let sourceUrl = $derived(source ? toDataUrl(source) : null);
|
? "—"
|
||||||
let resultUrl = $derived(result ? toDataUrl(result) : null);
|
: inputMode === "text"
|
||||||
|
? "text"
|
||||||
|
: source
|
||||||
|
? `${source.width} × ${source.height} px`
|
||||||
|
: "—",
|
||||||
|
);
|
||||||
|
const resultValue = $derived(
|
||||||
|
resultKind === "image"
|
||||||
|
? result
|
||||||
|
? `${result.width} × ${result.height} px`
|
||||||
|
: "—"
|
||||||
|
: textResult
|
||||||
|
? "text"
|
||||||
|
: "—",
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="panel-head">
|
<div class="panel-head">
|
||||||
<span class="label"
|
<span class="label"
|
||||||
>{isGenerator ? "GENERATOR / RESULT" : "SOURCE / RESULT"}</span
|
>{isGenerator ? "GENERATOR / RESULT" : "SOURCE / RESULT"}</span
|
||||||
>
|
>
|
||||||
<div class="head-actions">
|
<SchemaActions
|
||||||
{#if isGenerator}
|
{inputMode}
|
||||||
<button
|
canDownload={resultKind === "image" && Boolean(result)}
|
||||||
class="upload generate-btn"
|
{running}
|
||||||
onclick={ongenerate}
|
{onupload}
|
||||||
disabled={running}
|
ongenerate={ongenerate ?? (() => {})}
|
||||||
>
|
{ondownload}
|
||||||
<Sparkles size={14} />
|
/>
|
||||||
{running ? "Generating…" : "Generate"}
|
|
||||||
</button>
|
|
||||||
{:else if !isTextInput}
|
|
||||||
<label class="upload">
|
|
||||||
<Upload size={14} /> Open image
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
accept="image/*"
|
|
||||||
onchange={(e) => {
|
|
||||||
const f = (e.target as HTMLInputElement).files?.[0];
|
|
||||||
if (f) onupload(f);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
{/if}
|
|
||||||
{#if isImageDownload}
|
|
||||||
<DownloadButton label="Download result" onclick={ondownload} />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
@@ -88,85 +81,31 @@
|
|||||||
|
|
||||||
<div class="pair">
|
<div class="pair">
|
||||||
{#if !isGenerator}
|
{#if !isGenerator}
|
||||||
<figure class="tile">
|
<SchemaSourceTile
|
||||||
<figcaption><span>SOURCE</span></figcaption>
|
mode={inputMode === "text" ? "text" : "file"}
|
||||||
<div class="canvas">
|
{source}
|
||||||
{#if isTextInput}
|
{textSource}
|
||||||
<div class="text-source-wrap">
|
{running}
|
||||||
<SchemaTextSource
|
ontextinput={ontextsource}
|
||||||
value={textSource}
|
{onrendertext}
|
||||||
disabled={running}
|
/>
|
||||||
oninput={ontextsource ?? (() => {})}
|
|
||||||
onrender={onrendertext ?? (() => {})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else if sourceUrl}
|
|
||||||
<img src={sourceUrl} alt="source" />
|
|
||||||
{:else}
|
|
||||||
<span class="empty">choose an image</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</figure>
|
|
||||||
{/if}
|
{/if}
|
||||||
<figure class="tile" class:full={isGenerator || resultKind !== "image"}>
|
<SchemaResultTile
|
||||||
<figcaption><span>RESULT {running ? "…" : ""}</span></figcaption>
|
{resultKind}
|
||||||
<div class="canvas" class:checker={resultKind === "image"}>
|
{result}
|
||||||
{#if resultKind === "text" && textResult}
|
{textResult}
|
||||||
<div class="text-result-wrap">
|
wide={isGenerator || resultKind !== "image"}
|
||||||
<SchemaTextResult
|
{running}
|
||||||
value={textResult}
|
oncopy={oncopytext}
|
||||||
kind="text"
|
{ondownloadtxt}
|
||||||
oncopy={oncopytext ?? (() => {})}
|
/>
|
||||||
ondownload={ondownloadtxt ?? (() => {})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else if resultKind === "verdict" && textResult}
|
|
||||||
<div class="text-result-wrap">
|
|
||||||
<SchemaTextResult
|
|
||||||
value={textResult}
|
|
||||||
kind="verdict"
|
|
||||||
oncopy={oncopytext ?? (() => {})}
|
|
||||||
ondownload={ondownloadtxt ?? (() => {})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else if resultKind === "image" && resultUrl}
|
|
||||||
<img src={resultUrl} alt="result" />
|
|
||||||
{:else if running}
|
|
||||||
<Check size={22} />
|
|
||||||
{:else}
|
|
||||||
<span class="empty">
|
|
||||||
{isGenerator ? "click Generate" : "no result yet"}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</figure>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
<MetaList
|
<MetaList
|
||||||
items={[
|
items={[
|
||||||
{
|
{ caption: "SOURCE", value: sourceValue },
|
||||||
caption: "SOURCE",
|
{ caption: "RESULT", value: resultValue },
|
||||||
value:
|
|
||||||
!isGenerator && !isTextInput
|
|
||||||
? source
|
|
||||||
? `${source.width} × ${source.height} px`
|
|
||||||
: "—"
|
|
||||||
: isTextInput
|
|
||||||
? "text"
|
|
||||||
: "—",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
caption: "RESULT",
|
|
||||||
value:
|
|
||||||
resultKind === "image"
|
|
||||||
? result
|
|
||||||
? `${result.width} × ${result.height} px`
|
|
||||||
: "—"
|
|
||||||
: textResult
|
|
||||||
? "text"
|
|
||||||
: "—",
|
|
||||||
},
|
|
||||||
{ caption: "FORMAT", value: "PNG" },
|
{ caption: "FORMAT", value: "PNG" },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
@@ -187,35 +126,6 @@
|
|||||||
letter-spacing: var(--space-text-l);
|
letter-spacing: var(--space-text-l);
|
||||||
color: var(--color-main);
|
color: var(--color-main);
|
||||||
}
|
}
|
||||||
.head-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--space-l);
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.upload {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--space-m);
|
|
||||||
padding: var(--space-m) var(--space-l);
|
|
||||||
border: var(--size-border) solid var(--color-border);
|
|
||||||
border-radius: var(--radius-m);
|
|
||||||
font: var(--font-size-s) var(--font-mono);
|
|
||||||
color: var(--color-text-muted);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.generate-btn {
|
|
||||||
background: var(--color-main);
|
|
||||||
border-color: var(--color-main);
|
|
||||||
color: var(--color-background);
|
|
||||||
}
|
|
||||||
.generate-btn:disabled {
|
|
||||||
opacity: 0.6;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
.upload input {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.error {
|
.error {
|
||||||
margin: 0 0 var(--space-l);
|
margin: 0 0 var(--space-l);
|
||||||
color: var(--color-danger);
|
color: var(--color-danger);
|
||||||
@@ -226,50 +136,6 @@
|
|||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: var(--space-l);
|
gap: var(--space-l);
|
||||||
}
|
}
|
||||||
.pair > .full {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
}
|
|
||||||
.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-m);
|
|
||||||
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 {
|
|
||||||
font: var(--font-size-s) var(--font-mono);
|
|
||||||
}
|
|
||||||
.text-source-wrap,
|
|
||||||
.text-result-wrap {
|
|
||||||
width: 100%;
|
|
||||||
padding: var(--space-l);
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.meta {
|
.meta {
|
||||||
margin-top: var(--space-l);
|
margin-top: var(--space-l);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import SchemaTextResult from "./SchemaTextResult.svelte";
|
||||||
|
import { toDataUrl } from "$lib/core/io";
|
||||||
|
import type { PixelImage } from "$lib/core/types";
|
||||||
|
import { Check } from "@lucide/svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
resultKind?: "image" | "text" | "verdict";
|
||||||
|
result: PixelImage | null;
|
||||||
|
textResult?: string | null;
|
||||||
|
wide?: boolean;
|
||||||
|
running?: boolean;
|
||||||
|
oncopy?: () => void;
|
||||||
|
ondownloadtxt?: () => void;
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
resultKind = "image",
|
||||||
|
result,
|
||||||
|
textResult = null,
|
||||||
|
wide = false,
|
||||||
|
running = false,
|
||||||
|
oncopy,
|
||||||
|
ondownloadtxt,
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const resultUrl = $derived(result ? toDataUrl(result) : null);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<figure class="tile" style:grid-column={wide ? "1 / -1" : undefined}>
|
||||||
|
<figcaption><span>RESULT {running ? "…" : ""}</span></figcaption>
|
||||||
|
<div class="canvas" class:checker={resultKind === "image"}>
|
||||||
|
{#if resultKind === "text" && textResult}
|
||||||
|
<div class="text-result-wrap">
|
||||||
|
<SchemaTextResult
|
||||||
|
value={textResult}
|
||||||
|
kind="text"
|
||||||
|
oncopy={oncopy ?? (() => {})}
|
||||||
|
ondownload={ondownloadtxt ?? (() => {})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else if resultKind === "verdict" && textResult}
|
||||||
|
<div class="text-result-wrap">
|
||||||
|
<SchemaTextResult
|
||||||
|
value={textResult}
|
||||||
|
kind="verdict"
|
||||||
|
oncopy={oncopy ?? (() => {})}
|
||||||
|
ondownload={ondownloadtxt ?? (() => {})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else if resultKind === "image" && resultUrl}
|
||||||
|
<img src={resultUrl} alt="result" />
|
||||||
|
{:else if running}
|
||||||
|
<Check size={22} />
|
||||||
|
{:else}
|
||||||
|
<span class="empty">no result yet</span>
|
||||||
|
{/if}
|
||||||
|
</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);
|
||||||
|
}
|
||||||
|
.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-m);
|
||||||
|
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 {
|
||||||
|
font: var(--font-size-s) var(--font-mono);
|
||||||
|
}
|
||||||
|
.text-result-wrap {
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--space-l);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import SchemaTextSource from "./SchemaTextSource.svelte";
|
||||||
|
import { toDataUrl } from "$lib/core/io";
|
||||||
|
import type { PixelImage } from "$lib/core/types";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
mode: "file" | "text";
|
||||||
|
source: PixelImage | null;
|
||||||
|
textSource?: string;
|
||||||
|
running?: boolean;
|
||||||
|
ontextinput?: (text: string) => void;
|
||||||
|
onrendertext?: () => void;
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
mode,
|
||||||
|
source,
|
||||||
|
textSource = "",
|
||||||
|
running = false,
|
||||||
|
ontextinput,
|
||||||
|
onrendertext,
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
const sourceUrl = $derived(source ? toDataUrl(source) : null);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<figure class="tile">
|
||||||
|
<figcaption><span>SOURCE</span></figcaption>
|
||||||
|
<div class="canvas">
|
||||||
|
{#if mode === "text"}
|
||||||
|
<div class="text-source-wrap">
|
||||||
|
<SchemaTextSource
|
||||||
|
value={textSource}
|
||||||
|
disabled={running}
|
||||||
|
oninput={ontextinput ?? (() => {})}
|
||||||
|
onrender={onrendertext ?? (() => {})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else if sourceUrl}
|
||||||
|
<img src={sourceUrl} alt="source" />
|
||||||
|
{:else}
|
||||||
|
<span class="empty">choose an image</span>
|
||||||
|
{/if}
|
||||||
|
</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);
|
||||||
|
}
|
||||||
|
.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-m);
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--color-background-muted);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
.canvas img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.empty {
|
||||||
|
font: var(--font-size-s) var(--font-mono);
|
||||||
|
}
|
||||||
|
.text-source-wrap {
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--space-l);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -196,10 +196,10 @@
|
|||||||
{result}
|
{result}
|
||||||
{textSource}
|
{textSource}
|
||||||
{textResult}
|
{textResult}
|
||||||
|
{inputMode}
|
||||||
{resultKind}
|
{resultKind}
|
||||||
{running}
|
{running}
|
||||||
{error}
|
{error}
|
||||||
{isGenerator}
|
|
||||||
onupload={handleFile}
|
onupload={handleFile}
|
||||||
ongenerate={runGenerate}
|
ongenerate={runGenerate}
|
||||||
ontextsource={(t) => {
|
ontextsource={(t) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user