saturon 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -7
- package/README.md +121 -119
- package/dist/Color.d.ts +20 -11
- package/dist/Color.js +127 -97
- package/dist/converters.d.ts +4 -4
- package/dist/converters.js +14 -20
- package/dist/index.umd.js +163 -149
- package/dist/index.umd.min.js +1 -1
- package/dist/math.d.ts +1 -0
- package/dist/math.js +11 -10
- package/dist/temp.d.ts +1 -0
- package/dist/temp.js +3 -0
- package/dist/types.d.ts +4 -4
- package/dist/utils.js +26 -30
- package/package.json +127 -127
package/dist/Color.js
CHANGED
|
@@ -115,7 +115,7 @@ export class Color {
|
|
|
115
115
|
value = base + Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v) * dev;
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
118
|
-
let [min, max] = comp.value === "
|
|
118
|
+
let [min, max] = comp.value === "hue" ? [0, 360] : comp.value === "percentage" ? [0, 100] : comp.value;
|
|
119
119
|
const limits = options.limits?.[name];
|
|
120
120
|
if (limits) {
|
|
121
121
|
const [lMin, lMax] = limits;
|
|
@@ -128,7 +128,7 @@ export class Color {
|
|
|
128
128
|
r = biasFn(r);
|
|
129
129
|
value = min + r * (max - min);
|
|
130
130
|
}
|
|
131
|
-
if (comp.value === "
|
|
131
|
+
if (comp.value === "hue")
|
|
132
132
|
value = ((value % 360) + 360) % 360;
|
|
133
133
|
else if (comp.value === "percentage")
|
|
134
134
|
value = Math.min(100, Math.max(0, value));
|
|
@@ -179,7 +179,6 @@ export class Color {
|
|
|
179
179
|
cache.set("paths", paths);
|
|
180
180
|
}
|
|
181
181
|
const key = `${from}-${to}`;
|
|
182
|
-
const coords = this.coords.slice(0, 3);
|
|
183
182
|
if (!paths.has(key)) {
|
|
184
183
|
const queue = [from], parent = { [from]: null };
|
|
185
184
|
for (let i = 0; i < queue.length; i++) {
|
|
@@ -202,7 +201,7 @@ export class Color {
|
|
|
202
201
|
}
|
|
203
202
|
paths.set(key, path);
|
|
204
203
|
}
|
|
205
|
-
let value = [...coords];
|
|
204
|
+
let value = [...this.coords.map((v) => (isNaN(v) ? 0 : v))];
|
|
206
205
|
const path = paths.get(key);
|
|
207
206
|
for (let i = 0; i < path.length - 1; i++) {
|
|
208
207
|
const a = path[i], b = path[i + 1];
|
|
@@ -268,7 +267,7 @@ export class Color {
|
|
|
268
267
|
};
|
|
269
268
|
const normalize = (c, i) => {
|
|
270
269
|
const v = Object.values(defs)[i]?.value;
|
|
271
|
-
const [min, max] = Array.isArray(v) ? v : v === "
|
|
270
|
+
const [min, max] = Array.isArray(v) ? v : v === "hue" ? [0, 360] : [0, 100];
|
|
272
271
|
if (Number.isNaN(c))
|
|
273
272
|
return 0;
|
|
274
273
|
if (c === Infinity)
|
|
@@ -282,10 +281,10 @@ export class Color {
|
|
|
282
281
|
method: method,
|
|
283
282
|
precision,
|
|
284
283
|
});
|
|
285
|
-
return [...fitted
|
|
284
|
+
return [...fitted, coords[3]];
|
|
286
285
|
}
|
|
287
286
|
/**
|
|
288
|
-
*
|
|
287
|
+
* Creates a new Color instance with modified component values.
|
|
289
288
|
*
|
|
290
289
|
* This method supports several flexible update styles:
|
|
291
290
|
*
|
|
@@ -324,68 +323,65 @@ export class Color {
|
|
|
324
323
|
* color.with(({ r, g, b }) => [r * 0.5, g * 0.5, b * 0.5, 1]);
|
|
325
324
|
* ```
|
|
326
325
|
*
|
|
327
|
-
* @
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
* @
|
|
326
|
+
* @template M - The color model type
|
|
327
|
+
* @param values - The new component values to apply. Can be:
|
|
328
|
+
* - A partial object mapping component names to numbers or update functions
|
|
329
|
+
* - A function that receives current components and returns partial updates or an array of values
|
|
330
|
+
* - An array of new values corresponding to component indices
|
|
331
|
+
* @param normalize - Whether to normalize component values to their valid ranges. Defaults to `true`.
|
|
332
|
+
* When `false`, values are not clamped or validated against their ranges.
|
|
333
|
+
* @returns A new Color instance with the updated component values
|
|
333
334
|
*/
|
|
334
335
|
/* eslint-disable no-unused-vars */
|
|
335
|
-
with(values) {
|
|
336
|
-
|
|
336
|
+
with(values, normalize = true) {
|
|
337
|
+
const normRange = (defValue) => Array.isArray(defValue) ? defValue : defValue === "hue" ? [0, 360] : [0, 100];
|
|
338
|
+
const normalizeComponent = (c, defValue) => {
|
|
339
|
+
if (normalize === false)
|
|
340
|
+
return c;
|
|
341
|
+
const [min, max] = normRange(defValue);
|
|
342
|
+
if (Number.isNaN(c))
|
|
343
|
+
return 0;
|
|
344
|
+
if (c === Infinity)
|
|
345
|
+
return max;
|
|
346
|
+
if (c === -Infinity)
|
|
347
|
+
return min;
|
|
348
|
+
return c;
|
|
349
|
+
};
|
|
337
350
|
const { model } = this;
|
|
338
|
-
const coords = this.
|
|
339
|
-
const { components } = colorModels[model];
|
|
340
|
-
if (!components)
|
|
341
|
-
throw new Error(`Model ${model} does not have defined components.`);
|
|
351
|
+
const coords = this.coords.slice();
|
|
342
352
|
const defs = {
|
|
343
|
-
...components,
|
|
353
|
+
...colorModels[model].components, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
344
354
|
alpha: { index: 3, value: [0, 1], precision: 3 },
|
|
345
355
|
};
|
|
346
356
|
const names = Object.keys(defs);
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
newValues = values;
|
|
354
|
-
}
|
|
357
|
+
const newValues = typeof values === "function"
|
|
358
|
+
? values(Object.fromEntries(names.map((k) => {
|
|
359
|
+
const def = defs[k];
|
|
360
|
+
return [k, normalizeComponent(coords[def.index], def.value)];
|
|
361
|
+
})))
|
|
362
|
+
: values;
|
|
355
363
|
if (Array.isArray(newValues)) {
|
|
356
364
|
const adjusted = coords.map((curr, i) => {
|
|
357
365
|
const incoming = newValues[i];
|
|
358
|
-
const { value } = Object.values(defs).find((d) => d.index === i);
|
|
359
366
|
if (typeof incoming !== "number")
|
|
360
367
|
return curr;
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
return 0;
|
|
364
|
-
if (incoming === Infinity)
|
|
365
|
-
return max;
|
|
366
|
-
if (incoming === -Infinity)
|
|
367
|
-
return min;
|
|
368
|
-
return incoming;
|
|
368
|
+
const def = Object.values(defs).find((d) => d.index === i);
|
|
369
|
+
return normalizeComponent(incoming, def.value);
|
|
369
370
|
});
|
|
370
|
-
return new Color(model, [...adjusted.slice(0, 3), coords[3]]);
|
|
371
|
+
return new Color(model, [...adjusted.slice(0, 3), coords[3] ?? 1]);
|
|
371
372
|
}
|
|
372
373
|
const next = [...coords];
|
|
373
374
|
for (const name of names) {
|
|
374
375
|
if (!(name in newValues))
|
|
375
376
|
continue;
|
|
376
377
|
const { index, value } = defs[name];
|
|
377
|
-
const current = coords[index];
|
|
378
378
|
const raw = newValues[name];
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
val = max;
|
|
386
|
-
else if (val === -Infinity)
|
|
387
|
-
val = min;
|
|
388
|
-
}
|
|
379
|
+
const prev = normalizeComponent(coords[index], value);
|
|
380
|
+
const val = typeof raw === "function"
|
|
381
|
+
? normalizeComponent(raw(prev), value)
|
|
382
|
+
: typeof raw === "number"
|
|
383
|
+
? normalizeComponent(raw, value)
|
|
384
|
+
: coords[index];
|
|
389
385
|
next[index] = val;
|
|
390
386
|
}
|
|
391
387
|
return new Color(model, [...next.slice(0, 3), next[3] ?? coords[3]]);
|
|
@@ -400,71 +396,92 @@ export class Color {
|
|
|
400
396
|
*/
|
|
401
397
|
mix(other, options = {}) {
|
|
402
398
|
const { model } = this;
|
|
403
|
-
const
|
|
404
|
-
const
|
|
399
|
+
const A = this.coords.slice();
|
|
400
|
+
const B = (typeof other === "string" ? Color.from(other) : other).in(model).coords.slice();
|
|
401
|
+
const { components } = colorModels[model]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
405
402
|
if (!components)
|
|
406
403
|
throw new Error(`Model ${model} does not have defined components.`);
|
|
407
|
-
const { hue = "shorter", amount = 0.5, easing = "linear", gamma = 1.0 } = options;
|
|
408
404
|
const defs = {
|
|
409
405
|
...components,
|
|
410
406
|
alpha: { index: 3, value: [0, 1], precision: 3 },
|
|
411
407
|
};
|
|
408
|
+
const normRange = (v) => Array.isArray(v) ? v : v === "hue" ? [0, 360] : [0, 100];
|
|
409
|
+
const repairPair = (a, b, v) => {
|
|
410
|
+
const [min, max] = normRange(v);
|
|
411
|
+
const fixInf = (x) => (x === Infinity ? max : x === -Infinity ? min : x);
|
|
412
|
+
a = fixInf(a);
|
|
413
|
+
b = fixInf(b);
|
|
414
|
+
const aNaN = Number.isNaN(a);
|
|
415
|
+
const bNaN = Number.isNaN(b);
|
|
416
|
+
if (aNaN && bNaN)
|
|
417
|
+
return { a: 0, b: 0 };
|
|
418
|
+
if (aNaN)
|
|
419
|
+
return { a: b, b };
|
|
420
|
+
if (bNaN)
|
|
421
|
+
return { a, b: a };
|
|
422
|
+
return { a, b, ok: true };
|
|
423
|
+
};
|
|
424
|
+
const hueIndex = defs.h?.index ?? -1;
|
|
425
|
+
for (const key in defs) {
|
|
426
|
+
const { index, value } = defs[key];
|
|
427
|
+
if (index > 3)
|
|
428
|
+
continue;
|
|
429
|
+
const r = repairPair(A[index], B[index], value);
|
|
430
|
+
if (r.ok) {
|
|
431
|
+
const [min, max] = normRange(value);
|
|
432
|
+
const fixInf = (x) => (x === Infinity ? max : x === -Infinity ? min : x);
|
|
433
|
+
A[index] = fixInf(A[index]);
|
|
434
|
+
B[index] = fixInf(B[index]);
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
A[index] = r.a;
|
|
438
|
+
B[index] = r.b;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const { hue = "shorter", amount = 0.5, easing = "linear", gamma = 1.0 } = options;
|
|
442
|
+
const ease = typeof easing === "function" ? easing : EASINGS[easing];
|
|
443
|
+
const t = ease(Math.min(1, Math.max(0, amount)));
|
|
444
|
+
const tt = Math.pow(t, 1 / gamma);
|
|
445
|
+
const wrap = (v) => ((v % 360) + 360) % 360;
|
|
412
446
|
const hueDelta = (a, b) => {
|
|
413
|
-
const d = (
|
|
447
|
+
const d = wrap(b - a);
|
|
414
448
|
return d > 180 ? d - 360 : d;
|
|
415
449
|
};
|
|
416
450
|
const hueDeltaLong = (a, b) => hueDelta(a, b) >= 0 ? hueDelta(a, b) - 360 : hueDelta(a, b) + 360;
|
|
417
|
-
const
|
|
418
|
-
const wrapped = (v) => ((v % 360) + 360) % 360;
|
|
451
|
+
const interpHue = (a, b, t, method) => {
|
|
419
452
|
switch (method) {
|
|
420
453
|
case "shorter":
|
|
421
|
-
return
|
|
454
|
+
return wrap(a + t * hueDelta(a, b));
|
|
422
455
|
case "longer":
|
|
423
|
-
return
|
|
456
|
+
return wrap(a + t * hueDeltaLong(a, b));
|
|
424
457
|
case "increasing":
|
|
425
|
-
return
|
|
458
|
+
return wrap(a * (1 - t) + (b < a ? b + 360 : b) * t);
|
|
426
459
|
case "decreasing":
|
|
427
|
-
return
|
|
428
|
-
default:
|
|
429
|
-
throw new Error(`Invalid hue interpolation method: ${method}`);
|
|
460
|
+
return wrap(a * (1 - t) + (b > a ? b - 360 : b) * t);
|
|
430
461
|
}
|
|
462
|
+
throw new Error(`Invalid hue interpolation: ${method}`);
|
|
431
463
|
};
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
return new Color(model, [...otherCoords, otherAlpha]);
|
|
445
|
-
if (thisAlpha < 1 || otherAlpha < 1) {
|
|
446
|
-
const premixed = thisCoords.map((start, i) => {
|
|
447
|
-
const end = otherCoords[i];
|
|
448
|
-
if (i === hueIndex)
|
|
449
|
-
return interpolateHue(start, end, tt, hue);
|
|
450
|
-
const a = start * thisAlpha;
|
|
451
|
-
const b = end * otherAlpha;
|
|
452
|
-
return a * (1 - tt) + b * tt;
|
|
464
|
+
if (tt === 0)
|
|
465
|
+
return new Color(model, [...A]);
|
|
466
|
+
if (tt === 1)
|
|
467
|
+
return new Color(model, [...B]);
|
|
468
|
+
const aA = A[3];
|
|
469
|
+
const aB = B[3];
|
|
470
|
+
const resolvedA = A.slice(0, 3);
|
|
471
|
+
const resolvedB = B.slice(0, 3);
|
|
472
|
+
if (aA < 1 || aB < 1) {
|
|
473
|
+
const premixed = resolvedA.map((a, i) => {
|
|
474
|
+
const b = resolvedB[i];
|
|
475
|
+
return i === hueIndex ? interpHue(a, b, tt, hue) : a * aA * (1 - tt) + b * aB * tt;
|
|
453
476
|
});
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
? premixed.map((
|
|
457
|
-
:
|
|
458
|
-
return new Color(model, [...
|
|
477
|
+
const a = aA * (1 - tt) + aB * tt;
|
|
478
|
+
const out = a > 0
|
|
479
|
+
? premixed.map((v, i) => (i === hueIndex ? v : v / a))
|
|
480
|
+
: resolvedA.map((_, i) => (i === hueIndex ? premixed[i] : 0));
|
|
481
|
+
return new Color(model, [...out, a]);
|
|
459
482
|
}
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
if (!entry)
|
|
463
|
-
return start;
|
|
464
|
-
const end = otherCoords[i];
|
|
465
|
-
return entry.value === "angle" ? interpolateHue(start, end, tt, hue) : start + (end - start) * tt;
|
|
466
|
-
});
|
|
467
|
-
return new Color(model, [...mixedCoords, 1]);
|
|
483
|
+
const mixed = resolvedA.map((a, i) => i === hueIndex ? interpHue(a, resolvedB[i], tt, hue) : a + (resolvedB[i] - a) * tt);
|
|
484
|
+
return new Color(model, [...mixed, 1]);
|
|
468
485
|
}
|
|
469
486
|
/**
|
|
470
487
|
* Fits this color within the specified gamut using a given method.
|
|
@@ -481,6 +498,17 @@ export class Color {
|
|
|
481
498
|
const fitted = this.in(g).toArray({ fit: method, precision: null });
|
|
482
499
|
return new Color(g, fitted).in(this.model);
|
|
483
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* Creates a new Color instance with values fitted to the color model's gamut.
|
|
503
|
+
*
|
|
504
|
+
* @param options - Configuration options for fitting
|
|
505
|
+
* @returns A new Color instance with fitted values
|
|
506
|
+
*/
|
|
507
|
+
fit(options = {}) {
|
|
508
|
+
const { fit: method = config.defaults.fit, precision } = options;
|
|
509
|
+
const fitted = this.toArray({ fit: method, precision });
|
|
510
|
+
return new Color(this.model, fitted);
|
|
511
|
+
}
|
|
484
512
|
/**
|
|
485
513
|
* Calculates the WCAG 2.1 contrast ratio between this color and another.
|
|
486
514
|
*
|
|
@@ -657,8 +685,10 @@ export class Color {
|
|
|
657
685
|
*/
|
|
658
686
|
equals(other, epsilon = 1e-5) {
|
|
659
687
|
const o = typeof other === "string" ? Color.from(other) : other;
|
|
688
|
+
const thisCoords = this.toArray({ fit: "none", precision: null });
|
|
689
|
+
const otherCoords = o.toArray({ fit: "none", precision: null });
|
|
660
690
|
if (o.model === this.model)
|
|
661
|
-
return
|
|
691
|
+
return thisCoords.every((v, i) => Math.abs(v - otherCoords[i]) <= epsilon);
|
|
662
692
|
const a = this.in("xyz-d65").toArray({ fit: "none", precision: null });
|
|
663
693
|
const b = o.in("xyz-d65").toArray({ fit: "none", precision: null });
|
|
664
694
|
return a.every((v, i) => Math.abs(v - b[i]) <= epsilon);
|
|
@@ -680,7 +710,7 @@ export class Color {
|
|
|
680
710
|
const coords = this.in(g).toArray({ fit: "none", precision: null });
|
|
681
711
|
return Object.values(components).every(({ index, value }) => {
|
|
682
712
|
const v = coords[index];
|
|
683
|
-
const [min, max] = Array.isArray(value) ? value : value === "
|
|
713
|
+
const [min, max] = Array.isArray(value) ? value : value === "hue" ? [0, 360] : [0, 100];
|
|
684
714
|
return v >= min - epsilon && v <= max + epsilon;
|
|
685
715
|
});
|
|
686
716
|
}
|
package/dist/converters.d.ts
CHANGED
|
@@ -342,7 +342,7 @@ export declare const colorModels: {
|
|
|
342
342
|
readonly components: {
|
|
343
343
|
readonly h: {
|
|
344
344
|
readonly index: 0;
|
|
345
|
-
readonly value: "
|
|
345
|
+
readonly value: "hue";
|
|
346
346
|
readonly precision: 0;
|
|
347
347
|
};
|
|
348
348
|
readonly s: {
|
|
@@ -364,7 +364,7 @@ export declare const colorModels: {
|
|
|
364
364
|
readonly components: {
|
|
365
365
|
readonly h: {
|
|
366
366
|
readonly index: 0;
|
|
367
|
-
readonly value: "
|
|
367
|
+
readonly value: "hue";
|
|
368
368
|
readonly precision: 0;
|
|
369
369
|
};
|
|
370
370
|
readonly w: {
|
|
@@ -420,7 +420,7 @@ export declare const colorModels: {
|
|
|
420
420
|
};
|
|
421
421
|
readonly h: {
|
|
422
422
|
readonly index: 2;
|
|
423
|
-
readonly value: "
|
|
423
|
+
readonly value: "hue";
|
|
424
424
|
readonly precision: 5;
|
|
425
425
|
};
|
|
426
426
|
};
|
|
@@ -466,7 +466,7 @@ export declare const colorModels: {
|
|
|
466
466
|
};
|
|
467
467
|
readonly h: {
|
|
468
468
|
readonly index: 2;
|
|
469
|
-
readonly value: "
|
|
469
|
+
readonly value: "hue";
|
|
470
470
|
readonly precision: 5;
|
|
471
471
|
};
|
|
472
472
|
};
|
package/dist/converters.js
CHANGED
|
@@ -331,7 +331,7 @@ export const colorModels = {
|
|
|
331
331
|
supportsLegacy: true,
|
|
332
332
|
alphaVariant: "hsla",
|
|
333
333
|
components: {
|
|
334
|
-
h: { index: 0, value: "
|
|
334
|
+
h: { index: 0, value: "hue", precision: 0 },
|
|
335
335
|
s: { index: 1, value: "percentage", precision: 0 },
|
|
336
336
|
l: { index: 2, value: "percentage", precision: 0 },
|
|
337
337
|
},
|
|
@@ -341,7 +341,7 @@ export const colorModels = {
|
|
|
341
341
|
},
|
|
342
342
|
hwb: {
|
|
343
343
|
components: {
|
|
344
|
-
h: { index: 0, value: "
|
|
344
|
+
h: { index: 0, value: "hue", precision: 0 },
|
|
345
345
|
w: { index: 1, value: "percentage", precision: 0 },
|
|
346
346
|
b: { index: 2, value: "percentage", precision: 0 },
|
|
347
347
|
},
|
|
@@ -365,7 +365,7 @@ export const colorModels = {
|
|
|
365
365
|
components: {
|
|
366
366
|
l: { index: 0, value: "percentage", precision: 5 },
|
|
367
367
|
c: { index: 1, value: [0, 150], precision: 5 },
|
|
368
|
-
h: { index: 2, value: "
|
|
368
|
+
h: { index: 2, value: "hue", precision: 5 },
|
|
369
369
|
},
|
|
370
370
|
bridge: "lab",
|
|
371
371
|
toBridge: LCH_to_LAB,
|
|
@@ -387,7 +387,7 @@ export const colorModels = {
|
|
|
387
387
|
components: {
|
|
388
388
|
l: { index: 0, value: [0, 1], precision: 5 },
|
|
389
389
|
c: { index: 1, value: [0, 0.4], precision: 5 },
|
|
390
|
-
h: { index: 2, value: "
|
|
390
|
+
h: { index: 2, value: "hue", precision: 5 },
|
|
391
391
|
},
|
|
392
392
|
bridge: "oklab",
|
|
393
393
|
toBridge: OKLCH_to_OKLAB,
|
|
@@ -418,14 +418,9 @@ export const colorBases = {
|
|
|
418
418
|
const HEX = str.slice(1);
|
|
419
419
|
if (![3, 4, 6, 8].includes(HEX.length))
|
|
420
420
|
throw new Error("Invalid hex color length.");
|
|
421
|
-
for (const ch of HEX)
|
|
422
|
-
|
|
423
|
-
const isDigit = code >= 48 && code <= 57;
|
|
424
|
-
const isLower = code >= 97 && code <= 102;
|
|
425
|
-
const isUpper = code >= 65 && code <= 70;
|
|
426
|
-
if (!(isDigit || isLower || isUpper))
|
|
421
|
+
for (const ch of HEX)
|
|
422
|
+
if (!/^[0-9a-fA-F]$/.test(ch))
|
|
427
423
|
throw new Error("Invalid hex color character.");
|
|
428
|
-
}
|
|
429
424
|
const expand = (c) => parseInt(c.length === 1 ? c + c : c, 16);
|
|
430
425
|
const [r, g, b, a = 255] = HEX.length <= 4
|
|
431
426
|
? HEX.split("").map(expand)
|
|
@@ -595,7 +590,7 @@ export const colorBases = {
|
|
|
595
590
|
if (!comps) {
|
|
596
591
|
throw new Error(`Unknown color model: ${model}.`);
|
|
597
592
|
}
|
|
598
|
-
const hasHue = Object.values(comps).some((c) => c.value === "
|
|
593
|
+
const hasHue = Object.values(comps).some((c) => c.value === "hue");
|
|
599
594
|
if (!hasHue) {
|
|
600
595
|
throw new Error(`Hue interpolation not supported in ${model} space.`);
|
|
601
596
|
}
|
|
@@ -607,18 +602,17 @@ export const colorBases = {
|
|
|
607
602
|
const { color: color2, weight: weight2 } = extractColorAndWeight(parts[2]);
|
|
608
603
|
const { amount, alphaMultiplier = 1 } = getWeight2Prime(weight1, weight2);
|
|
609
604
|
return color1
|
|
610
|
-
.with({ alpha: (a) => a * alphaMultiplier })
|
|
605
|
+
.with({ alpha: (a) => (isNaN(a) ? a : a * alphaMultiplier) }, false)
|
|
611
606
|
.in(model)
|
|
612
|
-
.mix(color2.with({ alpha: (a) => a * alphaMultiplier }), { amount, hue })
|
|
613
|
-
.in("rgb")
|
|
614
|
-
.toArray({ fit: "none", precision: null });
|
|
607
|
+
.mix(color2.with({ alpha: (a) => (isNaN(a) ? a : a * alphaMultiplier) }, false), { amount, hue })
|
|
608
|
+
.in("rgb").coords;
|
|
615
609
|
},
|
|
616
610
|
},
|
|
617
611
|
transparent: {
|
|
618
612
|
isValid: (str) => str === "transparent",
|
|
619
613
|
bridge: "rgb",
|
|
620
614
|
toBridge: (coords) => coords,
|
|
621
|
-
parse: (str) => [
|
|
615
|
+
parse: (str) => [NaN, NaN, NaN, 0], // eslint-disable-line no-unused-vars
|
|
622
616
|
},
|
|
623
617
|
};
|
|
624
618
|
/**
|
|
@@ -651,7 +645,7 @@ export const colorTypes = {
|
|
|
651
645
|
toBridge: (coords) => coords,
|
|
652
646
|
parse: (str) => {
|
|
653
647
|
const inner = str.slice(15, -1);
|
|
654
|
-
const [, luminance] = Color.from(inner).in("xyz-d65").
|
|
648
|
+
const [, luminance] = Color.from(inner).in("xyz-d65").coords;
|
|
655
649
|
return luminance > 0.5 ? [0, 0, 0, 1] : [255, 255, 255, 1];
|
|
656
650
|
},
|
|
657
651
|
},
|
|
@@ -745,7 +739,7 @@ export const colorTypes = {
|
|
|
745
739
|
if (idx < tokens.length && tokens[idx] === ",") {
|
|
746
740
|
idx++;
|
|
747
741
|
const fallbackStr = tokens.slice(idx).join(" ");
|
|
748
|
-
return Color.from(fallbackStr).in("rgb").
|
|
742
|
+
return Color.from(fallbackStr).in("rgb").coords;
|
|
749
743
|
}
|
|
750
744
|
const red = 1 - Math.min(1, c * (1 - k) + k);
|
|
751
745
|
const green = 1 - Math.min(1, m * (1 - k) + k);
|
|
@@ -816,7 +810,7 @@ export const colorTypes = {
|
|
|
816
810
|
}
|
|
817
811
|
const [color1, color2] = parts;
|
|
818
812
|
const { theme } = config;
|
|
819
|
-
return Color.from(theme === "light" ? color1 : color2).
|
|
813
|
+
return Color.from(theme === "light" ? color1 : color2).coords;
|
|
820
814
|
},
|
|
821
815
|
},
|
|
822
816
|
};
|