mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-09-14 21:46:35 +00:00
feat: add step picker\list\editor
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import ParamForm from '../ParamForm.svelte';
|
||||
import type { PipelineStep } from '$lib/tools/pipeline';
|
||||
import { getTool } from '$lib/registry';
|
||||
|
||||
interface Props {
|
||||
step: PipelineStep;
|
||||
}
|
||||
|
||||
let { step }: Props = $props();
|
||||
|
||||
const tool = $derived(getTool(step.toolId));
|
||||
</script>
|
||||
|
||||
{#if tool}
|
||||
<div class="editor panel">
|
||||
<h3 class="heading-section">{tool.title}</h3>
|
||||
<p class="description text-caption text-muted">{tool.description}</p>
|
||||
{#if tool.params.length > 0}
|
||||
<ParamForm params={tool.params} bind:values={step.values} />
|
||||
{:else}
|
||||
<p class="hint text-caption text-muted">У этого шага нет параметров.</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.editor {
|
||||
padding: var(--space-3);
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: var(--space-1);
|
||||
font-size: var(--text-m);
|
||||
}
|
||||
|
||||
.description,
|
||||
.hint {
|
||||
margin: 0 0 var(--space-2);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,128 @@
|
||||
<script lang="ts">
|
||||
import type { PipelineStep } from '$lib/tools/pipeline';
|
||||
import { getTool } from '$lib/registry';
|
||||
|
||||
interface Props {
|
||||
steps: PipelineStep[];
|
||||
selectedIndex: number;
|
||||
onSelect: (index: number) => void;
|
||||
onMoveUp: (index: number) => void;
|
||||
onMoveDown: (index: number) => void;
|
||||
onRemove: (index: number) => void;
|
||||
}
|
||||
|
||||
let { steps, selectedIndex, onSelect, onMoveUp, onMoveDown, onRemove }: Props = $props();
|
||||
|
||||
function toolTitle(step: PipelineStep): string {
|
||||
return getTool(step.toolId)?.title ?? step.toolId;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if steps.length === 0}
|
||||
<p class="empty text-caption text-muted">Цепочка пуста — добавьте первый инструмент.</p>
|
||||
{:else}
|
||||
<ol>
|
||||
{#each steps as step, index (step.id)}
|
||||
<li>
|
||||
<button type="button" class="label" class:selected={index === selectedIndex} onclick={() => onSelect(index)}>
|
||||
<span class="num">{index + 1}</span>
|
||||
{toolTitle(step)}
|
||||
</button>
|
||||
<span class="controls">
|
||||
<button type="button" aria-label="Выше" disabled={index === 0} onclick={() => onMoveUp(index)}>↑</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Ниже"
|
||||
disabled={index === steps.length - 1}
|
||||
onclick={() => onMoveDown(index)}
|
||||
>↓</button>
|
||||
<button type="button" class="remove" aria-label="Удалить шаг" onclick={() => onRemove(index)}>✕</button>
|
||||
</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.label {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
text-align: left;
|
||||
padding: var(--space-1) var(--space-2);
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-s);
|
||||
background: none;
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
font-size: var(--text-m);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.label:hover,
|
||||
.label.selected {
|
||||
background: color-mix(in srgb, var(--accent) 8%, var(--surface));
|
||||
border-color: var(--border);
|
||||
}
|
||||
|
||||
.num {
|
||||
display: inline-block;
|
||||
min-width: 1.4ch;
|
||||
margin-right: var(--space-1);
|
||||
color: var(--text-muted);
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--text-xs);
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.controls button {
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-s);
|
||||
background: var(--surface);
|
||||
color: var(--text-muted);
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.controls button:hover:not(:disabled) {
|
||||
border-color: var(--accent);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.controls .remove:hover:not(:disabled) {
|
||||
border-color: var(--danger);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.controls button:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.empty {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import Button from '../ui/Button.svelte';
|
||||
import { CATEGORIES } from '$lib/categories';
|
||||
import { TOOLS } from '$lib/registry';
|
||||
|
||||
interface Props {
|
||||
onAdd: (toolId: string) => void;
|
||||
}
|
||||
|
||||
let { onAdd }: Props = $props();
|
||||
|
||||
const steppable = TOOLS.filter(
|
||||
(tool) => (tool.resultType ?? 'image') === 'image' && (!tool.sourceMode || tool.sourceMode === 'file')
|
||||
);
|
||||
|
||||
let selected = $state(steppable[0]?.id ?? '');
|
||||
</script>
|
||||
|
||||
<div class="picker">
|
||||
<select bind:value={selected} aria-label="Инструмент для нового шага">
|
||||
{#each CATEGORIES as category (category.id)}
|
||||
{@const categoryTools = steppable.filter((tool) => tool.category === category.id)}
|
||||
{#if categoryTools.length > 0}
|
||||
<optgroup label={category.label}>
|
||||
{#each categoryTools as tool (tool.id)}
|
||||
<option value={tool.id}>{tool.title}</option>
|
||||
{/each}
|
||||
</optgroup>
|
||||
{/if}
|
||||
{/each}
|
||||
</select>
|
||||
<Button variant="secondary" onclick={() => onAdd(selected)}>Добавить шаг</Button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.picker {
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
select {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: var(--space-1) var(--space-2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-s);
|
||||
background: var(--surface);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user