diff --git a/docs/plan-redesign.md b/docs/plan-redesign.md index 90a139c..1110bb6 100644 --- a/docs/plan-redesign.md +++ b/docs/plan-redesign.md @@ -330,7 +330,7 @@ src/routes/preview/tools/[id]/+page.svelte `CATEGORIES`, `ToolCard`). Ссылки пока `#` (реальные `/preview/tools/[id]` подключим на C12). - [x] **[C11]** `/preview/demo` — зеркало воркспейса (4 шага + панель превью), статичный приёмочный стенд. -- [ ] **[C12]** `/preview/tools/[id]` — раскладка gradient (settings-panel + preview-panel). +- [x] **[C12]** `/preview/tools/[id]` — data-driven settings-panel + preview-panel (gradient live, остальные — плейсхолдер); `NumberField`, `entries()` для prerender, ToolCard-ссылки подключены. - [ ] **[C13]** `/preview/tools/[id]` — раскладка background-remover (comparison-grid). - [ ] **[C14]** step-cards для chain в tool-page. diff --git a/web/eslint.config.js b/web/eslint.config.js index 7982c99..26cf310 100644 --- a/web/eslint.config.js +++ b/web/eslint.config.js @@ -10,6 +10,20 @@ import tseslint from "typescript-eslint"; // включается на весь код (см. план-redesign §10, шаг 6). const newCode = ["**/src/lib/components/kit/**", "**/src/routes/preview/**"]; +// Полные recommended-наборы — только на новый код (см. ниже, блок перед prettier). +const jsRecommended = Array.isArray(js.configs.recommended) + ? js.configs.recommended + : [js.configs.recommended]; +const svelteRecommended = Array.isArray(svelte.configs["flat/recommended"]) + ? svelte.configs["flat/recommended"] + : [svelte.configs["flat/recommended"]]; +// Svelte-рекомендации применяем только к .svelte-файлам нового кода, иначе +// svelte-eslint-parser "съедает" обычные .ts в тех же папках (напр. +page.ts). +const svelteFiles = [ + "**/src/lib/components/kit/**/*.svelte", + "**/src/routes/preview/**/*.svelte", +]; + export default tseslint.config( { ignores: [ @@ -68,15 +82,10 @@ export default tseslint.config( }, // Полные recommended-наборы — только на новый код. ...[ - ...(Array.isArray(js.configs.recommended) - ? js.configs.recommended - : [js.configs.recommended]), - ...tseslint.configs.recommended, - ...svelte.configs["flat/recommended"], - ].map((cfg) => ({ - ...cfg, - files: newCode, - })), + ...jsRecommended.map((cfg) => ({ ...cfg, files: newCode })), + ...tseslint.configs.recommended.map((cfg) => ({ ...cfg, files: newCode })), + ...svelteRecommended.map((cfg) => ({ ...cfg, files: svelteFiles })), + ], // В Svelte 5 пропсы деструктурируются через `let` (конвенция документации и // наш AGENTS.md), поэтому prefer-const на них — ложноположительный. diff --git a/web/src/lib/components/kit/NumberField.svelte b/web/src/lib/components/kit/NumberField.svelte new file mode 100644 index 0000000..424e47d --- /dev/null +++ b/web/src/lib/components/kit/NumberField.svelte @@ -0,0 +1,47 @@ + + + + + + + diff --git a/web/src/routes/preview/+page.svelte b/web/src/routes/preview/+page.svelte index bad4e20..f462aed 100644 --- a/web/src/routes/preview/+page.svelte +++ b/web/src/routes/preview/+page.svelte @@ -42,7 +42,11 @@
{#each results as tool (tool.id)} - + {/each}
diff --git a/web/src/routes/preview/list-tools/+page.svelte b/web/src/routes/preview/list-tools/+page.svelte index c5945bc..aa6487f 100644 --- a/web/src/routes/preview/list-tools/+page.svelte +++ b/web/src/routes/preview/list-tools/+page.svelte @@ -39,7 +39,7 @@ {#each group.tools as tool (tool.id)} {/each} diff --git a/web/src/routes/preview/tools/[id]/+page.svelte b/web/src/routes/preview/tools/[id]/+page.svelte new file mode 100644 index 0000000..9d9c1cd --- /dev/null +++ b/web/src/routes/preview/tools/[id]/+page.svelte @@ -0,0 +1,290 @@ + + + + easy-png-tools / {tool?.title ?? "Tool"} + + + +{#if !tool} +
+ +
+{:else} +
+
+ + + {#snippet actions()} + AUTO + {/snippet} + +

{tool.description}

+
+ {#each tool.params as p (p.id)} +
+ {#if p.type === "color"} + setParam(p.id, v)} + /> + {:else if p.type === "slider"} + setParam(p.id, v)} + /> + {:else if p.type === "select"} + setParam(p.id, v)} + /> + {:else if p.type === "checkbox"} + + {:else if p.type === "text"} + setParam(p.id, v)} + /> + {:else if p.type === "number"} + setParam(p.id, v)} + /> + {/if} +
+ {/each} +
+ + + +
+
+ +
+ + + {#snippet actions()} + + {/snippet} + +
+ {#if previewError} + + {:else if previewUrl} + + + result + + + {:else if tool.generate} +
+ +
+ {:else} + + {/if} + +
+
+
+
+{/if} + + diff --git a/web/src/routes/preview/tools/[id]/+page.ts b/web/src/routes/preview/tools/[id]/+page.ts new file mode 100644 index 0000000..84f50f3 --- /dev/null +++ b/web/src/routes/preview/tools/[id]/+page.ts @@ -0,0 +1,11 @@ +import { TOOLS } from "$lib/registry"; + +export const prerender = true; + +export function entries() { + return TOOLS.map((tool) => ({ id: tool.id })); +} + +export function load({ params }: { params: { id: string } }) { + return { id: params.id }; +}