From 7b799969c4bc0229de490921f29a15b84387ee21 Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Sun, 23 Aug 2026 06:12:37 +0500 Subject: [PATCH] feat: add color picker --- web/src/lib/components/ParamForm.svelte | 76 +++++++++++-------- web/src/lib/components/Preview.svelte | 36 ++++++++- web/src/lib/components/ToolPage.svelte | 22 +++++- web/src/lib/components/tool/ParamsCard.svelte | 6 +- web/src/lib/components/tool/SourceCard.svelte | 6 +- web/src/lib/components/ui/ColorField.svelte | 59 +++++++++++++- 6 files changed, 162 insertions(+), 43 deletions(-) diff --git a/web/src/lib/components/ParamForm.svelte b/web/src/lib/components/ParamForm.svelte index 9f8027a..ae820d8 100644 --- a/web/src/lib/components/ParamForm.svelte +++ b/web/src/lib/components/ParamForm.svelte @@ -9,42 +9,52 @@ interface Props { params: ParamDef[]; values: Record; + pipetteTargetId?: string | null; + onPipetteToggle?: (id: string) => void; } - let { params, values = $bindable() }: Props = $props(); + let { params, values = $bindable(), pipetteTargetId = null, onPipetteToggle }: Props = $props(); {#each params as param (param.id)} - {#if param.type === 'checkbox'} - - {:else if param.type === 'number'} - - {:else if param.type === 'slider'} - - {:else if param.type === 'select'} - - {:else if param.type === 'color'} - - {/if} +
+ {#if param.type === 'checkbox'} + + {:else if param.type === 'number'} + + {:else if param.type === 'slider'} + + {:else if param.type === 'select'} + + {:else if param.type === 'color'} + onPipetteToggle?.(param.id)} + /> + {/if} +
{/each} diff --git a/web/src/lib/components/Preview.svelte b/web/src/lib/components/Preview.svelte index 3f0e006..8df0b73 100644 --- a/web/src/lib/components/Preview.svelte +++ b/web/src/lib/components/Preview.svelte @@ -1,7 +1,14 @@ {#if image} - + +

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

{/if} @@ -32,9 +58,13 @@ border-radius: var(--radius-m); } + canvas.pipette { + cursor: crosshair; + } + .dims { margin-top: var(--space-1); color: var(--text-muted); - font-size: 0.85rem; + font-size: var(--text-s); } diff --git a/web/src/lib/components/ToolPage.svelte b/web/src/lib/components/ToolPage.svelte index 118c162..f865d88 100644 --- a/web/src/lib/components/ToolPage.svelte +++ b/web/src/lib/components/ToolPage.svelte @@ -26,6 +26,17 @@ let runToken = 0; let lastRunSource: PixelImage | null = null; let lastRunValuesJson = ''; + let pipetteTargetId = $state(null); + + function handlePipetteToggle(id: string) { + pipetteTargetId = pipetteTargetId === id ? null : id; + } + + function handlePickColor(hex: string) { + if (!pipetteTargetId) return; + values[pipetteTargetId] = hex; + pipetteTargetId = null; + } async function handleFile(file: File) { errorText = ''; @@ -36,6 +47,7 @@ result = null; previewResult = null; showMask = false; + pipetteTargetId = null; info = isInfo ? imageInfo(source) : null; if (isInfo) { status = 'loaded'; @@ -90,6 +102,7 @@ result = null; previewResult = null; showMask = false; + pipetteTargetId = null; info = null; errorText = ''; status = 'idle'; @@ -132,6 +145,8 @@ onFile={handleFile} onError={(message) => (errorText = message)} onReset={reset} + pipetteActive={!!pipetteTargetId} + onPickColor={handlePickColor} />
@@ -151,7 +166,12 @@
{#if source && !isInfo} - + {/if} diff --git a/web/src/lib/components/tool/ParamsCard.svelte b/web/src/lib/components/tool/ParamsCard.svelte index 2fb6e7a..e2985e3 100644 --- a/web/src/lib/components/tool/ParamsCard.svelte +++ b/web/src/lib/components/tool/ParamsCard.svelte @@ -5,15 +5,17 @@ interface Props { params: ParamDef[]; values: Record; + pipetteTargetId?: string | null; + onPipetteToggle?: (id: string) => void; } - let { params, values = $bindable() }: Props = $props(); + let { params, values = $bindable(), pipetteTargetId = null, onPipetteToggle }: Props = $props();

Параметры

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

У этого инструмента нет параметров — результат уже готов. diff --git a/web/src/lib/components/tool/SourceCard.svelte b/web/src/lib/components/tool/SourceCard.svelte index 6b12a94..52634b3 100644 --- a/web/src/lib/components/tool/SourceCard.svelte +++ b/web/src/lib/components/tool/SourceCard.svelte @@ -10,9 +10,11 @@ onFile: (file: File) => void; onError: (message: string) => void; onReset: () => void; + pipetteActive?: boolean; + onPickColor?: (hex: string) => void; } - let { source, onFile, onError, onReset }: Props = $props(); + let { source, onFile, onError, onReset, pipetteActive = false, onPickColor }: Props = $props();

@@ -22,7 +24,7 @@ {:else}
- +
diff --git a/web/src/lib/components/ui/ColorField.svelte b/web/src/lib/components/ui/ColorField.svelte index 3c94e03..45eaf7f 100644 --- a/web/src/lib/components/ui/ColorField.svelte +++ b/web/src/lib/components/ui/ColorField.svelte @@ -6,20 +6,75 @@ label: string; value?: string; hint?: string; + pipetteActive?: boolean; + onPipetteToggle?: () => void; } - let { id, label, value = $bindable('#000000'), hint }: Props = $props(); + let { id, label, value = $bindable('#000000'), hint, pipetteActive = false, onPipetteToggle }: + Props = $props(); - +
+ + {#if onPipetteToggle} + + {/if} +