@ixfx/components 0.2.3 → 0.2.5
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 +1 -1
- package/bundle/chunk-pbuEa-1d.js +13 -0
- package/bundle/index.d.ts +4702 -569
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +34929 -2800
- package/bundle/index.js.map +1 -1
- package/bundle/style.css +133 -0
- package/dist/ac-text.d.ts +97 -0
- package/dist/ac-text.d.ts.map +1 -0
- package/dist/ac-text.js +484 -0
- package/dist/ac-text.js.map +1 -0
- package/dist/button-DgKUzE5o.js +121 -0
- package/dist/button-DgKUzE5o.js.map +1 -0
- package/dist/button.d.ts +21 -0
- package/dist/button.d.ts.map +1 -0
- package/dist/button.js +3 -0
- package/dist/checkbox.d.ts +34 -0
- package/dist/checkbox.d.ts.map +1 -0
- package/dist/checkbox.js +251 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chunk-pbuEa-1d.js +13 -0
- package/dist/colour-C3MQIjFJ-BJV-QC-3.js +4138 -0
- package/dist/colour-C3MQIjFJ-BJV-QC-3.js.map +1 -0
- package/dist/colour-picker-Bw-AZoWx.js +922 -0
- package/dist/colour-picker-Bw-AZoWx.js.map +1 -0
- package/dist/colour-picker.d.ts +2 -0
- package/dist/colour-picker.js +2 -0
- package/dist/crumbs.d.ts +92 -0
- package/dist/crumbs.d.ts.map +1 -0
- package/dist/crumbs.js +789 -0
- package/dist/crumbs.js.map +1 -0
- package/dist/data-display.d.ts +24 -12
- package/dist/data-display.d.ts.map +1 -1
- package/dist/data-display.js +96 -105
- package/dist/data-display.js.map +1 -1
- package/dist/decorate-BZbkqIhA.js +9 -0
- package/dist/defaults-FEZaGiYZ.js +38 -0
- package/dist/defaults-FEZaGiYZ.js.map +1 -0
- package/dist/dist-By5URG0Y.js +1290 -0
- package/dist/dist-By5URG0Y.js.map +1 -0
- package/dist/dist-D7kJgnSE.js +1039 -0
- package/dist/dist-D7kJgnSE.js.map +1 -0
- package/dist/editable-label.d.ts +71 -0
- package/dist/editable-label.d.ts.map +1 -0
- package/dist/editable-label.js +279 -0
- package/dist/editable-label.js.map +1 -0
- package/dist/hex-editor-Gib1Grg2.d.ts +131 -0
- package/dist/hex-editor-Gib1Grg2.d.ts.map +1 -0
- package/dist/hex-editor-Wd6ZtZA2.js +1147 -0
- package/dist/hex-editor-Wd6ZtZA2.js.map +1 -0
- package/dist/hex.d.ts +2 -0
- package/dist/hex.js +2 -0
- package/dist/highlight-CAjwQ4GE.js +50 -0
- package/dist/highlight-CAjwQ4GE.js.map +1 -0
- package/dist/icon-BR5aTIiP.js +100 -0
- package/dist/icon-BR5aTIiP.js.map +1 -0
- package/dist/icon-DQKdfR7U.d.ts +36 -0
- package/dist/icon-DQKdfR7U.d.ts.map +1 -0
- package/dist/icons.d.ts +3 -0
- package/dist/icons.js +9 -0
- package/dist/icons.js.map +1 -0
- package/dist/incr-search-BjCNClnC.js +311 -0
- package/dist/incr-search-BjCNClnC.js.map +1 -0
- package/dist/incr-search.d.ts +2 -0
- package/dist/incr-search.js +3 -0
- package/dist/index-B1hNR7Z9.d.ts +36 -0
- package/dist/index-B1hNR7Z9.d.ts.map +1 -0
- package/dist/index-C5dK8RZa.d.ts +23 -0
- package/dist/index-C5dK8RZa.d.ts.map +1 -0
- package/dist/index-C9iBN908.d.ts +160 -0
- package/dist/index-C9iBN908.d.ts.map +1 -0
- package/dist/index-CPVcTTXo.d.ts +396 -0
- package/dist/index-CPVcTTXo.d.ts.map +1 -0
- package/dist/index-CQxanqXF.d.ts +183 -0
- package/dist/index-CQxanqXF.d.ts.map +1 -0
- package/dist/index-CpbBI3n7.d.ts +1239 -0
- package/dist/index-CpbBI3n7.d.ts.map +1 -0
- package/dist/index.d.ts +422 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5729 -14
- package/dist/index.js.map +1 -1
- package/dist/interaction-CQDQJf2Q.js +1 -0
- package/dist/keyboard-De_vOHLg.js +20 -0
- package/dist/keyboard-De_vOHLg.js.map +1 -0
- package/dist/labelled-input-base-DS6-6C0r.js +155 -0
- package/dist/labelled-input-base-DS6-6C0r.js.map +1 -0
- package/dist/labelled-input-base-DnRh4reU.d.ts +43 -0
- package/dist/labelled-input-base-DnRh4reU.d.ts.map +1 -0
- package/dist/labelled-radial-input.d.ts +34 -0
- package/dist/labelled-radial-input.d.ts.map +1 -0
- package/dist/labelled-radial-input.js +188 -0
- package/dist/labelled-radial-input.js.map +1 -0
- package/dist/labelled-range-input.d.ts +2 -0
- package/dist/labelled-range-input.js +132 -0
- package/dist/labelled-range-input.js.map +1 -0
- package/dist/led.d.ts +25 -0
- package/dist/led.d.ts.map +1 -0
- package/dist/led.js +92 -0
- package/dist/led.js.map +1 -0
- package/dist/menu-BV6UFx_z.js +813 -0
- package/dist/menu-BV6UFx_z.js.map +1 -0
- package/dist/menu-item-Cikacp4F.d.ts +128 -0
- package/dist/menu-item-Cikacp4F.d.ts.map +1 -0
- package/dist/menu-item-DEzL_Yjk.js +766 -0
- package/dist/menu-item-DEzL_Yjk.js.map +1 -0
- package/dist/menu.d.ts +3 -0
- package/dist/menu.js +3 -0
- package/dist/miller.d.ts +324 -0
- package/dist/miller.d.ts.map +1 -0
- package/dist/miller.js +1343 -0
- package/dist/miller.js.map +1 -0
- package/dist/narrowed-text.d.ts +72 -0
- package/dist/narrowed-text.d.ts.map +1 -0
- package/dist/narrowed-text.js +571 -0
- package/dist/narrowed-text.js.map +1 -0
- package/dist/panel.d.ts +43 -0
- package/dist/panel.d.ts.map +1 -0
- package/dist/panel.js +408 -0
- package/dist/panel.js.map +1 -0
- package/dist/plots.d.ts +2 -0
- package/dist/plots.js +2 -0
- package/dist/polar-pad.d.ts +67 -0
- package/dist/polar-pad.d.ts.map +1 -0
- package/dist/polar-pad.js +537 -0
- package/dist/polar-pad.js.map +1 -0
- package/dist/popup-Ddx9LCzY.js +24 -0
- package/dist/popup-Ddx9LCzY.js.map +1 -0
- package/dist/prominence-CreDBdCs.js +98 -0
- package/dist/prominence-CreDBdCs.js.map +1 -0
- package/dist/radial-input-CNJ8asY2.js +849 -0
- package/dist/radial-input-CNJ8asY2.js.map +1 -0
- package/dist/radial-input-xSTd4kEz.d.ts +70 -0
- package/dist/radial-input-xSTd4kEz.d.ts.map +1 -0
- package/dist/radial-input.d.ts +2 -0
- package/dist/radial-input.js +2 -0
- package/dist/range-input.d.ts +43 -0
- package/dist/range-input.d.ts.map +1 -0
- package/dist/range-input.js +459 -0
- package/dist/range-input.js.map +1 -0
- package/dist/range.d.ts +28 -0
- package/dist/range.d.ts.map +1 -0
- package/dist/range.js +136 -0
- package/dist/range.js.map +1 -0
- package/dist/registry-CZEB1YI9.js +21 -0
- package/dist/registry-CZEB1YI9.js.map +1 -0
- package/dist/selecthorizontal.d.ts +13 -8
- package/dist/selecthorizontal.d.ts.map +1 -1
- package/dist/selecthorizontal.js +21 -25
- package/dist/selecthorizontal.js.map +1 -1
- package/dist/snap-container.d.ts +50 -0
- package/dist/snap-container.d.ts.map +1 -0
- package/dist/snap-container.js +297 -0
- package/dist/snap-container.js.map +1 -0
- package/dist/split-layout.d.ts +56 -0
- package/dist/split-layout.d.ts.map +1 -0
- package/dist/split-layout.js +545 -0
- package/dist/split-layout.js.map +1 -0
- package/dist/style.css +133 -0
- package/dist/swipe.d.ts +48 -0
- package/dist/swipe.d.ts.map +1 -0
- package/dist/swipe.js +204 -0
- package/dist/swipe.js.map +1 -0
- package/dist/tab-list-CFF7uSYH.d.ts +66 -0
- package/dist/tab-list-CFF7uSYH.d.ts.map +1 -0
- package/dist/tabs.d.ts +2 -0
- package/dist/tabs.js +203 -0
- package/dist/tabs.js.map +1 -0
- package/dist/tickled-controller-Cq1Va0rR.d.ts +218 -0
- package/dist/tickled-controller-Cq1Va0rR.d.ts.map +1 -0
- package/dist/tickled-styles-Bg3QbcrD.js +327 -0
- package/dist/tickled-styles-Bg3QbcrD.js.map +1 -0
- package/dist/timeline-DBWJsSjd.js +1748 -0
- package/dist/timeline-DBWJsSjd.js.map +1 -0
- package/dist/timeline.d.ts +2 -0
- package/dist/timeline.js +2 -0
- package/dist/tooltip-DMxmBNky.js +104 -0
- package/dist/tooltip-DMxmBNky.js.map +1 -0
- package/dist/tooltip-kfUBWYVB.d.ts +26 -0
- package/dist/tooltip-kfUBWYVB.d.ts.map +1 -0
- package/dist/tree-component-CQpoPo4s.d.ts +326 -0
- package/dist/tree-component-CQpoPo4s.d.ts.map +1 -0
- package/dist/tree-data-model-DGvRVOFY.js +190 -0
- package/dist/tree-data-model-DGvRVOFY.js.map +1 -0
- package/dist/tree.d.ts +100 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +1144 -0
- package/dist/tree.js.map +1 -0
- package/dist/types-BKaqnpwx.d.ts +8 -0
- package/dist/types-BKaqnpwx.d.ts.map +1 -0
- package/dist/xy-axis-BANbgrI5.js +6243 -0
- package/dist/xy-axis-BANbgrI5.js.map +1 -0
- package/dist/xy-axis-CIFok7MF.d.ts +141 -0
- package/dist/xy-axis-CIFok7MF.d.ts.map +1 -0
- package/dist/xy-pad.d.ts +81 -0
- package/dist/xy-pad.d.ts.map +1 -0
- package/dist/xy-pad.js +435 -0
- package/dist/xy-pad.js.map +1 -0
- package/package.json +48 -39
- package/README.md +0 -14
- package/dist/charts/frequency-histogram-plot.d.ts +0 -33
- package/dist/charts/frequency-histogram-plot.d.ts.map +0 -1
- package/dist/charts/frequency-histogram-plot.js +0 -54
- package/dist/charts/frequency-histogram-plot.js.map +0 -1
- package/dist/charts/histogram-vis.d.ts +0 -57
- package/dist/charts/histogram-vis.d.ts.map +0 -1
- package/dist/charts/histogram-vis.js +0 -222
- package/dist/charts/histogram-vis.js.map +0 -1
- package/dist/charts/plot.d.ts +0 -199
- package/dist/charts/plot.d.ts.map +0 -1
- package/dist/charts/plot.js +0 -914
- package/dist/charts/plot.js.map +0 -1
- package/dist/crumb-nav.d.ts +0 -41
- package/dist/crumb-nav.d.ts.map +0 -1
- package/dist/crumb-nav.js +0 -198
- package/dist/crumb-nav.js.map +0 -1
- package/dist/crumb-navigation.d.ts +0 -30
- package/dist/crumb-navigation.d.ts.map +0 -1
- package/dist/crumb-navigation.js +0 -307
- package/dist/crumb-navigation.js.map +0 -1
- package/dist/dial.d.ts +0 -89
- package/dist/dial.d.ts.map +0 -1
- package/dist/dial.js +0 -506
- package/dist/dial.js.map +0 -1
- package/dist/my-element.d.ts +0 -14
- package/dist/my-element.d.ts.map +0 -1
- package/dist/my-element.js +0 -44
- package/dist/my-element.js.map +0 -1
- package/dist/split-layout/split-layout.d.ts +0 -35
- package/dist/split-layout/split-layout.d.ts.map +0 -1
- package/dist/split-layout/split-layout.js +0 -220
- package/dist/split-layout/split-layout.js.map +0 -1
- package/dist/svg-edit-label.d.ts +0 -2
- package/dist/svg-edit-label.d.ts.map +0 -1
- package/dist/svg-edit-label.js +0 -110
- package/dist/svg-edit-label.js.map +0 -1
- package/dist/tabs/tab-layout-item.d.ts +0 -10
- package/dist/tabs/tab-layout-item.d.ts.map +0 -1
- package/dist/tabs/tab-layout-item.js +0 -20
- package/dist/tabs/tab-layout-item.js.map +0 -1
- package/dist/tabs/tab-layout.d.ts +0 -10
- package/dist/tabs/tab-layout.d.ts.map +0 -1
- package/dist/tabs/tab-layout.js +0 -25
- package/dist/tabs/tab-layout.js.map +0 -1
- package/dist/tabs/tab-list-item.d.ts +0 -18
- package/dist/tabs/tab-list-item.d.ts.map +0 -1
- package/dist/tabs/tab-list-item.js +0 -63
- package/dist/tabs/tab-list-item.js.map +0 -1
- package/dist/tabs/tab-list.d.ts +0 -21
- package/dist/tabs/tab-list.d.ts.map +0 -1
- package/dist/tabs/tab-list.js +0 -148
- package/dist/tabs/tab-list.js.map +0 -1
- package/dist/tabs/tab-panel.d.ts +0 -11
- package/dist/tabs/tab-panel.d.ts.map +0 -1
- package/dist/tabs/tab-panel.js +0 -30
- package/dist/tabs/tab-panel.js.map +0 -1
- package/dist/tabs/tab-panels.d.ts +0 -30
- package/dist/tabs/tab-panels.d.ts.map +0 -1
- package/dist/tabs/tab-panels.js +0 -80
- package/dist/tabs/tab-panels.js.map +0 -1
- package/dist/util/circle-arc.d.ts +0 -34
- package/dist/util/circle-arc.d.ts.map +0 -1
- package/dist/util/circle-arc.js +0 -77
- package/dist/util/circle-arc.js.map +0 -1
- package/dist/util/compare.d.ts +0 -53
- package/dist/util/compare.d.ts.map +0 -1
- package/dist/util/compare.js +0 -91
- package/dist/util/compare.js.map +0 -1
- package/dist/util/content-editable.d.ts +0 -2
- package/dist/util/content-editable.d.ts.map +0 -1
- package/dist/util/content-editable.js +0 -13
- package/dist/util/content-editable.js.map +0 -1
- package/dist/util/drag-controller.d.ts +0 -13
- package/dist/util/drag-controller.d.ts.map +0 -1
- package/dist/util/drag-controller.js +0 -21
- package/dist/util/drag-controller.js.map +0 -1
- package/dist/util/key-value.d.ts +0 -5
- package/dist/util/key-value.d.ts.map +0 -1
- package/dist/util/key-value.js +0 -30
- package/dist/util/key-value.js.map +0 -1
- package/dist/util/primitive-types.d.ts +0 -6
- package/dist/util/primitive-types.d.ts.map +0 -1
- package/dist/util/primitive-types.js +0 -2
- package/dist/util/primitive-types.js.map +0 -1
- package/dist/util/svg-editable-text.d.ts +0 -22
- package/dist/util/svg-editable-text.d.ts.map +0 -1
- package/dist/util/svg-editable-text.js +0 -121
- package/dist/util/svg-editable-text.js.map +0 -1
- package/dist/util/time.d.ts +0 -2
- package/dist/util/time.d.ts.map +0 -1
- package/dist/util/time.js +0 -2
- package/dist/util/time.js.map +0 -1
|
@@ -0,0 +1,4138 @@
|
|
|
1
|
+
import { C as resultThrow, S as percentTest, a as movingAverageLight, b as numberInclusiveRangeTest, g as errorResult, i as interpolate, m as pairwise, t as clamp, u as scaleClamped, x as numberTest } from "./dist-D7kJgnSE.js";
|
|
2
|
+
//#region node_modules/.pnpm/@ixfx+visual@0.56.12/node_modules/@ixfx/visual/dist/chunk-pbuEa-1d.js
|
|
3
|
+
var __defProp$2 = Object.defineProperty;
|
|
4
|
+
var __exportAll$1 = (all, no_symbols) => {
|
|
5
|
+
let target = {};
|
|
6
|
+
for (var name in all) __defProp$2(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
if (!no_symbols) __defProp$2(target, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/chunk-pbuEa-1d.js
|
|
15
|
+
var __defProp$1 = Object.defineProperty;
|
|
16
|
+
var __exportAll = (all, no_symbols) => {
|
|
17
|
+
let target = {};
|
|
18
|
+
for (var name in all) __defProp$1(target, name, {
|
|
19
|
+
get: all[name],
|
|
20
|
+
enumerable: true
|
|
21
|
+
});
|
|
22
|
+
if (!no_symbols) __defProp$1(target, Symbol.toStringTag, { value: "Module" });
|
|
23
|
+
return target;
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/guard-CqkBirEd.js
|
|
27
|
+
/**
|
|
28
|
+
* Returns true if xy (and z, if present) are _null_.
|
|
29
|
+
* @param p
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
const isNull = (p) => {
|
|
33
|
+
if (isPoint3d(p)) {
|
|
34
|
+
if (p.z !== null) return false;
|
|
35
|
+
}
|
|
36
|
+
return p.x === null && p.y === null;
|
|
37
|
+
};
|
|
38
|
+
/***
|
|
39
|
+
* Returns true if either x, y, z isNaN.
|
|
40
|
+
*/
|
|
41
|
+
const isNaN = (p) => {
|
|
42
|
+
if (isPoint3d(p)) {
|
|
43
|
+
if (!Number.isNaN(p.z)) return false;
|
|
44
|
+
}
|
|
45
|
+
return Number.isNaN(p.x) || Number.isNaN(p.y);
|
|
46
|
+
};
|
|
47
|
+
function test(p, name = `Point`, extraInfo = ``) {
|
|
48
|
+
if (p === void 0) return errorResult(`'${name}' is undefined. Expected {x,y} got ${JSON.stringify(p)}`, extraInfo);
|
|
49
|
+
if (p === null) return errorResult(`'${name}' is null. Expected {x,y} got ${JSON.stringify(p)}`, extraInfo);
|
|
50
|
+
if (typeof p !== `object`) return errorResult(`'${name}' is type '${typeof p}'. Expected object.`, extraInfo);
|
|
51
|
+
if (p.x === void 0) return errorResult(`'${name}.x' is undefined. Expected {x,y} got ${JSON.stringify(p)}`, extraInfo);
|
|
52
|
+
if (p.y === void 0) return errorResult(`'${name}.y' is undefined. Expected {x,y} got ${JSON.stringify(p)}`, extraInfo);
|
|
53
|
+
if (typeof p.x !== `number`) return errorResult(`'${name}.x' must be a number. Got ${typeof p.x}`, extraInfo);
|
|
54
|
+
if (typeof p.y !== `number`) return errorResult(`'${name}.y' must be a number. Got ${typeof p.y}`, extraInfo);
|
|
55
|
+
if (p.z !== void 0) {
|
|
56
|
+
if (typeof p.z !== `number`) return errorResult(`${name}.z must be a number. Got: ${typeof p.z}`, extraInfo);
|
|
57
|
+
if (Number.isNaN(p.z)) return errorResult(`'${name}.z' is NaN. Got: ${JSON.stringify(p)}`, extraInfo);
|
|
58
|
+
}
|
|
59
|
+
if (p.x === null) return errorResult(`'${name}.x' is null`, extraInfo);
|
|
60
|
+
if (p.y === null) return errorResult(`'${name}.y' is null`, extraInfo);
|
|
61
|
+
if (Number.isNaN(p.x)) return errorResult(`'${name}.x' is NaN`, extraInfo);
|
|
62
|
+
if (Number.isNaN(p.y)) return errorResult(`'${name}.y' is NaN`, extraInfo);
|
|
63
|
+
return {
|
|
64
|
+
success: true,
|
|
65
|
+
value: p
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Throws an error if point is invalid
|
|
70
|
+
* @param p
|
|
71
|
+
* @param name
|
|
72
|
+
*/
|
|
73
|
+
function guard$5(p, name = `Point`, info) {
|
|
74
|
+
resultThrow(test(p, name, info));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Throws if parameter is not a valid point, or either x or y is 0
|
|
78
|
+
* @param pt
|
|
79
|
+
* @returns
|
|
80
|
+
*/
|
|
81
|
+
const guardNonZeroPoint = (pt, name = `pt`) => {
|
|
82
|
+
guard$5(pt, name);
|
|
83
|
+
resultThrow(numberTest(pt.x, `nonZero`, `${name}.x`), numberTest(pt.y, `nonZero`, `${name}.y`), () => {
|
|
84
|
+
if (typeof pt.z !== `undefined`) return numberTest(pt.z, `nonZero`, `${name}.z`);
|
|
85
|
+
});
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Returns _true_ if `p` has x & y properties.
|
|
90
|
+
* Returns _false_ if `p` is undefined, null or does not contain properties.
|
|
91
|
+
* Use {@link isPoint3d} to check further check for `z`.
|
|
92
|
+
* @param p
|
|
93
|
+
* @returns
|
|
94
|
+
*/
|
|
95
|
+
function isPoint(p) {
|
|
96
|
+
if (p === void 0) return false;
|
|
97
|
+
if (p === null) return false;
|
|
98
|
+
if (p.x === void 0) return false;
|
|
99
|
+
if (p.y === void 0) return false;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Returns _true_ if `p` has x, y, & z properties.
|
|
104
|
+
* Returns _false_ if `p` is undefined, null or does not contain properties.
|
|
105
|
+
* @param p
|
|
106
|
+
* @returns
|
|
107
|
+
*/
|
|
108
|
+
const isPoint3d = (p) => {
|
|
109
|
+
if (p === void 0) return false;
|
|
110
|
+
if (p === null) return false;
|
|
111
|
+
if (p.x === void 0) return false;
|
|
112
|
+
if (p.y === void 0) return false;
|
|
113
|
+
if (p.z === void 0) return false;
|
|
114
|
+
return true;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Returns true if both xy (and z, if present) are 0.
|
|
118
|
+
* Use `Points.Empty` to return an empty point.
|
|
119
|
+
* @param p
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
const isEmpty = (p) => {
|
|
123
|
+
if (isPoint3d(p)) {
|
|
124
|
+
if (p.z !== 0) return false;
|
|
125
|
+
}
|
|
126
|
+
return p.x === 0 && p.y === 0;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Returns true if point is a placeholder, where xy (and z, if present)
|
|
130
|
+
* are `NaN`.
|
|
131
|
+
*
|
|
132
|
+
* Use Points.Placeholder to return a placeholder point.
|
|
133
|
+
* @param p
|
|
134
|
+
* @returns
|
|
135
|
+
*/
|
|
136
|
+
const isPlaceholder = (p) => {
|
|
137
|
+
if (isPoint3d(p)) {
|
|
138
|
+
if (!Number.isNaN(p.z)) return false;
|
|
139
|
+
}
|
|
140
|
+
return Number.isNaN(p.x) && Number.isNaN(p.y);
|
|
141
|
+
};
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/to-jujzVMAL.js
|
|
144
|
+
function getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6) {
|
|
145
|
+
if (isPoint3d(a1) && isPoint3d(ab2)) return [a1, ab2];
|
|
146
|
+
if (isPoint(a1) && isPoint(ab2)) return [a1, ab2];
|
|
147
|
+
if (isPoint3d(a1)) {
|
|
148
|
+
const b = {
|
|
149
|
+
x: ab2,
|
|
150
|
+
y: ab3,
|
|
151
|
+
z: ab4
|
|
152
|
+
};
|
|
153
|
+
if (!isPoint3d(b)) throw new Error(`Expected x, y & z parameters`);
|
|
154
|
+
return [a1, b];
|
|
155
|
+
}
|
|
156
|
+
if (isPoint(a1)) {
|
|
157
|
+
const b = {
|
|
158
|
+
x: ab2,
|
|
159
|
+
y: ab3
|
|
160
|
+
};
|
|
161
|
+
if (!isPoint(b)) throw new Error(`Expected x & y parameters`);
|
|
162
|
+
return [a1, b];
|
|
163
|
+
}
|
|
164
|
+
if (typeof ab5 !== `undefined` && typeof ab4 !== `undefined`) {
|
|
165
|
+
const a = {
|
|
166
|
+
x: a1,
|
|
167
|
+
y: ab2,
|
|
168
|
+
z: ab3
|
|
169
|
+
};
|
|
170
|
+
const b = {
|
|
171
|
+
x: ab4,
|
|
172
|
+
y: ab5,
|
|
173
|
+
z: ab6
|
|
174
|
+
};
|
|
175
|
+
if (!isPoint3d(a)) throw new Error(`Expected x,y,z for first point`);
|
|
176
|
+
if (!isPoint3d(b)) throw new Error(`Expected x,y,z for second point`);
|
|
177
|
+
return [a, b];
|
|
178
|
+
}
|
|
179
|
+
const a = {
|
|
180
|
+
x: a1,
|
|
181
|
+
y: ab2
|
|
182
|
+
};
|
|
183
|
+
const b = {
|
|
184
|
+
x: ab3,
|
|
185
|
+
y: ab4
|
|
186
|
+
};
|
|
187
|
+
if (!isPoint(a)) throw new Error(`Expected x,y for first point`);
|
|
188
|
+
if (!isPoint(b)) throw new Error(`Expected x,y for second point`);
|
|
189
|
+
return [a, b];
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Returns a Point form of either a point, x,y params or x,y,z params.
|
|
193
|
+
* If parameters are undefined, an empty point is returned (0, 0)
|
|
194
|
+
* @ignore
|
|
195
|
+
* @param a
|
|
196
|
+
* @param b
|
|
197
|
+
* @returns
|
|
198
|
+
*/
|
|
199
|
+
function getPointParameter(a, b, c) {
|
|
200
|
+
if (a === void 0) return {
|
|
201
|
+
x: 0,
|
|
202
|
+
y: 0
|
|
203
|
+
};
|
|
204
|
+
if (Array.isArray(a)) {
|
|
205
|
+
if (a.length === 0) return Object.freeze({
|
|
206
|
+
x: 0,
|
|
207
|
+
y: 0
|
|
208
|
+
});
|
|
209
|
+
if (a.length === 1) return Object.freeze({
|
|
210
|
+
x: a[0],
|
|
211
|
+
y: 0
|
|
212
|
+
});
|
|
213
|
+
if (a.length === 2) return Object.freeze({
|
|
214
|
+
x: a[0],
|
|
215
|
+
y: a[1]
|
|
216
|
+
});
|
|
217
|
+
if (a.length === 3) return Object.freeze({
|
|
218
|
+
x: a[0],
|
|
219
|
+
y: a[1],
|
|
220
|
+
z: a[2]
|
|
221
|
+
});
|
|
222
|
+
throw new Error(`Expected array to be 1-3 elements in length. Got ${a.length}.`);
|
|
223
|
+
}
|
|
224
|
+
if (isPoint(a)) return a;
|
|
225
|
+
else if (typeof a !== `number` || typeof b !== `number`) throw new TypeError(`Expected point or x,y as parameters. Got: a: ${JSON.stringify(a)} b: ${JSON.stringify(b)}`);
|
|
226
|
+
if (typeof c === `number`) return Object.freeze({
|
|
227
|
+
x: a,
|
|
228
|
+
y: b,
|
|
229
|
+
z: c
|
|
230
|
+
});
|
|
231
|
+
return Object.freeze({
|
|
232
|
+
x: a,
|
|
233
|
+
y: b
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Calculate distance between two points.
|
|
238
|
+
* If both points have a `z` property, the distance is 3D distance is calculated.
|
|
239
|
+
* If only one point has a `z`, it is ignored. To force 2D distance, use {@link distance2d}
|
|
240
|
+
*
|
|
241
|
+
* ```js
|
|
242
|
+
* // Distance between two points
|
|
243
|
+
* const ptA = { x: 0.5, y:0.8 };
|
|
244
|
+
* const ptB = { x: 1, y: 0.4 };
|
|
245
|
+
* distance(ptA, ptB);
|
|
246
|
+
* // Or, provide x,y as parameters
|
|
247
|
+
* distance(ptA, 0.4, 0.9);
|
|
248
|
+
*
|
|
249
|
+
* // Distance from ptA to x: 0.5, y:0.8, z: 0.1
|
|
250
|
+
* const ptC = { x: 0.5, y:0.5, z: 0.3 };
|
|
251
|
+
* // With x,y,z as parameters:
|
|
252
|
+
* distance(ptC, 0.5, 0.8, 0.1);
|
|
253
|
+
* ```
|
|
254
|
+
* @param a First point
|
|
255
|
+
* @param xOrB Second point, or x coord
|
|
256
|
+
* @param y y coord, if x coord is given
|
|
257
|
+
* @param z Optional z coord, if x and y are given.
|
|
258
|
+
* @returns
|
|
259
|
+
*/
|
|
260
|
+
function distance(a, xOrB, y, z) {
|
|
261
|
+
const pt = getPointParameter(xOrB, y, z);
|
|
262
|
+
guard$5(pt, `b`);
|
|
263
|
+
guard$5(a, `a`);
|
|
264
|
+
return isPoint3d(pt) && isPoint3d(a) ? Math.hypot(pt.x - a.x, pt.y - a.y, pt.z - a.z) : Math.hypot(pt.x - a.x, pt.y - a.y);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* As {@link distance} but always compares by x,y only.
|
|
268
|
+
* @param a
|
|
269
|
+
* @param xOrB
|
|
270
|
+
* @param y
|
|
271
|
+
* @returns
|
|
272
|
+
*/
|
|
273
|
+
function distance2d(a, xOrB, y) {
|
|
274
|
+
const pt = getPointParameter(xOrB, y);
|
|
275
|
+
guard$5(pt, `b`);
|
|
276
|
+
guard$5(a, `a`);
|
|
277
|
+
return Math.hypot(pt.x - a.x, pt.y - a.y);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Returns a Point with the x,y,z values of two points subtracted (a-b).
|
|
281
|
+
*
|
|
282
|
+
* `z` parameter is used if present. Uses a default value of 0 for 'z' when subtracting a 2D point with a 3D one.
|
|
283
|
+
*
|
|
284
|
+
* Examples:
|
|
285
|
+
*
|
|
286
|
+
* ```js
|
|
287
|
+
* subtract(ptA, ptB);
|
|
288
|
+
* subtract(x1, y1, x2, y2);
|
|
289
|
+
* subtract(ptA, x2, y2);
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
function subtract(a1, ab2, ab3, ab4, ab5, ab6) {
|
|
293
|
+
const [ptA, ptB] = getTwoPointParameters(a1, ab2, ab3, ab4, ab5, ab6);
|
|
294
|
+
guard$5(ptA, `a`);
|
|
295
|
+
guard$5(ptB, `b`);
|
|
296
|
+
const pt = {
|
|
297
|
+
x: ptA.x - ptB.x,
|
|
298
|
+
y: ptA.y - ptB.y
|
|
299
|
+
};
|
|
300
|
+
if (isPoint3d(ptA) || isPoint3d(ptB)) pt.z = (ptA.z ?? 0) - (ptB.z ?? 0);
|
|
301
|
+
return Object.freeze(pt);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Returns a point with rounded x,y coordinates. By default uses `Math.round` to round.
|
|
305
|
+
* ```js
|
|
306
|
+
* toIntegerValues({x:1.234, y:5.567}); // Yields: {x:1, y:6}
|
|
307
|
+
* ```
|
|
308
|
+
*
|
|
309
|
+
* ```js
|
|
310
|
+
* toIntegerValues(pt, Math.ceil); // Use Math.ceil to round x,y of `pt`.
|
|
311
|
+
* ```
|
|
312
|
+
* @param pt Point to round
|
|
313
|
+
* @param rounder Rounding function, or Math.round by default
|
|
314
|
+
* @returns
|
|
315
|
+
*/
|
|
316
|
+
const toIntegerValues = (pt, rounder = Math.round) => {
|
|
317
|
+
guard$5(pt, `pt`);
|
|
318
|
+
return Object.freeze({
|
|
319
|
+
x: rounder(pt.x),
|
|
320
|
+
y: rounder(pt.y)
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* Returns a copy of `pt` with `z` field omitted.
|
|
325
|
+
* If it didn't have one to begin within, a copy is still returned.
|
|
326
|
+
* @param pt
|
|
327
|
+
* @returns
|
|
328
|
+
*/
|
|
329
|
+
const to2d = (pt) => {
|
|
330
|
+
guard$5(pt, `pt`);
|
|
331
|
+
let copy = { ...pt };
|
|
332
|
+
delete copy.z;
|
|
333
|
+
return Object.freeze(copy);
|
|
334
|
+
};
|
|
335
|
+
/**
|
|
336
|
+
* Returns a copy of `pt` with a `z` field set.
|
|
337
|
+
* Defaults to a z value of 0.
|
|
338
|
+
* @param pt Point
|
|
339
|
+
* @param z Z-value, defaults to 0
|
|
340
|
+
* @returns
|
|
341
|
+
*/
|
|
342
|
+
const to3d = (pt, z = 0) => {
|
|
343
|
+
guard$5(pt, `pt`);
|
|
344
|
+
return Object.freeze({
|
|
345
|
+
...pt,
|
|
346
|
+
z
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
/**
|
|
350
|
+
* Returns a human-friendly string representation `(x, y)`.
|
|
351
|
+
* If `precision` is supplied, this will be the number of significant digits.
|
|
352
|
+
* @param p
|
|
353
|
+
* @returns
|
|
354
|
+
*/
|
|
355
|
+
function toString(p, digits) {
|
|
356
|
+
if (p === void 0) return `(undefined)`;
|
|
357
|
+
if (p === null) return `(null)`;
|
|
358
|
+
guard$5(p, `pt`);
|
|
359
|
+
const x = digits ? p.x.toFixed(digits) : p.x;
|
|
360
|
+
const y = digits ? p.y.toFixed(digits) : p.y;
|
|
361
|
+
if (p.z === void 0) return `(${x},${y})`;
|
|
362
|
+
else return `(${x},${y},${digits ? p.z.toFixed(digits) : p.z})`;
|
|
363
|
+
}
|
|
364
|
+
//#endregion
|
|
365
|
+
//#region node_modules/.pnpm/@ixfx+geometry@0.56.12/node_modules/@ixfx/geometry/dist/polar-LvwxTwIf.js
|
|
366
|
+
const piPi = Math.PI * 2;
|
|
367
|
+
/**
|
|
368
|
+
* Averages a set of points, by default as a 'mean'.
|
|
369
|
+
*
|
|
370
|
+
* List of points has to all have Z property or none of them -- it's not
|
|
371
|
+
* possible to mix 2D and 3D points.
|
|
372
|
+
* @param points
|
|
373
|
+
* @returns
|
|
374
|
+
*/
|
|
375
|
+
const average$1 = (points, kind = `mean`) => {
|
|
376
|
+
let xSum = 0;
|
|
377
|
+
let ySum = 0;
|
|
378
|
+
let zSum = NaN;
|
|
379
|
+
let total = 0;
|
|
380
|
+
if (kind !== `mean`) throw new Error(`Unknown averaging kind: '${kind}' expected: 'mean'`);
|
|
381
|
+
for (const p of points) {
|
|
382
|
+
xSum += p.x;
|
|
383
|
+
ySum += p.y;
|
|
384
|
+
if (`z` in p && p.z !== void 0) zSum += p.z;
|
|
385
|
+
else if (Number.isNaN(zSum)) throw new Error(`List of points should all have Z property, or none`);
|
|
386
|
+
total++;
|
|
387
|
+
}
|
|
388
|
+
xSum /= total;
|
|
389
|
+
ySum /= total;
|
|
390
|
+
if (Number.isNaN(zSum)) return {
|
|
391
|
+
x: xSum,
|
|
392
|
+
y: ySum
|
|
393
|
+
};
|
|
394
|
+
else return {
|
|
395
|
+
x: xSum,
|
|
396
|
+
y: ySum,
|
|
397
|
+
z: zSum / total
|
|
398
|
+
};
|
|
399
|
+
};
|
|
400
|
+
function averager(kind, opts = {}) {
|
|
401
|
+
let x;
|
|
402
|
+
let y;
|
|
403
|
+
let z;
|
|
404
|
+
switch (kind) {
|
|
405
|
+
case `moving-average-light`: {
|
|
406
|
+
const scaling = opts.scaling ?? 3;
|
|
407
|
+
x = movingAverageLight(scaling);
|
|
408
|
+
y = movingAverageLight(scaling);
|
|
409
|
+
z = movingAverageLight(scaling);
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
default: throw new Error(`Unknown averaging kind '${kind}'. Expected: 'moving-average-light'`);
|
|
413
|
+
}
|
|
414
|
+
return (point) => {
|
|
415
|
+
const ax = x(point.x);
|
|
416
|
+
const ay = y(point.y);
|
|
417
|
+
if (isPoint3d(point)) {
|
|
418
|
+
const az = z(point.z);
|
|
419
|
+
return Object.freeze({
|
|
420
|
+
x: ax,
|
|
421
|
+
y: ay,
|
|
422
|
+
z: az
|
|
423
|
+
});
|
|
424
|
+
} else return Object.freeze({
|
|
425
|
+
x: ax,
|
|
426
|
+
y: ay
|
|
427
|
+
});
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function degreeToRadian(angleInDegrees) {
|
|
431
|
+
return Array.isArray(angleInDegrees) ? angleInDegrees.map((v) => v * (Math.PI / 180)) : angleInDegrees * (Math.PI / 180);
|
|
432
|
+
}
|
|
433
|
+
function degreeToGradian(angleInDegrees) {
|
|
434
|
+
return angleInDegrees * 1.111111;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Returns the gradian value converted to degrees.
|
|
438
|
+
* By default it wraps, so any value 360 or greater wraps around.
|
|
439
|
+
* @param angleInGradians
|
|
440
|
+
* @param wrap
|
|
441
|
+
* @returns
|
|
442
|
+
*/
|
|
443
|
+
function gradianToDegree(angleInGradians, wrap = true) {
|
|
444
|
+
if (wrap) return angleInGradians * .9 % 360;
|
|
445
|
+
return angleInGradians * .9;
|
|
446
|
+
}
|
|
447
|
+
function radianToGradian(angleInRadians) {
|
|
448
|
+
return angleInRadians * 63.6619772368;
|
|
449
|
+
}
|
|
450
|
+
function gradianToRadian(angleInGradian) {
|
|
451
|
+
return angleInGradian * .0157079633;
|
|
452
|
+
}
|
|
453
|
+
function radianToDegree(angleInRadians) {
|
|
454
|
+
return Array.isArray(angleInRadians) ? angleInRadians.map((v) => v * 180 / Math.PI) : angleInRadians * 180 / Math.PI;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Parses CSS-style angle strings into an 'Angle' type. By default assumes degrees.
|
|
458
|
+
*
|
|
459
|
+
* ```js
|
|
460
|
+
* angleParse(`100`); // { value: 100, unit: `deg` }
|
|
461
|
+
* angleParse(100); // { value: 100, unit: `deg` }
|
|
462
|
+
* angleParse(`100deg`); // { value: 100, unit: `deg` }
|
|
463
|
+
*
|
|
464
|
+
* // More exotic units:
|
|
465
|
+
* angleParse(`100rad`); // { value: 100, unit: `rad` }
|
|
466
|
+
* angleParse(`100turn`); // { value: 100, unit: `turn` }
|
|
467
|
+
* angleParse(`100grad`); // { value: 100, unit: `grad` }
|
|
468
|
+
* ```
|
|
469
|
+
*
|
|
470
|
+
* Once parsed in this format, use {@link angleConvert} to convert to
|
|
471
|
+
* a different unit.
|
|
472
|
+
* @param value
|
|
473
|
+
* @returns
|
|
474
|
+
*/
|
|
475
|
+
const angleParse = (value) => {
|
|
476
|
+
if (isAngleType(value)) return value;
|
|
477
|
+
if (typeof value === `number`) return {
|
|
478
|
+
value,
|
|
479
|
+
unit: `deg`
|
|
480
|
+
};
|
|
481
|
+
value = value.toLowerCase();
|
|
482
|
+
let unit = `deg`;
|
|
483
|
+
let numberValue = NaN;
|
|
484
|
+
if (value.endsWith(`grad`)) {
|
|
485
|
+
numberValue = Number.parseFloat(value.substring(0, value.length - 4));
|
|
486
|
+
unit = `grad`;
|
|
487
|
+
} else if (value.endsWith(`rad`)) {
|
|
488
|
+
numberValue = Number.parseFloat(value.substring(0, value.length - 3));
|
|
489
|
+
unit = `rad`;
|
|
490
|
+
} else if (value.endsWith(`turn`)) {
|
|
491
|
+
numberValue = Number.parseFloat(value.substring(0, value.length - 4));
|
|
492
|
+
unit = `turn`;
|
|
493
|
+
} else if (value.endsWith(`deg`)) {
|
|
494
|
+
numberValue = Number.parseFloat(value.substring(0, value.length - 3));
|
|
495
|
+
unit = `deg`;
|
|
496
|
+
} else numberValue = Number.parseFloat(value);
|
|
497
|
+
if (Number.isNaN(numberValue)) throw new Error(`Invalid angle (bad value?)`);
|
|
498
|
+
if (unit.length === 0) throw new Error(`Invalid angle (no unit)`);
|
|
499
|
+
return {
|
|
500
|
+
value: numberValue,
|
|
501
|
+
unit
|
|
502
|
+
};
|
|
503
|
+
};
|
|
504
|
+
const isAngleType = (v) => {
|
|
505
|
+
if (typeof v !== `object`) return false;
|
|
506
|
+
if (`unit` in v && `value` in v) {
|
|
507
|
+
if (typeof v.unit !== `string`) return false;
|
|
508
|
+
if (typeof v.value !== `number`) return false;
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
return false;
|
|
512
|
+
};
|
|
513
|
+
/**
|
|
514
|
+
* Converts an angle to another representation.
|
|
515
|
+
* Input value is assumed degrees unless it's an {@link Angle} type of has the unit.
|
|
516
|
+
*
|
|
517
|
+
* These are all identical inputs: 100, `100`, `100deg`
|
|
518
|
+
* ```js
|
|
519
|
+
* angleConvert(100, `rad`); // Converts 100deg to radians
|
|
520
|
+
* ```
|
|
521
|
+
*
|
|
522
|
+
* Other units can be used for string input: `2turn`, `1grad`, `2rad`.
|
|
523
|
+
* ```js
|
|
524
|
+
* angleConvert(`2rad`, `deg`); // Converts 2radians to degrees
|
|
525
|
+
* ```
|
|
526
|
+
*
|
|
527
|
+
* Can also use an object input:
|
|
528
|
+
* ```js
|
|
529
|
+
* angleConvert({ value: 10, unit: `deg`}, `rad`);
|
|
530
|
+
* ```
|
|
531
|
+
* @param angleOrDegrees
|
|
532
|
+
* @param destination
|
|
533
|
+
* @returns
|
|
534
|
+
*/
|
|
535
|
+
const angleConvert = (angleOrDegrees, destination) => {
|
|
536
|
+
const angle = typeof angleOrDegrees === `object` ? angleOrDegrees : angleParse(angleOrDegrees);
|
|
537
|
+
switch (destination) {
|
|
538
|
+
case `deg`:
|
|
539
|
+
if (angle.unit === `deg`) return angle;
|
|
540
|
+
if (angle.unit === `rad`) return {
|
|
541
|
+
value: radianToDegree(angle.value),
|
|
542
|
+
unit: `deg`
|
|
543
|
+
};
|
|
544
|
+
if (angle.unit === `grad`) return {
|
|
545
|
+
value: gradianToDegree(angle.value),
|
|
546
|
+
unit: `deg`
|
|
547
|
+
};
|
|
548
|
+
if (angle.unit === `turn`) return {
|
|
549
|
+
value: turnToDegree(angle.value),
|
|
550
|
+
unit: `deg`
|
|
551
|
+
};
|
|
552
|
+
throw new Error(`Unknown unit: ${angle.unit}`);
|
|
553
|
+
case `grad`:
|
|
554
|
+
if (angle.unit === `deg`) return {
|
|
555
|
+
value: degreeToGradian(angle.value),
|
|
556
|
+
unit: `grad`
|
|
557
|
+
};
|
|
558
|
+
if (angle.unit === `rad`) return {
|
|
559
|
+
value: radianToGradian(angle.value),
|
|
560
|
+
unit: `grad`
|
|
561
|
+
};
|
|
562
|
+
if (angle.unit === `grad`) return angle;
|
|
563
|
+
if (angle.unit === `turn`) return {
|
|
564
|
+
value: radianToGradian(turnToRadian(angle.value)),
|
|
565
|
+
unit: `grad`
|
|
566
|
+
};
|
|
567
|
+
throw new Error(`Unknown unit: ${angle.unit}`);
|
|
568
|
+
case `rad`:
|
|
569
|
+
if (angle.unit === `deg`) return {
|
|
570
|
+
value: degreeToRadian(angle.value),
|
|
571
|
+
unit: `rad`
|
|
572
|
+
};
|
|
573
|
+
if (angle.unit === `rad`) return angle;
|
|
574
|
+
if (angle.unit === `grad`) return {
|
|
575
|
+
value: gradianToRadian(angle.value),
|
|
576
|
+
unit: `rad`
|
|
577
|
+
};
|
|
578
|
+
if (angle.unit === `turn`) return {
|
|
579
|
+
value: radianToGradian(turnToRadian(angle.value)),
|
|
580
|
+
unit: `grad`
|
|
581
|
+
};
|
|
582
|
+
throw new Error(`Unknown unit: ${angle.unit}`);
|
|
583
|
+
case `turn`:
|
|
584
|
+
if (angle.unit === `deg`) return {
|
|
585
|
+
value: degreeToTurn(angle.value),
|
|
586
|
+
unit: `turn`
|
|
587
|
+
};
|
|
588
|
+
if (angle.unit === `rad`) return {
|
|
589
|
+
value: radianToTurn(angle.value),
|
|
590
|
+
unit: `turn`
|
|
591
|
+
};
|
|
592
|
+
if (angle.unit === `grad`) return {
|
|
593
|
+
value: radianToTurn(gradianToRadian(angle.value)),
|
|
594
|
+
unit: `turn`
|
|
595
|
+
};
|
|
596
|
+
if (angle.unit === `turn`) return angle;
|
|
597
|
+
throw new Error(`Unknown unit: ${angle.unit}`);
|
|
598
|
+
default: throw new Error(`Destination unit unknown ('${destination}). Expects: deg, grad, rad or turn`);
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
/**
|
|
602
|
+
* Converts 'turns' to degrees. By defaults wraps the value, so
|
|
603
|
+
* turn value of 1 or 2 equal 0deg instead of 360 or 720deg.
|
|
604
|
+
* @param turns
|
|
605
|
+
* @param wrap
|
|
606
|
+
* @returns
|
|
607
|
+
*/
|
|
608
|
+
const turnToDegree = (turns, wrap = true) => {
|
|
609
|
+
if (wrap) return turns * 360 % 360;
|
|
610
|
+
return turns * 360;
|
|
611
|
+
};
|
|
612
|
+
const turnToRadian = (turns) => turns * piPi;
|
|
613
|
+
const degreeToTurn = (degrees) => degrees / 360;
|
|
614
|
+
const radianToTurn = (radians) => radians / piPi;
|
|
615
|
+
/**
|
|
616
|
+
* Normalise a radian angle to 0..2*PI range
|
|
617
|
+
* @param angleRadian
|
|
618
|
+
* @returns
|
|
619
|
+
*/
|
|
620
|
+
const radiansNormalise = (angleRadian) => {
|
|
621
|
+
angleRadian %= piPi;
|
|
622
|
+
return angleRadian < 0 ? angleRadian + piPi : angleRadian;
|
|
623
|
+
};
|
|
624
|
+
/**
|
|
625
|
+
* Returns true if `p` seems to be a {@link Polar.Coord} (ie has both distance & angleRadian fields)
|
|
626
|
+
* @param p
|
|
627
|
+
* @returns True if `p` seems to be a PolarCoord
|
|
628
|
+
*/
|
|
629
|
+
const isPolarCoord = (p) => {
|
|
630
|
+
if (p.distance === void 0) return false;
|
|
631
|
+
if (p.angleRadian === void 0) return false;
|
|
632
|
+
return true;
|
|
633
|
+
};
|
|
634
|
+
/**
|
|
635
|
+
* Returns a rotated coordinate
|
|
636
|
+
* @param c Coordinate
|
|
637
|
+
* @param amountRadian Amount to rotate, in radians
|
|
638
|
+
* @returns
|
|
639
|
+
*/
|
|
640
|
+
const rotate$1 = (c, amountRadian) => Object.freeze({
|
|
641
|
+
...c,
|
|
642
|
+
angleRadian: c.angleRadian + amountRadian
|
|
643
|
+
});
|
|
644
|
+
/**
|
|
645
|
+
* An empty point of `{ x: 0, y: 0 }`.
|
|
646
|
+
*
|
|
647
|
+
* Use `isEmpty` to check if a point is empty.
|
|
648
|
+
* Use `Empty3d` to get an empty point with `z`.
|
|
649
|
+
*/
|
|
650
|
+
const Empty = {
|
|
651
|
+
x: 0,
|
|
652
|
+
y: 0
|
|
653
|
+
};
|
|
654
|
+
/**
|
|
655
|
+
* Returns { x:1, y:1 }
|
|
656
|
+
*/
|
|
657
|
+
const Unit = {
|
|
658
|
+
x: 1,
|
|
659
|
+
y: 1
|
|
660
|
+
};
|
|
661
|
+
/**
|
|
662
|
+
* An empty Point of `{ x: 0, y: 0, z: 0}`
|
|
663
|
+
* Use `isEmpty` to check if a point is empty.
|
|
664
|
+
* Use `Empty` to get an empty point without `z`.
|
|
665
|
+
*/
|
|
666
|
+
const Empty3d = {
|
|
667
|
+
x: 0,
|
|
668
|
+
y: 0,
|
|
669
|
+
z: 0
|
|
670
|
+
};
|
|
671
|
+
/**
|
|
672
|
+
* Returns { x:1,y:1,z:1 }
|
|
673
|
+
*/
|
|
674
|
+
const Unit3d = {
|
|
675
|
+
x: 1,
|
|
676
|
+
y: 1,
|
|
677
|
+
z: 1
|
|
678
|
+
};
|
|
679
|
+
/**
|
|
680
|
+
* Converts to Cartesian coordinate from polar.
|
|
681
|
+
*
|
|
682
|
+
* ```js
|
|
683
|
+
*
|
|
684
|
+
* const origin = { x: 50, y: 50}; // Polar origin
|
|
685
|
+
* // Yields: { x, y }
|
|
686
|
+
* const polar = Polar.toCartesian({ distance: 10, angleRadian: 0 }, origin);
|
|
687
|
+
* ```
|
|
688
|
+
*
|
|
689
|
+
* Distance and angle can be provided as numbers intead:
|
|
690
|
+
*
|
|
691
|
+
* ```
|
|
692
|
+
* // Yields: { x, y }
|
|
693
|
+
* const polar = Polar.toCartesian(10, 0, origin);
|
|
694
|
+
* ```
|
|
695
|
+
*
|
|
696
|
+
* @param a
|
|
697
|
+
* @param b
|
|
698
|
+
* @param c
|
|
699
|
+
* @returns
|
|
700
|
+
*/
|
|
701
|
+
const toCartesian$1 = (a, b, c) => {
|
|
702
|
+
if (isPolarCoord(a)) {
|
|
703
|
+
if (typeof b === `undefined`) b = Empty;
|
|
704
|
+
if (isPoint(b)) return polarToCartesian(a.distance, a.angleRadian, b);
|
|
705
|
+
throw new Error(`Expecting (Coord, Point). Second parameter is not a point`);
|
|
706
|
+
} else if (typeof a === `object`) throw new TypeError(`First param is an object, but not a Coord: ${JSON.stringify(a)}`);
|
|
707
|
+
else if (typeof a === `number` && typeof b === `number`) {
|
|
708
|
+
if (typeof c === `undefined`) c = Empty;
|
|
709
|
+
if (!isPoint(c)) throw new Error(`Expecting (number, number, Point). Point param wrong type`);
|
|
710
|
+
return polarToCartesian(a, b, c);
|
|
711
|
+
} else throw new TypeError(`Expecting parameters of (number, number). Got: (${typeof a}, ${typeof b}, ${typeof c}). a: ${JSON.stringify(a)}`);
|
|
712
|
+
};
|
|
713
|
+
/**
|
|
714
|
+
* Converts a Cartesian coordinate to polar
|
|
715
|
+
*
|
|
716
|
+
* ```js
|
|
717
|
+
*
|
|
718
|
+
* // Yields: { angleRadian, distance }
|
|
719
|
+
* const polar = Polar.fromCartesian({x: 50, y: 50}, origin);
|
|
720
|
+
* ```
|
|
721
|
+
*
|
|
722
|
+
* Any additional properties of `point` are copied to object.
|
|
723
|
+
*
|
|
724
|
+
* Options:
|
|
725
|
+
* * fullCircle: If _true_ (default) returns values on 0..2PI range. If _false_, 0....PI..-PI range.
|
|
726
|
+
* * digits: Rounding to apply
|
|
727
|
+
* @param point Point
|
|
728
|
+
* @param origin Origin. If unspecified, {x:0,y:0} is used
|
|
729
|
+
* @param options Options
|
|
730
|
+
* @returns
|
|
731
|
+
*/
|
|
732
|
+
const fromCartesian = (point, origin, options = {}) => {
|
|
733
|
+
if (typeof point !== `object`) throw new TypeError(`Param 'point' wrong. Expecting a Point, got: ${typeof point}`);
|
|
734
|
+
const fullCircle = options.fullCircle ?? true;
|
|
735
|
+
if (typeof origin === `object`) point = subtract(point, origin);
|
|
736
|
+
let angle = Math.atan2(point.y, point.x);
|
|
737
|
+
if (fullCircle) angle = radiansNormalise(angle);
|
|
738
|
+
let distance = Math.hypot(point.x, point.y);
|
|
739
|
+
if (typeof options.digits === `number`) {
|
|
740
|
+
angle = parseFloat(angle.toFixed(options.digits));
|
|
741
|
+
distance = parseFloat(distance.toFixed(options.digits));
|
|
742
|
+
}
|
|
743
|
+
const polar = {
|
|
744
|
+
...point,
|
|
745
|
+
angleRadian: angle,
|
|
746
|
+
distance
|
|
747
|
+
};
|
|
748
|
+
delete polar.x;
|
|
749
|
+
delete polar.y;
|
|
750
|
+
return Object.freeze(polar);
|
|
751
|
+
};
|
|
752
|
+
/**
|
|
753
|
+
* Converts a polar coordinate to Cartesian
|
|
754
|
+
* @param distance Distance
|
|
755
|
+
* @param angleRadians Angle in radians
|
|
756
|
+
* @param origin Origin, or 0,0 by default.
|
|
757
|
+
* @returns
|
|
758
|
+
*/
|
|
759
|
+
const polarToCartesian = (distance, angleRadians, origin = Empty) => {
|
|
760
|
+
guard$5(origin);
|
|
761
|
+
return Object.freeze({
|
|
762
|
+
x: origin.x + distance * Math.cos(angleRadians),
|
|
763
|
+
y: origin.y + distance * Math.sin(angleRadians)
|
|
764
|
+
});
|
|
765
|
+
};
|
|
766
|
+
/**
|
|
767
|
+
* Returns the angle in radians between `a` and `b`.
|
|
768
|
+
*
|
|
769
|
+
* Eg if `a` is the origin, and `b` is another point,
|
|
770
|
+
* in degrees one would get 0 to -180 when `b` was above `a`.
|
|
771
|
+
* -180 would be `b` in line with `a`.
|
|
772
|
+
* Same for under `a`.
|
|
773
|
+
*
|
|
774
|
+
* Providing a third point `c` gives the interior angle, where `b` is the middle point.
|
|
775
|
+
*
|
|
776
|
+
* See also {@link angleRadianCircle} which returns coordinates on 0..Math.Pi*2
|
|
777
|
+
* range. This avoids negative numbers.
|
|
778
|
+
*
|
|
779
|
+
* @example Calculate angle between a middle of canvas and the cursor
|
|
780
|
+
* ```js
|
|
781
|
+
* const canvasEl = document.querySelector('canvas');
|
|
782
|
+
* const middle = { x: canvasEl.width/2, y: canvasEl.height /2 }
|
|
783
|
+
*
|
|
784
|
+
* canvasEl.addEventListener(`pointermove`, event => {
|
|
785
|
+
* const cursor = {
|
|
786
|
+
* x: event.offsetX,
|
|
787
|
+
* y: event.offsetY
|
|
788
|
+
* }
|
|
789
|
+
* const a = G.Points.angleRadian(middle, cursor);
|
|
790
|
+
*});
|
|
791
|
+
* ```
|
|
792
|
+
* @param a
|
|
793
|
+
* @param b
|
|
794
|
+
* @param c
|
|
795
|
+
* @returns
|
|
796
|
+
*/
|
|
797
|
+
const angleRadian = (a, b, c) => {
|
|
798
|
+
guard$5(a, `a`);
|
|
799
|
+
if (b === void 0) return Math.atan2(a.y, a.x);
|
|
800
|
+
guard$5(b, `b`);
|
|
801
|
+
if (c === void 0) return Math.atan2(b.y - a.y, b.x - a.x);
|
|
802
|
+
guard$5(c, `c`);
|
|
803
|
+
return Math.atan2(b.y - a.y, b.x - a.x) - Math.atan2(c.y - a.y, c.x - a.x);
|
|
804
|
+
};
|
|
805
|
+
/**
|
|
806
|
+
* Returns the angle between point(s) using a radian circle system.
|
|
807
|
+
* ```
|
|
808
|
+
* 90deg
|
|
809
|
+
* Pi/2
|
|
810
|
+
* |
|
|
811
|
+
* Pi ---+--- 0
|
|
812
|
+
* 180 |
|
|
813
|
+
* 3PI/2
|
|
814
|
+
* 270deg
|
|
815
|
+
* ```
|
|
816
|
+
* @param a
|
|
817
|
+
* @param b
|
|
818
|
+
* @param c
|
|
819
|
+
* @returns
|
|
820
|
+
*/
|
|
821
|
+
const angleRadianCircle = (a, b, c) => {
|
|
822
|
+
const angle = angleRadian(a, b, c);
|
|
823
|
+
if (angle < 0) return angle + piPi;
|
|
824
|
+
return angle;
|
|
825
|
+
};
|
|
826
|
+
/**
|
|
827
|
+
* Return the angle of a wedge, defined by a, b and C points, where 'b'
|
|
828
|
+
* could be thought of as the origin or pivot.
|
|
829
|
+
*
|
|
830
|
+
* @param a
|
|
831
|
+
* @param b
|
|
832
|
+
* @param c
|
|
833
|
+
* @returns
|
|
834
|
+
*/
|
|
835
|
+
const angleRadianThreePoint = (a, b, c) => {
|
|
836
|
+
const ab = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
|
|
837
|
+
const bc = Math.sqrt(Math.pow(b.x - c.x, 2) + Math.pow(b.y - c.y, 2));
|
|
838
|
+
const ac = Math.sqrt(Math.pow(c.x - a.x, 2) + Math.pow(c.y - a.y, 2));
|
|
839
|
+
return Math.acos((bc * bc + ab * ab - ac * ac) / (2 * bc * ab));
|
|
840
|
+
};
|
|
841
|
+
//#endregion
|
|
842
|
+
//#region node_modules/.pnpm/@ixfx+visual@0.56.12/node_modules/@ixfx/visual/dist/colour-C3MQIjFJ.js
|
|
843
|
+
var __defProp = Object.defineProperty;
|
|
844
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
845
|
+
enumerable: true,
|
|
846
|
+
configurable: true,
|
|
847
|
+
writable: true,
|
|
848
|
+
value
|
|
849
|
+
}) : obj[key] = value;
|
|
850
|
+
var __export = (target, all) => {
|
|
851
|
+
for (var name2 in all) __defProp(target, name2, {
|
|
852
|
+
get: all[name2],
|
|
853
|
+
enumerable: true
|
|
854
|
+
});
|
|
855
|
+
};
|
|
856
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
857
|
+
var COLOR_KEYS = {
|
|
858
|
+
hsl: [
|
|
859
|
+
"h",
|
|
860
|
+
"s",
|
|
861
|
+
"l"
|
|
862
|
+
],
|
|
863
|
+
oklab: [
|
|
864
|
+
"l",
|
|
865
|
+
"a",
|
|
866
|
+
"b"
|
|
867
|
+
],
|
|
868
|
+
oklch: [
|
|
869
|
+
"l",
|
|
870
|
+
"c",
|
|
871
|
+
"h"
|
|
872
|
+
],
|
|
873
|
+
rgb: [
|
|
874
|
+
"r",
|
|
875
|
+
"g",
|
|
876
|
+
"b"
|
|
877
|
+
]
|
|
878
|
+
};
|
|
879
|
+
var COLOR_MODELS = [
|
|
880
|
+
"hsl",
|
|
881
|
+
"oklab",
|
|
882
|
+
"oklch",
|
|
883
|
+
"rgb"
|
|
884
|
+
];
|
|
885
|
+
var DEG2RAD = Math.PI / 180;
|
|
886
|
+
var LAB_TO_LMS = {
|
|
887
|
+
l: [.3963377773761749, .2158037573099136],
|
|
888
|
+
m: [-.1055613458156586, -.0638541728258133],
|
|
889
|
+
s: [-.0894841775298119, -1.2914855480194092]
|
|
890
|
+
};
|
|
891
|
+
var LRGB_TO_LMS = {
|
|
892
|
+
l: [
|
|
893
|
+
.4122214708,
|
|
894
|
+
.5363325363,
|
|
895
|
+
.0514459929
|
|
896
|
+
],
|
|
897
|
+
m: [
|
|
898
|
+
.2119034982,
|
|
899
|
+
.6806995451,
|
|
900
|
+
.1073969566
|
|
901
|
+
],
|
|
902
|
+
s: [
|
|
903
|
+
.0883024619,
|
|
904
|
+
.2817188376,
|
|
905
|
+
.6299787005
|
|
906
|
+
]
|
|
907
|
+
};
|
|
908
|
+
var LSM_TO_LAB = {
|
|
909
|
+
l: [
|
|
910
|
+
.2104542553,
|
|
911
|
+
.793617785,
|
|
912
|
+
.0040720468
|
|
913
|
+
],
|
|
914
|
+
a: [
|
|
915
|
+
1.9779984951,
|
|
916
|
+
2.428592205,
|
|
917
|
+
.4505937099
|
|
918
|
+
],
|
|
919
|
+
b: [
|
|
920
|
+
.0259040371,
|
|
921
|
+
.7827717662,
|
|
922
|
+
.808675766
|
|
923
|
+
]
|
|
924
|
+
};
|
|
925
|
+
var LSM_TO_RGB = {
|
|
926
|
+
r: [
|
|
927
|
+
4.076741636075958,
|
|
928
|
+
-3.307711539258063,
|
|
929
|
+
.2309699031821043
|
|
930
|
+
],
|
|
931
|
+
g: [
|
|
932
|
+
-1.2684379732850315,
|
|
933
|
+
2.609757349287688,
|
|
934
|
+
-.341319376002657
|
|
935
|
+
],
|
|
936
|
+
b: [
|
|
937
|
+
-.0041960761386756,
|
|
938
|
+
-.7034186179359362,
|
|
939
|
+
1.7076146940746117
|
|
940
|
+
]
|
|
941
|
+
};
|
|
942
|
+
var PRECISION = 5;
|
|
943
|
+
var RAD2DEG = 180 / Math.PI;
|
|
944
|
+
var MESSAGES = {
|
|
945
|
+
alpha: "alpha must be a number between 0 and 1",
|
|
946
|
+
alphaAdjustment: "alpha must be a number between -1 and 1",
|
|
947
|
+
amount: "amount must be a number between 0 and 100",
|
|
948
|
+
colorRequired: "color is required",
|
|
949
|
+
degreesRange: "degrees must be a number between -360 and 360",
|
|
950
|
+
hueArgs: "point, chroma and h are required",
|
|
951
|
+
hueRange: "hue must be a number between 0 and 360",
|
|
952
|
+
input: "input is required",
|
|
953
|
+
inputHex: "input is required and must be a hex",
|
|
954
|
+
inputNumber: "input is required and must be a number",
|
|
955
|
+
inputString: "input is required and must be a string",
|
|
956
|
+
invalid: "invalid input",
|
|
957
|
+
invalidColor: "invalid color",
|
|
958
|
+
invalidCSS: "invalid CSS string",
|
|
959
|
+
invalidHex: "invalid hex",
|
|
960
|
+
invalidKey: "invalid key",
|
|
961
|
+
invalidModel: "invalid model",
|
|
962
|
+
invalidRange: "color value out of range",
|
|
963
|
+
left: "left is required and must be a string",
|
|
964
|
+
lightnessRange: "lightness must be a number between 0 and 1",
|
|
965
|
+
options: "invalid options",
|
|
966
|
+
paletteSize: "palette size must be at least 2",
|
|
967
|
+
ratioRange: "ratio must be a number between 0 and 1",
|
|
968
|
+
right: "right is required and must be a string",
|
|
969
|
+
threshold: "threshold must be a number between 0 and 255",
|
|
970
|
+
thresholdNormalized: "threshold must be a number between 0 and 1"
|
|
971
|
+
};
|
|
972
|
+
function invariant(condition, message) {
|
|
973
|
+
if (condition) return;
|
|
974
|
+
const error = !message ? /* @__PURE__ */ new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.") : new Error(message);
|
|
975
|
+
error.name = "colorizr";
|
|
976
|
+
throw error;
|
|
977
|
+
}
|
|
978
|
+
var cssColors = {
|
|
979
|
+
aliceblue: "#f0f8ff",
|
|
980
|
+
antiquewhite: "#faebd7",
|
|
981
|
+
aqua: "#00ffff",
|
|
982
|
+
aquamarine: "#7fffd4",
|
|
983
|
+
azure: "#f0ffff",
|
|
984
|
+
beige: "#f5f5dc",
|
|
985
|
+
bisque: "#ffe4c4",
|
|
986
|
+
black: "#000000",
|
|
987
|
+
blanchedalmond: "#ffebcd",
|
|
988
|
+
blue: "#0000ff",
|
|
989
|
+
blueviolet: "#8a2be2",
|
|
990
|
+
brown: "#a52a2a",
|
|
991
|
+
burlywood: "#deb887",
|
|
992
|
+
cadetblue: "#5f9ea0",
|
|
993
|
+
chartreuse: "#7fff00",
|
|
994
|
+
chocolate: "#d2691e",
|
|
995
|
+
coral: "#ff7f50",
|
|
996
|
+
cornflowerblue: "#6495ed",
|
|
997
|
+
cornsilk: "#fff8dc",
|
|
998
|
+
crimson: "#dc143c",
|
|
999
|
+
cyan: "#00ffff",
|
|
1000
|
+
darkblue: "#00008b",
|
|
1001
|
+
darkcyan: "#008b8b",
|
|
1002
|
+
darkgoldenrod: "#b8860b",
|
|
1003
|
+
darkgray: "#a9a9a9",
|
|
1004
|
+
darkgreen: "#006400",
|
|
1005
|
+
darkkhaki: "#bdb76b",
|
|
1006
|
+
darkmagenta: "#8b008b",
|
|
1007
|
+
darkolivegreen: "#556b2f",
|
|
1008
|
+
darkorange: "#ff8c00",
|
|
1009
|
+
darkorchid: "#9932cc",
|
|
1010
|
+
darkred: "#8b0000",
|
|
1011
|
+
darksalmon: "#e9967a",
|
|
1012
|
+
darkseagreen: "#8fbc8f",
|
|
1013
|
+
darkslateblue: "#483d8b",
|
|
1014
|
+
darkslategray: "#2f4f4f",
|
|
1015
|
+
darkslategrey: "#2f4f4f",
|
|
1016
|
+
darkturquoise: "#00ced1",
|
|
1017
|
+
darkviolet: "#9400d3",
|
|
1018
|
+
deeppink: "#ff1493",
|
|
1019
|
+
deepskyblue: "#00bfff",
|
|
1020
|
+
dimgray: "#696969",
|
|
1021
|
+
dimgrey: "#696969",
|
|
1022
|
+
dodgerblue: "#1e90ff",
|
|
1023
|
+
firebrick: "#b22222",
|
|
1024
|
+
floralwhite: "#fffaf0",
|
|
1025
|
+
forestgreen: "#228b22",
|
|
1026
|
+
fuchsia: "#ff00ff",
|
|
1027
|
+
gainsboro: "#dcdcdc",
|
|
1028
|
+
ghostwhite: "#f8f8ff",
|
|
1029
|
+
gold: "#ffd700",
|
|
1030
|
+
goldenrod: "#daa520",
|
|
1031
|
+
gray: "#808080",
|
|
1032
|
+
grey: "#808080",
|
|
1033
|
+
green: "#008000",
|
|
1034
|
+
greenyellow: "#adff2f",
|
|
1035
|
+
honeydew: "#f0fff0",
|
|
1036
|
+
hotpink: "#ff69b4",
|
|
1037
|
+
indianred: "#cd5c5c",
|
|
1038
|
+
indigo: "#4b0082",
|
|
1039
|
+
ivory: "#fffff0",
|
|
1040
|
+
khaki: "#f0e68c",
|
|
1041
|
+
lavender: "#e6e6fa",
|
|
1042
|
+
lavenderblush: "#fff0f5",
|
|
1043
|
+
lawngreen: "#7cfc00",
|
|
1044
|
+
lemonchiffon: "#fffacd",
|
|
1045
|
+
lightblue: "#add8e6",
|
|
1046
|
+
lightcoral: "#f08080",
|
|
1047
|
+
lightcyan: "#e0ffff",
|
|
1048
|
+
lightgoldenrodyellow: "#fafad2",
|
|
1049
|
+
lightgray: "#d3d3d3",
|
|
1050
|
+
lightgreen: "#90ee90",
|
|
1051
|
+
lightgrey: "#d3d3d3",
|
|
1052
|
+
lightpink: "#ffb6c1",
|
|
1053
|
+
lightsalmon: "#ffa07a",
|
|
1054
|
+
lightseagreen: "#20b2aa",
|
|
1055
|
+
lightskyblue: "#87cefa",
|
|
1056
|
+
lightslategray: "#778899",
|
|
1057
|
+
lightslategrey: "#778899",
|
|
1058
|
+
lightsteelblue: "#b0c4de",
|
|
1059
|
+
lightyellow: "#ffffe0",
|
|
1060
|
+
lime: "#00ff00",
|
|
1061
|
+
limegreen: "#32cd32",
|
|
1062
|
+
linen: "#faf0e6",
|
|
1063
|
+
magenta: "#ff00ff",
|
|
1064
|
+
maroon: "#800000",
|
|
1065
|
+
mediumaquamarine: "#66cdaa",
|
|
1066
|
+
mediumblue: "#0000cd",
|
|
1067
|
+
mediumorchid: "#ba55d3",
|
|
1068
|
+
mediumpurple: "#9370db",
|
|
1069
|
+
mediumseagreen: "#3cb371",
|
|
1070
|
+
mediumslateblue: "#7b68ee",
|
|
1071
|
+
mediumspringgreen: "#00fa9a",
|
|
1072
|
+
mediumturquoise: "#48d1cc",
|
|
1073
|
+
mediumvioletred: "#c71585",
|
|
1074
|
+
midnightblue: "#191970",
|
|
1075
|
+
mintcream: "#f5fffa",
|
|
1076
|
+
mistyrose: "#ffe4e1",
|
|
1077
|
+
moccasin: "#ffe4b5",
|
|
1078
|
+
navajowhite: "#ffdead",
|
|
1079
|
+
navy: "#000080",
|
|
1080
|
+
oldlace: "#fdf5e6",
|
|
1081
|
+
olive: "#808000",
|
|
1082
|
+
olivedrab: "#6b8e23",
|
|
1083
|
+
orange: "#ffa500",
|
|
1084
|
+
orangered: "#ff4500",
|
|
1085
|
+
orchid: "#da70d6",
|
|
1086
|
+
palegoldenrod: "#eee8aa",
|
|
1087
|
+
palegreen: "#98fb98",
|
|
1088
|
+
paleturquoise: "#afeeee",
|
|
1089
|
+
palevioletred: "#db7093",
|
|
1090
|
+
papayawhip: "#ffefd5",
|
|
1091
|
+
peachpuff: "#ffdab9",
|
|
1092
|
+
peru: "#cd853f",
|
|
1093
|
+
pink: "#ffc0cb",
|
|
1094
|
+
plum: "#dda0dd",
|
|
1095
|
+
powderblue: "#b0e0e6",
|
|
1096
|
+
purple: "#800080",
|
|
1097
|
+
rebeccapurple: "#663399",
|
|
1098
|
+
red: "#ff0000",
|
|
1099
|
+
rosybrown: "#bc8f8f",
|
|
1100
|
+
royalblue: "#4169e1",
|
|
1101
|
+
saddlebrown: "#8b4513",
|
|
1102
|
+
salmon: "#fa8072",
|
|
1103
|
+
sandybrown: "#f4a460",
|
|
1104
|
+
seagreen: "#2e8b57",
|
|
1105
|
+
seashell: "#fff5ee",
|
|
1106
|
+
sienna: "#a0522d",
|
|
1107
|
+
silver: "#c0c0c0",
|
|
1108
|
+
skyblue: "#87ceeb",
|
|
1109
|
+
slateblue: "#6a5acd",
|
|
1110
|
+
slategray: "#708090",
|
|
1111
|
+
slategrey: "#708090",
|
|
1112
|
+
snow: "#fffafa",
|
|
1113
|
+
springgreen: "#00ff7f",
|
|
1114
|
+
steelblue: "#4682b4",
|
|
1115
|
+
tan: "#d2b48c",
|
|
1116
|
+
teal: "#008080",
|
|
1117
|
+
thistle: "#d8bfd8",
|
|
1118
|
+
tomato: "#ff6347",
|
|
1119
|
+
turquoise: "#40e0d0",
|
|
1120
|
+
violet: "#ee82ee",
|
|
1121
|
+
wheat: "#f5deb3",
|
|
1122
|
+
white: "#ffffff",
|
|
1123
|
+
whitesmoke: "#f5f5f5",
|
|
1124
|
+
yellow: "#ffff00",
|
|
1125
|
+
yellowgreen: "#9acd32"
|
|
1126
|
+
};
|
|
1127
|
+
var hexRegex = /^#(?:[\da-f]{3,4}|[\da-f]{6,8})$/i;
|
|
1128
|
+
function hasValidMatches(input) {
|
|
1129
|
+
return Array.isArray(input) && input.length === 6;
|
|
1130
|
+
}
|
|
1131
|
+
function isHex(input) {
|
|
1132
|
+
if (!isString(input)) return false;
|
|
1133
|
+
return hexRegex.test(input);
|
|
1134
|
+
}
|
|
1135
|
+
function isHSL(input) {
|
|
1136
|
+
if (!isPlainObject(input)) return false;
|
|
1137
|
+
const entries = Object.entries(input);
|
|
1138
|
+
return !!entries.length && entries.every(([key, value]) => {
|
|
1139
|
+
if (key === "h") return value >= 0 && value <= 360;
|
|
1140
|
+
if (key === "alpha") return value >= 0 && value <= 1;
|
|
1141
|
+
return COLOR_KEYS.hsl.includes(key) && value >= 0 && value <= 100;
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
function isLAB(input) {
|
|
1145
|
+
if (!isPlainObject(input)) return false;
|
|
1146
|
+
const entries = Object.entries(input);
|
|
1147
|
+
return !!entries.length && entries.every(([key, value]) => {
|
|
1148
|
+
if (key === "l") return value >= 0 && value <= 100;
|
|
1149
|
+
if (key === "alpha") return value >= 0 && value <= 1;
|
|
1150
|
+
return COLOR_KEYS.oklab.includes(key) && value >= -1 && value <= 1;
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
function isLCH(input) {
|
|
1154
|
+
if (!isPlainObject(input)) return false;
|
|
1155
|
+
const entries = Object.entries(input);
|
|
1156
|
+
return !!entries.length && entries.every(([key, value]) => {
|
|
1157
|
+
if (key === "l") return value >= 0 && value <= 100;
|
|
1158
|
+
if (key === "alpha") return value >= 0 && value <= 1;
|
|
1159
|
+
return COLOR_KEYS.oklch.includes(key) && value >= 0 && value <= (key === "h" ? 360 : 1);
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
function isNamedColor(input) {
|
|
1163
|
+
return isString(input) && Object.keys(cssColors).includes(input.toLowerCase());
|
|
1164
|
+
}
|
|
1165
|
+
function isNumber(input) {
|
|
1166
|
+
return typeof input === "number" && !Number.isNaN(input);
|
|
1167
|
+
}
|
|
1168
|
+
function isNumberInRange(input, min, max) {
|
|
1169
|
+
return isNumber(input) && input >= min && input <= max;
|
|
1170
|
+
}
|
|
1171
|
+
function isPlainObject(input) {
|
|
1172
|
+
if (!input) return false;
|
|
1173
|
+
const { toString } = Object.prototype;
|
|
1174
|
+
const prototype = Object.getPrototypeOf(input);
|
|
1175
|
+
return toString.call(input) === "[object Object]" && (prototype === null || prototype === Object.getPrototypeOf({}));
|
|
1176
|
+
}
|
|
1177
|
+
function isRGB(input) {
|
|
1178
|
+
if (!isPlainObject(input)) return false;
|
|
1179
|
+
const entries = Object.entries(input);
|
|
1180
|
+
return !!entries.length && entries.every(([key, value]) => {
|
|
1181
|
+
if (key === "alpha") return value >= 0 && value <= 1;
|
|
1182
|
+
return COLOR_KEYS.rgb.includes(key) && value >= 0 && value <= 255;
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
function isString(input, validate = true) {
|
|
1186
|
+
const isValid = typeof input === "string";
|
|
1187
|
+
if (validate) return isValid && !!input.trim().length;
|
|
1188
|
+
return isValid;
|
|
1189
|
+
}
|
|
1190
|
+
function isValidColorModel(input) {
|
|
1191
|
+
return isHSL(input) || isRGB(input) || isLAB(input) || isLCH(input);
|
|
1192
|
+
}
|
|
1193
|
+
function formatHex(input) {
|
|
1194
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1195
|
+
let color = input.replace("#", "");
|
|
1196
|
+
if (color.length === 3 || color.length === 4) {
|
|
1197
|
+
const values = [...color];
|
|
1198
|
+
color = "";
|
|
1199
|
+
values.forEach((d) => {
|
|
1200
|
+
color += `${d}${d}`;
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
const hex = `#${color}`;
|
|
1204
|
+
invariant(isHex(hex), MESSAGES.invalidHex);
|
|
1205
|
+
return hex;
|
|
1206
|
+
}
|
|
1207
|
+
function addAlpha(input, alpha) {
|
|
1208
|
+
invariant(isValidColorModel(input), MESSAGES.invalid);
|
|
1209
|
+
let value = alpha;
|
|
1210
|
+
if (value === void 0) return input;
|
|
1211
|
+
if (value > 1) value /= 100;
|
|
1212
|
+
if (value === 1) return input;
|
|
1213
|
+
return {
|
|
1214
|
+
...input,
|
|
1215
|
+
alpha: value
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
function clamp$1(value, min = 0, max = 100) {
|
|
1219
|
+
return Math.min(Math.max(value, min), max);
|
|
1220
|
+
}
|
|
1221
|
+
function constrainDegrees(input, amount) {
|
|
1222
|
+
invariant(isNumber(input), MESSAGES.inputNumber);
|
|
1223
|
+
let value = input + amount;
|
|
1224
|
+
if (value > 360) value %= 360;
|
|
1225
|
+
if (value < 0) value += 360;
|
|
1226
|
+
return Math.abs(value);
|
|
1227
|
+
}
|
|
1228
|
+
function extractAlpha(input) {
|
|
1229
|
+
if (Array.isArray(input)) return;
|
|
1230
|
+
return input.alpha;
|
|
1231
|
+
}
|
|
1232
|
+
function limit(input, model, key) {
|
|
1233
|
+
invariant(isNumber(input), MESSAGES.inputNumber);
|
|
1234
|
+
invariant(COLOR_MODELS.includes(model), `${MESSAGES.invalidModel}${model ? `: ${model}` : ""}`);
|
|
1235
|
+
invariant(COLOR_KEYS[model].includes(key), `${MESSAGES.invalidKey}${key ? `: ${key}` : ""}`);
|
|
1236
|
+
switch (model) {
|
|
1237
|
+
case "hsl":
|
|
1238
|
+
invariant(COLOR_KEYS.hsl.includes(key), MESSAGES.invalidKey);
|
|
1239
|
+
if (["l", "s"].includes(key)) return clamp$1(input);
|
|
1240
|
+
return clamp$1(input, 0, 360);
|
|
1241
|
+
case "rgb":
|
|
1242
|
+
invariant(COLOR_KEYS.rgb.includes(key), MESSAGES.invalidKey);
|
|
1243
|
+
return clamp$1(input, 0, 255);
|
|
1244
|
+
default: throw new Error("Invalid inputs");
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
function parseInput(input, model) {
|
|
1248
|
+
const keys = COLOR_KEYS[model];
|
|
1249
|
+
const validator = {
|
|
1250
|
+
hsl: isHSL,
|
|
1251
|
+
oklab: isLAB,
|
|
1252
|
+
oklch: isLCH,
|
|
1253
|
+
rgb: isRGB
|
|
1254
|
+
};
|
|
1255
|
+
invariant(isPlainObject(input) || Array.isArray(input), MESSAGES.invalid);
|
|
1256
|
+
const value = Array.isArray(input) ? {
|
|
1257
|
+
[keys[0]]: input[0],
|
|
1258
|
+
[keys[1]]: input[1],
|
|
1259
|
+
[keys[2]]: input[2]
|
|
1260
|
+
} : input;
|
|
1261
|
+
invariant(validator[model](value), `${MESSAGES.invalidColor}: ${model}`);
|
|
1262
|
+
return value;
|
|
1263
|
+
}
|
|
1264
|
+
function restrictValues(input, precision = PRECISION, forcePrecision = true) {
|
|
1265
|
+
const output = new Map(Object.entries(input));
|
|
1266
|
+
for (const [key, value] of output.entries()) output.set(key, round$1(value, precision, forcePrecision));
|
|
1267
|
+
return Object.fromEntries(output);
|
|
1268
|
+
}
|
|
1269
|
+
function round$1(input, precision = 2, forcePrecision = true) {
|
|
1270
|
+
if (!isNumber(input) || input === 0) return 0;
|
|
1271
|
+
if (forcePrecision) {
|
|
1272
|
+
const factor2 = 10 ** precision;
|
|
1273
|
+
return Math.round(input * factor2) / factor2;
|
|
1274
|
+
}
|
|
1275
|
+
let digits = Math.abs(Math.ceil(Math.log(Math.abs(input)) / Math.LN10));
|
|
1276
|
+
if (digits === 0) digits = 2;
|
|
1277
|
+
else if (digits > precision) digits = precision;
|
|
1278
|
+
let exponent = precision - (digits < 0 ? 0 : digits);
|
|
1279
|
+
if (exponent <= 1 && precision > 1) exponent = 2;
|
|
1280
|
+
else if (exponent > precision || exponent === 0) exponent = precision;
|
|
1281
|
+
const factor = 10 ** exponent;
|
|
1282
|
+
return Math.round(input * factor) / factor;
|
|
1283
|
+
}
|
|
1284
|
+
function addAlphaToHex(input, alpha) {
|
|
1285
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1286
|
+
invariant(isNumberInRange(alpha, 0, 1), MESSAGES.alpha);
|
|
1287
|
+
if (alpha >= 1) return removeAlphaFromHex(input);
|
|
1288
|
+
return `${removeAlphaFromHex(input)}${convertAlphaToHex(alpha)}`;
|
|
1289
|
+
}
|
|
1290
|
+
function convertAlphaToHex(input) {
|
|
1291
|
+
invariant(isNumber(input), MESSAGES.inputNumber);
|
|
1292
|
+
let alpha = input;
|
|
1293
|
+
if (input > 1) alpha /= 100;
|
|
1294
|
+
return Math.round(alpha * 255).toString(16).padStart(2, "0");
|
|
1295
|
+
}
|
|
1296
|
+
function extractAlphaFromHex(input) {
|
|
1297
|
+
invariant(isHex(input), MESSAGES.inputString);
|
|
1298
|
+
const alpha = input.substring(7, 9);
|
|
1299
|
+
if (!alpha) return 1;
|
|
1300
|
+
return round$1(parseInt(alpha, 16) / 255);
|
|
1301
|
+
}
|
|
1302
|
+
function removeAlphaFromHex(input) {
|
|
1303
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1304
|
+
if (input.length === 5) return input.substring(0, 4);
|
|
1305
|
+
return input.substring(0, 7);
|
|
1306
|
+
}
|
|
1307
|
+
function hex2rgb(input) {
|
|
1308
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1309
|
+
const hex = formatHex(input).slice(1);
|
|
1310
|
+
const alpha = extractAlphaFromHex(input);
|
|
1311
|
+
return addAlpha({
|
|
1312
|
+
r: parseInt(hex.charAt(0) + hex.charAt(1), 16),
|
|
1313
|
+
g: parseInt(hex.charAt(2) + hex.charAt(3), 16),
|
|
1314
|
+
b: parseInt(hex.charAt(4) + hex.charAt(5), 16)
|
|
1315
|
+
}, alpha);
|
|
1316
|
+
}
|
|
1317
|
+
var converters_exports = {};
|
|
1318
|
+
__export(converters_exports, {
|
|
1319
|
+
hex2hsl: () => hex2hsl,
|
|
1320
|
+
hex2oklab: () => hex2oklab,
|
|
1321
|
+
hex2oklch: () => hex2oklch,
|
|
1322
|
+
hex2rgb: () => hex2rgb,
|
|
1323
|
+
hsl2hex: () => hsl2hex,
|
|
1324
|
+
hsl2oklab: () => hsl2oklab,
|
|
1325
|
+
hsl2oklch: () => hsl2oklch,
|
|
1326
|
+
hsl2rgb: () => hsl2rgb,
|
|
1327
|
+
oklab2hex: () => oklab2hex,
|
|
1328
|
+
oklab2hsl: () => oklab2hsl,
|
|
1329
|
+
oklab2oklch: () => oklab2oklch,
|
|
1330
|
+
oklab2rgb: () => oklab2rgb,
|
|
1331
|
+
oklch2hex: () => oklch2hex,
|
|
1332
|
+
oklch2hsl: () => oklch2hsl,
|
|
1333
|
+
oklch2oklab: () => oklch2oklab,
|
|
1334
|
+
oklch2rgb: () => oklch2rgb,
|
|
1335
|
+
rgb2hex: () => rgb2hex,
|
|
1336
|
+
rgb2hsl: () => rgb2hsl,
|
|
1337
|
+
rgb2oklab: () => rgb2oklab,
|
|
1338
|
+
rgb2oklch: () => rgb2oklch
|
|
1339
|
+
});
|
|
1340
|
+
function rgb2hsl(input) {
|
|
1341
|
+
const value = parseInput(input, "rgb");
|
|
1342
|
+
const alpha = extractAlpha(input);
|
|
1343
|
+
const rLimit = limit(value.r, "rgb", "r") / 255;
|
|
1344
|
+
const gLimit = limit(value.g, "rgb", "g") / 255;
|
|
1345
|
+
const bLimit = limit(value.b, "rgb", "b") / 255;
|
|
1346
|
+
const min = Math.min(rLimit, gLimit, bLimit);
|
|
1347
|
+
const max = Math.max(rLimit, gLimit, bLimit);
|
|
1348
|
+
const delta = max - min;
|
|
1349
|
+
let h = 0;
|
|
1350
|
+
let s;
|
|
1351
|
+
const l = (max + min) / 2;
|
|
1352
|
+
let rate;
|
|
1353
|
+
switch (max) {
|
|
1354
|
+
case rLimit:
|
|
1355
|
+
rate = !delta ? 0 : (gLimit - bLimit) / delta;
|
|
1356
|
+
h = 60 * rate;
|
|
1357
|
+
break;
|
|
1358
|
+
case gLimit:
|
|
1359
|
+
rate = (bLimit - rLimit) / delta;
|
|
1360
|
+
h = 60 * rate + 120;
|
|
1361
|
+
break;
|
|
1362
|
+
case bLimit:
|
|
1363
|
+
rate = (rLimit - gLimit) / delta;
|
|
1364
|
+
h = 60 * rate + 240;
|
|
1365
|
+
break;
|
|
1366
|
+
default: break;
|
|
1367
|
+
}
|
|
1368
|
+
if (h < 0) h = 360 + h;
|
|
1369
|
+
if (min === max) s = 0;
|
|
1370
|
+
else s = l < .5 ? delta / (2 * l) : delta / (2 - 2 * l);
|
|
1371
|
+
return addAlpha({
|
|
1372
|
+
h: Math.abs(+(h % 360).toFixed(2)),
|
|
1373
|
+
s: +(s * 100).toFixed(2),
|
|
1374
|
+
l: +(l * 100).toFixed(2)
|
|
1375
|
+
}, alpha);
|
|
1376
|
+
}
|
|
1377
|
+
function hex2hsl(input) {
|
|
1378
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1379
|
+
const alpha = extractAlphaFromHex(input);
|
|
1380
|
+
return addAlpha(rgb2hsl(hex2rgb(input)), alpha);
|
|
1381
|
+
}
|
|
1382
|
+
var { cbrt, sign } = Math;
|
|
1383
|
+
function rgb2lrgb(input) {
|
|
1384
|
+
const abs2 = Math.abs(input);
|
|
1385
|
+
if (abs2 < .04045) return input / 12.92;
|
|
1386
|
+
return (sign(input) || 1) * ((abs2 + .055) / 1.055) ** 2.4;
|
|
1387
|
+
}
|
|
1388
|
+
function rgb2oklab(input, precision = PRECISION) {
|
|
1389
|
+
const value = parseInput(input, "rgb");
|
|
1390
|
+
const alpha = extractAlpha(input);
|
|
1391
|
+
const [lr, lg, lb] = [
|
|
1392
|
+
rgb2lrgb(value.r / 255),
|
|
1393
|
+
rgb2lrgb(value.g / 255),
|
|
1394
|
+
rgb2lrgb(value.b / 255)
|
|
1395
|
+
];
|
|
1396
|
+
const l = cbrt(LRGB_TO_LMS.l[0] * lr + LRGB_TO_LMS.l[1] * lg + LRGB_TO_LMS.l[2] * lb);
|
|
1397
|
+
const m = cbrt(LRGB_TO_LMS.m[0] * lr + LRGB_TO_LMS.m[1] * lg + LRGB_TO_LMS.m[2] * lb);
|
|
1398
|
+
const s = cbrt(LRGB_TO_LMS.s[0] * lr + LRGB_TO_LMS.s[1] * lg + LRGB_TO_LMS.s[2] * lb);
|
|
1399
|
+
return addAlpha(restrictValues({
|
|
1400
|
+
l: LSM_TO_LAB.l[0] * l + LSM_TO_LAB.l[1] * m - LSM_TO_LAB.l[2] * s,
|
|
1401
|
+
a: LSM_TO_LAB.a[0] * l - LSM_TO_LAB.a[1] * m + LSM_TO_LAB.a[2] * s,
|
|
1402
|
+
b: LSM_TO_LAB.b[0] * l + LSM_TO_LAB.b[1] * m - LSM_TO_LAB.b[2] * s
|
|
1403
|
+
}, precision), alpha);
|
|
1404
|
+
}
|
|
1405
|
+
function hex2oklab(input, precision) {
|
|
1406
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1407
|
+
const alpha = extractAlphaFromHex(input);
|
|
1408
|
+
return addAlpha(rgb2oklab(hex2rgb(input), precision), alpha);
|
|
1409
|
+
}
|
|
1410
|
+
var { atan2, sqrt } = Math;
|
|
1411
|
+
function oklab2oklch(input, precision) {
|
|
1412
|
+
const { l, a, b } = restrictValues(parseInput(input, "oklab"));
|
|
1413
|
+
const alpha = extractAlpha(input);
|
|
1414
|
+
const c = sqrt(a ** 2 + b ** 2);
|
|
1415
|
+
let h = (atan2(b, a) * RAD2DEG + 360) % 360;
|
|
1416
|
+
if (round$1(c * 1e4) === 0) h = 0;
|
|
1417
|
+
return addAlpha(restrictValues({
|
|
1418
|
+
l,
|
|
1419
|
+
c,
|
|
1420
|
+
h
|
|
1421
|
+
}, precision), alpha);
|
|
1422
|
+
}
|
|
1423
|
+
function rgb2oklch(input, precision) {
|
|
1424
|
+
const value = parseInput(input, "rgb");
|
|
1425
|
+
const alpha = extractAlpha(input);
|
|
1426
|
+
return addAlpha(oklab2oklch(rgb2oklab(value, precision), precision), alpha);
|
|
1427
|
+
}
|
|
1428
|
+
function hex2oklch(input, precision) {
|
|
1429
|
+
invariant(isHex(input), MESSAGES.inputHex);
|
|
1430
|
+
const alpha = extractAlphaFromHex(input);
|
|
1431
|
+
return addAlpha(rgb2oklch(hex2rgb(input), precision), alpha);
|
|
1432
|
+
}
|
|
1433
|
+
function hue2rgb(point, chroma2, h) {
|
|
1434
|
+
invariant(isNumber(point) && isNumber(chroma2) && isNumber(h), MESSAGES.hueArgs);
|
|
1435
|
+
let hue = h;
|
|
1436
|
+
if (hue < 0) hue += 1;
|
|
1437
|
+
if (hue > 1) hue -= 1;
|
|
1438
|
+
if (hue < 1 / 6) return round$1(point + (chroma2 - point) * 6 * hue, 4);
|
|
1439
|
+
if (hue < 1 / 2) return round$1(chroma2, 4);
|
|
1440
|
+
if (hue < 2 / 3) return round$1(point + (chroma2 - point) * (2 / 3 - hue) * 6, 4);
|
|
1441
|
+
return round$1(point, 4);
|
|
1442
|
+
}
|
|
1443
|
+
function hsl2rgb(input) {
|
|
1444
|
+
const value = parseInput(input, "hsl");
|
|
1445
|
+
const alpha = extractAlpha(input);
|
|
1446
|
+
const h = round$1(value.h) / 360;
|
|
1447
|
+
const s = round$1(value.s) / 100;
|
|
1448
|
+
const l = round$1(value.l) / 100;
|
|
1449
|
+
let r;
|
|
1450
|
+
let g;
|
|
1451
|
+
let b;
|
|
1452
|
+
let point;
|
|
1453
|
+
let chroma2;
|
|
1454
|
+
if (s === 0) {
|
|
1455
|
+
r = l;
|
|
1456
|
+
g = l;
|
|
1457
|
+
b = l;
|
|
1458
|
+
} else {
|
|
1459
|
+
chroma2 = l < .5 ? l * (1 + s) : l + s - l * s;
|
|
1460
|
+
point = 2 * l - chroma2;
|
|
1461
|
+
r = hue2rgb(point, chroma2, h + 1 / 3);
|
|
1462
|
+
g = hue2rgb(point, chroma2, h);
|
|
1463
|
+
b = hue2rgb(point, chroma2, h - 1 / 3);
|
|
1464
|
+
}
|
|
1465
|
+
return addAlpha({
|
|
1466
|
+
r: Math.round(r * 255),
|
|
1467
|
+
g: Math.round(g * 255),
|
|
1468
|
+
b: Math.round(b * 255)
|
|
1469
|
+
}, alpha);
|
|
1470
|
+
}
|
|
1471
|
+
function rgb2hex(input) {
|
|
1472
|
+
const rgb = parseInput(input, "rgb");
|
|
1473
|
+
const alpha = extractAlpha(input);
|
|
1474
|
+
const hex = `#${[
|
|
1475
|
+
rgb.r,
|
|
1476
|
+
rgb.g,
|
|
1477
|
+
rgb.b
|
|
1478
|
+
].map((d) => `0${Math.floor(d).toString(16)}`.slice(-2)).join("")}`;
|
|
1479
|
+
return alpha !== void 0 && alpha < 1 ? addAlphaToHex(hex, alpha) : hex;
|
|
1480
|
+
}
|
|
1481
|
+
function hsl2hex(input) {
|
|
1482
|
+
const value = parseInput(input, "hsl");
|
|
1483
|
+
const alpha = extractAlpha(input);
|
|
1484
|
+
const hex = rgb2hex(hsl2rgb(value));
|
|
1485
|
+
return alpha !== void 0 && alpha < 1 ? addAlphaToHex(hex, alpha) : hex;
|
|
1486
|
+
}
|
|
1487
|
+
function hsl2oklab(input, precision) {
|
|
1488
|
+
const value = parseInput(input, "hsl");
|
|
1489
|
+
const alpha = extractAlpha(input);
|
|
1490
|
+
return addAlpha(rgb2oklab(hsl2rgb(value), precision), alpha);
|
|
1491
|
+
}
|
|
1492
|
+
function hsl2oklch(input, precision) {
|
|
1493
|
+
const value = parseInput(input, "hsl");
|
|
1494
|
+
const alpha = extractAlpha(input);
|
|
1495
|
+
return addAlpha(rgb2oklch(hsl2rgb(value), precision), alpha);
|
|
1496
|
+
}
|
|
1497
|
+
var { abs } = Math;
|
|
1498
|
+
function lrgb2rgb(input) {
|
|
1499
|
+
const absoluteNumber = abs(input);
|
|
1500
|
+
const sign2 = input < 0 ? -1 : 1;
|
|
1501
|
+
if (absoluteNumber > .0031308) return sign2 * (absoluteNumber ** (1 / 2.4) * 1.055 - .055);
|
|
1502
|
+
return input * 12.92;
|
|
1503
|
+
}
|
|
1504
|
+
function oklab2rgb(input, precision = 0) {
|
|
1505
|
+
const { l: L, a: A, b: B } = parseInput(input, "oklab");
|
|
1506
|
+
const alpha = extractAlpha(input);
|
|
1507
|
+
const l = (L + LAB_TO_LMS.l[0] * A + LAB_TO_LMS.l[1] * B) ** 3;
|
|
1508
|
+
const m = (L + LAB_TO_LMS.m[0] * A + LAB_TO_LMS.m[1] * B) ** 3;
|
|
1509
|
+
const s = (L + LAB_TO_LMS.s[0] * A + LAB_TO_LMS.s[1] * B) ** 3;
|
|
1510
|
+
const r = 255 * lrgb2rgb(LSM_TO_RGB.r[0] * l + LSM_TO_RGB.r[1] * m + LSM_TO_RGB.r[2] * s);
|
|
1511
|
+
const g = 255 * lrgb2rgb(LSM_TO_RGB.g[0] * l + LSM_TO_RGB.g[1] * m + LSM_TO_RGB.g[2] * s);
|
|
1512
|
+
const b = 255 * lrgb2rgb(LSM_TO_RGB.b[0] * l + LSM_TO_RGB.b[1] * m + LSM_TO_RGB.b[2] * s);
|
|
1513
|
+
return addAlpha({
|
|
1514
|
+
r: clamp$1(round$1(r, precision), 0, 255),
|
|
1515
|
+
g: clamp$1(round$1(g, precision), 0, 255),
|
|
1516
|
+
b: clamp$1(round$1(b, precision), 0, 255)
|
|
1517
|
+
}, alpha);
|
|
1518
|
+
}
|
|
1519
|
+
function oklab2hex(input) {
|
|
1520
|
+
const value = parseInput(input, "oklab");
|
|
1521
|
+
const alpha = extractAlpha(input);
|
|
1522
|
+
const hex = rgb2hex(oklab2rgb(value));
|
|
1523
|
+
return alpha !== void 0 && alpha < 1 ? addAlphaToHex(hex, alpha) : hex;
|
|
1524
|
+
}
|
|
1525
|
+
function oklab2hsl(input) {
|
|
1526
|
+
const value = parseInput(input, "oklab");
|
|
1527
|
+
const alpha = extractAlpha(input);
|
|
1528
|
+
return addAlpha(rgb2hsl(oklab2rgb(value)), alpha);
|
|
1529
|
+
}
|
|
1530
|
+
var { sin, cos } = Math;
|
|
1531
|
+
function oklch2oklab(input, precision) {
|
|
1532
|
+
let { l, c, h } = parseInput(input, "oklch");
|
|
1533
|
+
const alpha = extractAlpha(input);
|
|
1534
|
+
if (Number.isNaN(h) || h < 0) h = 0;
|
|
1535
|
+
return addAlpha(restrictValues({
|
|
1536
|
+
l,
|
|
1537
|
+
a: c * cos(h * DEG2RAD),
|
|
1538
|
+
b: c * sin(h * DEG2RAD)
|
|
1539
|
+
}, precision), alpha);
|
|
1540
|
+
}
|
|
1541
|
+
function oklch2rgb(input, precision = 0) {
|
|
1542
|
+
const value = parseInput(input, "oklch");
|
|
1543
|
+
const alpha = extractAlpha(input);
|
|
1544
|
+
return addAlpha(oklab2rgb(oklch2oklab(value), precision), alpha);
|
|
1545
|
+
}
|
|
1546
|
+
function oklch2hex(input) {
|
|
1547
|
+
const value = parseInput(input, "oklch");
|
|
1548
|
+
const alpha = extractAlpha(input);
|
|
1549
|
+
const hex = rgb2hex(oklch2rgb(value));
|
|
1550
|
+
return alpha !== void 0 && alpha < 1 ? addAlphaToHex(hex, alpha) : hex;
|
|
1551
|
+
}
|
|
1552
|
+
function oklch2hsl(input) {
|
|
1553
|
+
const value = parseInput(input, "oklch");
|
|
1554
|
+
const alpha = extractAlpha(input);
|
|
1555
|
+
return addAlpha(rgb2hsl(oklch2rgb(value)), alpha);
|
|
1556
|
+
}
|
|
1557
|
+
var MODEL = "(rgb|hsl|oklab|oklch)a?";
|
|
1558
|
+
var SEP = "(?:\\s*[,/]\\s*|\\s+)";
|
|
1559
|
+
var VALUE = "(none|[\\d%.-]+(?:deg|grad|rad|turn)?)";
|
|
1560
|
+
var colorRegex = new RegExp(`${MODEL}\\s*\\(\\s*${VALUE}${SEP}${VALUE}${SEP}${VALUE}(?:${SEP}${VALUE})?\\s*\\)`, "i");
|
|
1561
|
+
function parseAngle(value) {
|
|
1562
|
+
const number_ = parseFloat(value);
|
|
1563
|
+
let result;
|
|
1564
|
+
if (value.endsWith("grad")) result = number_ * .9;
|
|
1565
|
+
else if (value.endsWith("rad")) result = number_ * (180 / Math.PI);
|
|
1566
|
+
else if (value.endsWith("turn")) result = number_ * 360;
|
|
1567
|
+
else result = number_;
|
|
1568
|
+
return Math.round(result * 1e5) / 1e5;
|
|
1569
|
+
}
|
|
1570
|
+
function extractColorParts(input) {
|
|
1571
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1572
|
+
if (isHex(input)) {
|
|
1573
|
+
const keys2 = COLOR_KEYS.rgb;
|
|
1574
|
+
const { r, g, b } = hex2rgb(input);
|
|
1575
|
+
const alpha2 = extractAlphaFromHex(input);
|
|
1576
|
+
return {
|
|
1577
|
+
model: "rgb",
|
|
1578
|
+
[keys2[0]]: r,
|
|
1579
|
+
[keys2[1]]: g,
|
|
1580
|
+
[keys2[2]]: b,
|
|
1581
|
+
alpha: alpha2 < 1 ? alpha2 : void 0
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
const matches = colorRegex.exec(input);
|
|
1585
|
+
invariant(hasValidMatches(matches), MESSAGES.invalidCSS);
|
|
1586
|
+
const model = matches[1];
|
|
1587
|
+
const keys = COLOR_KEYS[model];
|
|
1588
|
+
let alpha = matches[5] ? parseFloat(matches[5]) : 1;
|
|
1589
|
+
if (alpha > 1) alpha /= 100;
|
|
1590
|
+
const parseValue = (value, index) => {
|
|
1591
|
+
if (value === "none") return 0;
|
|
1592
|
+
if (model === "hsl" && index === 0 || model === "oklch" && index === 2) return parseAngle(value);
|
|
1593
|
+
const parsedValue = parseFloat(value);
|
|
1594
|
+
if (!value.includes("%")) return parsedValue;
|
|
1595
|
+
if (model === "oklch") {
|
|
1596
|
+
if (index === 1) return parsedValue * .4 / 100;
|
|
1597
|
+
} else if (model === "oklab") {
|
|
1598
|
+
if (index === 1 || index === 2) return parsedValue * .4 / 100;
|
|
1599
|
+
}
|
|
1600
|
+
return parsedValue;
|
|
1601
|
+
};
|
|
1602
|
+
const values = [
|
|
1603
|
+
parseValue(matches[2], 0),
|
|
1604
|
+
parseValue(matches[3], 1),
|
|
1605
|
+
parseValue(matches[4], 2)
|
|
1606
|
+
];
|
|
1607
|
+
if (model === "oklab") {
|
|
1608
|
+
invariant(values[1] >= -.4 && values[1] <= .4, MESSAGES.invalidRange);
|
|
1609
|
+
invariant(values[2] >= -.4 && values[2] <= .4, MESSAGES.invalidRange);
|
|
1610
|
+
} else if (model === "oklch") invariant(values[1] >= 0 && values[1] <= .4, MESSAGES.invalidRange);
|
|
1611
|
+
return {
|
|
1612
|
+
model,
|
|
1613
|
+
[keys[0]]: values[0],
|
|
1614
|
+
[keys[1]]: values[1],
|
|
1615
|
+
[keys[2]]: values[2],
|
|
1616
|
+
alpha: alpha < 1 ? alpha : void 0
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
var toHslConverters = {
|
|
1620
|
+
oklab: oklab2hsl,
|
|
1621
|
+
oklch: oklch2hsl,
|
|
1622
|
+
rgb: rgb2hsl
|
|
1623
|
+
};
|
|
1624
|
+
var toOklabConverters = {
|
|
1625
|
+
hsl: hsl2oklab,
|
|
1626
|
+
oklch: oklch2oklab,
|
|
1627
|
+
rgb: rgb2oklab
|
|
1628
|
+
};
|
|
1629
|
+
var toOklchConverters = {
|
|
1630
|
+
hsl: hsl2oklch,
|
|
1631
|
+
oklab: oklab2oklch,
|
|
1632
|
+
rgb: rgb2oklch
|
|
1633
|
+
};
|
|
1634
|
+
var toRgbConverters = {
|
|
1635
|
+
hsl: hsl2rgb,
|
|
1636
|
+
oklab: oklab2rgb,
|
|
1637
|
+
oklch: oklch2rgb
|
|
1638
|
+
};
|
|
1639
|
+
var toHexConverters = {
|
|
1640
|
+
hsl: hsl2hex,
|
|
1641
|
+
oklab: oklab2hex,
|
|
1642
|
+
oklch: oklch2hex,
|
|
1643
|
+
rgb: rgb2hex
|
|
1644
|
+
};
|
|
1645
|
+
var fromHexConverters = {
|
|
1646
|
+
hsl: hex2hsl,
|
|
1647
|
+
oklab: hex2oklab,
|
|
1648
|
+
oklch: hex2oklch,
|
|
1649
|
+
rgb: hex2rgb
|
|
1650
|
+
};
|
|
1651
|
+
var converterTables = {
|
|
1652
|
+
hsl: toHslConverters,
|
|
1653
|
+
oklab: toOklabConverters,
|
|
1654
|
+
oklch: toOklchConverters,
|
|
1655
|
+
rgb: toRgbConverters
|
|
1656
|
+
};
|
|
1657
|
+
function convertFromCSS(value, output) {
|
|
1658
|
+
const { alpha, model, ...color } = extractColorParts(value);
|
|
1659
|
+
if (["oklab", "oklch"].includes(model) && color.l > 1) color.l = round$1(color.l / 100, PRECISION);
|
|
1660
|
+
const colorTuple = Object.values(color);
|
|
1661
|
+
if (output === "hex") {
|
|
1662
|
+
const alphaPrefix = alpha ? convertAlphaToHex(alpha) : "";
|
|
1663
|
+
return `${toHexConverters[model](colorTuple)}${alphaPrefix}`;
|
|
1664
|
+
}
|
|
1665
|
+
const converter = converterTables[output]?.[model];
|
|
1666
|
+
return addAlpha(converter ? converter(colorTuple) : color, alpha);
|
|
1667
|
+
}
|
|
1668
|
+
function convertFromHex(value, output) {
|
|
1669
|
+
const alpha = extractAlphaFromHex(value);
|
|
1670
|
+
if (output === "hex") return `${removeAlphaFromHex(value)}${alpha !== 1 ? convertAlphaToHex(alpha) : ""}`;
|
|
1671
|
+
return addAlpha(fromHexConverters[output](value), alpha);
|
|
1672
|
+
}
|
|
1673
|
+
function parseCSS(input, format) {
|
|
1674
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1675
|
+
const value = isNamedColor(input) ? cssColors[input.toLowerCase()] : input;
|
|
1676
|
+
const output = format ?? (isHex(value) ? "hex" : extractColorParts(value).model);
|
|
1677
|
+
if (isHex(value)) return convertFromHex(value, output);
|
|
1678
|
+
return convertFromCSS(value, output);
|
|
1679
|
+
}
|
|
1680
|
+
var mainTRC = 2.4;
|
|
1681
|
+
var normBG = .56;
|
|
1682
|
+
var normTXT = .57;
|
|
1683
|
+
var revBG = .65;
|
|
1684
|
+
var revTXT = .62;
|
|
1685
|
+
var sRco = .2126729;
|
|
1686
|
+
var sGco = .7151522;
|
|
1687
|
+
var sBco = .072175;
|
|
1688
|
+
var blkThreshold = .022;
|
|
1689
|
+
var blkClamp = 1.414;
|
|
1690
|
+
var scaleBoW = 1.14;
|
|
1691
|
+
var scaleWoB = 1.14;
|
|
1692
|
+
var loBoWOffset = .027;
|
|
1693
|
+
var loWoBOffset = .027;
|
|
1694
|
+
var loClip = .1;
|
|
1695
|
+
var deltaYmin = 5e-4;
|
|
1696
|
+
function softClamp(Y) {
|
|
1697
|
+
return Y > blkThreshold ? Y : Y + (blkThreshold - Y) ** blkClamp;
|
|
1698
|
+
}
|
|
1699
|
+
function sRGBtoY(r, g, b) {
|
|
1700
|
+
return sRco * (r / 255) ** mainTRC + sGco * (g / 255) ** mainTRC + sBco * (b / 255) ** mainTRC;
|
|
1701
|
+
}
|
|
1702
|
+
function apcaContrast(background, foreground) {
|
|
1703
|
+
invariant(isString(background), MESSAGES.inputString);
|
|
1704
|
+
invariant(isString(foreground), MESSAGES.inputString);
|
|
1705
|
+
const bg = hex2rgb(parseCSS(background, "hex"));
|
|
1706
|
+
const fg = hex2rgb(parseCSS(foreground, "hex"));
|
|
1707
|
+
const txtY = softClamp(sRGBtoY(fg.r, fg.g, fg.b));
|
|
1708
|
+
const bgY = softClamp(sRGBtoY(bg.r, bg.g, bg.b));
|
|
1709
|
+
if (Math.abs(bgY - txtY) < deltaYmin) return 0;
|
|
1710
|
+
const SAPC = bgY > txtY ? (bgY ** normBG - txtY ** normTXT) * scaleBoW : (bgY ** revBG - txtY ** revTXT) * scaleWoB;
|
|
1711
|
+
if (Math.abs(SAPC) < loClip) return 0;
|
|
1712
|
+
return round$1(SAPC > 0 ? (SAPC - loBoWOffset) * 100 : (SAPC + loWoBOffset) * 100, 5);
|
|
1713
|
+
}
|
|
1714
|
+
function brightnessDifference(left, right, precision = PRECISION) {
|
|
1715
|
+
invariant(isString(left), MESSAGES.left);
|
|
1716
|
+
invariant(isString(right), MESSAGES.right);
|
|
1717
|
+
const RGBLeft = parseCSS(left, "rgb");
|
|
1718
|
+
const RGBRight = parseCSS(right, "rgb");
|
|
1719
|
+
const brightnessLeft = (RGBLeft.r * 299 + RGBLeft.g * 587 + RGBLeft.b * 114) / 1e3;
|
|
1720
|
+
const brightnessRight = (RGBRight.r * 299 + RGBRight.g * 587 + RGBRight.b * 114) / 1e3;
|
|
1721
|
+
return round$1(Math.abs(brightnessRight - brightnessLeft), precision);
|
|
1722
|
+
}
|
|
1723
|
+
function chroma(input) {
|
|
1724
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1725
|
+
const { r, g, b } = parseCSS(input, "rgb");
|
|
1726
|
+
return round$1((Math.max(r, g, b) - Math.min(r, g, b)) / 255, 4);
|
|
1727
|
+
}
|
|
1728
|
+
function colorDifference(left, right) {
|
|
1729
|
+
invariant(isString(left), MESSAGES.left);
|
|
1730
|
+
invariant(isString(right), MESSAGES.right);
|
|
1731
|
+
const RGBLeft = parseCSS(left, "rgb");
|
|
1732
|
+
const RGBRight = parseCSS(right, "rgb");
|
|
1733
|
+
return Math.max(RGBLeft.r, RGBRight.r) - Math.min(RGBLeft.r, RGBRight.r) + (Math.max(RGBLeft.g, RGBRight.g) - Math.min(RGBLeft.g, RGBRight.g)) + (Math.max(RGBLeft.b, RGBRight.b) - Math.min(RGBLeft.b, RGBRight.b));
|
|
1734
|
+
}
|
|
1735
|
+
function luminance(input) {
|
|
1736
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1737
|
+
const { r, g, b } = parseCSS(input, "rgb");
|
|
1738
|
+
const rgb = [
|
|
1739
|
+
r / 255,
|
|
1740
|
+
g / 255,
|
|
1741
|
+
b / 255
|
|
1742
|
+
];
|
|
1743
|
+
for (let index = 0; index < rgb.length; index++) if (rgb[index] <= .04045) rgb[index] /= 12.92;
|
|
1744
|
+
else rgb[index] = ((rgb[index] + .055) / 1.055) ** 2.4;
|
|
1745
|
+
return round$1(.2126 * rgb[0] + .7152 * rgb[1] + .0722 * rgb[2], 4);
|
|
1746
|
+
}
|
|
1747
|
+
function contrast(left, right) {
|
|
1748
|
+
invariant(isString(left), MESSAGES.left);
|
|
1749
|
+
invariant(isString(right), MESSAGES.right);
|
|
1750
|
+
const LuminanceLeft = luminance(left);
|
|
1751
|
+
const LuminanceRight = luminance(right);
|
|
1752
|
+
return round$1(LuminanceLeft >= LuminanceRight ? (LuminanceLeft + .05) / (LuminanceRight + .05) : (LuminanceRight + .05) / (LuminanceLeft + .05));
|
|
1753
|
+
}
|
|
1754
|
+
function compare(left, right) {
|
|
1755
|
+
invariant(isString(left), MESSAGES.left);
|
|
1756
|
+
invariant(isString(right), MESSAGES.right);
|
|
1757
|
+
const colorThreshold = 500;
|
|
1758
|
+
const brightnessThreshold = 125;
|
|
1759
|
+
const colorDifference2 = colorDifference(left, right);
|
|
1760
|
+
const contrast2 = contrast(left, right);
|
|
1761
|
+
const brightnessDifference2 = brightnessDifference(left, right);
|
|
1762
|
+
const isBright = brightnessDifference2 >= brightnessThreshold;
|
|
1763
|
+
const hasEnoughDifference = colorDifference2 >= colorThreshold;
|
|
1764
|
+
let compliant = 0;
|
|
1765
|
+
if (isBright && hasEnoughDifference) compliant = 2;
|
|
1766
|
+
else if (isBright || hasEnoughDifference) compliant = 1;
|
|
1767
|
+
return {
|
|
1768
|
+
brightnessDifference: brightnessDifference2,
|
|
1769
|
+
colorDifference: colorDifference2,
|
|
1770
|
+
compliant,
|
|
1771
|
+
contrast: contrast2,
|
|
1772
|
+
largeAA: contrast2 >= 3,
|
|
1773
|
+
largeAAA: contrast2 >= 4.5,
|
|
1774
|
+
normalAA: contrast2 >= 4.5,
|
|
1775
|
+
normalAAA: contrast2 >= 7
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
function getColorModel(input) {
|
|
1779
|
+
if (isHex(input) || isNamedColor(input)) return "hex";
|
|
1780
|
+
if (isHSL(input)) return "hsl";
|
|
1781
|
+
if (isLAB(input)) return "oklab";
|
|
1782
|
+
if (isLCH(input)) return "oklch";
|
|
1783
|
+
if (isRGB(input)) return "rgb";
|
|
1784
|
+
throw new Error(MESSAGES.invalid);
|
|
1785
|
+
}
|
|
1786
|
+
function getColorValue(input, output) {
|
|
1787
|
+
const value = isNamedColor(input) ? cssColors[input.toLowerCase()] : input;
|
|
1788
|
+
const from = getColorModel(value);
|
|
1789
|
+
if (from === output) return value;
|
|
1790
|
+
const converter = converters_exports[`${from}2${output}`];
|
|
1791
|
+
if (!converter) throw new Error(`Converter not found for ${from} to ${output}`);
|
|
1792
|
+
return converter(value);
|
|
1793
|
+
}
|
|
1794
|
+
function formatCSS(input, options = {}) {
|
|
1795
|
+
invariant(isHex(input) || isValidColorModel(input), MESSAGES.invalid);
|
|
1796
|
+
const { alpha, format = "hex", precision = PRECISION, separator: baseSeparator = " " } = options;
|
|
1797
|
+
const opacity2 = alpha && alpha !== 1 ? `${round$1(alpha * 100)}%` : null;
|
|
1798
|
+
let params = [];
|
|
1799
|
+
let separator = baseSeparator;
|
|
1800
|
+
switch (format) {
|
|
1801
|
+
case "hsl": {
|
|
1802
|
+
const { h, s, l } = getColorValue(input, "hsl");
|
|
1803
|
+
params = [
|
|
1804
|
+
h,
|
|
1805
|
+
`${s}%`,
|
|
1806
|
+
`${l}%`
|
|
1807
|
+
];
|
|
1808
|
+
break;
|
|
1809
|
+
}
|
|
1810
|
+
case "oklab": {
|
|
1811
|
+
separator = " ";
|
|
1812
|
+
const { l, a, b } = restrictValues(getColorValue(input, "oklab"), precision);
|
|
1813
|
+
params = [
|
|
1814
|
+
`${round$1(l * 100, precision)}%`,
|
|
1815
|
+
a,
|
|
1816
|
+
b
|
|
1817
|
+
];
|
|
1818
|
+
break;
|
|
1819
|
+
}
|
|
1820
|
+
case "oklch": {
|
|
1821
|
+
separator = " ";
|
|
1822
|
+
const { l, c, h } = restrictValues(getColorValue(input, "oklch"), precision);
|
|
1823
|
+
params = [
|
|
1824
|
+
`${round$1(l * 100, precision)}%`,
|
|
1825
|
+
c,
|
|
1826
|
+
h
|
|
1827
|
+
];
|
|
1828
|
+
break;
|
|
1829
|
+
}
|
|
1830
|
+
case "rgb": {
|
|
1831
|
+
const { r, g, b } = getColorValue(input, "rgb");
|
|
1832
|
+
params = [
|
|
1833
|
+
r,
|
|
1834
|
+
g,
|
|
1835
|
+
b
|
|
1836
|
+
];
|
|
1837
|
+
break;
|
|
1838
|
+
}
|
|
1839
|
+
default: {
|
|
1840
|
+
const hex = removeAlphaFromHex(getColorValue(input, "hex"));
|
|
1841
|
+
if (alpha && alpha !== 1) return `${hex}${convertAlphaToHex(alpha)}`;
|
|
1842
|
+
return hex;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return `${format}(${params.join(separator)}${opacity2 ? ` / ${opacity2}` : ""})`;
|
|
1846
|
+
}
|
|
1847
|
+
function updater(key, operator, format) {
|
|
1848
|
+
return (input, amount) => {
|
|
1849
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1850
|
+
invariant(isNumberInRange(amount, 0, 100), MESSAGES.amount);
|
|
1851
|
+
const color = parseCSS(input, "hsl");
|
|
1852
|
+
const output = isHex(input) || isNamedColor(input) ? "hex" : extractColorParts(input).model;
|
|
1853
|
+
return formatCSS({
|
|
1854
|
+
...color,
|
|
1855
|
+
[key]: clamp$1(color[key] + (operator === "+" ? amount : -amount), 0, 100)
|
|
1856
|
+
}, { format: format ?? output });
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
function darken(input, amount, format) {
|
|
1860
|
+
return updater("l", "-", format)(input, amount);
|
|
1861
|
+
}
|
|
1862
|
+
function desaturate(input, amount, format) {
|
|
1863
|
+
return updater("s", "-", format)(input, amount);
|
|
1864
|
+
}
|
|
1865
|
+
function grayscale(input, format) {
|
|
1866
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1867
|
+
const output = isHex(input) || isNamedColor(input) ? "hex" : extractColorParts(input).model;
|
|
1868
|
+
const lch = parseCSS(input, "oklch");
|
|
1869
|
+
return formatCSS({
|
|
1870
|
+
...lch,
|
|
1871
|
+
c: 0
|
|
1872
|
+
}, {
|
|
1873
|
+
format: format ?? output,
|
|
1874
|
+
alpha: lch.alpha
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
function rotate(input, degrees, format) {
|
|
1878
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1879
|
+
invariant(isNumberInRange(degrees, -360, 360), MESSAGES.degreesRange);
|
|
1880
|
+
const color = parseCSS(input, "hsl");
|
|
1881
|
+
const output = isHex(input) || isNamedColor(input) ? "hex" : extractColorParts(input).model;
|
|
1882
|
+
return formatCSS({
|
|
1883
|
+
...color,
|
|
1884
|
+
h: constrainDegrees(color.h, degrees)
|
|
1885
|
+
}, { format: format ?? output });
|
|
1886
|
+
}
|
|
1887
|
+
function invert(input) {
|
|
1888
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1889
|
+
const format = isHex(input) || isNamedColor(input) ? "hex" : extractColorParts(input).model;
|
|
1890
|
+
return formatCSS(rotate(parseCSS(input, "hex"), 180), { format });
|
|
1891
|
+
}
|
|
1892
|
+
function lighten(input, amount, format) {
|
|
1893
|
+
return updater("l", "+", format)(input, amount);
|
|
1894
|
+
}
|
|
1895
|
+
function interpolateHue(h1, h2, c1, c2, ratio) {
|
|
1896
|
+
if (c1 < 1e-4) return h2;
|
|
1897
|
+
if (c2 < 1e-4) return h1;
|
|
1898
|
+
let diff = h2 - h1;
|
|
1899
|
+
if (diff > 180) diff -= 360;
|
|
1900
|
+
else if (diff < -180) diff += 360;
|
|
1901
|
+
let result = h1 + diff * ratio;
|
|
1902
|
+
if (result < 0) result += 360;
|
|
1903
|
+
else if (result >= 360) result -= 360;
|
|
1904
|
+
return result;
|
|
1905
|
+
}
|
|
1906
|
+
function mix(color1, color2, ratio = .5, format) {
|
|
1907
|
+
invariant(isString(color1), MESSAGES.inputString);
|
|
1908
|
+
invariant(isString(color2), MESSAGES.inputString);
|
|
1909
|
+
invariant(isNumberInRange(ratio, 0, 1), MESSAGES.ratioRange);
|
|
1910
|
+
const output = isHex(color1) || isNamedColor(color1) ? "hex" : extractColorParts(color1).model;
|
|
1911
|
+
const lch1 = parseCSS(color1, "oklch");
|
|
1912
|
+
const lch2 = parseCSS(color2, "oklch");
|
|
1913
|
+
const l = lch1.l + (lch2.l - lch1.l) * ratio;
|
|
1914
|
+
const c = lch1.c + (lch2.c - lch1.c) * ratio;
|
|
1915
|
+
const h = interpolateHue(lch1.h, lch2.h, lch1.c, lch2.c, ratio);
|
|
1916
|
+
const alpha1 = lch1.alpha ?? 1;
|
|
1917
|
+
const alpha = alpha1 + ((lch2.alpha ?? 1) - alpha1) * ratio;
|
|
1918
|
+
return formatCSS({
|
|
1919
|
+
l,
|
|
1920
|
+
c,
|
|
1921
|
+
h
|
|
1922
|
+
}, {
|
|
1923
|
+
format: format ?? output,
|
|
1924
|
+
alpha: alpha < 1 ? alpha : void 0
|
|
1925
|
+
});
|
|
1926
|
+
}
|
|
1927
|
+
function parseColor(color) {
|
|
1928
|
+
invariant(!!color, MESSAGES.input);
|
|
1929
|
+
const output = {};
|
|
1930
|
+
if (isString(color)) {
|
|
1931
|
+
const { alpha = 1 } = extractColorParts(color);
|
|
1932
|
+
const type = isHex(color) ? "hex" : extractColorParts(color).model;
|
|
1933
|
+
output.hex = addAlphaToHex(parseCSS(color, "hex"), alpha);
|
|
1934
|
+
output.hsl = addAlpha(parseCSS(color, "hsl"), alpha);
|
|
1935
|
+
output.oklab = addAlpha(parseCSS(color, "oklab"), alpha);
|
|
1936
|
+
output.oklch = addAlpha(parseCSS(color, "oklch"), alpha);
|
|
1937
|
+
output.rgb = addAlpha(parseCSS(color, "rgb"), alpha);
|
|
1938
|
+
output.alpha = alpha;
|
|
1939
|
+
output.type = type;
|
|
1940
|
+
} else if (isPlainObject(color)) {
|
|
1941
|
+
const { alpha = 1 } = color;
|
|
1942
|
+
if (isHSL(color)) {
|
|
1943
|
+
output.hsl = {
|
|
1944
|
+
h: limit(color.h, "hsl", "h"),
|
|
1945
|
+
s: limit(color.s, "hsl", "s"),
|
|
1946
|
+
l: limit(color.l, "hsl", "l")
|
|
1947
|
+
};
|
|
1948
|
+
output.rgb = hsl2rgb(output.hsl);
|
|
1949
|
+
output.oklab = hsl2oklab(output.hsl);
|
|
1950
|
+
output.oklch = hsl2oklch(output.hsl);
|
|
1951
|
+
output.type = "hsl";
|
|
1952
|
+
} else if (isLAB(color)) {
|
|
1953
|
+
output.hsl = oklab2hsl(color);
|
|
1954
|
+
output.oklab = color;
|
|
1955
|
+
output.oklch = oklab2oklch(color);
|
|
1956
|
+
output.rgb = oklab2rgb(color);
|
|
1957
|
+
output.type = "oklab";
|
|
1958
|
+
} else if (isLCH(color)) {
|
|
1959
|
+
output.hsl = oklch2hsl(color);
|
|
1960
|
+
output.oklab = oklch2oklab(color);
|
|
1961
|
+
output.oklch = color;
|
|
1962
|
+
output.rgb = oklch2rgb(color);
|
|
1963
|
+
output.type = "oklch";
|
|
1964
|
+
} else if (isRGB(color)) {
|
|
1965
|
+
output.rgb = {
|
|
1966
|
+
r: limit(color.r, "rgb", "r"),
|
|
1967
|
+
g: limit(color.g, "rgb", "g"),
|
|
1968
|
+
b: limit(color.b, "rgb", "b")
|
|
1969
|
+
};
|
|
1970
|
+
output.hsl = rgb2hsl(output.rgb);
|
|
1971
|
+
output.oklab = rgb2oklab(output.rgb);
|
|
1972
|
+
output.oklch = rgb2oklch(output.rgb);
|
|
1973
|
+
output.type = "rgb";
|
|
1974
|
+
} else throw new Error("invalid color");
|
|
1975
|
+
output.hex = addAlphaToHex(hsl2hex(output.hsl), alpha);
|
|
1976
|
+
output.hsl = addAlpha(output.hsl, alpha);
|
|
1977
|
+
output.oklab = addAlpha(output.oklab, alpha);
|
|
1978
|
+
output.oklch = addAlpha(output.oklch, alpha);
|
|
1979
|
+
output.rgb = addAlpha(output.rgb, alpha);
|
|
1980
|
+
output.alpha = alpha;
|
|
1981
|
+
} else throw new Error(MESSAGES.input);
|
|
1982
|
+
return output;
|
|
1983
|
+
}
|
|
1984
|
+
function opacify(input, alpha, format) {
|
|
1985
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1986
|
+
invariant(isNumberInRange(alpha, 0, 1), MESSAGES.alpha);
|
|
1987
|
+
const type = isHex(input) || isNamedColor(input) ? "hex" : extractColorParts(input).model;
|
|
1988
|
+
return formatCSS(parseCSS(input, "rgb"), {
|
|
1989
|
+
format: format ?? type,
|
|
1990
|
+
alpha
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
function opacity(input) {
|
|
1994
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
1995
|
+
if (isHex(input)) return extractAlphaFromHex(input);
|
|
1996
|
+
else if (Object.keys(cssColors).includes(input)) return 1;
|
|
1997
|
+
const { alpha } = extractColorParts(input);
|
|
1998
|
+
if (!alpha) return 1;
|
|
1999
|
+
return alpha;
|
|
2000
|
+
}
|
|
2001
|
+
function pickByContrast(darkContrast, lightContrast, darkColor, lightColor) {
|
|
2002
|
+
return darkContrast >= lightContrast ? darkColor : lightColor;
|
|
2003
|
+
}
|
|
2004
|
+
function readableColor(backgroundColor, options = {}) {
|
|
2005
|
+
const { darkColor = "#000000", lightColor = "#ffffff", method = "yiq", threshold } = options;
|
|
2006
|
+
invariant(isString(backgroundColor), MESSAGES.inputString);
|
|
2007
|
+
switch (method) {
|
|
2008
|
+
case "yiq": {
|
|
2009
|
+
const yiqThreshold = threshold ?? 128;
|
|
2010
|
+
invariant(yiqThreshold >= 0 && yiqThreshold <= 255, MESSAGES.threshold);
|
|
2011
|
+
const { r, g, b } = hex2rgb(parseCSS(backgroundColor, "hex"));
|
|
2012
|
+
return (r * 299 + g * 587 + b * 114) / 1e3 >= yiqThreshold ? darkColor : lightColor;
|
|
2013
|
+
}
|
|
2014
|
+
case "wcag": {
|
|
2015
|
+
const wcagThreshold = threshold ?? .5;
|
|
2016
|
+
invariant(wcagThreshold >= 0 && wcagThreshold <= 1, MESSAGES.thresholdNormalized);
|
|
2017
|
+
return luminance(backgroundColor) >= wcagThreshold ? darkColor : lightColor;
|
|
2018
|
+
}
|
|
2019
|
+
case "contrast": return pickByContrast(contrast(darkColor, backgroundColor), contrast(lightColor, backgroundColor), darkColor, lightColor);
|
|
2020
|
+
case "oklab": {
|
|
2021
|
+
const oklabThreshold = threshold ?? .5;
|
|
2022
|
+
invariant(oklabThreshold >= 0 && oklabThreshold <= 1, MESSAGES.thresholdNormalized);
|
|
2023
|
+
const { l } = hex2oklab(parseCSS(backgroundColor, "hex"));
|
|
2024
|
+
return l >= oklabThreshold ? darkColor : lightColor;
|
|
2025
|
+
}
|
|
2026
|
+
case "apca": return pickByContrast(Math.abs(apcaContrast(backgroundColor, darkColor)), Math.abs(apcaContrast(backgroundColor, lightColor)), darkColor, lightColor);
|
|
2027
|
+
default: throw new Error(`Unknown method: ${method}`);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
function saturate(input, amount, format) {
|
|
2031
|
+
return updater("s", "+", format)(input, amount);
|
|
2032
|
+
}
|
|
2033
|
+
function transparentize(input, alpha, format) {
|
|
2034
|
+
invariant(isString(input), MESSAGES.inputString);
|
|
2035
|
+
invariant(isNumberInRange(alpha, -1, 1), MESSAGES.alphaAdjustment);
|
|
2036
|
+
return formatCSS(parseCSS(input, "oklab"), {
|
|
2037
|
+
format,
|
|
2038
|
+
alpha: round$1(clamp$1(opacity(input) - alpha, 0, 1))
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
var Colorizr = class {
|
|
2042
|
+
constructor(color, options = {}) {
|
|
2043
|
+
/** The alpha/opacity value (0-1). */
|
|
2044
|
+
__publicField(this, "alpha");
|
|
2045
|
+
__publicField(this, "hex");
|
|
2046
|
+
__publicField(this, "hsl");
|
|
2047
|
+
__publicField(this, "oklab");
|
|
2048
|
+
__publicField(this, "oklch");
|
|
2049
|
+
__publicField(this, "rgb");
|
|
2050
|
+
__publicField(this, "type");
|
|
2051
|
+
invariant(!!color, MESSAGES.colorRequired);
|
|
2052
|
+
const { alpha, hex, hsl, oklab, oklch, rgb, type } = parseColor(color);
|
|
2053
|
+
this.hex = hex;
|
|
2054
|
+
this.hsl = hsl;
|
|
2055
|
+
this.oklab = oklab;
|
|
2056
|
+
this.oklch = oklch;
|
|
2057
|
+
this.rgb = rgb;
|
|
2058
|
+
this.alpha = alpha;
|
|
2059
|
+
this.type = options.format ?? type;
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Get CSS string
|
|
2063
|
+
*/
|
|
2064
|
+
get css() {
|
|
2065
|
+
return this.currentColor;
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Get the red value
|
|
2069
|
+
*/
|
|
2070
|
+
get red() {
|
|
2071
|
+
return this.rgb.r;
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Get the green value
|
|
2075
|
+
*/
|
|
2076
|
+
get green() {
|
|
2077
|
+
return this.rgb.g;
|
|
2078
|
+
}
|
|
2079
|
+
/**
|
|
2080
|
+
* Get the blue value
|
|
2081
|
+
*/
|
|
2082
|
+
get blue() {
|
|
2083
|
+
return this.rgb.b;
|
|
2084
|
+
}
|
|
2085
|
+
/**
|
|
2086
|
+
* Get the hue value
|
|
2087
|
+
*/
|
|
2088
|
+
get hue() {
|
|
2089
|
+
return this.hsl.h;
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Get the saturation value
|
|
2093
|
+
*/
|
|
2094
|
+
get saturation() {
|
|
2095
|
+
return this.hsl.s;
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Get the lightness value
|
|
2099
|
+
*/
|
|
2100
|
+
get lightness() {
|
|
2101
|
+
return this.hsl.l;
|
|
2102
|
+
}
|
|
2103
|
+
/**
|
|
2104
|
+
* Get the luminance value
|
|
2105
|
+
*/
|
|
2106
|
+
get luminance() {
|
|
2107
|
+
return luminance(this.currentColor);
|
|
2108
|
+
}
|
|
2109
|
+
/**
|
|
2110
|
+
* Get the chroma value
|
|
2111
|
+
*/
|
|
2112
|
+
get chroma() {
|
|
2113
|
+
return chroma(this.currentColor);
|
|
2114
|
+
}
|
|
2115
|
+
get opacity() {
|
|
2116
|
+
return opacity(this.currentColor);
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Get the most readable color (light or dark) for this color as a background.
|
|
2120
|
+
*/
|
|
2121
|
+
get readableColor() {
|
|
2122
|
+
return readableColor(this.currentColor);
|
|
2123
|
+
}
|
|
2124
|
+
get currentColor() {
|
|
2125
|
+
return formatCSS(this[this.type], {
|
|
2126
|
+
format: this.type,
|
|
2127
|
+
alpha: this.alpha
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Get the brightness difference between this color and another.
|
|
2132
|
+
*
|
|
2133
|
+
* @param input - The color to compare against.
|
|
2134
|
+
* @returns The brightness difference value.
|
|
2135
|
+
*/
|
|
2136
|
+
brightnessDifference(input) {
|
|
2137
|
+
return brightnessDifference(this.currentColor, input);
|
|
2138
|
+
}
|
|
2139
|
+
/**
|
|
2140
|
+
* Get the color difference between this color and another.
|
|
2141
|
+
*
|
|
2142
|
+
* @param input - The color to compare against.
|
|
2143
|
+
* @returns The color difference value.
|
|
2144
|
+
*/
|
|
2145
|
+
colorDifference(input) {
|
|
2146
|
+
return colorDifference(this.currentColor, input);
|
|
2147
|
+
}
|
|
2148
|
+
/**
|
|
2149
|
+
* Test 2 colors for WCAG compliance.
|
|
2150
|
+
*
|
|
2151
|
+
* @param input - The color to compare against.
|
|
2152
|
+
* @returns Analysis object with compliance information.
|
|
2153
|
+
*/
|
|
2154
|
+
compare(input) {
|
|
2155
|
+
return compare(this.currentColor, input);
|
|
2156
|
+
}
|
|
2157
|
+
/**
|
|
2158
|
+
* Get the contrast ratio between this color and another.
|
|
2159
|
+
*
|
|
2160
|
+
* @param input - The color to compare against.
|
|
2161
|
+
* @returns The contrast ratio.
|
|
2162
|
+
*/
|
|
2163
|
+
contrast(input) {
|
|
2164
|
+
return contrast(this.currentColor, input);
|
|
2165
|
+
}
|
|
2166
|
+
/**
|
|
2167
|
+
* Format the color to a specific type.
|
|
2168
|
+
*
|
|
2169
|
+
* @param type - The color format to convert to.
|
|
2170
|
+
* @param precision - The decimal precision for the output.
|
|
2171
|
+
* @returns The formatted color string.
|
|
2172
|
+
*/
|
|
2173
|
+
format(type, precision) {
|
|
2174
|
+
return formatCSS(this.rgb, {
|
|
2175
|
+
alpha: this.alpha,
|
|
2176
|
+
format: type,
|
|
2177
|
+
precision
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Increase lightness.
|
|
2182
|
+
*
|
|
2183
|
+
* @param amount - A number between 0 and 100.
|
|
2184
|
+
* @returns The lightened color string.
|
|
2185
|
+
*/
|
|
2186
|
+
lighten(amount) {
|
|
2187
|
+
return lighten(this.currentColor, amount);
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Decrease lightness.
|
|
2191
|
+
*
|
|
2192
|
+
* @param amount - A number between 0 and 100.
|
|
2193
|
+
* @returns The darkened color string.
|
|
2194
|
+
*/
|
|
2195
|
+
darken(amount) {
|
|
2196
|
+
return darken(this.currentColor, amount);
|
|
2197
|
+
}
|
|
2198
|
+
/**
|
|
2199
|
+
* Increase saturation.
|
|
2200
|
+
*
|
|
2201
|
+
* @param amount - A number between 0 and 100.
|
|
2202
|
+
* @returns The saturated color string.
|
|
2203
|
+
*/
|
|
2204
|
+
saturate(amount) {
|
|
2205
|
+
return saturate(this.currentColor, amount);
|
|
2206
|
+
}
|
|
2207
|
+
/**
|
|
2208
|
+
* Decrease saturation.
|
|
2209
|
+
*
|
|
2210
|
+
* @param amount - A number between 0 and 100.
|
|
2211
|
+
* @returns The desaturated color string.
|
|
2212
|
+
*/
|
|
2213
|
+
desaturate(amount) {
|
|
2214
|
+
return desaturate(this.currentColor, amount);
|
|
2215
|
+
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Convert to grayscale.
|
|
2218
|
+
*
|
|
2219
|
+
* @returns The grayscale color string.
|
|
2220
|
+
*/
|
|
2221
|
+
grayscale() {
|
|
2222
|
+
return grayscale(this.currentColor);
|
|
2223
|
+
}
|
|
2224
|
+
/**
|
|
2225
|
+
* Invert color.
|
|
2226
|
+
*
|
|
2227
|
+
* @returns The inverted color string.
|
|
2228
|
+
*/
|
|
2229
|
+
invert() {
|
|
2230
|
+
return invert(this.currentColor);
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Mix with another color.
|
|
2234
|
+
*
|
|
2235
|
+
* @param color - The color to mix with.
|
|
2236
|
+
* @param ratio - A number between 0 and 1 (0 = this color, 1 = input color).
|
|
2237
|
+
* @returns The mixed color string.
|
|
2238
|
+
*/
|
|
2239
|
+
mix(color, ratio) {
|
|
2240
|
+
return mix(this.currentColor, color, ratio);
|
|
2241
|
+
}
|
|
2242
|
+
/**
|
|
2243
|
+
* Add opacity to the color.
|
|
2244
|
+
*
|
|
2245
|
+
* @param alpha - A number between 0 and 1.
|
|
2246
|
+
* @returns The opacified color string.
|
|
2247
|
+
*/
|
|
2248
|
+
opacify(alpha = .9) {
|
|
2249
|
+
return opacify(this.currentColor, alpha, this.type);
|
|
2250
|
+
}
|
|
2251
|
+
/**
|
|
2252
|
+
* Rotate color hue.
|
|
2253
|
+
*
|
|
2254
|
+
* @param degrees - A number between -360 and 360.
|
|
2255
|
+
* @returns The rotated color string.
|
|
2256
|
+
*/
|
|
2257
|
+
rotate(degrees) {
|
|
2258
|
+
return rotate(this.currentColor, degrees);
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* Make the color more transparent.
|
|
2262
|
+
*
|
|
2263
|
+
* @param alpha - A number between -1 and 1.
|
|
2264
|
+
* @returns The transparentized color string.
|
|
2265
|
+
*/
|
|
2266
|
+
transparentize(alpha = .1) {
|
|
2267
|
+
return transparentize(this.currentColor, alpha, this.type);
|
|
2268
|
+
}
|
|
2269
|
+
};
|
|
2270
|
+
function convert$1(input, format) {
|
|
2271
|
+
return formatCSS(parseCSS(input, format), { format });
|
|
2272
|
+
}
|
|
2273
|
+
/* v8 ignore next 3 -- @preserve */
|
|
2274
|
+
function isHsl(v) {
|
|
2275
|
+
if (typeof v !== `object`) return false;
|
|
2276
|
+
if (!(`h` in v)) return false;
|
|
2277
|
+
if (!(`s` in v)) return false;
|
|
2278
|
+
if (!(`l` in v)) return false;
|
|
2279
|
+
if (!(`unit` in v)) return false;
|
|
2280
|
+
if (!(`space` in v)) return false;
|
|
2281
|
+
if (v.space !== `hsl`) return false;
|
|
2282
|
+
return true;
|
|
2283
|
+
}
|
|
2284
|
+
function isRgb(v) {
|
|
2285
|
+
if (typeof v !== `object`) return false;
|
|
2286
|
+
if (!(`r` in v)) return false;
|
|
2287
|
+
if (!(`g` in v)) return false;
|
|
2288
|
+
if (!(`b` in v)) return false;
|
|
2289
|
+
if (!(`space` in v)) return false;
|
|
2290
|
+
if (!(`unit` in v)) return false;
|
|
2291
|
+
if (v.space === `srgb`) return true;
|
|
2292
|
+
return false;
|
|
2293
|
+
}
|
|
2294
|
+
/**
|
|
2295
|
+
* If the input object has r,g&b properties, it will return a fully-
|
|
2296
|
+
* formed Rgb type with `unit` and `space` properties.
|
|
2297
|
+
*
|
|
2298
|
+
* If it lacks these basic three properties or they are out of range,
|
|
2299
|
+
* _undefined_ is returned.
|
|
2300
|
+
*
|
|
2301
|
+
* If RGB values are less than 1 assumes unit:scalar. Otherwise unit:8bit.
|
|
2302
|
+
* If RGB values exceed 255, _undefined_ returned.
|
|
2303
|
+
* @param v
|
|
2304
|
+
* @returns
|
|
2305
|
+
*/
|
|
2306
|
+
function tryParseObjectToRgb(v) {
|
|
2307
|
+
if (typeof v !== `object`) throw new TypeError(`Param 'v' is expected to be an object, got: ${typeof v}`);
|
|
2308
|
+
if (!(`r` in v && `g` in v && `b` in v)) return;
|
|
2309
|
+
if (!(`unit` in v)) if (v.r <= 1 && v.g <= 1 && v.b <= 1) v.unit = `scalar`;
|
|
2310
|
+
else if (v.r > 255 && v.g <= 255 && v.b <= 255) return;
|
|
2311
|
+
else v.unit = `8bit`;
|
|
2312
|
+
if (!(`space` in v)) v.space = `srgb`;
|
|
2313
|
+
return v;
|
|
2314
|
+
}
|
|
2315
|
+
function tryParseObjectToHsl(v) {
|
|
2316
|
+
if (!(`h` in v && `s` in v && `l` in v)) return;
|
|
2317
|
+
if (!(`unit` in v)) if (v.s <= 1 && v.l <= 1) v.unit = `scalar`;
|
|
2318
|
+
else if (v.s > 100 || v.l > 100) return;
|
|
2319
|
+
else v.unit = `absolute`;
|
|
2320
|
+
if (!(`space` in v)) v.space = `hsl`;
|
|
2321
|
+
return v;
|
|
2322
|
+
}
|
|
2323
|
+
function isOkLch(v) {
|
|
2324
|
+
if (typeof v !== `object`) return false;
|
|
2325
|
+
if (!(`l` in v)) return false;
|
|
2326
|
+
if (!(`c` in v)) return false;
|
|
2327
|
+
if (!(`h` in v)) return false;
|
|
2328
|
+
if (!(`unit` in v)) return false;
|
|
2329
|
+
if (!(`space` in v)) return false;
|
|
2330
|
+
if (v.space === `lch`) return true;
|
|
2331
|
+
if (v.space === `oklch`) return true;
|
|
2332
|
+
return false;
|
|
2333
|
+
}
|
|
2334
|
+
function isColourish(v) {
|
|
2335
|
+
if (typeof v === `string`) return true;
|
|
2336
|
+
if (typeof v !== `object`) return false;
|
|
2337
|
+
if (isHsl(v)) return true;
|
|
2338
|
+
if (isOkLch(v)) return true;
|
|
2339
|
+
if (isRgb(v)) return true;
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
function calculateHueDistance(a, b, limit = 1) {
|
|
2343
|
+
let long = -1;
|
|
2344
|
+
let short = -1;
|
|
2345
|
+
if (b < a) {
|
|
2346
|
+
long = b - a;
|
|
2347
|
+
short = limit - (a - b);
|
|
2348
|
+
} else {
|
|
2349
|
+
long = b - a;
|
|
2350
|
+
short = long - limit;
|
|
2351
|
+
}
|
|
2352
|
+
const forward = short > 0 ? short : long;
|
|
2353
|
+
const backward = short > 0 ? long : short;
|
|
2354
|
+
if (Math.abs(long) < Math.abs(short)) {
|
|
2355
|
+
const t = short;
|
|
2356
|
+
short = long;
|
|
2357
|
+
long = t;
|
|
2358
|
+
}
|
|
2359
|
+
return {
|
|
2360
|
+
long,
|
|
2361
|
+
short,
|
|
2362
|
+
forward,
|
|
2363
|
+
backward
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
function libraryRgbToHexString(rgb) {
|
|
2367
|
+
const componentToHex = (c) => {
|
|
2368
|
+
const hex = Math.floor(c).toString(16);
|
|
2369
|
+
return hex.length === 1 ? `0${hex}` : hex;
|
|
2370
|
+
};
|
|
2371
|
+
let part = `#${componentToHex(rgb.r)}${componentToHex(rgb.g)}${componentToHex(rgb.b)}`;
|
|
2372
|
+
if (typeof rgb.alpha !== `undefined` && rgb.alpha !== 255) part += componentToHex(rgb.alpha);
|
|
2373
|
+
return part;
|
|
2374
|
+
}
|
|
2375
|
+
function wrapScalarHue(value) {
|
|
2376
|
+
value = value % 1;
|
|
2377
|
+
if (value < 0) return (1 - Math.abs(value)) % 1;
|
|
2378
|
+
return value;
|
|
2379
|
+
}
|
|
2380
|
+
var hsl_exports = /* @__PURE__ */ __exportAll$1({
|
|
2381
|
+
absolute: () => absolute$1,
|
|
2382
|
+
changeLightness: () => changeLightness$1,
|
|
2383
|
+
fromCss: () => fromCss$3,
|
|
2384
|
+
fromHexString: () => fromHexString$3,
|
|
2385
|
+
generateScalar: () => generateScalar$1,
|
|
2386
|
+
guard: () => guard$4,
|
|
2387
|
+
interpolator: () => interpolator$3,
|
|
2388
|
+
parseCssHslFunction: () => parseCssHslFunction,
|
|
2389
|
+
scalar: () => scalar$3,
|
|
2390
|
+
toAbsolute: () => toAbsolute$1,
|
|
2391
|
+
toCssString: () => toCssString$2,
|
|
2392
|
+
toHexString: () => toHexString$3,
|
|
2393
|
+
toLibraryRgb: () => toLibraryRgb,
|
|
2394
|
+
toScalar: () => toScalar$3,
|
|
2395
|
+
withOpacity: () => withOpacity$3
|
|
2396
|
+
});
|
|
2397
|
+
/**
|
|
2398
|
+
* Scales the opacity value of an input HSL value
|
|
2399
|
+
* ```js
|
|
2400
|
+
* withOpacity()
|
|
2401
|
+
* ```
|
|
2402
|
+
* @param value Colour
|
|
2403
|
+
* @param fn Function that calcules opacity based on input scalar value
|
|
2404
|
+
*/
|
|
2405
|
+
function withOpacity$3(value, fn) {
|
|
2406
|
+
switch (value.unit) {
|
|
2407
|
+
case `absolute`: return {
|
|
2408
|
+
...value,
|
|
2409
|
+
opacity: fn((value.opacity ?? 100) / 100, value) * 100
|
|
2410
|
+
};
|
|
2411
|
+
case `scalar`: return {
|
|
2412
|
+
...value,
|
|
2413
|
+
opacity: fn(value.opacity ?? 1, value)
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
/**
|
|
2418
|
+
* Increases or decreases lightness by this percentage, returning new colour
|
|
2419
|
+
*
|
|
2420
|
+
* Amount to change:
|
|
2421
|
+
* 'fixed': a fixed amount
|
|
2422
|
+
* 'delta': increase/decrease by this amount
|
|
2423
|
+
* 'pdelta': proportion of current value to change by ('percentage delta')
|
|
2424
|
+
*
|
|
2425
|
+
* ```
|
|
2426
|
+
* const colour = { h: 0.5, s: 0.5, l: 0.5, space: `hsl`, unit: `scalar` };
|
|
2427
|
+
* changeLightness(colour, { pdelta: 0.1 }); // l: 0.55
|
|
2428
|
+
* changeLightness(colour, { delta: 0.1 }); // l: 0.6
|
|
2429
|
+
* changeLightness(colour, { fixed: 0.5 }); // l: 0.5
|
|
2430
|
+
* ```
|
|
2431
|
+
*
|
|
2432
|
+
* Keep in mind the numerical value will depend on the unit of `value`. If it's scalar,
|
|
2433
|
+
* lightness is 0..1 scale, otherwise 0..100 scale.
|
|
2434
|
+
*
|
|
2435
|
+
* Use negative values to decrease (does not apply to 'fixed')
|
|
2436
|
+
* @param value Hsl colour
|
|
2437
|
+
* @param amount Amount to change
|
|
2438
|
+
*/
|
|
2439
|
+
function changeLightness$1(value, amount) {
|
|
2440
|
+
let newL = 0;
|
|
2441
|
+
if (typeof amount.pdelta !== `undefined`) newL = value.l + value.l * amount.pdelta;
|
|
2442
|
+
else if (typeof amount.delta !== `undefined`) newL = amount.delta + value.l;
|
|
2443
|
+
else if (typeof amount.fixed !== `undefined`) {
|
|
2444
|
+
if (amount.fixed < 0) throw new TypeError(`Cannot use negative value with 'fixed'`);
|
|
2445
|
+
newL = amount.fixed;
|
|
2446
|
+
} else throw new TypeError(`Parameter 'amount' is missing 'delta/pdelta/fixed' properties`);
|
|
2447
|
+
return {
|
|
2448
|
+
...value,
|
|
2449
|
+
l: scaleProperty(value, newL, `l`)
|
|
2450
|
+
};
|
|
2451
|
+
}
|
|
2452
|
+
function scaleProperty(hsl, value, property) {
|
|
2453
|
+
if (hsl.unit === `scalar`) {
|
|
2454
|
+
if (value > 1) value = 1;
|
|
2455
|
+
else if (value < 0) value = 0;
|
|
2456
|
+
} else if (value > 100) value = 100;
|
|
2457
|
+
else if (value < 0) value = 0;
|
|
2458
|
+
return value;
|
|
2459
|
+
}
|
|
2460
|
+
const hslTransparent = Object.freeze({
|
|
2461
|
+
h: 0,
|
|
2462
|
+
s: 0,
|
|
2463
|
+
l: 0,
|
|
2464
|
+
opacity: 0,
|
|
2465
|
+
unit: `absolute`,
|
|
2466
|
+
space: `hsl`
|
|
2467
|
+
});
|
|
2468
|
+
function fromHexString$3(hexString, options = {}) {
|
|
2469
|
+
return fromLibrary$2(hex2hsl(hexString), options);
|
|
2470
|
+
}
|
|
2471
|
+
function fromCss$3(value, options = {}) {
|
|
2472
|
+
value = value.toLowerCase();
|
|
2473
|
+
if (value.startsWith(`hsla(`)) throw new Error(`hsla() not supported`);
|
|
2474
|
+
if (value.startsWith(`rgba(`)) throw new Error(`rgba() not supported`);
|
|
2475
|
+
if (value.startsWith(`#`)) return fromHexString$3(value, options);
|
|
2476
|
+
if (value.startsWith(`--`)) try {
|
|
2477
|
+
value = resolveCss(value);
|
|
2478
|
+
} catch (error) {
|
|
2479
|
+
if (typeof options.fallbackString !== `undefined`) value = options.fallbackString;
|
|
2480
|
+
if (typeof options.fallbackColour !== `undefined`) return options.fallbackColour;
|
|
2481
|
+
throw error;
|
|
2482
|
+
}
|
|
2483
|
+
if (value === `transparent`) return hslTransparent;
|
|
2484
|
+
if (typeof cssDefinedHexColours[value] !== `undefined`) return fromHexString$3(cssDefinedHexColours[value], options);
|
|
2485
|
+
if (value.startsWith(`rgb(`)) return fromLibrary$2(toLibraryHsl(value), options);
|
|
2486
|
+
if (!value.startsWith(`hsl(`)) try {
|
|
2487
|
+
value = convert$1(value, `hsl`);
|
|
2488
|
+
} catch (error) {
|
|
2489
|
+
if (options.fallbackString) value = options.fallbackString;
|
|
2490
|
+
else throw error;
|
|
2491
|
+
}
|
|
2492
|
+
try {
|
|
2493
|
+
const hsl = parseCssHslFunction(value);
|
|
2494
|
+
if (options.scalar) return toScalar$3(hsl);
|
|
2495
|
+
return toAbsolute$1(hsl);
|
|
2496
|
+
} catch (error) {
|
|
2497
|
+
if (options.fallbackColour) return options.fallbackColour;
|
|
2498
|
+
throw error;
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
function toCssString$2(hsl) {
|
|
2502
|
+
const abs = toAbsolute$1(hsl);
|
|
2503
|
+
let css = `hsl(${abs.h}deg ${abs.s}% ${abs.l}%`;
|
|
2504
|
+
if (`opacity` in abs && abs.opacity !== void 0 && abs.opacity < 100) css += ` / ${abs.opacity}%`;
|
|
2505
|
+
css += `)`;
|
|
2506
|
+
return css;
|
|
2507
|
+
}
|
|
2508
|
+
function toHexString$3(hsl) {
|
|
2509
|
+
return libraryRgbToHexString(toLibraryRgb(hsl));
|
|
2510
|
+
}
|
|
2511
|
+
function fromLibrary$2(hsl, parsingOptions = {}) {
|
|
2512
|
+
if (typeof hsl === `undefined` || hsl === null) {
|
|
2513
|
+
if (parsingOptions.fallbackColour) return parsingOptions.fallbackColour;
|
|
2514
|
+
}
|
|
2515
|
+
const scalarOpt = parsingOptions.scalar ?? true;
|
|
2516
|
+
resultThrow(numberInclusiveRangeTest(hsl.h, 0, 360, `h`), numberInclusiveRangeTest(hsl.s, 0, 100, `s`), numberInclusiveRangeTest(hsl.l, 0, 100, `l`), percentTest(hsl.alpha ?? 1, `alpha`));
|
|
2517
|
+
if (scalarOpt) return scalar$3(hsl.h / 360, hsl.s / 100, hsl.l / 100, hsl.alpha ?? 1);
|
|
2518
|
+
else return absolute$1(hsl.h, hsl.s, hsl.l, (hsl.alpha ?? 1) * 100);
|
|
2519
|
+
}
|
|
2520
|
+
function toAbsolute$1(hslOrString) {
|
|
2521
|
+
if (typeof hslOrString === `string`) return fromCss$3(hslOrString, { scalar: false });
|
|
2522
|
+
if (isRgb(hslOrString)) return toAbsolute$1(fromLibrary$2(toLibraryHsl(hslOrString), { scalar: false }));
|
|
2523
|
+
const hsl = hslOrString;
|
|
2524
|
+
guard$4(hsl);
|
|
2525
|
+
if (hsl.unit === `absolute`) return hsl;
|
|
2526
|
+
return {
|
|
2527
|
+
h: hsl.h * 360,
|
|
2528
|
+
s: hsl.s * 100,
|
|
2529
|
+
l: hsl.l * 100,
|
|
2530
|
+
opacity: (hsl.opacity ?? 1) * 100,
|
|
2531
|
+
unit: `absolute`,
|
|
2532
|
+
space: `hsl`
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
/**
|
|
2536
|
+
* Generates a {@link HslScalar} value.
|
|
2537
|
+
*
|
|
2538
|
+
* ```js
|
|
2539
|
+
* generateScaler(10); // 10deg, default to full saturation, half lightness and full opacity
|
|
2540
|
+
*
|
|
2541
|
+
* // Generate HSL value from radian angle and 50% saturation
|
|
2542
|
+
* generateScalar(`10rad`, 0.5);
|
|
2543
|
+
*
|
|
2544
|
+
* // Generate from numeric CSS variable
|
|
2545
|
+
* generateScalar(`--hue`);
|
|
2546
|
+
* ```
|
|
2547
|
+
* @param absoluteHslOrVariable Hue angle or CSS variable
|
|
2548
|
+
* @param saturation
|
|
2549
|
+
* @param lightness
|
|
2550
|
+
* @param opacity
|
|
2551
|
+
*/
|
|
2552
|
+
function generateScalar$1(absoluteHslOrVariable, saturation = 1, lightness = .5, opacity = 1) {
|
|
2553
|
+
if (typeof absoluteHslOrVariable === `string`) {
|
|
2554
|
+
if (absoluteHslOrVariable.startsWith(`--`)) absoluteHslOrVariable = getComputedStyle(document.body).getPropertyValue(absoluteHslOrVariable).trim();
|
|
2555
|
+
}
|
|
2556
|
+
const hue = angleParse(absoluteHslOrVariable);
|
|
2557
|
+
if (saturation > 1) throw new TypeError(`Param 'saturation' must be between 0..1`);
|
|
2558
|
+
if (lightness > 1) throw new TypeError(`Param 'lightness' must be between 0..1`);
|
|
2559
|
+
if (opacity > 1) throw new TypeError(`Param 'opacity' must be between 0..1`);
|
|
2560
|
+
return {
|
|
2561
|
+
h: angleConvert(hue, `deg`).value / 360,
|
|
2562
|
+
s: saturation,
|
|
2563
|
+
l: lightness,
|
|
2564
|
+
opacity,
|
|
2565
|
+
unit: `scalar`,
|
|
2566
|
+
space: `hsl`
|
|
2567
|
+
};
|
|
2568
|
+
}
|
|
2569
|
+
/**
|
|
2570
|
+
* Converts a {@link Hsl} value to scalar units, or parses a colour string
|
|
2571
|
+
* and converts it.
|
|
2572
|
+
*
|
|
2573
|
+
* ```js
|
|
2574
|
+
* toScalar({ h: 100, s: 50, l: 100, unit: `absolute` });
|
|
2575
|
+
* toScalar(`red`);
|
|
2576
|
+
* ```
|
|
2577
|
+
* @param colour
|
|
2578
|
+
*/
|
|
2579
|
+
function toScalar$3(colour) {
|
|
2580
|
+
if (typeof colour === `string`) return fromCss$3(colour, { scalar: true });
|
|
2581
|
+
if (isRgb(colour)) return toScalar$3(fromLibrary$2(toLibraryHsl(colour), { scalar: true }));
|
|
2582
|
+
const hsl = colour;
|
|
2583
|
+
guard$4(hsl);
|
|
2584
|
+
if (hsl.unit === `scalar`) return hsl;
|
|
2585
|
+
return {
|
|
2586
|
+
h: hsl.h / 360,
|
|
2587
|
+
s: hsl.s / 100,
|
|
2588
|
+
l: hsl.l / 100,
|
|
2589
|
+
opacity: (hsl.opacity ?? 1) / 100,
|
|
2590
|
+
unit: `scalar`,
|
|
2591
|
+
space: `hsl`
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
function guard$4(hsl) {
|
|
2595
|
+
const { h, s, l, opacity, space, unit } = hsl;
|
|
2596
|
+
if (space !== `hsl`) throw new Error(`Space is expected to be 'hsl'. Got: ${space}`);
|
|
2597
|
+
if (unit === `absolute`) resultThrow(numberTest(h, `finite`, `h`), numberInclusiveRangeTest(s, 0, 100, `s`), numberInclusiveRangeTest(l, 0, 100, `l`), () => {
|
|
2598
|
+
if (typeof opacity === `number`) return numberInclusiveRangeTest(opacity, 0, 100, `opacity`);
|
|
2599
|
+
});
|
|
2600
|
+
else if (unit === `scalar`) resultThrow(numberTest(h, `percentage`, `h`), numberTest(s, `percentage`, `s`), numberTest(l, `percentage`, `l`), () => {
|
|
2601
|
+
if (typeof opacity === `number`) return numberTest(opacity, `percentage`, `opacity`);
|
|
2602
|
+
});
|
|
2603
|
+
else throw new Error(`Unit is expected to be 'absolute' or 'scalar'. Got: ${unit}`);
|
|
2604
|
+
}
|
|
2605
|
+
function interpolator$3(a, b, direction = `shorter`) {
|
|
2606
|
+
a = toScalar$3(a);
|
|
2607
|
+
b = toScalar$3(b);
|
|
2608
|
+
const aOpacity = a.opacity ?? 1;
|
|
2609
|
+
const distanceCalc = calculateHueDistance(a.h, b.h, 1);
|
|
2610
|
+
const hueDistance = direction === `longer` ? distanceCalc.long : distanceCalc.short;
|
|
2611
|
+
const satDistance = b.s - a.s;
|
|
2612
|
+
const lightDistance = b.l - a.l;
|
|
2613
|
+
const opacityDistance = (b.opacity ?? 1) - aOpacity;
|
|
2614
|
+
return (amount) => {
|
|
2615
|
+
amount = clamp(amount);
|
|
2616
|
+
let h = interpolate(amount, 0, Math.abs(hueDistance));
|
|
2617
|
+
if (hueDistance < 0) h = a.h - h;
|
|
2618
|
+
else h = a.h + h;
|
|
2619
|
+
const s = interpolate(amount, 0, satDistance);
|
|
2620
|
+
const l = interpolate(amount, 0, lightDistance);
|
|
2621
|
+
const o = interpolate(amount, 0, opacityDistance);
|
|
2622
|
+
return scalar$3(wrapScalarHue(h), s + a.s, l + a.l, o + aOpacity);
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
/**
|
|
2626
|
+
* Creates a HslScalar value from scalar (0..1) values
|
|
2627
|
+
* @param hue
|
|
2628
|
+
* @param sat
|
|
2629
|
+
* @param lightness
|
|
2630
|
+
* @param opacity
|
|
2631
|
+
*/
|
|
2632
|
+
function scalar$3(hue = .5, sat = 1, lightness = .5, opacity = 1) {
|
|
2633
|
+
const hsl = {
|
|
2634
|
+
unit: `scalar`,
|
|
2635
|
+
space: `hsl`,
|
|
2636
|
+
h: hue,
|
|
2637
|
+
s: sat,
|
|
2638
|
+
l: lightness,
|
|
2639
|
+
opacity
|
|
2640
|
+
};
|
|
2641
|
+
guard$4(hsl);
|
|
2642
|
+
return hsl;
|
|
2643
|
+
}
|
|
2644
|
+
function absolute$1(hue = 200, sat = 100, lightness = 50, opacity = 100) {
|
|
2645
|
+
const hsl = {
|
|
2646
|
+
unit: `absolute`,
|
|
2647
|
+
space: `hsl`,
|
|
2648
|
+
h: hue,
|
|
2649
|
+
s: sat,
|
|
2650
|
+
l: lightness,
|
|
2651
|
+
opacity
|
|
2652
|
+
};
|
|
2653
|
+
guard$4(hsl);
|
|
2654
|
+
return hsl;
|
|
2655
|
+
}
|
|
2656
|
+
/**
|
|
2657
|
+
* It seems Colorizr can't handle 'deg' units
|
|
2658
|
+
* @param value
|
|
2659
|
+
*/
|
|
2660
|
+
function parseCssHslFunction(value) {
|
|
2661
|
+
if (value.startsWith(`hsla`)) throw new Error(`hsla() is not supported`);
|
|
2662
|
+
if (!value.startsWith(`hsl(`)) throw new Error(`Expected hsl(..) CSS colour`);
|
|
2663
|
+
const start = value.indexOf(`(`);
|
|
2664
|
+
const end = value.indexOf(`)`);
|
|
2665
|
+
if (end < start) throw new Error(`Is hsl() not terminated? Missing ')'`);
|
|
2666
|
+
let split = value.substring(start + 1, end).split(/[\s,]+/);
|
|
2667
|
+
if (split.length < 3) throw new Error(`Expected three tokens. Got: ${split.length} length`);
|
|
2668
|
+
let returnRelative = false;
|
|
2669
|
+
if (split[0].endsWith(`%`)) returnRelative = true;
|
|
2670
|
+
if (split[1].endsWith(`%`) && split[2].endsWith(`%`)) returnRelative = true;
|
|
2671
|
+
const valueAsScalar = (v, pos) => {
|
|
2672
|
+
if (v === `none`) return 0;
|
|
2673
|
+
if (v.endsWith(`%`)) return Number.parseFloat(v.substring(0, v.length - 1)) / 100;
|
|
2674
|
+
if (v.endsWith(`deg`) && pos === 0) v = v.substring(0, v.length - 3);
|
|
2675
|
+
const vf = Number.parseFloat(v);
|
|
2676
|
+
if (pos === 0) return vf / 360;
|
|
2677
|
+
if (pos === 3) return vf;
|
|
2678
|
+
return vf / 100;
|
|
2679
|
+
};
|
|
2680
|
+
const valueAsAbs = (v, pos) => {
|
|
2681
|
+
if (v === `none`) return 0;
|
|
2682
|
+
if (v.endsWith(`%`)) {
|
|
2683
|
+
const vf = Number.parseFloat(v.substring(0, v.length - 1));
|
|
2684
|
+
if (pos === 0) return vf * 360;
|
|
2685
|
+
return vf;
|
|
2686
|
+
}
|
|
2687
|
+
if (v.endsWith(`deg`) && pos === 0) return Number.parseFloat(v.substring(0, v.length - 3));
|
|
2688
|
+
return Number.parseFloat(v);
|
|
2689
|
+
};
|
|
2690
|
+
if (split.length > 3) {
|
|
2691
|
+
if (split[3] === `/`) split = [
|
|
2692
|
+
split[0],
|
|
2693
|
+
split[1],
|
|
2694
|
+
split[2],
|
|
2695
|
+
split[4]
|
|
2696
|
+
];
|
|
2697
|
+
}
|
|
2698
|
+
if (returnRelative) return scalar$3(valueAsScalar(split[0], 0), valueAsScalar(split[1], 1), valueAsScalar(split[2], 2), valueAsScalar(split[3] ?? `100%`, 3));
|
|
2699
|
+
else return absolute$1(valueAsAbs(split[0], 0), valueAsAbs(split[1], 1), valueAsAbs(split[2], 2), valueAsAbs(split[3] ?? `100%`, 3));
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Converts a Hsl structure (or CSS string) to Colorizr's RGB format
|
|
2703
|
+
* @param hsl HSL colour
|
|
2704
|
+
*/
|
|
2705
|
+
function toLibraryRgb(hsl) {
|
|
2706
|
+
if (typeof hsl === `string`) return toLibraryRgb(fromCss$3(hsl, { scalar: false }));
|
|
2707
|
+
hsl = toAbsolute$1(hsl);
|
|
2708
|
+
return {
|
|
2709
|
+
...hsl2rgb({
|
|
2710
|
+
h: hsl.h,
|
|
2711
|
+
s: hsl.s,
|
|
2712
|
+
l: hsl.l
|
|
2713
|
+
}),
|
|
2714
|
+
alpha: (hsl.opacity ?? 100) / 100 * 255
|
|
2715
|
+
};
|
|
2716
|
+
}
|
|
2717
|
+
var srgb_exports = /* @__PURE__ */ __exportAll$1({
|
|
2718
|
+
changeLightness: () => changeLightness,
|
|
2719
|
+
eightBit: () => eightBit$1,
|
|
2720
|
+
fromCss: () => fromCss$2,
|
|
2721
|
+
fromHexString: () => fromHexString$2,
|
|
2722
|
+
guard: () => guard$3,
|
|
2723
|
+
interpolator: () => interpolator$2,
|
|
2724
|
+
lightness: () => lightness,
|
|
2725
|
+
parseCssRgbFunction: () => parseCssRgbFunction,
|
|
2726
|
+
scalar: () => scalar$2,
|
|
2727
|
+
to8bit: () => to8bit$1,
|
|
2728
|
+
toCssString: () => toCssString$1,
|
|
2729
|
+
toHexString: () => toHexString$2,
|
|
2730
|
+
toLibraryHsl: () => toLibraryHsl,
|
|
2731
|
+
toScalar: () => toScalar$2,
|
|
2732
|
+
withOpacity: () => withOpacity$2
|
|
2733
|
+
});
|
|
2734
|
+
function withOpacity$2(value, fn) {
|
|
2735
|
+
switch (value.unit) {
|
|
2736
|
+
case `8bit`: return {
|
|
2737
|
+
...value,
|
|
2738
|
+
opacity: fn((value.opacity ?? 255) / 255, value) * 255
|
|
2739
|
+
};
|
|
2740
|
+
case `scalar`: return {
|
|
2741
|
+
...value,
|
|
2742
|
+
opacity: fn(value.opacity ?? 1, value)
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
function fromHexString$2(hexString, scalar = true) {
|
|
2747
|
+
return fromLibrary$1(hex2rgb(hexString), { scalar });
|
|
2748
|
+
}
|
|
2749
|
+
const srgbTansparent = Object.freeze({
|
|
2750
|
+
r: 0,
|
|
2751
|
+
g: 0,
|
|
2752
|
+
b: 0,
|
|
2753
|
+
opacity: 0,
|
|
2754
|
+
unit: `8bit`,
|
|
2755
|
+
space: `srgb`
|
|
2756
|
+
});
|
|
2757
|
+
/**
|
|
2758
|
+
* Converts a colour in a legal CSS form into Rgb value, by default RgbScalar (0..1) scale.
|
|
2759
|
+
* ```js
|
|
2760
|
+
* fromCss(`rebeccapurple`);
|
|
2761
|
+
* fromCss(`rgb(40% 20% 60%)`);
|
|
2762
|
+
*
|
|
2763
|
+
* // Get 8bit version on 0..255 scale
|
|
2764
|
+
* fromCss(`blue`, { scalar: false });
|
|
2765
|
+
* ```
|
|
2766
|
+
*
|
|
2767
|
+
* @param value
|
|
2768
|
+
* @param options
|
|
2769
|
+
*/
|
|
2770
|
+
function fromCss$2(value, options = {}) {
|
|
2771
|
+
value = value.toLowerCase();
|
|
2772
|
+
if (value.startsWith(`hsla(`)) throw new Error(`hsla() not supported`);
|
|
2773
|
+
if (value.startsWith(`rgba(`)) throw new Error(`rgba() not supported`);
|
|
2774
|
+
const scalar = options.scalar ?? true;
|
|
2775
|
+
if (value.startsWith(`#`)) return fromHexString$2(value, scalar);
|
|
2776
|
+
if (value === `transparent`) return srgbTansparent;
|
|
2777
|
+
if (typeof cssDefinedHexColours[value] !== `undefined`) return fromHexString$2(cssDefinedHexColours[value], scalar);
|
|
2778
|
+
if (value.startsWith(`hsl(`)) return fromLibrary$1(toLibraryRgb(value), options);
|
|
2779
|
+
if (!value.startsWith(`rgb(`)) try {
|
|
2780
|
+
value = convert$1(value, `rgb`);
|
|
2781
|
+
} catch (error) {
|
|
2782
|
+
if (options.fallbackString) value = options.fallbackString;
|
|
2783
|
+
else throw error;
|
|
2784
|
+
}
|
|
2785
|
+
try {
|
|
2786
|
+
const rgb = parseCssRgbFunction(value);
|
|
2787
|
+
if (scalar) return toScalar$2(rgb);
|
|
2788
|
+
return to8bit$1(rgb);
|
|
2789
|
+
} catch (error) {
|
|
2790
|
+
if (options.fallbackColour) return options.fallbackColour;
|
|
2791
|
+
throw error;
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
function toHexString$2(rgb) {
|
|
2795
|
+
return libraryRgbToHexString(toLibrary$1(rgb));
|
|
2796
|
+
}
|
|
2797
|
+
function toCssString$1(rgb) {
|
|
2798
|
+
guard$3(rgb);
|
|
2799
|
+
switch (rgb.unit) {
|
|
2800
|
+
case `8bit`:
|
|
2801
|
+
if (rgb.opacity === void 0 || rgb.opacity === 255) return `rgb(${rgb.r} ${rgb.g} ${rgb.b})`;
|
|
2802
|
+
return `rgb(${rgb.r} ${rgb.g} ${rgb.b} / ${(rgb.opacity ?? 255) / 255})`;
|
|
2803
|
+
case `scalar`:
|
|
2804
|
+
if (rgb.opacity === void 0 || rgb.opacity === 1) return `rgb(${rgb.r * 100}% ${rgb.g * 100}% ${rgb.b * 100}%)`;
|
|
2805
|
+
return `rgb(${rgb.r * 100}% ${rgb.g * 100}% ${rgb.b * 100}% / ${(rgb.opacity ?? 1) * 100}%)`;
|
|
2806
|
+
default: throw new Error(`Unknown unit: ${rgb.unit}`);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
function toLibrary$1(rgb) {
|
|
2810
|
+
const abs = to8bit$1(rgb);
|
|
2811
|
+
return {
|
|
2812
|
+
r: abs.r,
|
|
2813
|
+
g: abs.g,
|
|
2814
|
+
b: abs.b,
|
|
2815
|
+
alpha: abs.opacity
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
function fromLibrary$1(rgb, parsingOptions = {}) {
|
|
2819
|
+
if (parsingOptions.scalar) return {
|
|
2820
|
+
r: rgb.r / 255,
|
|
2821
|
+
g: rgb.g / 255,
|
|
2822
|
+
b: rgb.b / 255,
|
|
2823
|
+
opacity: rgb.alpha ?? 1,
|
|
2824
|
+
unit: `scalar`,
|
|
2825
|
+
space: `srgb`
|
|
2826
|
+
};
|
|
2827
|
+
else return {
|
|
2828
|
+
r: rgb.r,
|
|
2829
|
+
g: rgb.g,
|
|
2830
|
+
b: rgb.b,
|
|
2831
|
+
opacity: rgb.alpha ?? 255,
|
|
2832
|
+
unit: `8bit`,
|
|
2833
|
+
space: `srgb`
|
|
2834
|
+
};
|
|
2835
|
+
}
|
|
2836
|
+
function to8bit$1(rgbOrString) {
|
|
2837
|
+
if (typeof rgbOrString === `string`) return fromCss$2(rgbOrString, { scalar: false });
|
|
2838
|
+
if (isHsl(rgbOrString)) return to8bit$1(fromLibrary$1(toLibraryRgb(rgbOrString), { scalar: false }));
|
|
2839
|
+
guard$3(rgbOrString);
|
|
2840
|
+
if (rgbOrString.unit === `8bit`) return rgbOrString;
|
|
2841
|
+
return {
|
|
2842
|
+
r: rgbOrString.r * 255,
|
|
2843
|
+
g: rgbOrString.g * 255,
|
|
2844
|
+
b: rgbOrString.b * 255,
|
|
2845
|
+
opacity: (rgbOrString.opacity ?? 1) * 255,
|
|
2846
|
+
unit: `8bit`,
|
|
2847
|
+
space: `srgb`
|
|
2848
|
+
};
|
|
2849
|
+
}
|
|
2850
|
+
function toScalar$2(rgbOrString) {
|
|
2851
|
+
if (typeof rgbOrString === `string`) return fromCss$2(rgbOrString, { scalar: true });
|
|
2852
|
+
if (isHsl(rgbOrString)) return toScalar$2(fromLibrary$1(toLibraryRgb(rgbOrString), { scalar: true }));
|
|
2853
|
+
guard$3(rgbOrString);
|
|
2854
|
+
if (rgbOrString.unit === `scalar`) return rgbOrString;
|
|
2855
|
+
return {
|
|
2856
|
+
r: rgbOrString.r / 255,
|
|
2857
|
+
g: rgbOrString.g / 255,
|
|
2858
|
+
b: rgbOrString.b / 255,
|
|
2859
|
+
opacity: (rgbOrString.opacity ?? 1) / 255,
|
|
2860
|
+
unit: `scalar`,
|
|
2861
|
+
space: `srgb`
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
function guard$3(rgb) {
|
|
2865
|
+
const { r, g, b, opacity, space, unit } = rgb;
|
|
2866
|
+
if (space !== `srgb`) throw new Error(`Space is expected to be 'srgb'. Got: ${space}`);
|
|
2867
|
+
if (unit === `8bit`) resultThrow(numberInclusiveRangeTest(r, 0, 255, `r`), numberInclusiveRangeTest(g, 0, 255, `g`), numberInclusiveRangeTest(b, 0, 255, `b`), () => {
|
|
2868
|
+
if (typeof opacity === `number`) return numberInclusiveRangeTest(opacity, 0, 255, `opacity`);
|
|
2869
|
+
});
|
|
2870
|
+
else if (unit === `scalar`) resultThrow(numberTest(r, `percentage`, `r`), numberTest(g, `percentage`, `g`), numberTest(b, `percentage`, `b`), () => {
|
|
2871
|
+
if (typeof opacity === `number`) return numberTest(opacity, `percentage`, `opacity`);
|
|
2872
|
+
});
|
|
2873
|
+
else throw new Error(`Unit is expected to be '8bit' or 'scalar'. Got: ${unit}`);
|
|
2874
|
+
}
|
|
2875
|
+
/**
|
|
2876
|
+
* Sets the lightness value.
|
|
2877
|
+
*
|
|
2878
|
+
* Amount to change:
|
|
2879
|
+
* 'fixed': a fixed amount
|
|
2880
|
+
* 'delta': increase/decrease by this amount
|
|
2881
|
+
* 'pdelta': proportion of current value to change by ('percentage delta')
|
|
2882
|
+
*
|
|
2883
|
+
* Use negative values to decrease
|
|
2884
|
+
* @param rgb Colour
|
|
2885
|
+
* @param amount Amount to change
|
|
2886
|
+
*/
|
|
2887
|
+
function changeLightness(rgb, amount) {
|
|
2888
|
+
let newL = 0;
|
|
2889
|
+
const co = new Colorizr(toCssString$1(rgb));
|
|
2890
|
+
const scalarUnit = rgb.unit === `scalar`;
|
|
2891
|
+
if (typeof amount.pdelta !== `undefined`) newL = co.oklab.l + co.oklab.l * amount.pdelta;
|
|
2892
|
+
else if (typeof amount.delta !== `undefined`) newL = co.oklab.l + amount.delta;
|
|
2893
|
+
else if (typeof amount.fixed !== `undefined`) {
|
|
2894
|
+
if (amount.fixed < 0) throw new TypeError(`Amount cannot be negative when using 'fixed'`);
|
|
2895
|
+
newL = amount.fixed;
|
|
2896
|
+
} else throw new TypeError(`Parameter 'amount' is missing 'pdelta/delta/fixed' properties`);
|
|
2897
|
+
if (newL < 0) newL = 0;
|
|
2898
|
+
else if (newL > 1) newL = 1;
|
|
2899
|
+
return fromLibrary$1(oklab2rgb({
|
|
2900
|
+
a: co.oklab.a,
|
|
2901
|
+
b: co.oklab.b,
|
|
2902
|
+
l: newL,
|
|
2903
|
+
alpha: co.oklab.alpha
|
|
2904
|
+
}), { scalar: scalarUnit });
|
|
2905
|
+
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Returns a lightness value (0..1) for an RGB input
|
|
2908
|
+
*
|
|
2909
|
+
* Calculates lightness by converting to Oklab and using the 'L' value
|
|
2910
|
+
* @param rgb
|
|
2911
|
+
*/
|
|
2912
|
+
function lightness(rgb) {
|
|
2913
|
+
return new Colorizr(toCssString$1(rgb)).oklab.l;
|
|
2914
|
+
}
|
|
2915
|
+
/**
|
|
2916
|
+
* Creates a Rgb8Bit value from 8bit (0..255) values
|
|
2917
|
+
* @param red
|
|
2918
|
+
* @param green
|
|
2919
|
+
* @param blue
|
|
2920
|
+
* @param opacity
|
|
2921
|
+
*/
|
|
2922
|
+
function eightBit$1(red = 100, green = 100, blue = 100, opacity = 255) {
|
|
2923
|
+
const rgb = {
|
|
2924
|
+
unit: `8bit`,
|
|
2925
|
+
space: `srgb`,
|
|
2926
|
+
r: red,
|
|
2927
|
+
g: green,
|
|
2928
|
+
b: blue,
|
|
2929
|
+
opacity
|
|
2930
|
+
};
|
|
2931
|
+
guard$3(rgb);
|
|
2932
|
+
return rgb;
|
|
2933
|
+
}
|
|
2934
|
+
/**
|
|
2935
|
+
* Creates a RgbScalar value from scalar (0..1) values
|
|
2936
|
+
* @param red
|
|
2937
|
+
* @param green
|
|
2938
|
+
* @param blue
|
|
2939
|
+
* @param opacity
|
|
2940
|
+
*/
|
|
2941
|
+
function scalar$2(red = .5, green = .5, blue = .5, opacity = 1) {
|
|
2942
|
+
const rgb = {
|
|
2943
|
+
unit: `scalar`,
|
|
2944
|
+
space: `srgb`,
|
|
2945
|
+
r: red,
|
|
2946
|
+
g: green,
|
|
2947
|
+
b: blue,
|
|
2948
|
+
opacity
|
|
2949
|
+
};
|
|
2950
|
+
guard$3(rgb);
|
|
2951
|
+
return rgb;
|
|
2952
|
+
}
|
|
2953
|
+
/**
|
|
2954
|
+
* It seems Colorizr can't handle % values properly :'(
|
|
2955
|
+
* @param value
|
|
2956
|
+
*/
|
|
2957
|
+
function parseCssRgbFunction(value) {
|
|
2958
|
+
if (value.startsWith(`rgba`)) throw new Error(`RGBA is not supported`);
|
|
2959
|
+
if (!value.startsWith(`rgb(`)) throw new Error(`Expected rgb(..) CSS colour`);
|
|
2960
|
+
const start = value.indexOf(`(`);
|
|
2961
|
+
const end = value.indexOf(`)`);
|
|
2962
|
+
if (end < start) throw new Error(`Is rgb() not terminated? Missing ')'`);
|
|
2963
|
+
let split = value.substring(start + 1, end).split(/[\s,]+/);
|
|
2964
|
+
if (split.length < 3) throw new Error(`Expected three tokens. Got: ${split.length} length`);
|
|
2965
|
+
let relativeCount = 0;
|
|
2966
|
+
for (const s of split) if (s.endsWith(`%`)) relativeCount++;
|
|
2967
|
+
const valueAsScalar = (v, pos) => {
|
|
2968
|
+
if (v.endsWith(`%`)) return Number.parseFloat(v.substring(0, v.length - 1)) / 100;
|
|
2969
|
+
if (pos < 3) return Number.parseFloat(v) / 255;
|
|
2970
|
+
else return Number.parseFloat(v);
|
|
2971
|
+
};
|
|
2972
|
+
const valueAs8bit = (v, pos) => {
|
|
2973
|
+
if (v.endsWith(`%`)) return Number.parseFloat(v.substring(0, v.length - 1)) / 100 * 255;
|
|
2974
|
+
if (pos < 3) return Number.parseFloat(v);
|
|
2975
|
+
else return Number.parseFloat(v) * 255;
|
|
2976
|
+
};
|
|
2977
|
+
if (split.length > 3) {
|
|
2978
|
+
if (split[3] === `/`) split = [
|
|
2979
|
+
split[0],
|
|
2980
|
+
split[1],
|
|
2981
|
+
split[2],
|
|
2982
|
+
split[4]
|
|
2983
|
+
];
|
|
2984
|
+
}
|
|
2985
|
+
if (relativeCount > 1) return scalar$2(valueAsScalar(split[0], 0), valueAsScalar(split[1], 1), valueAsScalar(split[2], 2), valueAsScalar(split[3] ?? `1`, 3));
|
|
2986
|
+
else return eightBit$1(valueAs8bit(split[0], 0), valueAs8bit(split[1], 1), valueAs8bit(split[2], 2), valueAs8bit(split[3] ?? `1`, 3));
|
|
2987
|
+
}
|
|
2988
|
+
/**
|
|
2989
|
+
* Interpolates colours in Srgb space. Probably
|
|
2990
|
+
* really ugly, use OkLch space isntead.
|
|
2991
|
+
*
|
|
2992
|
+
* ```js
|
|
2993
|
+
* const i = interpolator(`red`, `blue`);
|
|
2994
|
+
* i(0.5); // Get 50% between these colours
|
|
2995
|
+
* ```
|
|
2996
|
+
* @param colourA
|
|
2997
|
+
* @param colourB
|
|
2998
|
+
*/
|
|
2999
|
+
function interpolator$2(colourA, colourB) {
|
|
3000
|
+
const aa = toScalar$2(colourA);
|
|
3001
|
+
const bb = toScalar$2(colourB);
|
|
3002
|
+
const aOpacity = aa.opacity ?? 1;
|
|
3003
|
+
const opacityDistance = (bb.opacity ?? 1) - aOpacity;
|
|
3004
|
+
const r = bb.r - aa.r;
|
|
3005
|
+
const g = bb.g - aa.g;
|
|
3006
|
+
const b = bb.b - aa.b;
|
|
3007
|
+
return (amount) => {
|
|
3008
|
+
amount = clamp(amount);
|
|
3009
|
+
return scalar$2(aa.r + interpolate(amount, 0, r), aa.g + interpolate(amount, 0, g), aa.b + interpolate(amount, 0, b), aOpacity + interpolate(amount, 0, opacityDistance));
|
|
3010
|
+
};
|
|
3011
|
+
}
|
|
3012
|
+
/**
|
|
3013
|
+
* Converts a Rgb structure (or CSS string) to Colorizr's HSL format
|
|
3014
|
+
* @param rgb
|
|
3015
|
+
*/
|
|
3016
|
+
function toLibraryHsl(rgb) {
|
|
3017
|
+
if (typeof rgb === `string`) return toLibraryHsl(fromCss$2(rgb, { scalar: false }));
|
|
3018
|
+
rgb = to8bit$1(rgb);
|
|
3019
|
+
return {
|
|
3020
|
+
...rgb2hsl({
|
|
3021
|
+
r: rgb.r,
|
|
3022
|
+
g: rgb.g,
|
|
3023
|
+
b: rgb.b
|
|
3024
|
+
}),
|
|
3025
|
+
alpha: (rgb.opacity ?? 255) / 255
|
|
3026
|
+
};
|
|
3027
|
+
}
|
|
3028
|
+
var oklch_exports = /* @__PURE__ */ __exportAll$1({
|
|
3029
|
+
OKLCH_CHROMA_MAX: () => OKLCH_CHROMA_MAX,
|
|
3030
|
+
absolute: () => absolute,
|
|
3031
|
+
fromCss: () => fromCss$1,
|
|
3032
|
+
fromHexString: () => fromHexString$1,
|
|
3033
|
+
fromLibrary: () => fromLibrary,
|
|
3034
|
+
generateScalar: () => generateScalar,
|
|
3035
|
+
guard: () => guard$2,
|
|
3036
|
+
interpolator: () => interpolator$1,
|
|
3037
|
+
scalar: () => scalar$1,
|
|
3038
|
+
toAbsolute: () => toAbsolute,
|
|
3039
|
+
toCssString: () => toCssString,
|
|
3040
|
+
toHexString: () => toHexString$1,
|
|
3041
|
+
toScalar: () => toScalar$1,
|
|
3042
|
+
withOpacity: () => withOpacity$1
|
|
3043
|
+
});
|
|
3044
|
+
const OKLCH_CHROMA_MAX = .4;
|
|
3045
|
+
function guard$2(lch) {
|
|
3046
|
+
const { l, c, h, opacity, space, unit } = lch;
|
|
3047
|
+
if (space !== `oklch`) throw new Error(`Space is expected to be 'oklch'. Got: ${space}`);
|
|
3048
|
+
if (unit === `absolute`) resultThrow(percentTest(l, `l`), () => {
|
|
3049
|
+
if (typeof c === `number`) return numberInclusiveRangeTest(c, 0, OKLCH_CHROMA_MAX, `c`);
|
|
3050
|
+
}, () => {
|
|
3051
|
+
if (typeof h === `number`) return numberInclusiveRangeTest(h, 0, 360, `h`);
|
|
3052
|
+
}, percentTest(opacity ?? 1, `opacity`));
|
|
3053
|
+
else if (unit === `scalar`) resultThrow(percentTest(l, `l`), percentTest(c, `c`), percentTest(h, `h`), percentTest(lch.opacity ?? 1, `opacity`));
|
|
3054
|
+
else throw new Error(`Unit is expected to be 'absolute' or 'scalar'. Got: ${unit}`);
|
|
3055
|
+
}
|
|
3056
|
+
function fromLibrary(lch, parsingOptions = {}) {
|
|
3057
|
+
if (typeof lch === `undefined` || lch === null) {
|
|
3058
|
+
if (parsingOptions.fallbackColour) return parsingOptions.fallbackColour;
|
|
3059
|
+
}
|
|
3060
|
+
const scalarReturn = parsingOptions.scalar ?? true;
|
|
3061
|
+
resultThrow(percentTest(lch.l, `l`), percentTest(lch.c, `c`), numberInclusiveRangeTest(lch.h, 0, 360, `h`), percentTest(lch.alpha ?? 1, `alpha`));
|
|
3062
|
+
if (scalarReturn) return scalar$1(lch.l, lch.c / OKLCH_CHROMA_MAX, lch.h / 360, lch.alpha ?? 1);
|
|
3063
|
+
else return absolute(lch.l, lch.c, lch.h, lch.alpha ?? 1);
|
|
3064
|
+
}
|
|
3065
|
+
/**
|
|
3066
|
+
* Parse a HEX-formatted colour into OkLch structured format
|
|
3067
|
+
* @param hexString
|
|
3068
|
+
* @param options
|
|
3069
|
+
*/
|
|
3070
|
+
function fromHexString$1(hexString, options = {}) {
|
|
3071
|
+
return fromLibrary(hex2oklch(hexString), options);
|
|
3072
|
+
}
|
|
3073
|
+
const oklchTransparent = Object.freeze({
|
|
3074
|
+
l: 0,
|
|
3075
|
+
c: 0,
|
|
3076
|
+
h: 0,
|
|
3077
|
+
opacity: 0,
|
|
3078
|
+
unit: `absolute`,
|
|
3079
|
+
space: `oklch`
|
|
3080
|
+
});
|
|
3081
|
+
function fromCss$1(value, options = {}) {
|
|
3082
|
+
value = value.toLowerCase();
|
|
3083
|
+
if (value.startsWith(`#`)) return fromHexString$1(value, options);
|
|
3084
|
+
if (value === `transparent`) return oklchTransparent;
|
|
3085
|
+
if (typeof cssDefinedHexColours[value] !== `undefined`) return fromHexString$1(cssDefinedHexColours[value], options);
|
|
3086
|
+
if (value.startsWith(`rgb(`)) {
|
|
3087
|
+
const rgb = to8bit$1(parseCssRgbFunction(value));
|
|
3088
|
+
return fromLibrary(rgb2oklch({
|
|
3089
|
+
r: rgb.r,
|
|
3090
|
+
g: rgb.g,
|
|
3091
|
+
b: rgb.b
|
|
3092
|
+
}), options);
|
|
3093
|
+
}
|
|
3094
|
+
if (!value.startsWith(`hsl(`) && !value.startsWith(`oklch(`)) try {
|
|
3095
|
+
value = convert$1(value, `oklch`);
|
|
3096
|
+
} catch (error) {
|
|
3097
|
+
if (options.fallbackString) value = options.fallbackString;
|
|
3098
|
+
else throw error;
|
|
3099
|
+
}
|
|
3100
|
+
const lch = new Colorizr(value).oklch;
|
|
3101
|
+
return fromLibrary(lch, options);
|
|
3102
|
+
}
|
|
3103
|
+
/**
|
|
3104
|
+
* Returns a string or {@link OkLch} value to absolute form.
|
|
3105
|
+
*
|
|
3106
|
+
* This means ranges are:
|
|
3107
|
+
* lightness: 0..1
|
|
3108
|
+
* chroma: 0...CHROMA_MAX (0.4)
|
|
3109
|
+
* hue: 0..360
|
|
3110
|
+
* @param lchOrString
|
|
3111
|
+
*/
|
|
3112
|
+
function toAbsolute(lchOrString) {
|
|
3113
|
+
if (typeof lchOrString === `string`) return toAbsolute(fromCss$1(lchOrString, { scalar: true }));
|
|
3114
|
+
guard$2(lchOrString);
|
|
3115
|
+
if (lchOrString.unit === `absolute`) return lchOrString;
|
|
3116
|
+
return {
|
|
3117
|
+
space: `oklch`,
|
|
3118
|
+
unit: `absolute`,
|
|
3119
|
+
l: lchOrString.l,
|
|
3120
|
+
c: lchOrString.c * OKLCH_CHROMA_MAX,
|
|
3121
|
+
h: lchOrString.h * 360,
|
|
3122
|
+
opacity: lchOrString.opacity
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
function toScalar$1(lchOrString) {
|
|
3126
|
+
if (typeof lchOrString === `string`) return toScalar$1(fromCss$1(lchOrString, { scalar: true }));
|
|
3127
|
+
const lch = lchOrString;
|
|
3128
|
+
guard$2(lch);
|
|
3129
|
+
if (lch.unit === `scalar`) return lch;
|
|
3130
|
+
return {
|
|
3131
|
+
l: lch.l,
|
|
3132
|
+
c: lch.c / OKLCH_CHROMA_MAX,
|
|
3133
|
+
h: lch.h / 360,
|
|
3134
|
+
opacity: lch.opacity ?? 1,
|
|
3135
|
+
unit: `scalar`,
|
|
3136
|
+
space: `oklch`
|
|
3137
|
+
};
|
|
3138
|
+
}
|
|
3139
|
+
function toLibrary(lch) {
|
|
3140
|
+
const abs = toAbsolute(lch);
|
|
3141
|
+
return {
|
|
3142
|
+
l: abs.l,
|
|
3143
|
+
c: abs.c,
|
|
3144
|
+
h: abs.h,
|
|
3145
|
+
alpha: abs.opacity
|
|
3146
|
+
};
|
|
3147
|
+
}
|
|
3148
|
+
/**
|
|
3149
|
+
* Returns the colour as a CSS colour string: `oklch(l c h / opacity)`.
|
|
3150
|
+
*
|
|
3151
|
+
* @param lch Colour
|
|
3152
|
+
* @param precision Set precision of numbers, defaults to 3
|
|
3153
|
+
* @returns CSS colour string
|
|
3154
|
+
*/
|
|
3155
|
+
function toCssString(lch, precision = 3) {
|
|
3156
|
+
guard$2(lch);
|
|
3157
|
+
const { l, c, h, opacity } = lch;
|
|
3158
|
+
let css = ``;
|
|
3159
|
+
switch (lch.unit) {
|
|
3160
|
+
case `absolute`:
|
|
3161
|
+
css = `oklch(${(l * 100).toFixed(precision)}% ${c.toFixed(precision)} ${h.toFixed(precision)}`;
|
|
3162
|
+
break;
|
|
3163
|
+
case `scalar`:
|
|
3164
|
+
css = `oklch(${l.toFixed(precision)} ${(c * OKLCH_CHROMA_MAX).toFixed(precision)} ${(h * 360).toFixed(precision)}`;
|
|
3165
|
+
break;
|
|
3166
|
+
}
|
|
3167
|
+
if (typeof opacity !== `undefined` && opacity !== 1) css += ` / ${opacity.toFixed(precision)}`;
|
|
3168
|
+
css += `)`;
|
|
3169
|
+
return css;
|
|
3170
|
+
}
|
|
3171
|
+
function toHexString$1(lch) {
|
|
3172
|
+
return libraryRgbToHexString(oklch2rgb(toLibrary(lch)));
|
|
3173
|
+
}
|
|
3174
|
+
function generateScalar(absoluteHslOrVariable, chroma = 1, lightness = .5, opacity = 1) {
|
|
3175
|
+
if (typeof absoluteHslOrVariable === `string`) {
|
|
3176
|
+
if (absoluteHslOrVariable.startsWith(`--`)) absoluteHslOrVariable = getComputedStyle(document.body).getPropertyValue(absoluteHslOrVariable).trim();
|
|
3177
|
+
}
|
|
3178
|
+
if (lightness > 1) throw new TypeError(`Param 'lightness' must be between 0..1`);
|
|
3179
|
+
if (chroma > 1) throw new TypeError(`Param 'chroma' must be between 0..1`);
|
|
3180
|
+
const hueDeg = angleConvert(angleParse(absoluteHslOrVariable), `deg`).value / 360;
|
|
3181
|
+
if (opacity > 1) throw new TypeError(`Param 'opacity' must be between 0..1`);
|
|
3182
|
+
return {
|
|
3183
|
+
l: lightness,
|
|
3184
|
+
c: chroma,
|
|
3185
|
+
h: hueDeg,
|
|
3186
|
+
opacity,
|
|
3187
|
+
unit: `scalar`,
|
|
3188
|
+
space: `oklch`
|
|
3189
|
+
};
|
|
3190
|
+
}
|
|
3191
|
+
/**
|
|
3192
|
+
* Scales the opacity value of an input Oklch value
|
|
3193
|
+
* ```js
|
|
3194
|
+
* withOpacity()
|
|
3195
|
+
* ```
|
|
3196
|
+
* @param value
|
|
3197
|
+
* @param fn
|
|
3198
|
+
*/
|
|
3199
|
+
function withOpacity$1(value, fn) {
|
|
3200
|
+
switch (value.unit) {
|
|
3201
|
+
case `absolute`: return {
|
|
3202
|
+
...value,
|
|
3203
|
+
opacity: fn((value.opacity ?? 100) / 100, value) * 100
|
|
3204
|
+
};
|
|
3205
|
+
case `scalar`: return {
|
|
3206
|
+
...value,
|
|
3207
|
+
opacity: fn(value.opacity ?? 1, value)
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
function interpolator$1(a, b, direction = `shorter`) {
|
|
3212
|
+
a = toScalar$1(a);
|
|
3213
|
+
b = toScalar$1(b);
|
|
3214
|
+
const aOpacity = a.opacity ?? 1;
|
|
3215
|
+
const distanceCalc = calculateHueDistance(a.h, b.h, 1);
|
|
3216
|
+
const hueDistance = direction === `longer` ? distanceCalc.long : distanceCalc.short;
|
|
3217
|
+
const chromaDistance = b.c - a.c;
|
|
3218
|
+
const lightDistance = b.l - a.l;
|
|
3219
|
+
const opacityDistance = (b.opacity ?? 1) - aOpacity;
|
|
3220
|
+
return (amount) => {
|
|
3221
|
+
amount = clamp(amount);
|
|
3222
|
+
let h = interpolate(amount, 0, Math.abs(hueDistance));
|
|
3223
|
+
if (hueDistance < 0) h = a.h - h;
|
|
3224
|
+
else h = a.h + h;
|
|
3225
|
+
const c = interpolate(amount, 0, chromaDistance);
|
|
3226
|
+
const l = interpolate(amount, 0, lightDistance);
|
|
3227
|
+
const o = interpolate(amount, 0, opacityDistance);
|
|
3228
|
+
return scalar$1(l + a.l, c + a.c, wrapScalarHue(h), o + aOpacity);
|
|
3229
|
+
};
|
|
3230
|
+
}
|
|
3231
|
+
function scalar$1(lightness = .7, chroma = .1, hue = .5, opacity = 1) {
|
|
3232
|
+
const lch = {
|
|
3233
|
+
unit: `scalar`,
|
|
3234
|
+
space: `oklch`,
|
|
3235
|
+
l: lightness,
|
|
3236
|
+
c: chroma,
|
|
3237
|
+
h: hue,
|
|
3238
|
+
opacity
|
|
3239
|
+
};
|
|
3240
|
+
guard$2(lch);
|
|
3241
|
+
return lch;
|
|
3242
|
+
}
|
|
3243
|
+
/**
|
|
3244
|
+
* Create an LCH colour using absolute hue
|
|
3245
|
+
* @param l Lightness 0..1
|
|
3246
|
+
* @param c Chroma 0..4
|
|
3247
|
+
* @param h Hue 0..360
|
|
3248
|
+
* @param opacity
|
|
3249
|
+
*/
|
|
3250
|
+
function absolute(l, c, h, opacity = 1) {
|
|
3251
|
+
const lch = {
|
|
3252
|
+
space: `oklch`,
|
|
3253
|
+
unit: `absolute`,
|
|
3254
|
+
opacity,
|
|
3255
|
+
l,
|
|
3256
|
+
c,
|
|
3257
|
+
h
|
|
3258
|
+
};
|
|
3259
|
+
guard$2(lch);
|
|
3260
|
+
return lch;
|
|
3261
|
+
}
|
|
3262
|
+
/**
|
|
3263
|
+
* Converts from some kind of colour that is legal in CSS
|
|
3264
|
+
* into a structured Colour type.
|
|
3265
|
+
*
|
|
3266
|
+
* Handles: hex format, CSS variables, colour names
|
|
3267
|
+
* ```js
|
|
3268
|
+
* fromCssColour(`#ffffff`);
|
|
3269
|
+
* fromCssColour(`blue`);
|
|
3270
|
+
* fromCssColour(`--some-variable`);
|
|
3271
|
+
* fromCssColour(`hsl(50, 50%, 50%)`);
|
|
3272
|
+
* fromCssColour(`rgb(50, 100, 100)`);
|
|
3273
|
+
* ```
|
|
3274
|
+
* @param colour
|
|
3275
|
+
* @returns
|
|
3276
|
+
*/
|
|
3277
|
+
const fromCssColour = (colour) => {
|
|
3278
|
+
if (colour.startsWith(`#`)) return fromHexString$2(colour, true);
|
|
3279
|
+
if (colour.startsWith(`--`)) {
|
|
3280
|
+
const fromCss = getComputedStyle(document.body).getPropertyValue(colour).trim();
|
|
3281
|
+
if (fromCss.length === 0 || fromCss === null) throw new Error(`Variable missing: ${colour}`);
|
|
3282
|
+
return fromCssColour(fromCss);
|
|
3283
|
+
}
|
|
3284
|
+
const colourLower = colour.toLowerCase();
|
|
3285
|
+
if (typeof cssDefinedHexColours[colourLower] !== `undefined`) return fromHexString$2(cssDefinedHexColours[colourLower], true);
|
|
3286
|
+
if (colourLower.startsWith(`hsl(`)) return fromCss$3(colour, { scalar: true });
|
|
3287
|
+
if (colourLower.startsWith(`rgb(`)) return fromCss$2(colour, { scalar: true });
|
|
3288
|
+
if (colourLower.startsWith(`oklch(`)) return fromCss$1(colour, { scalar: true });
|
|
3289
|
+
throw new Error(`String colour is not a hex colour, CSS variable nor well-defined colour. Input: '${colour}'`);
|
|
3290
|
+
};
|
|
3291
|
+
/**
|
|
3292
|
+
* Resolves a named colour or CSS variable to a colour string.
|
|
3293
|
+
* Doesn't do conversion or parsing.
|
|
3294
|
+
*
|
|
3295
|
+
* ```js
|
|
3296
|
+
* resolveCss(`red`);
|
|
3297
|
+
* resolveCss(`my-var`);
|
|
3298
|
+
* ```
|
|
3299
|
+
* @param colour Colour
|
|
3300
|
+
* @param fallback Fallback if CSS variable is missing
|
|
3301
|
+
* @returns
|
|
3302
|
+
*/
|
|
3303
|
+
function resolveCss(colour, fallback) {
|
|
3304
|
+
if (colour.startsWith(`--`)) {
|
|
3305
|
+
const fromCss = getComputedStyle(document.body).getPropertyValue(colour).trim();
|
|
3306
|
+
if (fromCss.length === 0 || fromCss === null) {
|
|
3307
|
+
if (typeof fallback !== `undefined`) return fallback;
|
|
3308
|
+
throw new Error(`CSS variable missing: '${colour}'`);
|
|
3309
|
+
}
|
|
3310
|
+
return resolveCss(fromCss);
|
|
3311
|
+
}
|
|
3312
|
+
if (typeof cssDefinedHexColours[colour] !== `undefined`) return cssDefinedHexColours[colour];
|
|
3313
|
+
return colour;
|
|
3314
|
+
}
|
|
3315
|
+
const cssDefinedHexColours = Object.freeze({
|
|
3316
|
+
"aliceblue": "#f0f8ff",
|
|
3317
|
+
"antiquewhite": "#faebd7",
|
|
3318
|
+
"aqua": "#00ffff",
|
|
3319
|
+
"aquamarine": "#7fffd4",
|
|
3320
|
+
"azure": "#f0ffff",
|
|
3321
|
+
"beige": "#f5f5dc",
|
|
3322
|
+
"bisque": "#ffe4c4",
|
|
3323
|
+
"black": "#000000",
|
|
3324
|
+
"blanchedalmond": "#ffebcd",
|
|
3325
|
+
"blue": "#0000ff",
|
|
3326
|
+
"blueviolet": "#8a2be2",
|
|
3327
|
+
"brown": "#a52a2a",
|
|
3328
|
+
"burlywood": "#deb887",
|
|
3329
|
+
"cadetblue": "#5f9ea0",
|
|
3330
|
+
"chartreuse": "#7fff00",
|
|
3331
|
+
"chocolate": "#d2691e",
|
|
3332
|
+
"coral": "#ff7f50",
|
|
3333
|
+
"cornflowerblue": "#6495ed",
|
|
3334
|
+
"cornsilk": "#fff8dc",
|
|
3335
|
+
"crimson": "#dc143c",
|
|
3336
|
+
"cyan": "#00ffff",
|
|
3337
|
+
"darkblue": "#00008b",
|
|
3338
|
+
"darkcyan": "#008b8b",
|
|
3339
|
+
"darkgoldenrod": "#b8860b",
|
|
3340
|
+
"darkgray": "#a9a9a9",
|
|
3341
|
+
"darkgreen": "#006400",
|
|
3342
|
+
"darkkhaki": "#bdb76b",
|
|
3343
|
+
"darkmagenta": "#8b008b",
|
|
3344
|
+
"darkolivegreen": "#556b2f",
|
|
3345
|
+
"darkorange": "#ff8c00",
|
|
3346
|
+
"darkorchid": "#9932cc",
|
|
3347
|
+
"darkred": "#8b0000",
|
|
3348
|
+
"darksalmon": "#e9967a",
|
|
3349
|
+
"darkseagreen": "#8fbc8f",
|
|
3350
|
+
"darkslateblue": "#483d8b",
|
|
3351
|
+
"darkslategray": "#2f4f4f",
|
|
3352
|
+
"darkturquoise": "#00ced1",
|
|
3353
|
+
"darkviolet": "#9400d3",
|
|
3354
|
+
"deeppink": "#ff1493",
|
|
3355
|
+
"deepskyblue": "#00bfff",
|
|
3356
|
+
"dimgray": "#696969",
|
|
3357
|
+
"dodgerblue": "#1e90ff",
|
|
3358
|
+
"firebrick": "#b22222",
|
|
3359
|
+
"floralwhite": "#fffaf0",
|
|
3360
|
+
"forestgreen": "#228b22",
|
|
3361
|
+
"fuchsia": "#ff00ff",
|
|
3362
|
+
"gainsboro": "#dcdcdc",
|
|
3363
|
+
"ghostwhite": "#f8f8ff",
|
|
3364
|
+
"gold": "#ffd700",
|
|
3365
|
+
"goldenrod": "#daa520",
|
|
3366
|
+
"gray": "#808080",
|
|
3367
|
+
"green": "#008000",
|
|
3368
|
+
"greenyellow": "#adff2f",
|
|
3369
|
+
"honeydew": "#f0fff0",
|
|
3370
|
+
"hotpink": "#ff69b4",
|
|
3371
|
+
"indianred": "#cd5c5c",
|
|
3372
|
+
"indigo": "#4b0082",
|
|
3373
|
+
"ivory": "#fffff0",
|
|
3374
|
+
"khaki": "#f0e68c",
|
|
3375
|
+
"lavender": "#e6e6fa",
|
|
3376
|
+
"lavenderblush": "#fff0f5",
|
|
3377
|
+
"lawngreen": "#7cfc00",
|
|
3378
|
+
"lemonchiffon": "#fffacd",
|
|
3379
|
+
"lightblue": "#add8e6",
|
|
3380
|
+
"lightcoral": "#f08080",
|
|
3381
|
+
"lightcyan": "#e0ffff",
|
|
3382
|
+
"lightgoldenrodyellow": "#fafad2",
|
|
3383
|
+
"lightgray": "#d3d3d3",
|
|
3384
|
+
"lightgreen": "#90ee90",
|
|
3385
|
+
"lightpink": "#ffb6c1",
|
|
3386
|
+
"lightsalmon": "#ffa07a",
|
|
3387
|
+
"lightseagreen": "#20b2aa",
|
|
3388
|
+
"lightskyblue": "#87cefa",
|
|
3389
|
+
"lightslategray": "#778899",
|
|
3390
|
+
"lightsteelblue": "#b0c4de",
|
|
3391
|
+
"lightyellow": "#ffffe0",
|
|
3392
|
+
"lime": "#00ff00",
|
|
3393
|
+
"limegreen": "#32cd32",
|
|
3394
|
+
"linen": "#faf0e6",
|
|
3395
|
+
"magenta": "#ff00ff",
|
|
3396
|
+
"maroon": "#800000",
|
|
3397
|
+
"mediumaquamarine": "#66cdaa",
|
|
3398
|
+
"mediumblue": "#0000cd",
|
|
3399
|
+
"mediumorchid": "#ba55d3",
|
|
3400
|
+
"mediumpurple": "#9370db",
|
|
3401
|
+
"mediumseagreen": "#3cb371",
|
|
3402
|
+
"mediumslateblue": "#7b68ee",
|
|
3403
|
+
"mediumspringgreen": "#00fa9a",
|
|
3404
|
+
"mediumturquoise": "#48d1cc",
|
|
3405
|
+
"mediumvioletred": "#c71585",
|
|
3406
|
+
"midnightblue": "#191970",
|
|
3407
|
+
"mintcream": "#f5fffa",
|
|
3408
|
+
"mistyrose": "#ffe4e1",
|
|
3409
|
+
"moccasin": "#ffe4b5",
|
|
3410
|
+
"navajowhite": "#ffdead",
|
|
3411
|
+
"navy": "#000080",
|
|
3412
|
+
"oldlace": "#fdf5e6",
|
|
3413
|
+
"olive": "#808000",
|
|
3414
|
+
"olivedrab": "#6b8e23",
|
|
3415
|
+
"orange": "#ffa500",
|
|
3416
|
+
"orangered": "#ff4500",
|
|
3417
|
+
"orchid": "#da70d6",
|
|
3418
|
+
"palegoldenrod": "#eee8aa",
|
|
3419
|
+
"palegreen": "#98fb98",
|
|
3420
|
+
"paleturquoise": "#afeeee",
|
|
3421
|
+
"palevioletred": "#db7093",
|
|
3422
|
+
"papayawhip": "#ffefd5",
|
|
3423
|
+
"peachpuff": "#ffdab9",
|
|
3424
|
+
"peru": "#cd853f",
|
|
3425
|
+
"pink": "#ffc0cb",
|
|
3426
|
+
"plum": "#dda0dd",
|
|
3427
|
+
"powderblue": "#b0e0e6",
|
|
3428
|
+
"purple": "#800080",
|
|
3429
|
+
"rebeccapurple": "#663399",
|
|
3430
|
+
"red": "#ff0000",
|
|
3431
|
+
"rosybrown": "#bc8f8f",
|
|
3432
|
+
"royalblue": "#4169e1",
|
|
3433
|
+
"saddlebrown": "#8b4513",
|
|
3434
|
+
"salmon": "#fa8072",
|
|
3435
|
+
"sandybrown": "#f4a460",
|
|
3436
|
+
"seagreen": "#2e8b57",
|
|
3437
|
+
"seashell": "#fff5ee",
|
|
3438
|
+
"sienna": "#a0522d",
|
|
3439
|
+
"silver": "#c0c0c0",
|
|
3440
|
+
"skyblue": "#87ceeb",
|
|
3441
|
+
"slateblue": "#6a5acd",
|
|
3442
|
+
"slategray": "#708090",
|
|
3443
|
+
"snow": "#fffafa",
|
|
3444
|
+
"springgreen": "#00ff7f",
|
|
3445
|
+
"steelblue": "#4682b4",
|
|
3446
|
+
"tan": "#d2b48c",
|
|
3447
|
+
"teal": "#008080",
|
|
3448
|
+
"thistle": "#d8bfd8",
|
|
3449
|
+
"tomato": "#ff6347",
|
|
3450
|
+
"turquoise": "#40e0d0",
|
|
3451
|
+
"violet": "#ee82ee",
|
|
3452
|
+
"wheat": "#f5deb3",
|
|
3453
|
+
"white": "#ffffff",
|
|
3454
|
+
"whitesmoke": "#f5f5f5",
|
|
3455
|
+
"yellow": "#ffff00",
|
|
3456
|
+
"yellowgreen": "#9acd32",
|
|
3457
|
+
"transparent": "#00000000"
|
|
3458
|
+
});
|
|
3459
|
+
/**
|
|
3460
|
+
* Converts an object or string representation of colour to ixfx's
|
|
3461
|
+
* structured colour.
|
|
3462
|
+
* Use {@link convertToString} if you want a CSS colour string instead.
|
|
3463
|
+
* @param colour
|
|
3464
|
+
* @param destination
|
|
3465
|
+
*/
|
|
3466
|
+
function convert(colour, destination) {
|
|
3467
|
+
if (destination === `hsl-scalar`) {
|
|
3468
|
+
if (typeof colour === `string` || isHsl(colour) || isRgb(colour)) return toScalar$3(colour);
|
|
3469
|
+
} else if (destination === `hsl-absolute`) {
|
|
3470
|
+
if (typeof colour === `string` || isHsl(colour)) return toAbsolute$1(colour);
|
|
3471
|
+
} else if (destination === `oklch-scalar`) {
|
|
3472
|
+
if (typeof colour === `string` || isOkLch(colour)) return toScalar$1(colour);
|
|
3473
|
+
} else if (destination === `oklch-absolute`) {
|
|
3474
|
+
if (typeof colour === `string` || isOkLch(colour)) return toAbsolute(colour);
|
|
3475
|
+
} else if (destination === `srgb-8bit`) {
|
|
3476
|
+
if (typeof colour === `string` || isRgb(colour)) return to8bit$1(colour);
|
|
3477
|
+
} else if (destination === `srgb-scalar`) {
|
|
3478
|
+
if (typeof colour === `string` || isRgb(colour)) return toScalar$2(colour);
|
|
3479
|
+
} else throw new Error(`Destination '${destination}' not supported for input: ${JSON.stringify(colour)}`);
|
|
3480
|
+
return convert(toCssColour(colour), destination);
|
|
3481
|
+
}
|
|
3482
|
+
/**
|
|
3483
|
+
* Like {@link convert}, but result is a CSS colour string
|
|
3484
|
+
* @param colour
|
|
3485
|
+
* @param destination
|
|
3486
|
+
*/
|
|
3487
|
+
function convertToString(colour, destination) {
|
|
3488
|
+
return toCssColour(convert(colour, destination));
|
|
3489
|
+
}
|
|
3490
|
+
/**
|
|
3491
|
+
* Converts some kind of colour into a scalar representation. Supports oklch, hsl and srgb.
|
|
3492
|
+
* @param colour Colour to convert
|
|
3493
|
+
* @param destination Destination colour format
|
|
3494
|
+
*/
|
|
3495
|
+
function convertScalar(colour, destination) {
|
|
3496
|
+
if (destination === `oklch`) return convert(colour, `oklch-scalar`);
|
|
3497
|
+
if (destination === `srgb`) return convert(colour, `srgb-scalar`);
|
|
3498
|
+
if (destination === `hsl`) return convert(colour, `hsl-scalar`);
|
|
3499
|
+
throw new Error(`Unknown destination: '${destination}'`);
|
|
3500
|
+
}
|
|
3501
|
+
function toCssColour(colour) {
|
|
3502
|
+
if (typeof colour === `string`) return colour;
|
|
3503
|
+
if (isHsl(colour)) return toCssString$2(colour);
|
|
3504
|
+
if (isRgb(colour)) return toCssString$1(colour);
|
|
3505
|
+
if (isOkLch(colour)) return toCssString(colour);
|
|
3506
|
+
const asRgb = tryParseObjectToRgb(colour);
|
|
3507
|
+
if (asRgb) return toCssString$1(asRgb);
|
|
3508
|
+
const asHsl = tryParseObjectToHsl(colour);
|
|
3509
|
+
if (asHsl) return toCssString$2(asHsl);
|
|
3510
|
+
throw new Error(`Unknown colour format: '${JSON.stringify(colour)}'`);
|
|
3511
|
+
}
|
|
3512
|
+
function toHexColour(colour) {
|
|
3513
|
+
if (isHsl(colour)) return toHexString$3(colour);
|
|
3514
|
+
if (isRgb(colour)) return toHexString$2(colour);
|
|
3515
|
+
if (isOkLch(colour)) return toHexString$1(colour);
|
|
3516
|
+
if (typeof colour === `string`) {
|
|
3517
|
+
if (colour.startsWith(`#`)) return colour;
|
|
3518
|
+
return toHexString$2(convert(colour, `srgb-8bit`));
|
|
3519
|
+
}
|
|
3520
|
+
const asRgb = tryParseObjectToRgb(colour);
|
|
3521
|
+
if (asRgb) return toHexString$2(asRgb);
|
|
3522
|
+
const asHsl = tryParseObjectToHsl(colour);
|
|
3523
|
+
if (asHsl) return toHexString$3(asHsl);
|
|
3524
|
+
throw new Error(`Unknown colour format: '${JSON.stringify(colour)}'`);
|
|
3525
|
+
}
|
|
3526
|
+
function toLibraryColour(colour) {
|
|
3527
|
+
return new Colorizr(toCssColour(colour));
|
|
3528
|
+
}
|
|
3529
|
+
function guard$1(colour) {
|
|
3530
|
+
switch (colour.space) {
|
|
3531
|
+
case `hsl`:
|
|
3532
|
+
guard$4(colour);
|
|
3533
|
+
break;
|
|
3534
|
+
case `srgb`:
|
|
3535
|
+
guard$3(colour);
|
|
3536
|
+
break;
|
|
3537
|
+
case `oklch`:
|
|
3538
|
+
guard$2(colour);
|
|
3539
|
+
break;
|
|
3540
|
+
default: throw new Error(`Unsupported colour space: '${colour.space}'`);
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
function toColour(colourish) {
|
|
3544
|
+
if (!isColourish(colourish)) throw new Error(`Could not parse input. Expected CSS colour string or structured colour {r,g,b}, {h,s,l} etc. Got: ${JSON.stringify(colourish)}`);
|
|
3545
|
+
let c;
|
|
3546
|
+
if (typeof colourish === `string`) c = fromCssColour(colourish);
|
|
3547
|
+
else c = colourish;
|
|
3548
|
+
if (c === void 0) throw new Error(`Could not parse input. Expected CSS colour string or structured colour {r,g,b}, {h,s,l} etc.`);
|
|
3549
|
+
guard$1(c);
|
|
3550
|
+
return c;
|
|
3551
|
+
}
|
|
3552
|
+
/**
|
|
3553
|
+
* Returns a CSS-ready string
|
|
3554
|
+
* representation.
|
|
3555
|
+
* ```js
|
|
3556
|
+
* element.style.backgroundColor = resolveToString(`red`);
|
|
3557
|
+
* ```
|
|
3558
|
+
*
|
|
3559
|
+
* Tries each parameter in turn, returning the value
|
|
3560
|
+
* for the first that resolves. This can be useful for
|
|
3561
|
+
* having fallback values.
|
|
3562
|
+
*
|
|
3563
|
+
* ```js
|
|
3564
|
+
* // Try a CSS variable, a object property or finally fallback to red.
|
|
3565
|
+
* element.style.backgroundColor = toStringFirst('--some-var', opts.background, `red`);
|
|
3566
|
+
* ```
|
|
3567
|
+
* @param colours Array of colours to resolve
|
|
3568
|
+
*/
|
|
3569
|
+
function toStringFirst(...colours) {
|
|
3570
|
+
for (const colour of colours) {
|
|
3571
|
+
if (colour === void 0) continue;
|
|
3572
|
+
if (colour === null) continue;
|
|
3573
|
+
try {
|
|
3574
|
+
return toCssColour(toColour(colour));
|
|
3575
|
+
} catch {}
|
|
3576
|
+
}
|
|
3577
|
+
return `rebeccapurple`;
|
|
3578
|
+
}
|
|
3579
|
+
function rgbToHsl(rgb, scalarResult) {
|
|
3580
|
+
let { r, g, b } = rgb;
|
|
3581
|
+
const opacity = rgb.opacity ?? 1;
|
|
3582
|
+
if (rgb.unit === `8bit`) {
|
|
3583
|
+
r /= 255;
|
|
3584
|
+
g /= 255;
|
|
3585
|
+
b /= 255;
|
|
3586
|
+
}
|
|
3587
|
+
const max = Math.max(r, g, b);
|
|
3588
|
+
const min = Math.min(r, g, b);
|
|
3589
|
+
let h = (max + min) / 2;
|
|
3590
|
+
let s = h;
|
|
3591
|
+
const l = h;
|
|
3592
|
+
if (max === min) if (scalarResult) return scalar$3(0, 0, 0, opacity);
|
|
3593
|
+
else return absolute$1(0, 0, 0, opacity);
|
|
3594
|
+
const d = max - min;
|
|
3595
|
+
s = l >= .5 ? d / (2 - (max + min)) : d / (max + min);
|
|
3596
|
+
switch (max) {
|
|
3597
|
+
case r:
|
|
3598
|
+
h = ((g - b) / d + 0) * 60;
|
|
3599
|
+
break;
|
|
3600
|
+
case g:
|
|
3601
|
+
h = ((b - r) / d + 2) * 60;
|
|
3602
|
+
break;
|
|
3603
|
+
case b:
|
|
3604
|
+
h = ((r - g) / d + 4) * 60;
|
|
3605
|
+
break;
|
|
3606
|
+
}
|
|
3607
|
+
if (scalarResult) return scalar$3(h / 360, s, l, opacity);
|
|
3608
|
+
else return absolute$1(h, s * 100, l * 100, opacity);
|
|
3609
|
+
}
|
|
3610
|
+
/**
|
|
3611
|
+
* Returns a full HSL colour string (eg `hsl(20,50%,75%)`) based on a index.
|
|
3612
|
+
* It's useful for generating perceptually different shades as the index increments.
|
|
3613
|
+
*
|
|
3614
|
+
* ```
|
|
3615
|
+
* el.style.backgroundColor = goldenAgeColour(10);
|
|
3616
|
+
* ```
|
|
3617
|
+
*
|
|
3618
|
+
* Saturation and lightness can be specified, as numeric ranges of 0-1.
|
|
3619
|
+
*
|
|
3620
|
+
* @param saturation Saturation (0-1), defaults to 0.5
|
|
3621
|
+
* @param lightness Lightness (0-1), defaults to 0.75
|
|
3622
|
+
* @param alpha Opacity (0-1), defaults to 1.0
|
|
3623
|
+
* @returns HSL colour string eg `hsl(20,50%,75%)`
|
|
3624
|
+
*/
|
|
3625
|
+
const goldenAngleColour = (index, saturation = .5, lightness = .75, alpha = 1) => {
|
|
3626
|
+
resultThrow(numberTest(index, `positive`, `index`), numberTest(saturation, `percentage`, `saturation`), numberTest(lightness, `percentage`, `lightness`), numberTest(alpha, `percentage`, `alpha`));
|
|
3627
|
+
return toCssString$2(scalar$3(index * 137.508 % 360 / 360, saturation, lightness, alpha));
|
|
3628
|
+
};
|
|
3629
|
+
/**
|
|
3630
|
+
* Returns a random hue component (0..359)
|
|
3631
|
+
*
|
|
3632
|
+
* ```
|
|
3633
|
+
* // Generate hue
|
|
3634
|
+
* const h = randomHue(); // 0-359
|
|
3635
|
+
*
|
|
3636
|
+
* // Generate hue and assign as part of a HSL string
|
|
3637
|
+
* el.style.backgroundColor = `hsl(${randomHue(), 50%, 75%})`;
|
|
3638
|
+
* ```
|
|
3639
|
+
* @param rand
|
|
3640
|
+
* @returns
|
|
3641
|
+
*/
|
|
3642
|
+
const randomHue = (rand = Math.random) => rand() * 360;
|
|
3643
|
+
/**
|
|
3644
|
+
* Returns a function to interpolate between colours, with results as a structured {@link Colour} object.
|
|
3645
|
+
* ```js
|
|
3646
|
+
* const i = interpolator([`orange`, `yellow`, `red`]);
|
|
3647
|
+
*
|
|
3648
|
+
* // Get a random colour on the above spectrum
|
|
3649
|
+
* i(Math.random());
|
|
3650
|
+
* ```
|
|
3651
|
+
*
|
|
3652
|
+
* Results will vary depending on the colour space used, play with the options.
|
|
3653
|
+
* When using a hue-based colour space, the `hue` option sets the logic for how hue values wrap.
|
|
3654
|
+
*
|
|
3655
|
+
* ```js
|
|
3656
|
+
* interpolator([`orange`, `yellow`, `red`], { space: `hsl`, hue: `longer })
|
|
3657
|
+
* ```
|
|
3658
|
+
*
|
|
3659
|
+
* Example: Draw the interpolation as a spectrum on a canvas, where each pixel is one step
|
|
3660
|
+
* ```js
|
|
3661
|
+
* let v = 0;
|
|
3662
|
+
* let incrementBy = 0.01;
|
|
3663
|
+
* while (v <= 1) {
|
|
3664
|
+
* // Get colour at this interpolation point 0..1
|
|
3665
|
+
* const colour = fn(v);
|
|
3666
|
+
* // Convert to a CSS string
|
|
3667
|
+
* ctx.fillStyle = Colour.toCssColour(colour);
|
|
3668
|
+
* // Draw a 1px wide rect, and shuffle along to the next x position
|
|
3669
|
+
* ctx.fillRect(x, y, 1, h);
|
|
3670
|
+
* x += 1;
|
|
3671
|
+
* v += incrementBy;
|
|
3672
|
+
* }
|
|
3673
|
+
* ```
|
|
3674
|
+
* @param colours Colours to interpolate between
|
|
3675
|
+
* @param opts Options for interpolation
|
|
3676
|
+
* @returns Function that interpolates based on an amount, returning a structured Colour
|
|
3677
|
+
*/
|
|
3678
|
+
function interpolator(colours, opts = {}) {
|
|
3679
|
+
const direction = opts.direction ?? `shorter`;
|
|
3680
|
+
const destination = opts.destination ?? `oklch-scalar`;
|
|
3681
|
+
const space = opts.space ?? `oklch`;
|
|
3682
|
+
const ranges = interpolateInit(colours, space);
|
|
3683
|
+
const rangeInterpolators = ranges.map((range) => interpolatorDual(range[0], range[1], {
|
|
3684
|
+
space,
|
|
3685
|
+
direction,
|
|
3686
|
+
destination
|
|
3687
|
+
}));
|
|
3688
|
+
const asTargetDestination = colours.map((c) => convert(c, destination));
|
|
3689
|
+
return (amt) => {
|
|
3690
|
+
if (amt >= 1) return asTargetDestination.at(-1);
|
|
3691
|
+
if (amt <= 0) return asTargetDestination.at(0);
|
|
3692
|
+
const s = scaleClamped(amt, 0, 1, 0, ranges.length);
|
|
3693
|
+
const index = Math.floor(s);
|
|
3694
|
+
const amtAdjusted = s - index;
|
|
3695
|
+
const ri = rangeInterpolators[index];
|
|
3696
|
+
return ri(amtAdjusted);
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
/**
|
|
3700
|
+
* Returns a set of pairwise colours, convert to the destination colour space in scalar form
|
|
3701
|
+
* @param colours
|
|
3702
|
+
* @param destination
|
|
3703
|
+
* @returns Array of pairwise colours, converted to destination scalar
|
|
3704
|
+
*/
|
|
3705
|
+
function interpolateInit(colours, destination = `hsl`) {
|
|
3706
|
+
if (!Array.isArray(colours)) throw new Error(`Param 'colours' is not an array as expected. Got: ${typeof colours}`);
|
|
3707
|
+
if (colours.length < 2) throw new Error(`Param 'colours' should be at least two in length. Got: ${colours.length}`);
|
|
3708
|
+
return [...pairwise(colours.map((colour) => convertScalar(colour, destination)))];
|
|
3709
|
+
}
|
|
3710
|
+
/**
|
|
3711
|
+
* Returns a CSS `linear-gradient` with stops corresponding to the given list of `colours`.
|
|
3712
|
+
* ```js
|
|
3713
|
+
* element.style.background = Colour.cssLinearGradient(['red','green','blue']);
|
|
3714
|
+
* ```
|
|
3715
|
+
* @param colours
|
|
3716
|
+
* @returns A 'linear-gradient' string for use in CSS, eg for background.
|
|
3717
|
+
*/
|
|
3718
|
+
function cssLinearGradient(colours) {
|
|
3719
|
+
return `linear-gradient(to right, ${colours.map((c) => toCssColour(c)).join(`, `)})`;
|
|
3720
|
+
}
|
|
3721
|
+
/**
|
|
3722
|
+
* Returns a function that interpolates between two colours. Returns string colour values.
|
|
3723
|
+
* If you want the result as a structured colour, use {@link interpolatorDual} instead.
|
|
3724
|
+
*
|
|
3725
|
+
* By default takes a shorter direction and uses the OkLCH colourspace.
|
|
3726
|
+
* ```js
|
|
3727
|
+
* const i = interpolator(`blue`, `red`);
|
|
3728
|
+
* i(0.5); // Get the colour at 50%, as a string.
|
|
3729
|
+
* ```
|
|
3730
|
+
*
|
|
3731
|
+
* To work with structured colour values, use one of the space's `interpolate` functions.
|
|
3732
|
+
*
|
|
3733
|
+
* If you want to create discrete steps, consider {@link createSteps} or {@link scale}.
|
|
3734
|
+
*
|
|
3735
|
+
* @param colourA First colour
|
|
3736
|
+
* @param colourB Second colour
|
|
3737
|
+
* @param options Interpolation options. By default uses shorter direction and OkLCH colour space.
|
|
3738
|
+
*/
|
|
3739
|
+
function interpolatorDualToString(colourA, colourB, options = {}) {
|
|
3740
|
+
const f = interpolatorDual(colourA, colourB, options);
|
|
3741
|
+
return (amount) => toCssColour(f(amount));
|
|
3742
|
+
}
|
|
3743
|
+
/**
|
|
3744
|
+
* Returns a function that interpolates between two colours. Returns structured colour values.
|
|
3745
|
+
* If you want the result as a ready-to-use CSS string, use {@link interpolatorDualToString} instead.
|
|
3746
|
+
*
|
|
3747
|
+
* By default takes a shorter direction and uses the OkLCH colourspace.
|
|
3748
|
+
* ```js
|
|
3749
|
+
* const i = interpolator(`blue`, `red`);
|
|
3750
|
+
* i(0.5); // Get the colour at 50%, as a Colour structure.
|
|
3751
|
+
* ```
|
|
3752
|
+
*
|
|
3753
|
+
* If you want to create discrete steps, consider {@link createSteps} or {@link scale}.
|
|
3754
|
+
* @param colourA First colour
|
|
3755
|
+
* @param colourB Second colour
|
|
3756
|
+
* @param options Interpolation options. By default uses shorter direction and OkLCH colour space.
|
|
3757
|
+
* @returns Function that interpolates between two colours, returning a structured Colour
|
|
3758
|
+
*/
|
|
3759
|
+
function interpolatorDual(colourA, colourB, options = {}) {
|
|
3760
|
+
const space = options.space ?? `oklch`;
|
|
3761
|
+
const direction = options.direction ?? `shorter`;
|
|
3762
|
+
const destination = options.destination ?? `oklch-scalar`;
|
|
3763
|
+
let inter;
|
|
3764
|
+
switch (space) {
|
|
3765
|
+
case `hsl`: {
|
|
3766
|
+
const hslInter = interpolator$3(convert(colourA, `hsl-scalar`), convert(colourB, `hsl-scalar`), direction);
|
|
3767
|
+
inter = (amount) => {
|
|
3768
|
+
return convert(hslInter(amount), destination);
|
|
3769
|
+
};
|
|
3770
|
+
break;
|
|
3771
|
+
}
|
|
3772
|
+
case `srgb`: {
|
|
3773
|
+
const srgbInter = interpolator$2(convert(colourA, `srgb-scalar`), convert(colourB, `srgb-scalar`));
|
|
3774
|
+
inter = (amount) => {
|
|
3775
|
+
return convert(srgbInter(amount), destination);
|
|
3776
|
+
};
|
|
3777
|
+
break;
|
|
3778
|
+
}
|
|
3779
|
+
default: {
|
|
3780
|
+
const oklchInter = interpolator$1(convert(colourA, `oklch-scalar`), convert(colourB, `oklch-scalar`), direction);
|
|
3781
|
+
inter = (amount) => {
|
|
3782
|
+
return convert(oklchInter(amount), destination);
|
|
3783
|
+
};
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
return (amount) => inter(amount);
|
|
3787
|
+
}
|
|
3788
|
+
/**
|
|
3789
|
+
* Produces a stepped scale of colours.
|
|
3790
|
+
*
|
|
3791
|
+
* Builds off {@link createSteps} which can only step between two colours.
|
|
3792
|
+
*
|
|
3793
|
+
* ```js
|
|
3794
|
+
* // A scale of from red to green, with three colours in-between
|
|
3795
|
+
* const steps = Colour.scale([ `red`, `green` ], { stepsBetween: 3 });
|
|
3796
|
+
* for (const step of steps) {
|
|
3797
|
+
* // A CSS colour string
|
|
3798
|
+
* }
|
|
3799
|
+
* ```
|
|
3800
|
+
*
|
|
3801
|
+
* {@link cssLinearGradient} can produce a smooth gradient in CSS on the basis
|
|
3802
|
+
* of the stepped colours.
|
|
3803
|
+
* @param colours
|
|
3804
|
+
* @param opts
|
|
3805
|
+
* @returns Array of colours in string form
|
|
3806
|
+
*/
|
|
3807
|
+
function scale(colours, opts = {}) {
|
|
3808
|
+
const direction = opts.direction ?? `shorter`;
|
|
3809
|
+
const space = opts.space ?? `oklch`;
|
|
3810
|
+
const pieces = interpolateInit(colours, space);
|
|
3811
|
+
let stepsBetween = 0;
|
|
3812
|
+
if (typeof opts.stepsBetween === `number`) {
|
|
3813
|
+
stepsBetween = opts.stepsBetween;
|
|
3814
|
+
if (stepsBetween < 1) throw new Error(`Param 'stepsBetween' must be at least 1`);
|
|
3815
|
+
} else if (typeof opts.stepsTotal === `number`) {
|
|
3816
|
+
if (opts.stepsTotal <= colours.length) throw new Error(`Param 'stepsTotal' must be greater than number of provided colour stops (${colours.length}) +1 per stop`);
|
|
3817
|
+
const totalSteps = opts.stepsTotal - colours.length;
|
|
3818
|
+
stepsBetween = Math.floor(totalSteps / pieces.length);
|
|
3819
|
+
}
|
|
3820
|
+
const steps = pieces.map((piece) => {
|
|
3821
|
+
const pieceSteps = createSteps(piece[0], piece[1], {
|
|
3822
|
+
steps: stepsBetween,
|
|
3823
|
+
space,
|
|
3824
|
+
direction,
|
|
3825
|
+
exclusive: true
|
|
3826
|
+
});
|
|
3827
|
+
pieceSteps.push(piece[1]);
|
|
3828
|
+
return pieceSteps;
|
|
3829
|
+
});
|
|
3830
|
+
const firstPiece = pieces[0];
|
|
3831
|
+
steps.unshift([firstPiece[0]]);
|
|
3832
|
+
return steps.flat().map((c) => toCssColour(c));
|
|
3833
|
+
}
|
|
3834
|
+
function createSteps(a, b, options = {}) {
|
|
3835
|
+
const exclusive = options.exclusive ?? false;
|
|
3836
|
+
const steps = options.steps ?? 5;
|
|
3837
|
+
const space = options.space ?? `oklch`;
|
|
3838
|
+
const direction = options.direction ?? `shorter`;
|
|
3839
|
+
if (!exclusive && steps < 2) throw new Error(`Param 'steps' should be at least 2 when 'exclusive' is false`);
|
|
3840
|
+
if (exclusive && steps < 1) throw new Error(`Param 'steps' should be at least 1 when 'exlusive' is true`);
|
|
3841
|
+
const aa = convertScalar(a, space);
|
|
3842
|
+
const bb = convertScalar(b, space);
|
|
3843
|
+
let inter;
|
|
3844
|
+
switch (space) {
|
|
3845
|
+
case `hsl`:
|
|
3846
|
+
inter = interpolator$3(aa, bb, direction);
|
|
3847
|
+
break;
|
|
3848
|
+
case `oklch`:
|
|
3849
|
+
inter = interpolator$1(aa, bb, direction);
|
|
3850
|
+
break;
|
|
3851
|
+
case `srgb`:
|
|
3852
|
+
inter = interpolator$2(aa, bb);
|
|
3853
|
+
break;
|
|
3854
|
+
default: throw new Error(`Colour space '${space}' not supported for interpolation.`);
|
|
3855
|
+
}
|
|
3856
|
+
if (!inter) throw new Error(`Could not create interpolator for space: ${space}`);
|
|
3857
|
+
let stepBy = 0;
|
|
3858
|
+
let startAt = 0;
|
|
3859
|
+
let endAt = 1;
|
|
3860
|
+
if (exclusive) {
|
|
3861
|
+
stepBy = 1 / (steps + 1);
|
|
3862
|
+
startAt = stepBy;
|
|
3863
|
+
endAt = 1 - stepBy;
|
|
3864
|
+
} else stepBy = 1 / (steps - 1);
|
|
3865
|
+
const results = [];
|
|
3866
|
+
for (let interpolateAmount = startAt; interpolateAmount <= endAt; interpolateAmount += stepBy) results.push(inter(interpolateAmount));
|
|
3867
|
+
return results;
|
|
3868
|
+
}
|
|
3869
|
+
/**
|
|
3870
|
+
* Multiplies the opacity of a colour by `amount`, returning a computed CSS colour.
|
|
3871
|
+
*
|
|
3872
|
+
* ```js
|
|
3873
|
+
* multiplyOpacity(`red`, 0.5); // Returns a colour string
|
|
3874
|
+
* ```
|
|
3875
|
+
*
|
|
3876
|
+
* For example, to half the opacity, use `amount: 0.5`.
|
|
3877
|
+
* Clamps the result to ensure it's between 0..1
|
|
3878
|
+
* @param colourish Colour
|
|
3879
|
+
* @param amount Amount
|
|
3880
|
+
*/
|
|
3881
|
+
function multiplyOpacity(colourish, amount) {
|
|
3882
|
+
return withOpacity(colourish, (o) => clamp(o * amount));
|
|
3883
|
+
}
|
|
3884
|
+
/**
|
|
3885
|
+
* Does a computation with the opacity of a colour, returning colour.
|
|
3886
|
+
*
|
|
3887
|
+
* Passes operation to `HslSpace` or `SrgbSpace` depending on space of `colourish`.
|
|
3888
|
+
* @param colourish Colour
|
|
3889
|
+
* @param fn Function that takes original opacity as input and returns output opacity
|
|
3890
|
+
*/
|
|
3891
|
+
function withOpacity(colourish, fn) {
|
|
3892
|
+
const colour = toColour(colourish);
|
|
3893
|
+
let result;
|
|
3894
|
+
switch (colour.space) {
|
|
3895
|
+
case `hsl`:
|
|
3896
|
+
result = withOpacity$3(colour, fn);
|
|
3897
|
+
break;
|
|
3898
|
+
case `srgb`:
|
|
3899
|
+
result = withOpacity$2(colour, fn);
|
|
3900
|
+
break;
|
|
3901
|
+
case `oklch`:
|
|
3902
|
+
result = withOpacity$1(colour, fn);
|
|
3903
|
+
break;
|
|
3904
|
+
default: throw new Error(`Unknown space: '${colour.space}'. Expected hsl, srgb, oklch`);
|
|
3905
|
+
}
|
|
3906
|
+
if (!result) throw new Error(`Is colour in correct form?`);
|
|
3907
|
+
if (typeof colourish === `string`) return toCssColour(result);
|
|
3908
|
+
return result;
|
|
3909
|
+
}
|
|
3910
|
+
function setOpacity(colourish, opacity) {
|
|
3911
|
+
const colour = toColour(colourish);
|
|
3912
|
+
colour.opacity = opacity;
|
|
3913
|
+
if (typeof colourish === `string`) return toCssColour(colour);
|
|
3914
|
+
return colour;
|
|
3915
|
+
}
|
|
3916
|
+
/**
|
|
3917
|
+
* Encode 8-bit RGB values into a 24-bit value (0...16_777_215)
|
|
3918
|
+
*
|
|
3919
|
+
* Assumes RGB values are within 0..255 range
|
|
3920
|
+
* @param rgb
|
|
3921
|
+
* @returns
|
|
3922
|
+
*/
|
|
3923
|
+
function encodeRgbTo24Bit(rgb) {
|
|
3924
|
+
return rgb.r << 16 | rgb.g << 8 | rgb.b;
|
|
3925
|
+
}
|
|
3926
|
+
/**
|
|
3927
|
+
* Decode a 24-bit number (0...16_777_215) into 8-bit RGB
|
|
3928
|
+
* @param colour
|
|
3929
|
+
* @returns
|
|
3930
|
+
*/
|
|
3931
|
+
function decodeRgbFrom24Bit(colour) {
|
|
3932
|
+
if (colour > 16777215) throw new TypeError(`Param 'colour' is out of range. Expected max value of 16_777_215, got ${colour}`);
|
|
3933
|
+
return {
|
|
3934
|
+
r: colour >> 16 & 255,
|
|
3935
|
+
g: colour >> 8 & 255,
|
|
3936
|
+
b: colour & 255,
|
|
3937
|
+
unit: `8bit`,
|
|
3938
|
+
space: `srgb`
|
|
3939
|
+
};
|
|
3940
|
+
}
|
|
3941
|
+
/**
|
|
3942
|
+
* Encodes 8-bit RGB value into 16-bit RGB565 (0..65_535)
|
|
3943
|
+
* 5-bit are used for R & B channels, 6 bits for G
|
|
3944
|
+
*
|
|
3945
|
+
* Read more: https://rgbcolorpicker.com/565
|
|
3946
|
+
* @param rgb
|
|
3947
|
+
* @returns
|
|
3948
|
+
*/
|
|
3949
|
+
function encodeRgbTo16Bit565(rgb) {
|
|
3950
|
+
const r = rgb.r >> 3 & 31;
|
|
3951
|
+
const g = rgb.g >> 2 & 63;
|
|
3952
|
+
const b = rgb.b >> 3 & 31;
|
|
3953
|
+
return r << 11 | g << 5 | b;
|
|
3954
|
+
}
|
|
3955
|
+
/**
|
|
3956
|
+
* Decodes 8-bit RGB value from a 16-bit RGB565 value (0...65_535)
|
|
3957
|
+
* Read more: https://rgbcolorpicker.com/565
|
|
3958
|
+
* @param colour
|
|
3959
|
+
* @returns
|
|
3960
|
+
*/
|
|
3961
|
+
function decodeRgbFrom16Bit565(colour) {
|
|
3962
|
+
if (colour > 65535) throw new TypeError(`Param 'colour' is out of range. Expected max: 65_535. Got: ${colour}`);
|
|
3963
|
+
return {
|
|
3964
|
+
r: (colour >> 11 & 31) << 3,
|
|
3965
|
+
g: (colour >> 5 & 63) << 2,
|
|
3966
|
+
b: (colour & 31) << 3,
|
|
3967
|
+
unit: `8bit`,
|
|
3968
|
+
space: `srgb`
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3971
|
+
var ycbcr_exports = /* @__PURE__ */ __exportAll$1({
|
|
3972
|
+
eightBit: () => eightBit,
|
|
3973
|
+
fromCss: () => fromCss,
|
|
3974
|
+
fromHexString: () => fromHexString,
|
|
3975
|
+
fromSrgTo8bit: () => fromSrgTo8bit,
|
|
3976
|
+
guard: () => guard,
|
|
3977
|
+
scalar: () => scalar,
|
|
3978
|
+
to8bit: () => to8bit,
|
|
3979
|
+
toHexString: () => toHexString,
|
|
3980
|
+
toScalar: () => toScalar,
|
|
3981
|
+
toSrgb8bit: () => toSrgb8bit
|
|
3982
|
+
});
|
|
3983
|
+
/**
|
|
3984
|
+
* Creates a YCbCr8bit value from 8bit (0..255) values
|
|
3985
|
+
* @param y Luma 0..255
|
|
3986
|
+
* @param cb Chroma blue 0..255
|
|
3987
|
+
* @param cr Chroma red 0..255
|
|
3988
|
+
* @param opacity 0..255
|
|
3989
|
+
* @returns YCbCr8bit
|
|
3990
|
+
*/
|
|
3991
|
+
function eightBit(y = 100, cb = 100, cr = 100, opacity = 255) {
|
|
3992
|
+
const rgb = {
|
|
3993
|
+
unit: `8bit`,
|
|
3994
|
+
space: `ycbcr`,
|
|
3995
|
+
y,
|
|
3996
|
+
cb,
|
|
3997
|
+
cr,
|
|
3998
|
+
opacity
|
|
3999
|
+
};
|
|
4000
|
+
guard(rgb);
|
|
4001
|
+
return rgb;
|
|
4002
|
+
}
|
|
4003
|
+
/**
|
|
4004
|
+
* Creates a YCbCr8bit value from scalar (0..1) values
|
|
4005
|
+
* @param y Luma 0..1
|
|
4006
|
+
* @param cb Chroma blue 0..1
|
|
4007
|
+
* @param cr Chroma red 0..1
|
|
4008
|
+
* @param opacity 0..1
|
|
4009
|
+
* @returns YCbCrScalar
|
|
4010
|
+
*/
|
|
4011
|
+
function scalar(y = .5, cb = .5, cr = .5, opacity = 1) {
|
|
4012
|
+
const rgb = {
|
|
4013
|
+
unit: `scalar`,
|
|
4014
|
+
space: `ycbcr`,
|
|
4015
|
+
y,
|
|
4016
|
+
cb,
|
|
4017
|
+
cr,
|
|
4018
|
+
opacity
|
|
4019
|
+
};
|
|
4020
|
+
guard(rgb);
|
|
4021
|
+
return rgb;
|
|
4022
|
+
}
|
|
4023
|
+
/**
|
|
4024
|
+
* Converts from scalar or 8bit RGB to YCbCr8bit
|
|
4025
|
+
* @param rgb
|
|
4026
|
+
* @returns
|
|
4027
|
+
*/
|
|
4028
|
+
function fromSrgTo8bit(rgb) {
|
|
4029
|
+
const { r, g, b, opacity } = to8bit$1(rgb);
|
|
4030
|
+
return eightBit(.299 * r + .587 * g + .114 * b + 0, -.169 * r + -.331 * g + .5 * b + 128, .5 * r + -.419 * g + -.081 * b + 128, opacity);
|
|
4031
|
+
}
|
|
4032
|
+
function toSrgb8bit(ycbcr) {
|
|
4033
|
+
const { y, cb, cr, opacity } = to8bit(ycbcr);
|
|
4034
|
+
return {
|
|
4035
|
+
unit: `8bit`,
|
|
4036
|
+
space: `srgb`,
|
|
4037
|
+
r: 1 * y + 0 * (cb - 128) + 1.4 * (cr - 128),
|
|
4038
|
+
g: 1 * y + -.343 * (cb - 128) + -.711 * (cr - 128),
|
|
4039
|
+
b: 1 * y + 1.765 * (cb - 128) + 0 * (cr - 128),
|
|
4040
|
+
opacity
|
|
4041
|
+
};
|
|
4042
|
+
}
|
|
4043
|
+
/**
|
|
4044
|
+
* Returns a YCbCr8bit format from either scalar or 8bit.
|
|
4045
|
+
* If the input is already 8bit, it is returned as-is.
|
|
4046
|
+
* @param ycbcr 8bit or scalar YCbCr value
|
|
4047
|
+
* @returns YCbCr8bit
|
|
4048
|
+
*/
|
|
4049
|
+
function to8bit(ycbcr) {
|
|
4050
|
+
guard(ycbcr);
|
|
4051
|
+
if (ycbcr.unit === `8bit`) return ycbcr;
|
|
4052
|
+
const { y, cb, cr, opacity } = ycbcr;
|
|
4053
|
+
return eightBit(y * 255, cb * 255, cr * 255, typeof opacity === `number` ? opacity * 255 : 255);
|
|
4054
|
+
}
|
|
4055
|
+
function fromHexString(hexString, options = {}) {
|
|
4056
|
+
return fromSrgTo8bit(fromHexString$2(hexString, false));
|
|
4057
|
+
}
|
|
4058
|
+
function fromCss(value, options = {}) {
|
|
4059
|
+
const scalar = options.scalar ?? false;
|
|
4060
|
+
const rgb = fromCss$2(value, {
|
|
4061
|
+
fallbackString: options.fallbackString,
|
|
4062
|
+
scalar: false,
|
|
4063
|
+
ensureSafe: options.ensureSafe
|
|
4064
|
+
});
|
|
4065
|
+
if (scalar) return toScalar(fromSrgTo8bit(rgb));
|
|
4066
|
+
else return fromSrgTo8bit(rgb);
|
|
4067
|
+
}
|
|
4068
|
+
function toScalar(colour) {
|
|
4069
|
+
if (typeof colour === `string`) return fromCss(colour, { scalar: true });
|
|
4070
|
+
if (isHsl(colour) || isRgb(colour)) return toScalar(fromSrgTo8bit(toScalar$2(colour)));
|
|
4071
|
+
guard(colour);
|
|
4072
|
+
if (colour.unit === `scalar`) return colour;
|
|
4073
|
+
const { y, cb, cr, opacity } = colour;
|
|
4074
|
+
return scalar(y / 255, cb / 255, cr / 255, typeof opacity === `number` ? opacity / 255 : 1);
|
|
4075
|
+
}
|
|
4076
|
+
function guard(rgb) {
|
|
4077
|
+
const { y, cb, cr, opacity, space, unit } = rgb;
|
|
4078
|
+
if (space !== `ycbcr`) throw new Error(`Space is expected to be 'ycbcr'. Got: ${space}`);
|
|
4079
|
+
if (unit === `8bit`) resultThrow(numberInclusiveRangeTest(y, 0, 255, `y`), numberInclusiveRangeTest(cb, 0, 255, `cb`), numberInclusiveRangeTest(cr, 0, 255, `cr`), () => {
|
|
4080
|
+
if (typeof opacity === `number`) return numberInclusiveRangeTest(opacity, 0, 255, `opacity`);
|
|
4081
|
+
});
|
|
4082
|
+
else if (unit === `scalar`) resultThrow(numberTest(y, `percentage`, `y`), numberTest(cb, `percentage`, `cb`), numberTest(cr, `percentage`, `cr`), () => {
|
|
4083
|
+
if (typeof opacity === `number`) return numberTest(opacity, `percentage`, `opacity`);
|
|
4084
|
+
});
|
|
4085
|
+
else throw new Error(`Unit is expected to be '8bit' or 'scalar'. Got: ${unit}`);
|
|
4086
|
+
}
|
|
4087
|
+
/**
|
|
4088
|
+
* Converts a YCbCr colour to a RGB hex string.
|
|
4089
|
+
* @param ycbcr
|
|
4090
|
+
* @returns
|
|
4091
|
+
*/
|
|
4092
|
+
function toHexString(ycbcr) {
|
|
4093
|
+
return toHexString$2(toSrgb8bit(ycbcr));
|
|
4094
|
+
}
|
|
4095
|
+
var colour_exports = /* @__PURE__ */ __exportAll$1({
|
|
4096
|
+
HslSpace: () => hsl_exports,
|
|
4097
|
+
OklchSpace: () => oklch_exports,
|
|
4098
|
+
SrgbSpace: () => srgb_exports,
|
|
4099
|
+
YCbCrSpace: () => ycbcr_exports,
|
|
4100
|
+
convert: () => convert,
|
|
4101
|
+
convertScalar: () => convertScalar,
|
|
4102
|
+
convertToString: () => convertToString,
|
|
4103
|
+
createSteps: () => createSteps,
|
|
4104
|
+
cssDefinedHexColours: () => cssDefinedHexColours,
|
|
4105
|
+
cssLinearGradient: () => cssLinearGradient,
|
|
4106
|
+
decodeRgbFrom16Bit565: () => decodeRgbFrom16Bit565,
|
|
4107
|
+
decodeRgbFrom24Bit: () => decodeRgbFrom24Bit,
|
|
4108
|
+
encodeRgbTo16Bit565: () => encodeRgbTo16Bit565,
|
|
4109
|
+
encodeRgbTo24Bit: () => encodeRgbTo24Bit,
|
|
4110
|
+
fromCssColour: () => fromCssColour,
|
|
4111
|
+
goldenAngleColour: () => goldenAngleColour,
|
|
4112
|
+
guard: () => guard$1,
|
|
4113
|
+
interpolator: () => interpolator,
|
|
4114
|
+
interpolatorDual: () => interpolatorDual,
|
|
4115
|
+
interpolatorDualToString: () => interpolatorDualToString,
|
|
4116
|
+
isColourish: () => isColourish,
|
|
4117
|
+
isHsl: () => isHsl,
|
|
4118
|
+
isOkLch: () => isOkLch,
|
|
4119
|
+
isRgb: () => isRgb,
|
|
4120
|
+
multiplyOpacity: () => multiplyOpacity,
|
|
4121
|
+
randomHue: () => randomHue,
|
|
4122
|
+
resolveCss: () => resolveCss,
|
|
4123
|
+
rgbToHsl: () => rgbToHsl,
|
|
4124
|
+
scale: () => scale,
|
|
4125
|
+
setOpacity: () => setOpacity,
|
|
4126
|
+
toColour: () => toColour,
|
|
4127
|
+
toCssColour: () => toCssColour,
|
|
4128
|
+
toHexColour: () => toHexColour,
|
|
4129
|
+
toLibraryColour: () => toLibraryColour,
|
|
4130
|
+
toStringFirst: () => toStringFirst,
|
|
4131
|
+
tryParseObjectToHsl: () => tryParseObjectToHsl,
|
|
4132
|
+
tryParseObjectToRgb: () => tryParseObjectToRgb,
|
|
4133
|
+
withOpacity: () => withOpacity
|
|
4134
|
+
});
|
|
4135
|
+
//#endregion
|
|
4136
|
+
export { isPoint3d as A, guard$5 as C, isNull as D, isNaN as E, __exportAll as M, isPlaceholder as O, toString as S, isEmpty as T, getTwoPointParameters as _, Unit3d as a, to3d as b, angleRadianThreePoint as c, fromCartesian as d, rotate$1 as f, getPointParameter as g, distance2d as h, Unit as i, test as j, isPoint as k, average$1 as l, distance as m, Empty as n, angleRadian as o, toCartesian$1 as p, Empty3d as r, angleRadianCircle as s, colour_exports as t, averager as u, subtract as v, guardNonZeroPoint as w, toIntegerValues as x, to2d as y };
|
|
4137
|
+
|
|
4138
|
+
//# sourceMappingURL=colour-C3MQIjFJ-BJV-QC-3.js.map
|