105 lines
8.0 KiB
Markdown
105 lines
8.0 KiB
Markdown
# План: range-слайдеры и пипетка цвета
|
||
|
||
> **СТАТУС: ВЫПОЛНЕН 2026-08-23.**
|
||
|
||
## 1. Целевое поведение
|
||
|
||
1. «Процентные» параметры (яркость, контраст, качество JPEG/WebP, порог
|
||
похожести) — слайдеры с числовым значением рядом; точные координаты и размеры
|
||
(resize/crop) остаются полями ввода.
|
||
2. У цветовых параметров появляется кнопка-переключатель «Пипетка»: активна →
|
||
клик по превью исходника снимает цвет пикселя и подставляет его в поле цвета;
|
||
после выбора режим гаснет.
|
||
3. В режиме пипетки возле курсора видна лупа: увеличенный блок пикселей вокруг
|
||
точки с перекрестием и подписью hex текущего пикселя; клик выбирает центр
|
||
перекрестия.
|
||
4. Активная пипетка видна на превью перекрестием курсора; повторный клик по
|
||
кнопке отменяет режим без выбора.
|
||
5. Всё работает поверх текущего процесса: авто-применение с задержкой, токен
|
||
запусков, маски — без изменений.
|
||
|
||
## 2. Слайдеры
|
||
|
||
- В реестре новый тип параметра `'slider'` с обязательными `min`/`max`;
|
||
валидируется как число (дефолт в диапазоне, минимум меньше максимума).
|
||
- Форма маппит его на готовый `SliderField` из `ui/`; санитизация параметров
|
||
обрабатывает slider так же, как number.
|
||
- Переводятся: яркость и контраст, качество JPEG, качество WebP, порог
|
||
похожести. Остальные инструменты — без изменений.
|
||
|
||
## 3. Пипетка и лупа
|
||
|
||
- В ядро добавляется чистая функция `rgbToHex(r, g, b)` → строка вида `#rrggbb`,
|
||
с юнит-тестами; чтение пикселя — из уже отрисованного canvas превью исходника
|
||
через `getImageData(x, y, 1, 1)`.
|
||
- `Preview.svelte` получает опциональный режим пипетки: пропсы «активна» и
|
||
колбэк «цвет выбран»; курсор перекрестие, клик вычисляет координату пикселя с
|
||
учётом разницы CSS-размера canvas и его внутренней ширины.
|
||
- **Лупа** — компонент `PipetteLoupe.svelte`: канвас около 110×110 px у курсора
|
||
(позиция fixed, `pointer-events: none`); рисует блок 15×15 пикселей из
|
||
исходника с увеличением ×8 без сглаживания, перекрестие в центре, подпись hex
|
||
текущего пикселя. Координаты блока клампятся у краёв изображения; лупа скрыта
|
||
вне превью и вне режима пипетки. Тач-устройства: прямой тап выбирает пиксель
|
||
без лупы.
|
||
- Проводка: кнопка у каждого цветового поля в карточке параметров → состояние
|
||
«активное цветовое поле» живёт в оркестраторе → выбор цвета записывает hex в
|
||
это поле и выключает режим.
|
||
- Пипетка работает только по левой панели (исходнику): удаляемый цвет и подложка
|
||
берутся с оригинала.
|
||
|
||
## 4. Этапы и проверки
|
||
|
||
- **A. Слайдеры** — тип в реестре, перевод четырёх инструментов, тесты реестра и
|
||
санитизации, тест `rgbToHex`. Проверка: `pnpm test/check`, визуально слайдеры.
|
||
- **B. Пипетка** — режим в Preview, проводка через карточки до полей цвета.
|
||
Проверка: смоук §6 пп. 5–7.
|
||
- **B2. Лупа** — компонент лупы поверх режима пипетки. Проверка: смоук §6 пп.
|
||
8–10.
|
||
- **C. Итог** — полный прогон `test/check/build`.
|
||
|
||
## 5. Изменения по файлам
|
||
|
||
- `registry.ts` — тип `'slider'` в `ParamDef`, перевод четырёх записей, ветка в
|
||
`sanitizeParams`.
|
||
- `ParamForm.svelte` — ветка slider → `SliderField`.
|
||
- `core/color.ts` — `rgbToHex`.
|
||
- `Preview.svelte` — режим пипетки (курсор, клик, колбэк).
|
||
- `PipetteLoupe.svelte` — лупа у курсора в режиме пипетки.
|
||
- `SourceCard.svelte` — проброс режима и колбэка наверх.
|
||
- `ParamsCard.svelte` + `ColorField.svelte` — кнопка «Пипетка» у цветового поля.
|
||
- `ToolPage.svelte` — состояние активного поля, обработчик выбора цвета.
|
||
|
||
## 6. Смоук-чеклист
|
||
|
||
1. Яркость/контраст — слайдеры со значением справа, результат обновляется сам
|
||
при перетаскивании.
|
||
2. Качество JPEG/WebP — слайдер от 1 до 100.
|
||
3. Порог похожести — слайдер от 0 до 100.
|
||
4. Resize и crop остались числовыми полями.
|
||
5. Удаление цвета: «Пипетка» → клик по красной области исходника → поле цвета
|
||
получил hex этого пикселя, режим погас, результат пересчитался.
|
||
6. Повторный клик по кнопке или выбор без подтверждения — режим снят, цвет не
|
||
изменился.
|
||
7. Подложка JPEG: пипетка проставляет цвет подложки тем же способом.
|
||
8. В режиме пипетки лупа следует за курсором, перекрестие показывает пиксель под
|
||
ним, подпись hex совпадает с выбранным при клике.
|
||
9. У края картинки блок лупи корректно клампится — за границей тянется
|
||
чёрный/прозрачный фон, выбор по-прежнему точен.
|
||
10. Курсор ушёл с превью или режим выключен — лупа скрыта; клики по кнопкам под
|
||
превью не перехватываются лупой.
|
||
11. Слайдеры и пипетка дружат с быстрыми правками: одна финальная версия
|
||
результата, чип «Пересчёт…» на месте.
|
||
|
||
## 7. Критерии готовности
|
||
|
||
- Все процентные параметры — слайдеры; числовые поля остались только там, где
|
||
нужен точный ввод.
|
||
- Цвет любого color-параметра можно взять кликом с исходника.
|
||
- `test/check/build` зелёные, чеклист §6 пройден.
|
||
|
||
## 8. Что сознательно не делаем
|
||
|
||
- Пипетка и лупа на превью результата и маски — только исходник.
|
||
- Кастомная стилизация слайдеров за пределами дизайн-системы.
|
||
- Лупа для тач-устройств — там прямой тап без лупы.
|