From c0225552e4d5970b81a3dba51e357821da38977b Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Sat, 22 Aug 2026 10:20:18 +0500 Subject: [PATCH] feat: add svelte components --- web/src/app.css | 39 ++++ web/src/lib/components/DownloadButton.svelte | 41 ++++ web/src/lib/components/DropZone.svelte | 107 +++++++++++ web/src/lib/components/InfoPanel.svelte | 49 +++++ web/src/lib/components/ParamForm.svelte | 89 +++++++++ web/src/lib/components/Preview.svelte | 40 ++++ web/src/lib/components/ToolPage.svelte | 187 +++++++++++++++++++ 7 files changed, 552 insertions(+) create mode 100644 web/src/lib/components/DownloadButton.svelte create mode 100644 web/src/lib/components/DropZone.svelte create mode 100644 web/src/lib/components/InfoPanel.svelte create mode 100644 web/src/lib/components/ParamForm.svelte create mode 100644 web/src/lib/components/Preview.svelte create mode 100644 web/src/lib/components/ToolPage.svelte diff --git a/web/src/app.css b/web/src/app.css index 243c323..725b3ea 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -82,3 +82,42 @@ select { outline-offset: 2px; border-radius: var(--radius-s); } + +button.primary, +button.secondary { + padding: var(--space-2) var(--space-3); + border-radius: var(--radius-s); + border: 1px solid transparent; + font-weight: 600; + font-size: 0.95rem; + cursor: pointer; + transition: + background 120ms ease, + border-color 120ms ease, + color 120ms ease; +} + +button.primary { + background: var(--accent); + color: #ffffff; +} + +button.primary:hover:not(:disabled) { + background: var(--accent-hover); +} + +button.secondary { + background: var(--surface); + color: var(--text); + border-color: var(--border); +} + +button.secondary:hover:not(:disabled) { + border-color: var(--accent); + color: var(--accent); +} + +button:disabled { + opacity: 0.55; + cursor: not-allowed; +} diff --git a/web/src/lib/components/DownloadButton.svelte b/web/src/lib/components/DownloadButton.svelte new file mode 100644 index 0000000..1658f01 --- /dev/null +++ b/web/src/lib/components/DownloadButton.svelte @@ -0,0 +1,41 @@ + + + diff --git a/web/src/lib/components/DropZone.svelte b/web/src/lib/components/DropZone.svelte new file mode 100644 index 0000000..c9a697e --- /dev/null +++ b/web/src/lib/components/DropZone.svelte @@ -0,0 +1,107 @@ + + +
{ + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + openPicker(); + } + }} + ondragover={(e) => { + e.preventDefault(); + dragging = true; + }} + ondragleave={() => (dragging = false)} + ondrop={(e) => { + e.preventDefault(); + dragging = false; + accept(e.dataTransfer?.files[0]); + }} +> + + {label} +
+ { + accept(input?.files?.[0]); + if (input) { + input.value = ''; + } + }} +/> + + diff --git a/web/src/lib/components/InfoPanel.svelte b/web/src/lib/components/InfoPanel.svelte new file mode 100644 index 0000000..88b863f --- /dev/null +++ b/web/src/lib/components/InfoPanel.svelte @@ -0,0 +1,49 @@ + + +{#if info} +
+
+
Размеры
+
{info.width} × {info.height} px
+
+
+
Альфа-канал
+
{info.hasAlpha ? 'есть — есть полупрозрачные пиксели' : 'нет'}
+
+
+
Уникальных цветов (RGBA)
+
{info.colorCount.toLocaleString('ru-RU')}
+
+
+{/if} + + diff --git a/web/src/lib/components/ParamForm.svelte b/web/src/lib/components/ParamForm.svelte new file mode 100644 index 0000000..b821aa6 --- /dev/null +++ b/web/src/lib/components/ParamForm.svelte @@ -0,0 +1,89 @@ + + +{#each params as param (param.id)} +
+ {#if param.type === 'checkbox'} + + {:else} + + {#if param.type === 'number'} + + {:else if param.type === 'select'} + + {:else if param.type === 'color'} + + {/if} + {/if} +
+{/each} + + diff --git a/web/src/lib/components/Preview.svelte b/web/src/lib/components/Preview.svelte new file mode 100644 index 0000000..1a1090b --- /dev/null +++ b/web/src/lib/components/Preview.svelte @@ -0,0 +1,40 @@ + + +{#if image} + +

{image.width} × {image.height} px

+{/if} + + diff --git a/web/src/lib/components/ToolPage.svelte b/web/src/lib/components/ToolPage.svelte new file mode 100644 index 0000000..f24e2e3 --- /dev/null +++ b/web/src/lib/components/ToolPage.svelte @@ -0,0 +1,187 @@ + + +
+

{tool.title}

+

{tool.description}

+ + {#if errorText} + + {/if} + + {#if !source} + (errorText = message)} /> + {:else} +
+
+

{isInfo ? 'Изображение' : 'Результат'}

+ {#if status === 'processing' && !result} +

Обработка…

+ {:else} + + {/if} + {#if isInfo && info} + + {/if} + +
+ + {#if !isInfo} +
+

Параметры

+ {#if tool.params.length > 0} + + + {:else} +

У этого инструмента нет параметров — результат уже готов.

+ {/if} +
+ +
+
+ {/if} +
+ {/if} +
+ +