@vibrant/color
Advanced tools
Comparing version 3.2.1-alpha.1 to 4.0.0-alpha.1
{ | ||
"name": "@vibrant/color", | ||
"version": "3.2.1-alpha.1", | ||
"version": "4.0.0-alpha.1", | ||
"description": "Color utilities for vibrant", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"build": "vite build" | ||
}, | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"type": "module", | ||
"types": "dist/esm/index.d.ts", | ||
"main": "dist/cjs/index.cjs", | ||
"module": "dist/esm/index.js", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/esm/index.d.ts", | ||
"default": "./dist/esm/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/cjs/index.d.cts", | ||
"default": "./dist/cjs/index.cjs" | ||
} | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"sideEffects": false, | ||
"files": [ | ||
"dist", | ||
"src" | ||
], | ||
"author": { | ||
@@ -20,3 +40,5 @@ "name": "akfish", | ||
"devDependencies": { | ||
"typescript": "^3.7.2" | ||
"@tanstack/config": "^0.14.2", | ||
"typescript": "^4.5.2", | ||
"vite": "^6.0.3" | ||
}, | ||
@@ -26,3 +48,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "e667d4c12e1de66e251d451710b093e9cb4630c2" | ||
"gitHead": "968ad565c625279b5d3e2baf3e5da7f764551ade" | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Vec3 } from './' | ||
import { Vec3 } from "./"; | ||
@@ -8,4 +8,4 @@ export const DELTAE94_DIFF_STATUS = { | ||
GOOD: 10, | ||
SIMILAR: 50 | ||
} | ||
SIMILAR: 50, | ||
}; | ||
@@ -17,8 +17,8 @@ /** | ||
*/ | ||
export function hexToRgb (hex: string): Vec3 { | ||
let m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) | ||
export function hexToRgb(hex: string): Vec3 { | ||
const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); | ||
if (!m) throw new RangeError(`'${hex}' is not a valid hex color`) | ||
if (!m) throw new RangeError(`'${hex}' is not a valid hex color`); | ||
return [m[1], m[2], m[3]].map((s) => parseInt(s, 16)) as Vec3 | ||
return [m[1], m[2], m[3]].map((s) => parseInt(s, 16)) as Vec3; | ||
} | ||
@@ -33,4 +33,4 @@ | ||
*/ | ||
export function rgbToHex (r: number, g: number, b: number): string { | ||
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1, 7) | ||
export function rgbToHex(r: number, g: number, b: number): string { | ||
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1, 7); | ||
} | ||
@@ -45,172 +45,168 @@ | ||
*/ | ||
export function rgbToHsl (r: number, g: number, b: number): Vec3 { | ||
r /= 255 | ||
g /= 255 | ||
b /= 255 | ||
let max = Math.max(r, g, b) | ||
let min = Math.min(r, g, b) | ||
let h: number = 0 | ||
let s: number = 0 | ||
let l = (max + min) / 2 | ||
export function rgbToHsl(r: number, g: number, b: number): Vec3 { | ||
r /= 255; | ||
g /= 255; | ||
b /= 255; | ||
const max = Math.max(r, g, b); | ||
const min = Math.min(r, g, b); | ||
let h = 0; | ||
let s = 0; | ||
const l = (max + min) / 2; | ||
if (max !== min) { | ||
let d = max - min | ||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min) | ||
const d = max - min; | ||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min); | ||
switch (max) { | ||
case r: | ||
h = (g - b) / d + (g < b ? 6 : 0) | ||
break | ||
h = (g - b) / d + (g < b ? 6 : 0); | ||
break; | ||
case g: | ||
h = (b - r) / d + 2 | ||
break | ||
h = (b - r) / d + 2; | ||
break; | ||
case b: | ||
h = (r - g) / d + 4 | ||
break | ||
h = (r - g) / d + 4; | ||
break; | ||
} | ||
h /= 6 | ||
h /= 6; | ||
} | ||
return [h, s, l] | ||
return [h, s, l]; | ||
} | ||
export function hslToRgb (h: number, s: number, l: number): Vec3 { | ||
let r: number | ||
let g: number | ||
let b: number | ||
export function hslToRgb(h: number, s: number, l: number): Vec3 { | ||
let r: number; | ||
let g: number; | ||
let b: number; | ||
function hue2rgb (p: number, q: number, t: number): number { | ||
if (t < 0) t += 1 | ||
if (t > 1) t -= 1 | ||
if (t < 1 / 6) return p + (q - p) * 6 * t | ||
if (t < 1 / 2) return q | ||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6 | ||
return p | ||
function hue2rgb(p: number, q: number, t: number): number { | ||
if (t < 0) t += 1; | ||
if (t > 1) t -= 1; | ||
if (t < 1 / 6) return p + (q - p) * 6 * t; | ||
if (t < 1 / 2) return q; | ||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; | ||
return p; | ||
} | ||
if (s === 0) { | ||
r = g = b = l | ||
r = g = b = l; | ||
} else { | ||
let q = l < 0.5 ? l * (1 + s) : l + s - (l * s) | ||
let p = 2 * l - q | ||
r = hue2rgb(p, q, h + 1 / 3) | ||
g = hue2rgb(p, q, h) | ||
b = hue2rgb(p, q, h - (1 / 3)) | ||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s; | ||
const p = 2 * l - q; | ||
r = hue2rgb(p, q, h + 1 / 3); | ||
g = hue2rgb(p, q, h); | ||
b = hue2rgb(p, q, h - 1 / 3); | ||
} | ||
return [ | ||
r * 255, | ||
g * 255, | ||
b * 255 | ||
] | ||
return [r * 255, g * 255, b * 255]; | ||
} | ||
export function rgbToXyz (r: number, g: number, b: number): Vec3 { | ||
r /= 255 | ||
g /= 255 | ||
b /= 255 | ||
r = r > 0.04045 ? Math.pow((r + 0.005) / 1.055, 2.4) : r / 12.92 | ||
g = g > 0.04045 ? Math.pow((g + 0.005) / 1.055, 2.4) : g / 12.92 | ||
b = b > 0.04045 ? Math.pow((b + 0.005) / 1.055, 2.4) : b / 12.92 | ||
export function rgbToXyz(r: number, g: number, b: number): Vec3 { | ||
r /= 255; | ||
g /= 255; | ||
b /= 255; | ||
r = r > 0.04045 ? Math.pow((r + 0.005) / 1.055, 2.4) : r / 12.92; | ||
g = g > 0.04045 ? Math.pow((g + 0.005) / 1.055, 2.4) : g / 12.92; | ||
b = b > 0.04045 ? Math.pow((b + 0.005) / 1.055, 2.4) : b / 12.92; | ||
r *= 100 | ||
g *= 100 | ||
b *= 100 | ||
r *= 100; | ||
g *= 100; | ||
b *= 100; | ||
let x = r * 0.4124 + g * 0.3576 + b * 0.1805 | ||
let y = r * 0.2126 + g * 0.7152 + b * 0.0722 | ||
let z = r * 0.0193 + g * 0.1192 + b * 0.9505 | ||
const x = r * 0.4124 + g * 0.3576 + b * 0.1805; | ||
const y = r * 0.2126 + g * 0.7152 + b * 0.0722; | ||
const z = r * 0.0193 + g * 0.1192 + b * 0.9505; | ||
return [x, y, z] | ||
return [x, y, z]; | ||
} | ||
export function xyzToCIELab (x: number, y: number, z: number): Vec3 { | ||
let REF_X = 95.047 | ||
let REF_Y = 100 | ||
let REF_Z = 108.883 | ||
export function xyzToCIELab(x: number, y: number, z: number): Vec3 { | ||
const REF_X = 95.047; | ||
const REF_Y = 100; | ||
const REF_Z = 108.883; | ||
x /= REF_X | ||
y /= REF_Y | ||
z /= REF_Z | ||
x /= REF_X; | ||
y /= REF_Y; | ||
z /= REF_Z; | ||
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116 | ||
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116 | ||
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116 | ||
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116; | ||
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116; | ||
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116; | ||
let L = 116 * y - 16 | ||
let a = 500 * (x - y) | ||
let b = 200 * (y - z) | ||
const L = 116 * y - 16; | ||
const a = 500 * (x - y); | ||
const b = 200 * (y - z); | ||
return [L, a, b] | ||
return [L, a, b]; | ||
} | ||
export function rgbToCIELab (r: number, g: number, b: number): Vec3 { | ||
let [x, y, z] = rgbToXyz(r, g, b) | ||
return xyzToCIELab(x, y, z) | ||
export function rgbToCIELab(r: number, g: number, b: number): Vec3 { | ||
const [x, y, z] = rgbToXyz(r, g, b); | ||
return xyzToCIELab(x, y, z); | ||
} | ||
export function deltaE94 (lab1: Vec3, lab2: Vec3): number { | ||
let WEIGHT_L = 1 | ||
let WEIGHT_C = 1 | ||
let WEIGHT_H = 1 | ||
export function deltaE94(lab1: Vec3, lab2: Vec3): number { | ||
const WEIGHT_L = 1; | ||
const WEIGHT_C = 1; | ||
const WEIGHT_H = 1; | ||
let [L1, a1, b1] = lab1 | ||
let [L2, a2, b2] = lab2 | ||
let dL = L1 - L2 | ||
let da = a1 - a2 | ||
let db = b1 - b2 | ||
const [L1, a1, b1] = lab1; | ||
const [L2, a2, b2] = lab2; | ||
const dL = L1 - L2; | ||
const da = a1 - a2; | ||
const db = b1 - b2; | ||
let xC1 = Math.sqrt(a1 * a1 + b1 * b1) | ||
let xC2 = Math.sqrt(a2 * a2 + b2 * b2) | ||
const xC1 = Math.sqrt(a1 * a1 + b1 * b1); | ||
const xC2 = Math.sqrt(a2 * a2 + b2 * b2); | ||
let xDL = L2 - L1 | ||
let xDC = xC2 - xC1 | ||
let xDE = Math.sqrt(dL * dL + da * da + db * db) | ||
let xDL = L2 - L1; | ||
let xDC = xC2 - xC1; | ||
const xDE = Math.sqrt(dL * dL + da * da + db * db); | ||
let xDH = (Math.sqrt(xDE) > Math.sqrt(Math.abs(xDL)) + Math.sqrt(Math.abs(xDC))) | ||
? Math.sqrt(xDE * xDE - xDL * xDL - xDC * xDC) | ||
: 0 | ||
let xDH = | ||
Math.sqrt(xDE) > Math.sqrt(Math.abs(xDL)) + Math.sqrt(Math.abs(xDC)) | ||
? Math.sqrt(xDE * xDE - xDL * xDL - xDC * xDC) | ||
: 0; | ||
let xSC = 1 + 0.045 * xC1 | ||
let xSH = 1 + 0.015 * xC1 | ||
const xSC = 1 + 0.045 * xC1; | ||
const xSH = 1 + 0.015 * xC1; | ||
xDL /= WEIGHT_L | ||
xDC /= WEIGHT_C * xSC | ||
xDH /= WEIGHT_H * xSH | ||
xDL /= WEIGHT_L; | ||
xDC /= WEIGHT_C * xSC; | ||
xDH /= WEIGHT_H * xSH; | ||
return Math.sqrt(xDL * xDL + xDC * xDC + xDH * xDH) | ||
return Math.sqrt(xDL * xDL + xDC * xDC + xDH * xDH); | ||
} | ||
export function rgbDiff (rgb1: Vec3, rgb2: Vec3): number { | ||
let lab1 = rgbToCIELab.apply(undefined, rgb1) | ||
let lab2 = rgbToCIELab.apply(undefined, rgb2) | ||
return deltaE94(lab1, lab2) | ||
export function rgbDiff(rgb1: Vec3, rgb2: Vec3): number { | ||
const lab1 = rgbToCIELab.apply(undefined, rgb1); | ||
const lab2 = rgbToCIELab.apply(undefined, rgb2); | ||
return deltaE94(lab1, lab2); | ||
} | ||
export function hexDiff (hex1: string, hex2: string): number { | ||
let rgb1 = hexToRgb(hex1) | ||
let rgb2 = hexToRgb(hex2) | ||
export function hexDiff(hex1: string, hex2: string): number { | ||
const rgb1 = hexToRgb(hex1); | ||
const rgb2 = hexToRgb(hex2); | ||
return rgbDiff(rgb1, rgb2) | ||
return rgbDiff(rgb1, rgb2); | ||
} | ||
export function getColorDiffStatus (d: number): string { | ||
export function getColorDiffStatus(d: number): string { | ||
if (d < DELTAE94_DIFF_STATUS.NA) { | ||
return 'N/A' | ||
return "N/A"; | ||
} | ||
// Not perceptible by human eyes | ||
if (d <= DELTAE94_DIFF_STATUS.PERFECT) { | ||
return 'Perfect' | ||
return "Perfect"; | ||
} | ||
// Perceptible through close observation | ||
if (d <= DELTAE94_DIFF_STATUS.CLOSE) { | ||
return 'Close' | ||
return "Close"; | ||
} | ||
// Perceptible at a glance | ||
if (d <= DELTAE94_DIFF_STATUS.GOOD) { | ||
return 'Good' | ||
return "Good"; | ||
} | ||
// Colors are more similar than opposite | ||
if (d < DELTAE94_DIFF_STATUS.SIMILAR) { | ||
return 'Similar' | ||
return "Similar"; | ||
} | ||
return 'Wrong' | ||
return "Wrong"; | ||
} |
149
src/index.ts
@@ -1,5 +0,6 @@ | ||
import { rgbToHsl, rgbToHex } from './converter' | ||
export * from "./converter"; | ||
import { rgbToHsl, rgbToHex } from "./converter"; | ||
export interface Filter { | ||
(red: number, green: number, blue: number, alpha: number): boolean | ||
(red: number, green: number, blue: number, alpha: number): boolean; | ||
} | ||
@@ -10,3 +11,3 @@ | ||
*/ | ||
export type Vec3 = [number, number, number] | ||
export type Vec3 = [number, number, number]; | ||
@@ -17,22 +18,22 @@ /** | ||
export interface Palette { | ||
Vibrant: Swatch | null | ||
Muted: Swatch | null | ||
DarkVibrant: Swatch | null | ||
DarkMuted: Swatch | null | ||
LightVibrant: Swatch | null | ||
LightMuted: Swatch | null | ||
Vibrant: Swatch | null; | ||
Muted: Swatch | null; | ||
DarkVibrant: Swatch | null; | ||
DarkMuted: Swatch | null; | ||
LightVibrant: Swatch | null; | ||
LightMuted: Swatch | null; | ||
// ? | ||
[name: string]: Swatch | null | ||
[name: string]: Swatch | null; | ||
} | ||
export class Swatch { | ||
static applyFilters (colors: Swatch[], filters: Filter[]): Swatch[] { | ||
static applyFilters(colors: Swatch[], filters: Filter[]): Swatch[] { | ||
return filters.length > 0 | ||
? colors.filter(({ r, g, b }) => { | ||
for (let j = 0; j < filters.length; j++) { | ||
if (!filters[j](r, g, b, 255)) return false | ||
} | ||
return true | ||
}) | ||
: colors | ||
for (let j = 0; j < filters.length; j++) { | ||
if (!filters[j](r, g, b, 255)) return false; | ||
} | ||
return true; | ||
}) | ||
: colors; | ||
} | ||
@@ -44,10 +45,10 @@ | ||
*/ | ||
static clone (swatch: Swatch) { | ||
return new Swatch(swatch._rgb, swatch._population) | ||
static clone(swatch: Swatch) { | ||
return new Swatch(swatch._rgb, swatch._population); | ||
} | ||
private _hsl: Vec3 | ||
private _rgb: Vec3 | ||
private _yiq: number | ||
private _population: number | ||
private _hex: string | ||
private _hsl: Vec3; | ||
private _rgb: Vec3; | ||
private _yiq: number; | ||
private _population: number; | ||
private _hex: string; | ||
@@ -57,4 +58,4 @@ /** | ||
*/ | ||
get r (): number { | ||
return this._rgb[0] | ||
get r(): number { | ||
return this._rgb[0]; | ||
} | ||
@@ -64,4 +65,4 @@ /** | ||
*/ | ||
get g (): number { | ||
return this._rgb[1] | ||
get g(): number { | ||
return this._rgb[1]; | ||
} | ||
@@ -71,4 +72,4 @@ /** | ||
*/ | ||
get b (): number { | ||
return this._rgb[2] | ||
get b(): number { | ||
return this._rgb[2]; | ||
} | ||
@@ -78,4 +79,4 @@ /** | ||
*/ | ||
get rgb (): Vec3 { | ||
return this._rgb | ||
get rgb(): Vec3 { | ||
return this._rgb; | ||
} | ||
@@ -85,8 +86,8 @@ /** | ||
*/ | ||
get hsl (): Vec3 { | ||
get hsl(): Vec3 { | ||
if (!this._hsl) { | ||
let [r, g, b] = this._rgb | ||
this._hsl = rgbToHsl(r, g, b) | ||
const [r, g, b] = this._rgb; | ||
this._hsl = rgbToHsl(r, g, b); | ||
} | ||
return this._hsl | ||
return this._hsl; | ||
} | ||
@@ -97,11 +98,11 @@ | ||
*/ | ||
get hex (): string { | ||
get hex(): string { | ||
if (!this._hex) { | ||
let [r, g, b] = this._rgb | ||
this._hex = rgbToHex(r, g, b) | ||
const [r, g, b] = this._rgb; | ||
this._hex = rgbToHex(r, g, b); | ||
} | ||
return this._hex | ||
return this._hex; | ||
} | ||
get population (): number { | ||
return this._population | ||
get population(): number { | ||
return this._population; | ||
} | ||
@@ -112,7 +113,7 @@ | ||
*/ | ||
toJSON (): {rgb: Vec3, population: number} { | ||
toJSON(): { rgb: Vec3; population: number } { | ||
return { | ||
rgb: this.rgb, | ||
population: this.population | ||
} | ||
population: this.population, | ||
}; | ||
} | ||
@@ -125,4 +126,4 @@ | ||
// TODO: deprecate internally, use property instead | ||
getRgb (): Vec3 { | ||
return this._rgb | ||
getRgb(): Vec3 { | ||
return this._rgb; | ||
} | ||
@@ -134,4 +135,4 @@ /** | ||
// TODO: deprecate internally, use property instead | ||
getHsl (): Vec3 { | ||
return this.hsl | ||
getHsl(): Vec3 { | ||
return this.hsl; | ||
} | ||
@@ -142,4 +143,4 @@ /** | ||
// TODO: deprecate internally, use property instead | ||
getPopulation (): number { | ||
return this._population | ||
getPopulation(): number { | ||
return this._population; | ||
} | ||
@@ -151,41 +152,41 @@ /** | ||
// TODO: deprecate internally, use property instead | ||
getHex (): string { | ||
return this.hex | ||
getHex(): string { | ||
return this.hex; | ||
} | ||
private getYiq (): number { | ||
private getYiq(): number { | ||
if (!this._yiq) { | ||
let rgb = this._rgb | ||
this._yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000 | ||
const rgb = this._rgb; | ||
this._yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; | ||
} | ||
return this._yiq | ||
return this._yiq; | ||
} | ||
private _titleTextColor: string | ||
private _bodyTextColor: string | ||
private _titleTextColor: string; | ||
private _bodyTextColor: string; | ||
get titleTextColor () { | ||
if (this._titleTextColor) { | ||
this._titleTextColor = this.getYiq() < 200 ? '#fff' : '#000' | ||
get titleTextColor() { | ||
if (!this._titleTextColor) { | ||
this._titleTextColor = this.getYiq() < 200 ? "#fff" : "#000"; | ||
} | ||
return this._titleTextColor | ||
return this._titleTextColor; | ||
} | ||
get bodyTextColor () { | ||
if (this._bodyTextColor) { | ||
this._bodyTextColor = this.getYiq() < 150 ? '#fff' : '#000' | ||
get bodyTextColor() { | ||
if (!this._bodyTextColor) { | ||
this._bodyTextColor = this.getYiq() < 150 ? "#fff" : "#000"; | ||
} | ||
return this._bodyTextColor | ||
return this._bodyTextColor; | ||
} | ||
getTitleTextColor (): string { | ||
return this.titleTextColor | ||
getTitleTextColor(): string { | ||
return this.titleTextColor; | ||
} | ||
getBodyTextColor (): string { | ||
return this.bodyTextColor | ||
getBodyTextColor(): string { | ||
return this.bodyTextColor; | ||
} | ||
constructor (rgb: Vec3, population: number) { | ||
this._rgb = rgb | ||
this._population = population | ||
constructor(rgb: Vec3, population: number) { | ||
this._rgb = rgb; | ||
this._population = population; | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
64641
16
1099
2
Yes
3