color-value-tools 1.1.1: от конвертера форматов до полноценного инструментария для работы с цветом

30.03.2026
color-value-tools 1.1.1: от конвертера форматов до полноценного инструментария для работы с цветом

В первой версии color-value-tools закрывал базовую задачу: распознать формат цвета, конвертировать между hex, RGB, HSL, HSV, Lab, LCH, CMYK, распарсить CSS-переменную, вычислить контрастность по WCAG. Этого хватает, пока нужно просто «перевести цвет из одного формата в другой». Но как только появляется реальный UI — осветлить кнопку при hover, подобрать читаемый цвет текста, сгенерировать палитру из акцентного цвета, проверить доступность на градиентном фоне или сделать плавный переход без «серой зоны» посередине — базовых конвертаций быстро перестаёт хватать.

В этом посте — что изменилось в 1.1.1: поддержка современного CSS (oklch(), color(), Display P3), расширенная интерполяция с перцептивно правильными переходами, манипуляции и цветовые гармонии, генерация палитр, WCAG-утилиты с готовыми ответами, симуляция дальтонизма, кеш для hot-path, генераторы для больших последовательностей и CLI прямо из терминала.


Парсинг современных CSS-форматов

Функция normalizeColor теперь понимает CSS Color Level 4: oklch(), color(display-p3 ...), а также 4-значный hex #RGBA. Все они нормализуются в единую структуру {type, hex, r, g, b, a, h, s, l, v}.

ts Copy
import { normalizeColor, parseOklchString, parseCssVar } from 'color-value-tools';

normalizeColor('oklch(0.65 0.15 25)');
// { type: 'oklch', hex: '#e3553e', r: 227, g: 85, b: 62, ... }

normalizeColor('color(display-p3 1 0.5 0)');
// { type: 'color', hex: '#ff8000', r: 255, g: 128, b: 0, ... }

normalizeColor('#f0f0');
// { type: 'hex', hex: '#ff00ff', a: 0, ... }  (#RGBA shorthand)

Для парсинга в отдельных сценариях — специализированные функции:

ts Copy
parseOklchString('oklch(65% 0.15 25 / 0.8)');
// { L: 0.65, C: 0.15, H: 25, alpha: 0.8 }

parseCssVar('var(--primary, #3498db)');
// { variableName: '--primary', fallback: '#3498db' }

getColorType возвращает 'oklch' и 'color' для новых форматов. isOklchColor и isColorFunction — для явной проверки.


Display P3 и широкие гаммы

Для работы с широким цветовым охватом добавлена полная цепочка конвертации. Display P3 покрывает примерно на 25% больше видимого спектра, чем sRGB.

ts Copy
import { rgbToDisplayP3, toDisplayP3Hex, toColorP3String } from 'color-value-tools';

// sRGB (0–255) → Display P3 (0–1 на канал)
rgbToDisplayP3({ r: 255, g: 0, b: 0 });
// { r: 0.9175, g: 0.2003, b: 0.1386 }

// Форматирование как CSS Color Level 4
toColorP3String('#3498db');
// 'color(display-p3 0.2862 0.5862 0.8431)'

toColorP3String('#3498db', 0.9);
// 'color(display-p3 0.2862 0.5862 0.8431 / 0.9)'

Манипуляции с цветом

Набор функций для изменения отдельных характеристик. Все принимают любой поддерживаемый формат, возвращают hex.

lighten / darken — светлота через HSL:

ts Copy
lighten('#3498db', 15);  // '#6ab4e8'
darken('#3498db', 15);   // '#1a6da3'

saturate / desaturate — насыщенность:

ts Copy
desaturate('#ff0000', 60);  // ближе к серому
saturate('#888888', 40);    // цвет приобретает оттенок

setAlpha / getAlpha — прозрачность:

ts Copy
setAlpha('#3498db', 0.4);             // 'rgba(52, 152, 219, 0.4)'
getAlpha('rgba(52, 152, 219, 0.4)');  // 0.4

invertColor и grayscale — инверсия и обесцвечивание. grayscale использует перцептивные веса ITU-R BT.709:

ts Copy
invertColor('#ff0000');  // '#00ffff'
grayscale('#3498db');    // '#666666'

Интерполяция и цветовые шкалы

Главное улучшение в работе с переходами — поддержка перцептивных пространств. В sRGB и HSL при интерполяции между контрастными цветами посередине часто появляется «грязный» серый участок. В Oklab и Oklch этого нет.

mixColors расширен до шести пространств и управления интерполяцией оттенка:

ts Copy
import { mixColors } from 'color-value-tools';

// Серый посередине — типичная проблема RGB
mixColors('#ff0000', '#0000ff', 0.5, { mode: 'rgb' });   // '#800080'

// Oklch: насыщенный переход без потери яркости
mixColors('#ff0000', '#0000ff', 0.5, { mode: 'oklch' });

// Управление дугой оттенка
mixColors('#ff0000', '#0000ff', 0.5, {
  mode: 'oklch',
  hueInterpolation: 'longer',  // через длинную дугу
});

interpolateColors — массив шагов между двумя цветами:

ts Copy
import { interpolateColors } from 'color-value-tools';

interpolateColors('#ff0000', '#0000ff', 5, { space: 'oklab' });
// ['#ff0000', '#cc00cc', '#9900ff', '#6600ff', '#0000ff']

createColorScale — шкала из нескольких якорных цветов с опциональными позициями (0–1):

ts Copy
import { createColorScale } from 'color-value-tools';

// Три якоря, равномерно
createColorScale(['#ff0000', '#ffff00', '#00ff00'], 7);

// С позициями — белый занимает 80% шкалы
createColorScale([
  { color: '#ffffff', position: 0 },
  { color: '#3498db', position: 0.8 },
  { color: '#1a3a5c', position: 1 },
], 9);

midpointColor — перцептивная середина между двумя цветами (по умолчанию в Oklab):

ts Copy
import { midpointColor } from 'color-value-tools';

midpointColor('#ff0000', '#0000ff');
midpointColor('#ff0000', '#0000ff', { space: 'oklch' });

Палитры

Три терминологически корректные функции на основе смешивания в Oklab:

ts Copy
import { tints, shades, tones } from 'color-value-tools';

tints('#3498db', 5);            // от исходного к белому
shades('#3498db', 5);           // от исходного к чёрному
tones('#3498db', 5);            // от исходного к серому (#808080)
tones('#3498db', 5, '#a0a0a0'); // кастомный серый

Для дизайн-систем доступны также colorShades (HSL-шкала от белого до чёрного, 9 шагов по умолчанию) и monochromatic (варьирует насыщенность при фиксированной яркости).


Цветовые гармонии

ts Copy
import { complement, triadic, analogous, splitComplementary, tetradic } from 'color-value-tools';

complement('#3498db');         // '#db6034'
triadic('#3498db');            // ['#3498db', '#db3498', '#98db34']
analogous('#3498db', 40);      // три соседних через ±40°
splitComplementary('#3498db'); // ['#3498db', '#db9834', '#db3498']
tetradic('#3498db');           // четыре цвета через 90°

Первый элемент массива — всегда исходный цвет.


WCAG-доступность

В первой версии были только relativeLuminance и contrastRatio — числа без интерпретации. Теперь есть утилиты с готовыми ответами.

wcagLevel — уровень WCAG одной строкой:

ts Copy
wcagLevel('#ffffff', '#000000');  // 'AAA'
wcagLevel('#ffffff', '#3498db');  // 'AA'
wcagLevel('#ffffff', '#aaaaaa');  // 'fail'

bestTextColor / bestContrastColor — автоподбор:

ts Copy
bestTextColor('#3498db');  // '#ffffff' или '#000000' — что контрастнее
bestContrastColor('#3498db', ['#ffffff', '#000000', '#ffe0b2']);

bestContrastPalette — из набора палитр выбирает ту, что даёт наилучший суммарный контраст. Можно взвешивать элементы:

ts Copy
import { bestContrastPalette } from 'color-value-tools';

bestContrastPalette('#3498db', [
  ['#ffffff', '#f0f0f0', '#cccccc'],
  ['#000000', '#222222', '#444444'],
]);
// { paletteIndex: 1, palette: [...], minContrastRatio: 8.4, avgContrastRatio: 10.2 }

isReadableOnBackground — проверяет читаемость на сложном фоне: сплошном, полупрозрачном или градиентном:

ts Copy
import { isReadableOnBackground } from 'color-value-tools';

// Полупрозрачный фон поверх белой подложки
isReadableOnBackground('#ffffff', {
  type: 'semi-transparent',
  color: 'rgba(52,152,219,0.6)',
  underlay: '#ffffff',
});
// { readable: true, minContrastRatio: 3.8, wcagLevel: 'AA-large' }

// Градиент — проверяет минимальный контраст по всем стопам
isReadableOnBackground('#ffffff', {
  type: 'gradient',
  stops: ['#3498db', '#1a3a5c'],
});

Симуляция дальтонизма

Позволяет увидеть, как цвет воспринимается при трёх типах нарушения цветового зрения. Используются матрицы Vienot 1999, применяются к линеаризованному RGB.

ts Copy
import { simulateProtanopia, simulateDeuteranopia, simulateTritanopia } from 'color-value-tools';

simulateProtanopia('#3498db');   // нет L-колбочек (красный)
simulateDeuteranopia('#3498db'); // нет M-колбочек (зелёный)
simulateTritanopia('#3498db');   // нет S-колбочек (синий)

// Обобщённая версия
simulateColorBlindness('#3498db', 'deuteranopia');

Практический сценарий — прогнать каждый цвет палитры через все три симуляции и убедиться, что элементы интерфейса различимы при любом типе восприятия.


Цветовые пространства: HWB, OKLAB, OKLCH

HWB (Hue / Whiteness / Blackness) — нативно в CSS Color Level 4. Интуитивная модель: оттенок + сколько белого + сколько чёрного.

ts Copy
rgbToHwb({ r: 52, g: 152, b: 219 });  // [204, 20, 14]
toHwbString(204, 20, 14);             // 'hwb(204 20% 14%)'
toHwbString(204, 20, 14, 0.8);        // 'hwb(204 20% 14% / 0.8)'

OKLAB / OKLCH — перцептивно равномерные пространства. Для форматирования:

ts Copy
toOklchString('#3498db');        // 'oklch(0.627 0.111 251.3)'
toOklchString('#3498db', 0.9);   // 'oklch(0.627 0.111 251.3 / 0.9)'

Утилиты

colorDeltaE — перцептивное расстояние по CIEDE2000. < 1 — разница незаметна, > 10 — явное различие:

ts Copy
colorDeltaE('#ff0000', '#fe0000');  // ~0.9
colorDeltaE('#ff0000', '#0000ff');  // ~52

toNearestNamedColor — ближайший CSS named color. База расширена до 148 имён (включая rebeccapurple):

ts Copy
toNearestNamedColor('#4169e1');  // 'royalblue'
toNearestNamedColor('#663399');  // 'rebeccapurple'

randomColor — случайный цвет с контролем диапазонов оттенка, насыщенности и яркости:

ts Copy
randomColor({ hRange: [200, 260], sRange: [60, 80], lRange: [40, 60] });

Кеш и производительность

При многократном разборе одних строк — normalizeColorCached не пересчитывает, берёт из Map:

ts Copy
import { normalizeColorCached, getCacheStats, clearColorCache, disableCache } from 'color-value-tools';

normalizeColorCached('#3498db');  // первый вызов — вычисляет
normalizeColorCached('#3498db');  // повторный — из кеша

getCacheStats();   // { size: 1, hits: 1 }
clearColorCache(); // сброс
disableCache();    // отключить глобально

Генераторы

Для больших последовательностей — без выделения массива:

ts Copy
import { generateGradientColors, generateTints, generateShades } from 'color-value-tools';

// Покадровая анимация в Oklab
for (const color of generateGradientColors('#ff0000', '#0000ff', 60, { mode: 'oklab' })) {
  element.style.background = color;
  await nextFrame();
}

// Тинты к белому
for (const tint of generateTints('#3498db', 9)) {
  paletteEl.append(createSwatch(tint));
}

CLI

После глобальной установки или через npx:

bash Copy
npm install -g color-value-tools
bash Copy
cvt "#3498db"                         # полная информация
cvt "#3498db" convert                 # все форматы: hex, rgb, hsl, oklch, cmyk...
cvt "#3498db" contrast "#ffffff"      # контрастность и WCAG
cvt "#3498db" shades 7                # 7 оттенков
cvt "#3498db" harmonies               # все гармонии
cvt "cornflowerblue" nearest          # ближайший named color

Изменения в сборке

В первой версии vue был в dependencies без использования в коде — тянулся в бандл. В 1.1.1 убран полностью. Сборка теперь генерирует CJS (dist/cjs/), ESM (dist/esm/) и CLI (dist/cli/). exports в package.json маршрутизирует автоматически.


Краткий итог

color-value-tools 1.1.1 — полноценный инструментарий для работы с цветом в TypeScript-проектах. Парсинг любого CSS-формата (в том числе oklch(), color(display-p3 ...), #RGBA), конвертации между 12 пространствами, перцептивная интерполяция в Oklab/Oklch, генерация палитр (tints/shades/tones, гармонии, многоякорные шкалы), полный набор WCAG-утилит, симуляция дальтонизма по трём типам, кеш, генераторы, CLI — без runtime-зависимостей.

Пакет на npm: color-value-tools
Репозиторий: macrulezru/color-value-tools


Про первую версию пакета и базовые конвертации — в предыдущем посте: color-value-tools: конвертация и манипуляция цветами в любых форматах

Читать далее

31.03.2026

css-magic-gradient 1.2.0 — гармонии, палитры, WCAG по всей длине и canvas-экспорт

Версия 1.2.0 библиотеки css-magic-gradient: расширенные цветовые гармонии, генераторы тинтов и шейдов, переработанная доступность с проверкой по всем точкам градиента, CSS-переменные, экспорт в canvas и 9 новых хуков для Vue и React.

Метки
css-градиентыtypescriptreactvuewcagcolor-harmony
28.03.2026

vue-i18n-kit — локализация для Vue 3 с ICU-плюрализацией, lazy loading и CLI

Написал собственный npm-пакет для локализации Vue 3, потому что устал каждый раз копировать один и тот же бойлерплейт из проекта в проект. ICU-плюрализация, lazy loading, метаданные локалей, форматирование дат и валют, Vite-плагин и CLI — всё из коробки.

Метки
vue3i18nlocalizationnpmopen-source