From 5ce8681a2487feb50cb8fe0fc0e470a06b4a405f Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Wed, 16 Sep 2026 17:36:37 +0500 Subject: [PATCH] docs: update plan for field audit --- docs/plan-fields-audit-fixes.md | 388 ++++++++++++++++++++++++++++++++ docs/tools-audit.md | 99 +++++--- 2 files changed, 455 insertions(+), 32 deletions(-) create mode 100644 docs/plan-fields-audit-fixes.md diff --git a/docs/plan-fields-audit-fixes.md b/docs/plan-fields-audit-fixes.md new file mode 100644 index 0000000..cb118cc --- /dev/null +++ b/docs/plan-fields-audit-fixes.md @@ -0,0 +1,388 @@ +# План: исправления по аудиту UX/UI + +> Статус: **draft** — на ревью. +> +> Источник: `docs/tools-audit.md`. Этот документ разбивает аудит на конкретные +> шаги, группирует по типу работы и фиксирует решения. + +## 0. Ключевое решение: select → buttons + +Существующий `Segmented.svelte` — компонент с группированными кнопками (общая +рамка, разделители между сегментами). Для параметров инструментов он не +подходит: при 3+ опциях сегменты сжимаются, текст не читается. + +**Решение:** новый компонент `ButtonsControl` — раздельные outline-кнопки с +отступами. Каждая опция — отдельная ` + {/each} + +``` + +```css +.buttons { + display: flex; + flex-wrap: wrap; + gap: var(--space-m); +} +.btn { + padding: var(--space-m) var(--space-l); + border: var(--size-border) solid var(--color-border); + border-radius: var(--radius-s); + font: var(--font-size-s) var(--font-mono); + color: var(--color-text-muted); + background: transparent; + cursor: pointer; +} +.btn.selected { + background: var(--color-main); + color: var(--color-background); + border-color: var(--color-main); +} +``` + +### Схема: `field.buttons()` + +Новый тип в `registry-schema.ts`: + +```ts +export interface ButtonsSpec extends FieldSpecBase { + kind: "buttons"; + default: V; + options: { value: V; label: string }[]; +} +``` + +Фабрика: + +```ts +buttons: (s: Omit, "kind">): Field => ({ + spec: { kind: "buttons", ...s }, +}), +``` + +Регистрация: добавить `"buttons": {} as ButtonsSpec` в `fieldSpecs`, добавить +`ButtonsControl` в `FIELDS` в `SchemaFields.svelte`, добавить дефолт/санитайз в +`sanitizeSchemaParams` и `defaultSchemaParams`. + +--- + +## 1. Волна A — инфраструктура (1 коммит) + +### Шаг A1. Новый тип `buttons` в схеме + +Файлы: + +- `web/src/lib/registry-schema.ts` — `ButtonsSpec`, фабрика `field.buttons()`, + кейс в `sanitizeSchemaParams`, кейс в `defaultSchemaParams` +- `web/src/lib/components/fields/schema/ButtonsControl.svelte` — новый компонент +- `web/src/lib/components/SchemaFields.svelte` — импорт + запись в `FIELDS` + +### Шаг A2. Seed → input + randomize + +Для `field.number()` с `kind: "seed"` (или новый подтип `field.seed()`) — +рендерить поле ввода + кнопку «Random» вместо range slider. + +Решение: новый вид `field.seed()` (наследует от number, но рендерится иначе). +Или проще: опциональное поле `variant?: "seed"` в `NumberSpec` — тогда +`RangeControl` покажет input + кнопку. + +Решение: **`variant: "seed"` в `NumberSpec`** — меньше новых типов. + +Файлы: + +- `web/src/lib/registry-schema.ts` — `NumberSpec.variant?: "seed"` +- `web/src/lib/components/fields/schema/RangeControl.svelte` — условный рендер +- `web/src/lib/registry/filters.ts` — `randomizePixels`, `addNoise`: поле seed → + `{ ...field.number(...), spec: { ...spec, variant: "seed" } }` (или + пересоздать через `field.seed()`) + +--- + +## 2. Волна B — select → buttons (по файлам) + +Каждый шаг — один коммит, < 500 строк. Меняем `field.select()` → +`field.buttons()` в перечисленных ниже схемах. + +### B1. geometry.ts (8 инструментов) + +| Инструмент | Поле | Опции | +| ----------------------- | -------- | ----------------------------------------- | +| rotate-png | angle | 90° / 180° / 270° | +| flip-png | axis | horizontal / vertical | +| swap-orientation-png | target | portrait / landscape | +| symmetric-copy-png | axis | vertical / horizontal | +| symmetric-copy-png | keepSide | left / right / top / bottom | +| change-aspect-ratio-png | ratio | 1:1 / 4:3 / 3:4 / 3:2 / 2:3 / 16:9 / 9:16 | +| change-aspect-ratio-png | mode | crop / pad | + +**Исключение:** `change-canvas-size-png` (anchor, 9 опций) — оставить +`field.select()`, т.к. 9 кнопок в ряд не поместятся. Аналогично `position9` (уже +отдельный компонент `PositionControl`). + +### B2. color.ts (4 инструмента) + +| Инструмент | Поле | Опции | +| ------------------------ | --------- | ------------------------------------ | +| dithering-png | pattern | floyd-steinberg / bayer | +| extract-channel-png | channel | red / green / blue | +| swap-channels-png | pair | r-g / r-b / g-b | +| decrease-color-count-png | maxColors | 2 / 4 / 8 / 16 / 32 / 64 / 128 / 256 | + +**Исключение:** channel spaces (hsl/hsv/... component) — 3-6 опций, но это +динамические инструменты, оставить `select`. + +### B3. analyze.ts (5 инструментов) + +| Инструмент | Поле | Опции | +| ------------------------- | ---- | ------------------ | +| show-transparent-png | mode | binary / highlight | +| show-grayscale-pixels-png | mode | (тот же) | +| show-color-pixels-png | mode | (тот же) | +| light-pixel-mask-png | mode | (тот же) | +| dark-pixel-mask-png | mode | (тот же) | + +Все используют общий `maskBaseFields` — правка в одном месте. + +### B4. filters.ts (1 инструмент) + +| Инструмент | Поле | Опции | +| ------------- | ---- | ------------ | +| add-noise-png | mode | mono / color | + +### B5. generate.ts (12 инструментов) + +| Инструмент | Поле | Опции | +| ------------------ | ------------ | --------------------- | +| color-spectrum-png | direction | horizontal / vertical | +| step-colors-png | layout | grid / strip | +| complementary-png | layout | grid / strip | +| triadic-png | layout | grid / strip | +| tetradic-png | layout | grid / strip | +| analogous-png | layout | grid / strip | +| monochromatic-png | layout | grid / strip | +| shades-png | layout | grid / strip | +| sort-colors-png | layout | grid / strip | +| mix-colors-png | (нет select) | — | + +--- + +## 3. Волна C — обязательные фиксы (баги + дефолты) + +### C1. resize-png: дефолт 0×0 → осмысленный + +`geometry.ts`: `width: 0, height: 0` → `width: 512, height: 512` (или +`width: imgWidth, height: imgHeight` — но дефолт в схеме не может знать размер +изображения). **Решение:** дефолт `512×512`. + +### C2. symmetric-copy-png: "keep side" не работает + +Баг в `run()`: `keepSide` не учитывает `axis`. При `axis: "vertical"` (удвоение +ширины) работают только `left`/`right`, `top`/`bottom` не имеют смысла. Нужно: +либо фильтровать опции `keepSide` в зависимости от `axis` (reactive schema), +либо нормализовать в `run()`. + +**Решение:** reactive — при смене `axis` сбрасывать `keepSide` на допустимое +значение. Пока достаточно в `run()`: если `axis === "vertical"` и `keepSide` ∈ +{top, bottom} → заменить на `left`. + +### C3. Механизм проброса размеров картинки в схему + +**Проблема.** Поля, значения которых зависят от размеров исходника (crop x/y, +resize, offsets), объявлены в статической схеме (`-100000…100000`), а реальная +картинка обычно 800–4000px. Диапазон надо считать от фактического размера +изображения, а не от потолков. + +**Что нужно спроектировать и завести:** + +1. **Где берём размер.** `SchemaToolView` уже знает размер после `decodeFile()` + → `PixelImage` (width/height). Сейчас он никуда не пробрасывается — надо + прокинуть в `SchemaFields` и дальше в контролы, например через context или + проп `sourceSize`. + +2. **Как схеме описать зависимость.** В спеках добавить ссылку на размер + источника вместо жёстких чисел. Кандидат: + + ```ts + x: field.slider({ + label: "fields.x", + bound: "sourceWidth", // min/max = ±sourceWidth + default: 0, + }), + ``` + + `BoundSpec = "sourceWidth" | "sourceHeight" | "minSide" | "maxSide"`, + применимо к `NumberSpec`, `SliderSpec`, `OffsetSpec`, `DimensionSpec`. + +3. **Что делает RangeControl.** При `bound` вычисляет min/max из текущего + размера источника; при смене картинки диапазон пересчитывается, текущее + значение пере-клампится. Дефолт и `sanitize` остаются на статической основе + (или тоже учат bound) — решить при проектировании. + +4. **Первые потребители:** crop (x/y → ±sourceWidth/sourceHeight), shift + (offsetX/offsetY), resize (max → maxSide). + +Это отдельный шаг плана: **завести механизм**, спроектировать на ревью интерфейс +спека (`bound` vs `range: (size) => [min, max]`), затем применить к crop и +остальным полям размерности. Пока механизма нет — поля crop остаются как есть. + +### C4. verify-is-png: неверное название + +Проверяет текст, не PNG-файл. Переименовать: + +- `id` → `verify-is-png-data` (или оставить для обратной совместимости) +- `title` → "Verify PNG data" +- `description` → уточнить + +**Решение:** поменять title и description, id не трогать (url-dependent). + +--- + +## 4. Волна D — обязательные фиксы (новые параметры) + +### D1. remove-alpha-channel-png: выбор цвета фона + +Сейчас захардкожен `#ffffff`. Добавить `field.color({ default: "#ffffff" })`. + +Файл: `alpha.ts`, схема `removeAlphaChannelSchema`. + +### D2. extract-alpha-mask-png: галочка «инвертировать» + +Добавить `field.checkbox({ label: "fields.invertMask", default: false })`. В +`run()`: если `invert`, вызвать `invertAlpha()` после `extractAlphaMask()`. + +Файл: `alpha.ts`. + +### D3. change-canvas-size-png: position9 вместо select + +`anchor` сейчас `field.select()` с 9 опциями → `field.position9()`. + +Файл: `geometry.ts`. Уже есть `PositionControl`. + +### D4. Generators: добавить height + +Инструменты без `size`/`height`: + +- blend-two-png — добавить + `height: field.slider({ min: 1, max: 1024, default: 512 })` +- step-colors-png — аналогично +- complementary, triadic, tetradic, analogous, monochromatic, shades, + sort-colors — все используют `paletteBaseSchema` (общий объект), добавить + `height` туда +- mix-colors-png — добавить height + +Файл: `generate.ts`. + +### D5. add-border-png: прозрачность цвета + +Текущий `field.color()` не поддерживает alpha. Пока что: оставить как есть +(прозрачность не поддерживается нативным color picker). Отметить в аудите как +blocked. + +--- + +## 5. Волна E — полировка (некритично) + +### E1. Плейсхолдер "нет параметров" + +Инструменты с пустой схемой (`EmptyParams`) выглядят странно. Добавить +`EmptyState` или подсказку "No parameters — click Run". + +Файл: `SchemaToolView.svelte` — показать подсказку если `schema.fields` пуст. + +### E2. quantize-png: пресеты + +`field.slider` с max 64 → добавить пресеты (8, 16, 32, 64) как кнопки под +слайдером. Либо `field.buttons()` с 4 опциями вместо слайдера. + +### E3. trim-empty-space-png: 0-254 → проценты + +Текущий `min: 0, max: 254` — нестандартно. Добавить переключатель px/% (аналог +шага A1 — `variant: "alpha-threshold"` в NumberSpec). + +### E4. add-text-png: plate offset + +Plate снизу имеет большой отступ — добавить галочку "compact plate" или +уменьшить дефолтный padding. + +### E5. emoji-to-png: выбор эмодзи + +Поле `text` → добавить группу часто используемых эмодзи как кнопки- пресеты над +полем ввода. + +--- + +## 6. Верификация + +После каждой волны: + +1. `pnpm --dir web build` — без ошибок +2. `pnpm --dir web exec svelte-check --tsconfig ./tsconfig.json` — без ошибок +3. `pnpm --dir web lint` — без ошибок (кроме ожидаемых долгов) +4. Ручная проверка в браузере: параметры рендерятся, инструменты работают + +--- + +## 7. Не покрыто / требует решения + +Эти пункты из аудита не попали в волны A–E. Требуют либо дополнительного +исследования, либо нормативного решения, либо отложены. + +### 7.1 Требуют normative решения + +- **Pixel ↔ Percent** (circle-mask, square-mask, star-mask, wavy-mask — %→px, + round-corners — px→%): нужен компонент переключателя единиц в слайдере. + Отложен до волны E, т.к. требует правки `RangeControl` + всех схем. +- **Smoothing checkbox** для масок (circle, square, star, wavy, round-corners, + invert-alpha): нужен `field.checkbox("smoothing")` + правка core (shapes.ts, + alpha). Отложен — требует визуального тестирования. +- **Vignette**: выбор центра + цвет + feather — 3 новых параметра. Требует + normative решения по UI. +- **Remove-background**: выбор точки удаления — либо параметр, либо отдельный + инструмент. +- **Precision/quality**: select в resize (bilinear/bicubic/nearest) — нужен ли + выбор алгоритма? +- **Placeholders**: "нет параметров" — какой текст/компонент показывать. + +### 7.2 Операционные (тест-кейсы, описания) + +- find-contour-png: расширять на толщину линии (требует правки core) +- make-thicker-png: расширять картинку на толщину линии +- make-thinner-png: уменьшать от краев, fix выступа +- feather-edges-png: расширять картинку на толщину линии +- clean-edges-png: найти тест-кейс, возможно увеличить максимум +- despeckle-alpha-png: найти более заметный тест-кейс +- close-holes-png: проверить поведение на больших полупрозрачных областях +- auto-contrast-png: найти тестовый кейс +- sharpen-png: добавить тест-кейс +- center-by-alpha-png: найти тест-кейс +- png-is-grayscale: улучшить видимость результата + +### 7.3 Дизайн-вопросы + +- add-padding-png vs add-border-png: разница неочевидна, нужен review +- change-aspect-ratio-png: не видно что меняется — рамка результата +- watermark-tile-png: заполняет не полностью +- sepia-png: нужна ли настройка силы эффекта? +- posterize-png: настройка для каждого канала отдельно? +- pixelate-png: разные алгоритмы? +- swap-channels-png: обдумать flow через более простые инструменты + +### 7.4 Аудит полей (компоненты) + +- Range slider: поле ввода + кнопки +/- + кнопка сброса +- Color picker: пипетка с картинки, прозрачность +- Width/height с keep-aspect-ratio: единый компонент +- Position offset: отдельные слайдеры x/y (уже сделано в `OffsetControl`) diff --git a/docs/tools-audit.md b/docs/tools-audit.md index 9433d87..5103a5e 100644 --- a/docs/tools-audit.md +++ b/docs/tools-audit.md @@ -3,49 +3,71 @@ ## везде - возможность переключать пиксели\проценты -- инструменты без параметров выглядят странно, пересмотреть, может добавить какую-то надпись "нет параметров" +- инструменты без параметров выглядят странно, пересмотреть, может добавить + какую-то надпись "нет параметров" - удаление\маски и т.д. - надо добавить галочку сглаживание -- производительность: почему flip заметно тормозит, но нет индикации работы инструмента (также sharpen-png) -- производительность: исследовать, есть ли смысл на инструментах геометрии выводить рамку результата до полноценной работы (например на skew \ rotate будет удобнее) +- производительность: почему flip заметно тормозит, но нет индикации работы + инструмента (также sharpen-png) +- производительность: исследовать, есть ли смысл на инструментах геометрии + выводить рамку результата до полноценной работы (например на skew \ rotate + будет удобнее) ## аудит инструментов ### transparency - add-stroke-png: добавить галочку "расширить на толщину линии" -- find-contour-png: если толщина линии более 1px - круг боле с искажениями, надо расширять на толщину линии +- find-contour-png: если толщина линии более 1px - круг боле с искажениями, надо + расширять на толщину линии - circle-mask-png: размеры заданы в процентах, надо задавать в пикселях - square-mask-png: размеры заданы в процентах, надо задавать в пикселях -- star-mask-png: размеры заданы в процентах, надо задавать в пикселях, проверить форму звезды - сейчас выпуклые края, радиус задан до 100%, а более 50 - смысле нет -- wavy-mask-png:размеры заданы в процентах, надо задавать в пикселях, пересмотреть форму и параметры. как будто неудобно конфигурировать -- remove-alpha-channel-png: выбор цвета фона, как будет работать с полупрозрачной картинкой? +- star-mask-png: размеры заданы в процентах, надо задавать в пикселях, проверить + форму звезды - сейчас выпуклые края, радиус задан до 100%, а более 50 - смысле + нет +- wavy-mask-png:размеры заданы в процентах, надо задавать в пикселях, + пересмотреть форму и параметры. как будто неудобно конфигурировать +- remove-alpha-channel-png: выбор цвета фона, как будет работать с + полупрозрачной картинкой? - extract-alpha-mask-png: галочка инвертировать маску -- round-corners-png: размеры заданы в пикселях, должна быть возможность задать в процентах, нету сглаживания по вырезанным пикселям -- invert-alpha-png: края со сглаживанием странно обрабатываются, может галочка\слайдер обрезать сглаживание? -- remove-background-png: возможность выбора точки, от которой удалять (или отдельный инструмент?) +- round-corners-png: размеры заданы в пикселях, должна быть возможность задать в + процентах, нету сглаживания по вырезанным пикселям +- invert-alpha-png: края со сглаживанием странно обрабатываются, может + галочка\слайдер обрезать сглаживание? +- remove-background-png: возможность выбора точки, от которой удалять (или + отдельный инструмент?) - make-thicker-png: расширять картинку на толщину линии -- make-thinner-png: уменьшать от краев, если картинка начинается от края, то остается выступ -- feather-edges-png: расширять картинку на толщину линии, (выбор цвета возможен? другой инструмент?) -- clean-edges-png: непонятный инструмент (слишком маленький максимум?). найти тест кейс для него +- make-thinner-png: уменьшать от краев, если картинка начинается от края, то + остается выступ +- feather-edges-png: расширять картинку на толщину линии, (выбор цвета возможен? + другой инструмент?) +- clean-edges-png: непонятный инструмент (слишком маленький максимум?). найти + тест кейс для него - despeckle-alpha-png: найти более заметный тест-кейс -- close-holes-png: проверить, как должен работать, картинки с большой полупрозрачной областью - закрывает всё, по описанию должен закрывать только небольшие дырки +- close-holes-png: проверить, как должен работать, картинки с большой + полупрозрачной областью - закрывает всё, по описанию должен закрывать только + небольшие дырки ### colors - two-colors-png: в range slider добавить описание что это luminance threshold -- gamma-png: проверить правильность работы - яркое изображение выглядит не контрастным, проверить максимум и минимум -- temperature-png: проверить правильность работы - не слишком ли отдает желтым\синим? +- gamma-png: проверить правильность работы - яркое изображение выглядит не + контрастным, проверить максимум и минимум +- temperature-png: проверить правильность работы - не слишком ли отдает + желтым\синим? - quantize-png: максимум 64 - не слишком мало? сделать кнопки с пресетами -- custom-palette-png: копирует two-colors-png, только ввод через текстовое поле и нет выбора порога luminance +- custom-palette-png: копирует two-colors-png, только ввод через текстовое поле + и нет выбора порога luminance - dithering-png: проверить алгоритм Floyd–Steinberg на малом количестве цветов - sepia-png: не нужна настройка силы эффекта? - extract-channel-png: мульти вывод сразу в 3 канала? -- swap-channels-png: обдумать описание подобных инструментов через flow более простых? +- swap-channels-png: обдумать описание подобных инструментов через flow более + простых? - black-and-white-png: аналог two-colors-png, только без выбора цветов - posterize-png: не нужен вариант настройки для каждого канала отдельно? - auto-contrast-png: найти тестовый кейс - decrease-color-count-png: сделать кнопки вместо селекта -- png-to-hsl: проверить, что `space as rgb` должна выдавать одинаковые результаты, вне зависимости от выбора h s l. может выбрать отдельные кнопки? +- png-to-hsl: проверить, что `space as rgb` должна выдавать одинаковые + результаты, вне зависимости от выбора h s l. может выбрать отдельные кнопки? - png-to-hsv: тоже самое ^ - png-to-hsi: тоже самое ^, нужно ли разделять на отдельные инструменты? - png-to-cmyk: тоже самое ^ @@ -56,43 +78,53 @@ - add-border-png: прозрачность цвета (аудит полей) - fit-on-background-png: цвет - change-canvas-size-png: использовать position9 вместо селекта -- resize-png: по умолчанию размеры 0х0, надо поменять; выбор метода масштабирования +- resize-png: по умолчанию размеры 0х0, надо поменять; выбор метода + масштабирования - crop-png: offset - слишком большие значения - rotate-png: кнопки вместо select - flip-png: кнопки вместо select - add-padding-png: чем отличается от add-border-png? - center-by-alpha-png: найти тест кейс - zoom-png: выбор точки центра -- trim-empty-space-png: выбор от 0 до 254 (надо везде привести к единому стилю - переключение 0-100 проценты и 0-255) -- change-aspect-ratio-png: не видно что меняется, добавить рамку вокруг результата, а не вокруг div +- trim-empty-space-png: выбор от 0 до 254 (надо везде привести к единому стилю - + переключение 0-100 проценты и 0-255) +- change-aspect-ratio-png: не видно что меняется, добавить рамку вокруг + результата, а не вокруг div - swap-orientation-png: кнопки вместо select -- symmetric-copy-png: кнопки вместо select, два выбора в селекте `keep side` не работают (в зависимости от выбора `axis`) +- symmetric-copy-png: кнопки вместо select, два выбора в селекте `keep side` не + работают (в зависимости от выбора `axis`) - shift-png: цвет (прозрачность) - split-into-parts-png: результат с несколькими файлами, обдумать процесс ### filters -- vignette-png: выбор точки центра, цвет, кроме силы нужен еще параметр прироста силы (как называется?) +- vignette-png: выбор точки центра, цвет, кроме силы нужен еще параметр прироста + силы (как называется?) - pixelate-png: разные алгоритмы? выглядит не очень. тест кейс? -- randomize-pixels-png: настройка размеров другим вариантом - на сколько кусков делить. seed - поменять +- randomize-pixels-png: настройка размеров другим вариантом - на сколько кусков + делить. seed - поменять - add-noise-png: кнопки вместо select, seed - поменять - sharpen-png: добавить тест кейс - silhouette-png: аналог extract-alpha-mask-png? ### text -- add-text-png: plate снизу большой отступ, сделать галочку для этого (некоторые буквы будут обрезаться - y, g) +- add-text-png: plate снизу большой отступ, сделать галочку для этого (некоторые + буквы будут обрезаться - y, g) - watermark-tile-png: заполняет не полностью ### analyze -- extract-color-from-png: надо описать или дать выбор на основе какого параметра работает threshold +- extract-color-from-png: надо описать или дать выбор на основе какого параметра + работает threshold - show-transparent-png: кнопки вместо select - show-grayscale-pixels-png: кнопки вместо select - show-color-pixels-png: кнопки вместо select - light-pixel-mask-png: кнопки вместо select -- verify-is-png: название неверное, в описании указано изображение, а фактически проверяется текст -- png-is-grayscale: результат плохо виден, нужно ли копирование на полный вердикт? может отдельные поля - 0\1, yes\no? +- verify-is-png: название неверное, в описании указано изображение, а фактически + проверяется текст +- png-is-grayscale: результат плохо виден, нужно ли копирование на полный + вердикт? может отдельные поля - 0\1, yes\no? ### generators @@ -100,10 +132,12 @@ - draw-grid-png: выбор цвета фона - placeholder-png: с галочкой "показать текст" нет заполнения фона - blend-two-png: высота не задается -- step-colors-png: кнопки вместо select, высота не задается, не слишком ли маленький max steps? +- step-colors-png: кнопки вместо select, высота не задается, не слишком ли + маленький max steps? - emoji-to-png: выбор эмодзи - color-wheel-png: сглаживание краев -- complementary-png: кнопки вместо select(?), не меняется, всего 2 цвета, высота не задается +- complementary-png: кнопки вместо select(?), не меняется, всего 2 цвета, высота + не задается - triadic-png: кнопки вместо select, высота не задается - tetradic-png: кнопки вместо select, высота не задается - analogous-png: кнопки вместо select, высота не задается @@ -119,4 +153,5 @@ - range slider with presets: слайдер, как выше, добавочные кнопки с пресетами - color picker: пикер с картинки (как исходника, так и результата), прозрачность - ввод высоты и ширины с keep aspect ratio должен быть единым компонентом -- поле seed (random) - range slider не нужен, поле для ввода и "randomize" кнопка +- поле seed (random) - range slider не нужен, поле для ввода и "randomize" + кнопка