From e866975045aebda6353808d419189f6aae986687 Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Sun, 11 Oct 2026 02:16:44 +0500 Subject: [PATCH] fix: update dnd tools in pipeline --- .../schema/SchemaAlignedLayout.svelte | 374 --------------- .../components/schema/SchemaPreview.svelte | 178 ------- .../components/schema/SchemaToolView.svelte | 453 +++++++++++++----- .../lib/components/schema/step-dnd.svelte.ts | 16 +- 4 files changed, 348 insertions(+), 673 deletions(-) delete mode 100644 web/src/lib/components/schema/SchemaAlignedLayout.svelte delete mode 100644 web/src/lib/components/schema/SchemaPreview.svelte diff --git a/web/src/lib/components/schema/SchemaAlignedLayout.svelte b/web/src/lib/components/schema/SchemaAlignedLayout.svelte deleted file mode 100644 index 1e746f6..0000000 --- a/web/src/lib/components/schema/SchemaAlignedLayout.svelte +++ /dev/null @@ -1,374 +0,0 @@ - - -{#snippet maskChip(i: number)} - {#if stepMaskable[i]} - ontogglestepmask(i)} - /> - {/if} -{/snippet} - -
-
-
-
- {t("resultCard.previewPanel")} - - -
-
- {#if errorText} - - {/if} - {#each warnings as w (w)} -

{w}

- {/each} - {#if canExtend && !stepDnd?.active} -
- onaddstep(0, id)} /> -
-
- {/if} - {#each steps as step, i (step.key)} - {#if stepDnd?.isIndicatorAt(i)} -
- -
-
- {/if} - {@const input = i === 0 ? null : stepResults[i - 1]} - {@const out = stepResults[i]} - {#if i > 0} -
-
-
- {/if} -
- {@render stepCard(step, i)} -
- {#if i === 0} - - {:else} - {@const inSet = stepFileSets[i - 1] ?? []} - 1 ? inSet.length : undefined} - > - {#if inSet.length > 1} - - {:else if input} - - {:else} - {t("resultCard.noResult")} - {/if} - - {/if} - {#if i === steps.length - 1} - ontogglestepmask(i) - : undefined} - {oncopy} - {ondownloadtxt} - /> - {:else} - {@const outSet = stepFileSets[i] ?? []} - 1 ? outSet.length : undefined} - > - {#snippet actions()} - {@render maskChip(i)} - {/snippet} - {#if outSet.length > 1 && !stepMaskOn[i]} - - {:else if out} - - {:else} - {t("resultCard.noResult")} - {/if} - - {/if} -
-
- {#if canExtend && !stepDnd?.active} -
- onaddstep(i + 1, id)} /> -
-
- {/if} - {/each} - {#if stepDnd?.isIndicatorAt(steps.length)} -
- -
-
- {/if} -
- - diff --git a/web/src/lib/components/schema/SchemaPreview.svelte b/web/src/lib/components/schema/SchemaPreview.svelte deleted file mode 100644 index 66ebce2..0000000 --- a/web/src/lib/components/schema/SchemaPreview.svelte +++ /dev/null @@ -1,178 +0,0 @@ - - -
- {t("resultCard.previewPanel")} - {#if stepResults.length > 1} - - {/if} - -
- -{#if error} - -{/if} - -
- - {#each stepResults.slice(0, -1) as img, i (i)} - {@const set = stepFileSets[i] ?? []} - {#if set.length > 1 && !stepMaskOn[i]} - - {#snippet actions()} - {#if stepMaskable[i]} - steps.ontogglestepmask?.(i)} - /> - {/if} - {/snippet} - - - {:else if img} - - {#snippet actions()} - {#if stepMaskable[i]} - steps.ontogglestepmask?.(i)} - /> - {/if} - {/snippet} - - - {/if} - {/each} - -
- - diff --git a/web/src/lib/components/schema/SchemaToolView.svelte b/web/src/lib/components/schema/SchemaToolView.svelte index a46c843..e737032 100644 --- a/web/src/lib/components/schema/SchemaToolView.svelte +++ b/web/src/lib/components/schema/SchemaToolView.svelte @@ -9,7 +9,7 @@ import { hasTransparency } from "$lib/core/analyze"; import { debounce } from "$lib/core/debounce"; import { ToolError } from "$lib/core/errors"; - import { decodeFile, type OutputMime } from "$lib/core/io"; + import { decodeFile, toDataUrl, type OutputMime } from "$lib/core/io"; import { outputFormatByMime } from "$lib/output-formats"; import type { PixelImage } from "$lib/core/types"; import { baseName, uniqueName, type ChainWarning } from "$lib/run-chain"; @@ -44,15 +44,21 @@ clampSourceAwareMaxes, sanitizeSchemaParams, } from "$lib/registry-schema"; + import ChipButton from "$lib/components/ui/ChipButton.svelte"; + import Toggle from "$lib/components/ui/Toggle.svelte"; import { onMount } from "svelte"; import { SvelteSet } from "svelte/reactivity"; import AddStepButton from "./AddStepButton.svelte"; - import SchemaAlignedLayout from "./SchemaAlignedLayout.svelte"; + import PartsGrid from "./PartsGrid.svelte"; + import PreviewTile from "./PreviewTile.svelte"; + import SchemaActions from "./SchemaActions.svelte"; import SchemaFields from "./SchemaFields.svelte"; - import SchemaPreview from "./SchemaPreview.svelte"; + import SchemaResultTile from "./SchemaResultTile.svelte"; + import SchemaSourceTile from "./SchemaSourceTile.svelte"; import SortableStepCard from "./SortableStepCard.svelte"; import StepDropIndicator from "./StepDropIndicator.svelte"; import ToolPickerButton from "./ToolPickerButton.svelte"; + import { hasPreviewResult } from "./schema-preview-model"; import { createSchemaToolRunner } from "./schema-tool-runner.svelte"; import { createStepDnd } from "./step-dnd.svelte"; import { @@ -175,6 +181,15 @@ const alignedMode = $derived( aligned && resultKind === "image" && steps.length > 1, ); + const hasResult = $derived( + hasPreviewResult({ + inputMode, + resultKind: displayResultKind, + result, + fileResult, + textResult, + }), + ); const alphaLoss = $derived( resultKind === "image" && @@ -477,132 +492,199 @@ {/snippet} + {#snippet maskChip(i: number)} + {#if stepMaskable[i]} + toggleStepMaskByIndex(i)} + /> + {/if} + {/snippet} + + {#snippet inputTile(i: number)} + {#if i === 0} + (textSource = v)} + onrendertext={run} + onupload={handleFile} + onuploadmany={handleFiles} + /> + {:else} + {@const input = stepResults[i - 1]} + {@const inSet = stepFileSets[i - 1] ?? []} + 1 ? inSet.length : undefined} + > + {#if inSet.length > 1} + + {:else if input} + + {:else} + {t("resultCard.noResult")} + {/if} + + {/if} + {/snippet} + + {#snippet outputTile(i: number)} + {@const out = stepResults[i]} + {#if i === steps.length - 1} + toggleStepMaskByIndex(i) + : undefined} + oncopy={copyText} + ondownloadtxt={downloadText} + /> + {:else} + {@const outSet = stepFileSets[i] ?? []} + 1 ? outSet.length : undefined} + > + {#snippet actions()} + {@render maskChip(i)} + {/snippet} + {#if outSet.length > 1 && !stepMaskOn[i]} + + {:else if out} + + {:else} + {t("resultCard.noResult")} + {/if} + + {/if} + {/snippet} + + {#snippet panelHead()} +
+ {t("resultCard.previewPanel")} + {#if resultKind === "image" && steps.length > 1} + + {/if} + (format = v)} + onquality={setFormatQuality} + onlimit={(v) => (limitKb = v)} + /> +
+ {/snippet} + + {#snippet addRow(index: number)} + {#if canExtend && !stepDnd.active} +
+ addStepAt(index, id)} /> + {#if alignedMode} + + {/if} +
+ {/if} + {/snippet} + + {#snippet indicator(slot: number)} + {#if stepDnd.isIndicatorAt(slot)} +
+ + {#if alignedMode} + + {/if} +
+ {/if} + {/snippet} + - {#if !alignedMode} -
+ {#if alignedMode} +
+ + {@render panelHead()} + {@render addRow(0)} + {#each steps as step, i (step.key)} + {@render indicator(i)} + {@render stepCard(step, i)} +
+ {@render inputTile(i)} + {@render outputTile(i)} +
+ {@render addRow(i + 1)} + {/each} + {@render indicator(steps.length)} + +
+ {:else} +
- {#if canExtend && !stepDnd.active} - addStepAt(0, id)} /> - {/if} + {@render addRow(0)} {#each steps as step, i (step.key)} - {#if stepDnd.isIndicatorAt(i)} - - {/if} + {@render indicator(i)} {@render stepCard(step, i)} - {#if canExtend && !stepDnd.active} - addStepAt(i + 1, id)} /> - {/if} + {@render addRow(i + 1)} {/each} - {#if stepDnd.isIndicatorAt(steps.length)} - - {/if} + {@render indicator(steps.length)}
-
- (format = v), - onquality: setFormatQuality, - onlimit: (v) => (limitKb = v), - }} - source={{ - source, - sources: sourceFiles, - fileCount: sourceFiles.length, - textSource, - ontextinput: (v) => (textSource = v), - onrendertext: run, - onuploadmany: handleFiles, - }} - steps={{ - results: stepResults, - fileSets: stepFileSets, - maskable: stepMaskable, - maskOn: stepMaskOn, - masks: stepMasks, - ontogglestepmask: toggleStepMaskByIndex, - }} - result={{ - result, - resultNote, - fileResult, - textResult, - textVars: verdictVars, - mask: stepMasks.at(-1) ?? null, - maskOn: stepMaskOn.at(-1) ?? false, - ontogglemask: stepMaskable.at(-1) - ? () => toggleStepMask(steps[steps.length - 1].key) - : undefined, - oncopy: copyText, - ondownloadtxt: downloadText, - }} - /> + {@render panelHead()} +
+
{@render inputTile(0)}
+ {#each steps as step, i (step.key)} +
{@render outputTile(i)}
+ {/each} +
- {#each allWarnings as w (warningText(w))} -

{warningText(w)}

- {/each} - {:else} - (textSource = v)} - onrendertext={run} - onupload={handleFile} - onuploadmany={handleFiles} - ondownload={download} - oncopy={copyText} - ondownloadtxt={downloadText} - onformat={(v) => (format = v)} - onquality={setFormatQuality} - onlimit={(v) => (limitKb = v)} - /> {/if} + {#if errorText} + + {/if} + {#each allWarnings as w (warningText(w))} +

{warningText(w)}

+ {/each} {#if stepDnd.activeData && stepDnd.pointer}
:global(.step-card) { + grid-column: 1; + } + .aligned .head-spacer { + grid-column: 1; + } + .aligned .panel-head { + grid-column: 2 / -1; + padding: var(--space-l) var(--space-xl); + border: var(--size-border) solid var(--color-border); + border-bottom: none; + border-radius: var(--radius-m) var(--radius-m) 0 0; + background: var(--color-panel); + margin-bottom: 0; + } + .aligned .pair { + grid-column: 2 / -1; + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-l); padding: var(--space-xl); + border-right: var(--size-border) solid var(--color-border); + border-left: var(--size-border) solid var(--color-border); + background: var(--color-panel); + } + /* The workspace has align-items: start; panel pieces must stretch to the + row height or the side borders break when a card is taller than its + pair. */ + .aligned .panel-head, + .aligned .pair, + .aligned .row-bridge, + .aligned .panel-foot { + align-self: stretch; + } + .aligned .add-row, + .aligned .indicator-row { + grid-column: 1 / -1; + display: grid; + grid-template-columns: subgrid; + } + .aligned .row-bridge { + grid-column: 2 / -1; + border-right: var(--size-border) solid var(--color-border); + border-left: var(--size-border) solid var(--color-border); + background: var(--color-panel); + } + .aligned .panel-foot { + grid-column: 2 / -1; + min-height: var(--space-xl); + border: var(--size-border) solid var(--color-border); + border-top: none; + border-radius: 0 0 var(--radius-m) var(--radius-m); + background: var(--color-panel); + } + /* Compact drag: while a step is dragged, cards collapse to headers so the + reorder happens in a tight list; aligned additionally drops the preview + panel (its rows are too tall to drag across). */ + .dnd-active :global(.step-body) { + display: none; + } + .aligned.dnd-active .panel-head, + .aligned.dnd-active .pair, + .aligned.dnd-active .row-bridge, + .aligned.dnd-active .panel-foot, + .aligned.dnd-active .head-spacer { + display: none; + } + .error { + margin: var(--space-l) 0 0; + color: var(--color-danger); + font: var(--font-size-s) var(--font-mono); + } + .empty { + font: var(--font-size-s) var(--font-mono); } .no-schema { font: var(--font-size-s) var(--font-mono); } .warn { - margin: 0; + margin: var(--space-s) 0 0; color: var(--color-warning); font: var(--font-size-s) var(--font-mono); } @media (--bp-tablet) { - .workspace { + .workspace, + .workspace.aligned { grid-template-columns: 1fr; } + .pair-grid, + .aligned .pair { + grid-template-columns: 1fr; + } + .aligned .head-spacer, + .aligned .row-bridge { + display: none; + } + .aligned .panel-head, + .aligned .pair, + .aligned .panel-foot { + grid-column: 1 / -1; + } } diff --git a/web/src/lib/components/schema/step-dnd.svelte.ts b/web/src/lib/components/schema/step-dnd.svelte.ts index 8a4ac9f..746275e 100644 --- a/web/src/lib/components/schema/step-dnd.svelte.ts +++ b/web/src/lib/components/schema/step-dnd.svelte.ts @@ -20,14 +20,17 @@ interface DndEvent { } // Count the slot the pointer is over: how many non-source cards have their -// vertical midpoint above the pointer. +// vertical midpoint above the pointer. Also reports the height of the first +// visible card: during drag all cards collapse to headers, so the indicator +// takes that uniform height rather than the hidden source's stale height. function indexAtPosition( source: SortableDraggable, pointerY: number, -): number { +): { index: number; cardHeight: number } { const manager = source.sortable.manager; let index = 0; - if (!manager) return index; + let cardHeight = 0; + if (!manager) return { index, cardHeight }; for (const droppable of manager.registry.droppables) { if (!isSortable(droppable)) continue; if (droppable.sortable.id === source.id) continue; @@ -35,9 +38,10 @@ function indexAtPosition( if (!el) continue; const rect = el.getBoundingClientRect(); if (rect.height === 0) continue; + if (!cardHeight) cardHeight = rect.height; if (pointerY > rect.top + rect.height / 2) index++; } - return index; + return { index, cardHeight }; } // Step-reorder state for SchemaToolView, single list. The dragged card is @@ -65,10 +69,12 @@ export function createStepDnd({ onMove }: StepDndOptions) { const position = event.operation?.position?.current; if (!position || !sourceX) return null; if (position.x < sourceX.left || position.x > sourceX.right) return null; - return indexAtPosition( + const { index, cardHeight } = indexAtPosition( source as SortableDraggable, position.y, ); + if (cardHeight) dragHeight = cardHeight; + return index; } function onDragStart(event: DndEvent) {