@a_ng_d/utils-ui-color-palette 1.7.1 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -3
- package/dist/modules/color-harmony/color-harmony.d.ts +1 -0
- package/dist/modules/color-harmony/color-harmony.d.ts.map +1 -1
- package/dist/modules/color-harmony/color-harmony.js +57 -46
- package/dist/modules/color-harmony/color-harmony.js.map +1 -1
- package/dist/modules/dominant-colors/dominant-colors.d.ts +18 -3
- package/dist/modules/dominant-colors/dominant-colors.d.ts.map +1 -1
- package/dist/modules/dominant-colors/dominant-colors.js +137 -64
- package/dist/modules/dominant-colors/dominant-colors.js.map +1 -1
- package/dist/types/color.types.d.ts +1 -1
- package/dist/types/color.types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ UI Color Palette is available for:
|
|
|
36
36
|
|
|
37
37
|
- **Color Harmony Generation**:
|
|
38
38
|
|
|
39
|
-
- Generate analogous, complementary, triadic, tetradic, and
|
|
39
|
+
- Generate analogous, complementary, triadic, tetradic, square, and compound color harmonies
|
|
40
40
|
- Configurable analogous spread angle
|
|
41
41
|
- Automatic color relationship calculations
|
|
42
42
|
- Support for all major color harmony types
|
|
@@ -184,6 +184,52 @@ dominantColors.updateOptions({
|
|
|
184
184
|
const options = dominantColors.getOptions()
|
|
185
185
|
```
|
|
186
186
|
|
|
187
|
+
#### Working with File Uploads (ArrayBuffer)
|
|
188
|
+
|
|
189
|
+
For modern web applications that need to extract colors from uploaded image files:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { DominantColors } from '@a_ng_d/utils-ui-color-palette'
|
|
193
|
+
|
|
194
|
+
// Handle file upload from user input
|
|
195
|
+
const handleImageUpload = async (event: Event) => {
|
|
196
|
+
const file = (event.target as HTMLInputElement).files?.[0]
|
|
197
|
+
if (!file) return
|
|
198
|
+
|
|
199
|
+
// Convert file to ArrayBuffer
|
|
200
|
+
const arrayBuffer = await file.arrayBuffer()
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
// Simple usage: extract 5 dominant colors
|
|
204
|
+
const colors = await DominantColors.extract(arrayBuffer, 5)
|
|
205
|
+
|
|
206
|
+
console.log('Extracted colors:', colors)
|
|
207
|
+
// Each color object contains: { color, hex, percentage, count }
|
|
208
|
+
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Error extracting colors:', error)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Advanced usage with custom options
|
|
215
|
+
const extractColorsAdvanced = async (arrayBuffer: ArrayBuffer) => {
|
|
216
|
+
const colors = await DominantColors.fromArrayBuffer(arrayBuffer, {
|
|
217
|
+
colorCount: 8,
|
|
218
|
+
maxIterations: 100,
|
|
219
|
+
tolerance: 0.005,
|
|
220
|
+
skipTransparent: true,
|
|
221
|
+
maxImageSize: 300, // Resize large images for faster processing
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
return colors
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// HTML file input example
|
|
228
|
+
// <input type="file" accept="image/*" onChange={handleImageUpload} />
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Note**: ArrayBuffer extraction requires a browser environment with Canvas API support.
|
|
232
|
+
|
|
187
233
|
### Color Harmony Generation
|
|
188
234
|
|
|
189
235
|
```typescript
|
|
@@ -201,11 +247,12 @@ const complementary = colorHarmony.generateComplementary()
|
|
|
201
247
|
const triadic = colorHarmony.generateTriadic()
|
|
202
248
|
const tetradic = colorHarmony.generateTetradic()
|
|
203
249
|
const square = colorHarmony.generateSquare()
|
|
250
|
+
const compound = colorHarmony.generateCompound()
|
|
204
251
|
|
|
205
252
|
// Generate harmony by type
|
|
206
|
-
const harmony = colorHarmony.generateHarmony('
|
|
253
|
+
const harmony = colorHarmony.generateHarmony('TRIADIC')
|
|
207
254
|
|
|
208
|
-
// Generate all harmonies at once
|
|
255
|
+
// Generate all harmonies at once (now includes 6 harmonies)
|
|
209
256
|
const allHarmonies = colorHarmony.getAllHarmonies()
|
|
210
257
|
|
|
211
258
|
// Results contain both RGB and hex values
|
|
@@ -12,6 +12,7 @@ export default class ColorHarmony {
|
|
|
12
12
|
generateTriadic: () => ColorHarmonyResult;
|
|
13
13
|
generateTetradic: () => ColorHarmonyResult;
|
|
14
14
|
generateSquare: () => ColorHarmonyResult;
|
|
15
|
+
generateCompound: () => ColorHarmonyResult;
|
|
15
16
|
generateHarmony: (type: HarmonyType) => ColorHarmonyResult;
|
|
16
17
|
getAllHarmonies: () => ColorHarmonyResult[];
|
|
17
18
|
private normalizeHue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-harmony.d.ts","sourceRoot":"","sources":["../../../src/modules/color-harmony/color-harmony.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EAEP,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AAEzB,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,YAAY,CAAwB;gBAEhC,EACV,SAAuB,EACvB,eAAoB,EACpB,YAAqB,GACtB,EAAE;QACD,SAAS,CAAC,EAAE,OAAO,CAAA;KACpB,GAAG,mBAAmB;IAMvB,iBAAiB,QAAO,kBAAkB,CAmBzC;IAED,qBAAqB,QAAO,kBAAkB,CAU7C;IAED,eAAe,QAAO,kBAAkB,CAWvC;IAED,gBAAgB,QAAO,kBAAkB,CAYxC;IAED,cAAc,QAAO,kBAAkB,CAYtC;IAED,eAAe,SAAU,WAAW,KAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"color-harmony.d.ts","sourceRoot":"","sources":["../../../src/modules/color-harmony/color-harmony.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EAEP,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AAEzB,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,YAAY,CAAwB;gBAEhC,EACV,SAAuB,EACvB,eAAoB,EACpB,YAAqB,GACtB,EAAE;QACD,SAAS,CAAC,EAAE,OAAO,CAAA;KACpB,GAAG,mBAAmB;IAMvB,iBAAiB,QAAO,kBAAkB,CAmBzC;IAED,qBAAqB,QAAO,kBAAkB,CAU7C;IAED,eAAe,QAAO,kBAAkB,CAWvC;IAED,gBAAgB,QAAO,kBAAkB,CAYxC;IAED,cAAc,QAAO,kBAAkB,CAYtC;IAED,gBAAgB,QAAO,kBAAkB,CAYxC;IAED,eAAe,SAAU,WAAW,KAAG,kBAAkB,CAiBxD;IAED,eAAe,QAAO,kBAAkB,EAAE,CASzC;IAED,OAAO,CAAC,YAAY,CAInB;IAED,OAAO,CAAC,QAAQ,CAOf;IAED,OAAO,CAAC,YAAY,CA8BnB;IAED,YAAY,UAAW,OAAO,KAAG,IAAI,CAEpC;IAED,kBAAkB,WAAY,MAAM,KAAG,IAAI,CAE1C;IAED,aAAa,YAAa,OAAO,CAAC,mBAAmB,CAAC,KAAG,IAAI,CAO5D;IAED,UAAU,QAAO,mBAAmB,CAGlC;CACH"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
var i = Object.defineProperty;
|
|
2
|
-
var u = (
|
|
3
|
-
var
|
|
4
|
-
import { c as
|
|
2
|
+
var u = (h, e, t) => e in h ? i(h, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[e] = t;
|
|
3
|
+
var o = (h, e, t) => u(h, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { c as r } from "../../index-Beb8qoyd.js";
|
|
5
5
|
class m {
|
|
6
6
|
constructor({
|
|
7
7
|
baseColor: e = [255, 0, 0],
|
|
8
8
|
analogousSpread: t = 30,
|
|
9
9
|
returnFormat: s = "both"
|
|
10
10
|
}) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const e =
|
|
11
|
+
o(this, "baseColor");
|
|
12
|
+
o(this, "analogousSpread");
|
|
13
|
+
o(this, "returnFormat");
|
|
14
|
+
o(this, "generateAnalogous", () => {
|
|
15
|
+
const e = r(this.baseColor).hsl(), t = e[0] || 0, s = [
|
|
16
16
|
this.baseColor,
|
|
17
17
|
this.hueToRgb(
|
|
18
18
|
this.normalizeHue(t - this.analogousSpread),
|
|
@@ -25,82 +25,93 @@ class m {
|
|
|
25
25
|
e[2]
|
|
26
26
|
)
|
|
27
27
|
];
|
|
28
|
-
return this.formatResult("
|
|
28
|
+
return this.formatResult("ANALOGOUS", s);
|
|
29
29
|
});
|
|
30
|
-
|
|
31
|
-
const e =
|
|
30
|
+
o(this, "generateComplementary", () => {
|
|
31
|
+
const e = r(this.baseColor).hsl(), t = e[0] || 0, s = [
|
|
32
32
|
this.baseColor,
|
|
33
33
|
this.hueToRgb(this.normalizeHue(t + 180), e[1], e[2])
|
|
34
34
|
];
|
|
35
|
-
return this.formatResult("
|
|
35
|
+
return this.formatResult("COMPLEMENTARY", s);
|
|
36
36
|
});
|
|
37
|
-
|
|
38
|
-
const e =
|
|
37
|
+
o(this, "generateTriadic", () => {
|
|
38
|
+
const e = r(this.baseColor).hsl(), t = e[0] || 0, s = [
|
|
39
39
|
this.baseColor,
|
|
40
40
|
this.hueToRgb(this.normalizeHue(t + 120), e[1], e[2]),
|
|
41
41
|
this.hueToRgb(this.normalizeHue(t + 240), e[1], e[2])
|
|
42
42
|
];
|
|
43
|
-
return this.formatResult("
|
|
43
|
+
return this.formatResult("TRIADIC", s);
|
|
44
44
|
});
|
|
45
|
-
|
|
46
|
-
const e =
|
|
45
|
+
o(this, "generateTetradic", () => {
|
|
46
|
+
const e = r(this.baseColor).hsl(), t = e[0] || 0, s = [
|
|
47
47
|
this.baseColor,
|
|
48
48
|
this.hueToRgb(this.normalizeHue(t + 90), e[1], e[2]),
|
|
49
49
|
this.hueToRgb(this.normalizeHue(t + 180), e[1], e[2]),
|
|
50
50
|
this.hueToRgb(this.normalizeHue(t + 270), e[1], e[2])
|
|
51
51
|
];
|
|
52
|
-
return this.formatResult("
|
|
52
|
+
return this.formatResult("TETRADIC", s);
|
|
53
53
|
});
|
|
54
|
-
|
|
55
|
-
const e =
|
|
54
|
+
o(this, "generateSquare", () => {
|
|
55
|
+
const e = r(this.baseColor).hsl(), t = e[0] || 0, s = [
|
|
56
56
|
this.baseColor,
|
|
57
57
|
this.hueToRgb(this.normalizeHue(t + 90), e[1], e[2]),
|
|
58
58
|
this.hueToRgb(this.normalizeHue(t + 180), e[1], e[2]),
|
|
59
59
|
this.hueToRgb(this.normalizeHue(t + 270), e[1], e[2])
|
|
60
60
|
];
|
|
61
|
-
return this.formatResult("
|
|
61
|
+
return this.formatResult("SQUARE", s);
|
|
62
62
|
});
|
|
63
|
-
|
|
63
|
+
o(this, "generateCompound", () => {
|
|
64
|
+
const e = r(this.baseColor).hsl(), t = e[0] || 0, s = this.normalizeHue(t + 180), a = [
|
|
65
|
+
this.baseColor,
|
|
66
|
+
this.hueToRgb(this.normalizeHue(s - 30), e[1], e[2]),
|
|
67
|
+
this.hueToRgb(this.normalizeHue(s + 30), e[1], e[2])
|
|
68
|
+
];
|
|
69
|
+
return this.formatResult("COMPOUND", a);
|
|
70
|
+
});
|
|
71
|
+
o(this, "generateHarmony", (e) => {
|
|
64
72
|
switch (e) {
|
|
65
|
-
case "
|
|
73
|
+
case "ANALOGOUS":
|
|
66
74
|
return this.generateAnalogous();
|
|
67
|
-
case "
|
|
75
|
+
case "COMPLEMENTARY":
|
|
68
76
|
return this.generateComplementary();
|
|
69
|
-
case "
|
|
77
|
+
case "TRIADIC":
|
|
70
78
|
return this.generateTriadic();
|
|
71
|
-
case "
|
|
79
|
+
case "TETRADIC":
|
|
72
80
|
return this.generateTetradic();
|
|
73
|
-
case "
|
|
81
|
+
case "SQUARE":
|
|
74
82
|
return this.generateSquare();
|
|
83
|
+
case "COMPOUND":
|
|
84
|
+
return this.generateCompound();
|
|
75
85
|
default:
|
|
76
86
|
throw new Error(`Unknown harmony type: ${e}`);
|
|
77
87
|
}
|
|
78
88
|
});
|
|
79
|
-
|
|
89
|
+
o(this, "getAllHarmonies", () => [
|
|
80
90
|
this.generateAnalogous(),
|
|
81
91
|
this.generateComplementary(),
|
|
82
92
|
this.generateTriadic(),
|
|
83
93
|
this.generateTetradic(),
|
|
84
|
-
this.generateSquare()
|
|
94
|
+
this.generateSquare(),
|
|
95
|
+
this.generateCompound()
|
|
85
96
|
]);
|
|
86
|
-
|
|
97
|
+
o(this, "normalizeHue", (e) => {
|
|
87
98
|
for (; e < 0; ) e += 360;
|
|
88
99
|
for (; e >= 360; ) e -= 360;
|
|
89
100
|
return e;
|
|
90
101
|
});
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
return [Math.round(
|
|
102
|
+
o(this, "hueToRgb", (e, t, s) => {
|
|
103
|
+
const a = r.hsl(e, t, s).rgb();
|
|
104
|
+
return [Math.round(a[0]), Math.round(a[1]), Math.round(a[2])];
|
|
94
105
|
});
|
|
95
|
-
|
|
106
|
+
o(this, "formatResult", (e, t) => {
|
|
96
107
|
const s = t.map(
|
|
97
|
-
(
|
|
98
|
-
Math.round(
|
|
99
|
-
Math.round(
|
|
100
|
-
Math.round(
|
|
108
|
+
(n) => [
|
|
109
|
+
Math.round(n[0]),
|
|
110
|
+
Math.round(n[1]),
|
|
111
|
+
Math.round(n[2])
|
|
101
112
|
]
|
|
102
|
-
),
|
|
103
|
-
(
|
|
113
|
+
), a = s.map(
|
|
114
|
+
(n) => r.rgb(n[0], n[1], n[2]).hex()
|
|
104
115
|
);
|
|
105
116
|
return {
|
|
106
117
|
type: e,
|
|
@@ -109,21 +120,21 @@ class m {
|
|
|
109
120
|
Math.round(this.baseColor[1]),
|
|
110
121
|
Math.round(this.baseColor[2])
|
|
111
122
|
],
|
|
112
|
-
baseHex:
|
|
123
|
+
baseHex: r.rgb(this.baseColor[0], this.baseColor[1], this.baseColor[2]).hex(),
|
|
113
124
|
colors: s,
|
|
114
|
-
hexColors:
|
|
125
|
+
hexColors: a
|
|
115
126
|
};
|
|
116
127
|
});
|
|
117
|
-
|
|
128
|
+
o(this, "setBaseColor", (e) => {
|
|
118
129
|
this.baseColor = e;
|
|
119
130
|
});
|
|
120
|
-
|
|
131
|
+
o(this, "setAnalogousSpread", (e) => {
|
|
121
132
|
this.analogousSpread = Math.max(1, Math.min(e, 180));
|
|
122
133
|
});
|
|
123
|
-
|
|
134
|
+
o(this, "updateOptions", (e) => {
|
|
124
135
|
e.analogousSpread !== void 0 && this.setAnalogousSpread(e.analogousSpread), e.returnFormat !== void 0 && (this.returnFormat = e.returnFormat);
|
|
125
136
|
});
|
|
126
|
-
|
|
137
|
+
o(this, "getOptions", () => ({
|
|
127
138
|
analogousSpread: this.analogousSpread,
|
|
128
139
|
returnFormat: this.returnFormat
|
|
129
140
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-harmony.js","sources":["../../../src/modules/color-harmony/color-harmony.ts"],"sourcesContent":["import chroma from 'chroma-js'\nimport {\n Channel,\n HexModel,\n HarmonyType,\n ColorHarmonyResult,\n ColorHarmonyOptions,\n} from '@tps/color.types'\n\nexport default class ColorHarmony {\n private baseColor: Channel\n private analogousSpread: number\n private returnFormat: 'rgb' | 'hex' | 'both'\n\n constructor({\n baseColor = [255, 0, 0],\n analogousSpread = 30,\n returnFormat = 'both',\n }: {\n baseColor?: Channel\n } & ColorHarmonyOptions) {\n this.baseColor = baseColor\n this.analogousSpread = analogousSpread\n this.returnFormat = returnFormat\n }\n\n generateAnalogous = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(\n this.normalizeHue(baseHue - this.analogousSpread),\n hsl[1],\n hsl[2]\n ),\n this.hueToRgb(\n this.normalizeHue(baseHue + this.analogousSpread),\n hsl[1],\n hsl[2]\n ),\n ]\n\n return this.formatResult('analogous', colors)\n }\n\n generateComplementary = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 180), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('complementary', colors)\n }\n\n generateTriadic = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 120), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 240), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('triadic', colors)\n }\n\n generateTetradic = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 90), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 180), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 270), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('tetradic', colors)\n }\n\n generateSquare = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 90), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 180), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 270), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('square', colors)\n }\n\n generateHarmony = (type: HarmonyType): ColorHarmonyResult => {\n switch (type) {\n case 'analogous':\n return this.generateAnalogous()\n case 'complementary':\n return this.generateComplementary()\n case 'triadic':\n return this.generateTriadic()\n case 'tetradic':\n return this.generateTetradic()\n case 'square':\n return this.generateSquare()\n default:\n throw new Error(`Unknown harmony type: ${type}`)\n }\n }\n\n getAllHarmonies = (): ColorHarmonyResult[] => {\n return [\n this.generateAnalogous(),\n this.generateComplementary(),\n this.generateTriadic(),\n this.generateTetradic(),\n this.generateSquare(),\n ]\n }\n\n private normalizeHue = (hue: number): number => {\n while (hue < 0) hue += 360\n while (hue >= 360) hue -= 360\n return hue\n }\n\n private hueToRgb = (\n hue: number,\n saturation: number,\n lightness: number\n ): Channel => {\n const rgb = chroma.hsl(hue, saturation, lightness).rgb()\n return [Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2])]\n }\n\n private formatResult = (\n type: HarmonyType,\n colors: Channel[]\n ): ColorHarmonyResult => {\n const cleanColors = colors.map(\n (color) =>\n [\n Math.round(color[0]),\n Math.round(color[1]),\n Math.round(color[2]),\n ] as Channel\n )\n\n const hexColors = cleanColors.map(\n (color) => chroma.rgb(color[0], color[1], color[2]).hex() as HexModel\n )\n\n return {\n type,\n baseColor: [\n Math.round(this.baseColor[0]),\n Math.round(this.baseColor[1]),\n Math.round(this.baseColor[2]),\n ],\n baseHex: chroma\n .rgb(this.baseColor[0], this.baseColor[1], this.baseColor[2])\n .hex() as HexModel,\n colors: cleanColors,\n hexColors,\n }\n }\n\n setBaseColor = (color: Channel): void => {\n this.baseColor = color\n }\n\n setAnalogousSpread = (spread: number): void => {\n this.analogousSpread = Math.max(1, Math.min(spread, 180))\n }\n\n updateOptions = (options: Partial<ColorHarmonyOptions>): void => {\n if (options.analogousSpread !== undefined) {\n this.setAnalogousSpread(options.analogousSpread)\n }\n if (options.returnFormat !== undefined) {\n this.returnFormat = options.returnFormat\n }\n }\n\n getOptions = (): ColorHarmonyOptions => ({\n analogousSpread: this.analogousSpread,\n returnFormat: this.returnFormat,\n })\n}\n"],"names":["ColorHarmony","baseColor","analogousSpread","returnFormat","__publicField","hsl","chroma","baseHue","colors","type","hue","saturation","lightness","rgb","cleanColors","color","hexColors","spread","options"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"color-harmony.js","sources":["../../../src/modules/color-harmony/color-harmony.ts"],"sourcesContent":["import chroma from 'chroma-js'\nimport {\n Channel,\n HexModel,\n HarmonyType,\n ColorHarmonyResult,\n ColorHarmonyOptions,\n} from '@tps/color.types'\n\nexport default class ColorHarmony {\n private baseColor: Channel\n private analogousSpread: number\n private returnFormat: 'rgb' | 'hex' | 'both'\n\n constructor({\n baseColor = [255, 0, 0],\n analogousSpread = 30,\n returnFormat = 'both',\n }: {\n baseColor?: Channel\n } & ColorHarmonyOptions) {\n this.baseColor = baseColor\n this.analogousSpread = analogousSpread\n this.returnFormat = returnFormat\n }\n\n generateAnalogous = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(\n this.normalizeHue(baseHue - this.analogousSpread),\n hsl[1],\n hsl[2]\n ),\n this.hueToRgb(\n this.normalizeHue(baseHue + this.analogousSpread),\n hsl[1],\n hsl[2]\n ),\n ]\n\n return this.formatResult('ANALOGOUS', colors)\n }\n\n generateComplementary = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 180), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('COMPLEMENTARY', colors)\n }\n\n generateTriadic = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 120), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 240), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('TRIADIC', colors)\n }\n\n generateTetradic = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 90), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 180), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 270), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('TETRADIC', colors)\n }\n\n generateSquare = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(baseHue + 90), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 180), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(baseHue + 270), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('SQUARE', colors)\n }\n\n generateCompound = (): ColorHarmonyResult => {\n const hsl = chroma(this.baseColor).hsl()\n const baseHue = hsl[0] || 0\n const complementaryHue = this.normalizeHue(baseHue + 180)\n\n const colors = [\n this.baseColor,\n this.hueToRgb(this.normalizeHue(complementaryHue - 30), hsl[1], hsl[2]),\n this.hueToRgb(this.normalizeHue(complementaryHue + 30), hsl[1], hsl[2]),\n ]\n\n return this.formatResult('COMPOUND', colors)\n }\n\n generateHarmony = (type: HarmonyType): ColorHarmonyResult => {\n switch (type) {\n case 'ANALOGOUS':\n return this.generateAnalogous()\n case 'COMPLEMENTARY':\n return this.generateComplementary()\n case 'TRIADIC':\n return this.generateTriadic()\n case 'TETRADIC':\n return this.generateTetradic()\n case 'SQUARE':\n return this.generateSquare()\n case 'COMPOUND':\n return this.generateCompound()\n default:\n throw new Error(`Unknown harmony type: ${type}`)\n }\n }\n\n getAllHarmonies = (): ColorHarmonyResult[] => {\n return [\n this.generateAnalogous(),\n this.generateComplementary(),\n this.generateTriadic(),\n this.generateTetradic(),\n this.generateSquare(),\n this.generateCompound(),\n ]\n }\n\n private normalizeHue = (hue: number): number => {\n while (hue < 0) hue += 360\n while (hue >= 360) hue -= 360\n return hue\n }\n\n private hueToRgb = (\n hue: number,\n saturation: number,\n lightness: number\n ): Channel => {\n const rgb = chroma.hsl(hue, saturation, lightness).rgb()\n return [Math.round(rgb[0]), Math.round(rgb[1]), Math.round(rgb[2])]\n }\n\n private formatResult = (\n type: HarmonyType,\n colors: Channel[]\n ): ColorHarmonyResult => {\n const cleanColors = colors.map(\n (color) =>\n [\n Math.round(color[0]),\n Math.round(color[1]),\n Math.round(color[2]),\n ] as Channel\n )\n\n const hexColors = cleanColors.map(\n (color) => chroma.rgb(color[0], color[1], color[2]).hex() as HexModel\n )\n\n return {\n type,\n baseColor: [\n Math.round(this.baseColor[0]),\n Math.round(this.baseColor[1]),\n Math.round(this.baseColor[2]),\n ],\n baseHex: chroma\n .rgb(this.baseColor[0], this.baseColor[1], this.baseColor[2])\n .hex() as HexModel,\n colors: cleanColors,\n hexColors,\n }\n }\n\n setBaseColor = (color: Channel): void => {\n this.baseColor = color\n }\n\n setAnalogousSpread = (spread: number): void => {\n this.analogousSpread = Math.max(1, Math.min(spread, 180))\n }\n\n updateOptions = (options: Partial<ColorHarmonyOptions>): void => {\n if (options.analogousSpread !== undefined) {\n this.setAnalogousSpread(options.analogousSpread)\n }\n if (options.returnFormat !== undefined) {\n this.returnFormat = options.returnFormat\n }\n }\n\n getOptions = (): ColorHarmonyOptions => ({\n analogousSpread: this.analogousSpread,\n returnFormat: this.returnFormat,\n })\n}\n"],"names":["ColorHarmony","baseColor","analogousSpread","returnFormat","__publicField","hsl","chroma","baseHue","colors","complementaryHue","type","hue","saturation","lightness","rgb","cleanColors","color","hexColors","spread","options"],"mappings":"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"}
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import { ImageData, DominantColorResult, DominantColorsOptions } from '../../types/color.types';
|
|
2
2
|
|
|
3
|
+
interface DominantColorsInput extends DominantColorsOptions {
|
|
4
|
+
imageData?: ImageData;
|
|
5
|
+
arrayBuffer?: ArrayBuffer;
|
|
6
|
+
maxImageSize?: number;
|
|
7
|
+
}
|
|
3
8
|
export default class DominantColors {
|
|
4
9
|
private imageData;
|
|
5
10
|
private colorCount;
|
|
6
11
|
private maxIterations;
|
|
7
12
|
private tolerance;
|
|
8
13
|
private skipTransparent;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
private maxImageSize;
|
|
15
|
+
constructor({ imageData, arrayBuffer, colorCount, maxIterations, tolerance, skipTransparent, maxImageSize, }: DominantColorsInput);
|
|
16
|
+
private arrayBuffer?;
|
|
17
|
+
private ensureImageData;
|
|
18
|
+
private decodeImageFromArrayBuffer;
|
|
19
|
+
/** Synchronous extraction for ImageData (backward compatibility) */
|
|
12
20
|
extractDominantColors: () => DominantColorResult[];
|
|
21
|
+
/** Asynchronous extraction for ArrayBuffer */
|
|
22
|
+
extractDominantColorsAsync: () => Promise<DominantColorResult[]>;
|
|
13
23
|
private extractPixels;
|
|
14
24
|
private performKMeans;
|
|
15
25
|
private initializeCentroids;
|
|
@@ -21,5 +31,10 @@ export default class DominantColors {
|
|
|
21
31
|
setColorCount: (count: number) => void;
|
|
22
32
|
updateOptions: (options: Partial<DominantColorsOptions>) => void;
|
|
23
33
|
getOptions: () => DominantColorsOptions;
|
|
34
|
+
/** Static method for simplified ArrayBuffer usage */
|
|
35
|
+
static fromArrayBuffer(arrayBuffer: ArrayBuffer, options?: Omit<DominantColorsInput, 'arrayBuffer' | 'imageData'>): Promise<DominantColorResult[]>;
|
|
36
|
+
/** Simplified static method for quick color extraction */
|
|
37
|
+
static extract(arrayBuffer: ArrayBuffer, colorCount?: number): Promise<DominantColorResult[]>;
|
|
24
38
|
}
|
|
39
|
+
export {};
|
|
25
40
|
//# sourceMappingURL=dominant-colors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dominant-colors.d.ts","sourceRoot":"","sources":["../../../src/modules/dominant-colors/dominant-colors.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,SAAS,EACT,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,kBAAkB,CAAA;AAEzB,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"dominant-colors.d.ts","sourceRoot":"","sources":["../../../src/modules/dominant-colors/dominant-colors.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,SAAS,EACT,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,kBAAkB,CAAA;AAEzB,UAAU,mBAAoB,SAAQ,qBAAqB;IACzD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAQ;gBAEhB,EACV,SAAS,EACT,WAAW,EACX,UAAc,EACd,aAAkB,EAClB,SAAgB,EAChB,eAAsB,EACtB,YAAkB,GACnB,EAAE,mBAAmB;IAiBtB,OAAO,CAAC,WAAW,CAAC,CAAa;YAEnB,eAAe;YAMf,0BAA0B;IA2ExC,oEAAoE;IACpE,qBAAqB,QAAO,mBAAmB,EAAE,CAchD;IAED,8CAA8C;IAC9C,0BAA0B,QAAa,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAgBpE;IAED,OAAO,CAAC,aAAa,CAoBpB;IAED,OAAO,CAAC,aAAa,CA+BpB;IAED,OAAO,CAAC,mBAAmB,CA8B1B;IAED,OAAO,CAAC,mBAAmB,CAgB1B;IAED,OAAO,CAAC,iBAAiB,CAOxB;IAED,OAAO,CAAC,iBAAiB,CAWxB;IAED,OAAO,CAAC,YAAY,CAUnB;IAED,OAAO,CAAC,yBAAyB,CAmBhC;IAED,aAAa,UAAW,MAAM,KAAG,IAAI,CAEpC;IAED,aAAa,YAAa,OAAO,CAAC,qBAAqB,CAAC,KAAG,IAAI,CAO9D;IAED,UAAU,QAAO,qBAAqB,CAKpC;IAEF,qDAAqD;WACxC,eAAe,CAC1B,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,IAAI,CAAC,mBAAmB,EAAE,aAAa,GAAG,WAAW,CAAM,GACnE,OAAO,CAAC,mBAAmB,EAAE,CAAC;IASjC,0DAA0D;WAC7C,OAAO,CAClB,WAAW,EAAE,WAAW,EACxB,UAAU,GAAE,MAAU,GACrB,OAAO,CAAC,mBAAmB,EAAE,CAAC;CAGlC"}
|
|
@@ -1,86 +1,108 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { c as
|
|
5
|
-
class
|
|
1
|
+
var C = Object.defineProperty;
|
|
2
|
+
var x = (l, t, e) => t in l ? C(l, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[t] = e;
|
|
3
|
+
var i = (l, t, e) => x(l, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { c as p } from "../../index-Beb8qoyd.js";
|
|
5
|
+
class f {
|
|
6
6
|
constructor({
|
|
7
7
|
imageData: t,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
arrayBuffer: e,
|
|
9
|
+
colorCount: a = 5,
|
|
10
|
+
maxIterations: r = 50,
|
|
11
|
+
tolerance: s = 0.01,
|
|
12
|
+
skipTransparent: n = !0,
|
|
13
|
+
maxImageSize: o = 200
|
|
12
14
|
}) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
i(this, "imageData", null);
|
|
16
|
+
i(this, "colorCount");
|
|
17
|
+
i(this, "maxIterations");
|
|
18
|
+
i(this, "tolerance");
|
|
19
|
+
i(this, "skipTransparent");
|
|
20
|
+
i(this, "maxImageSize");
|
|
21
|
+
i(this, "arrayBuffer");
|
|
22
|
+
/** Synchronous extraction for ImageData (backward compatibility) */
|
|
23
|
+
i(this, "extractDominantColors", () => {
|
|
24
|
+
if (!this.imageData)
|
|
25
|
+
throw new Error(
|
|
26
|
+
"No image data available. Use extractDominantColorsAsync() for ArrayBuffer."
|
|
27
|
+
);
|
|
28
|
+
const t = this.extractPixels();
|
|
29
|
+
if (t.length === 0) return [];
|
|
30
|
+
const e = this.performKMeans(t);
|
|
31
|
+
return this.calculateColorFrequencies(t, e).sort((r, s) => s.percentage - r.percentage);
|
|
32
|
+
});
|
|
33
|
+
/** Asynchronous extraction for ArrayBuffer */
|
|
34
|
+
i(this, "extractDominantColorsAsync", async () => {
|
|
35
|
+
if (await this.ensureImageData(), !this.imageData)
|
|
36
|
+
throw new Error(
|
|
37
|
+
"No image data available. Ensure ArrayBuffer was successfully decoded."
|
|
38
|
+
);
|
|
19
39
|
const t = this.extractPixels();
|
|
20
40
|
if (t.length === 0) return [];
|
|
21
41
|
const e = this.performKMeans(t);
|
|
22
|
-
return this.calculateColorFrequencies(t, e).sort((
|
|
42
|
+
return this.calculateColorFrequencies(t, e).sort((r, s) => s.percentage - r.percentage);
|
|
23
43
|
});
|
|
24
|
-
|
|
44
|
+
i(this, "extractPixels", () => {
|
|
45
|
+
if (!this.imageData)
|
|
46
|
+
throw new Error("No image data available");
|
|
25
47
|
const t = [], e = this.imageData.data;
|
|
26
|
-
for (let
|
|
27
|
-
const
|
|
28
|
-
this.skipTransparent &&
|
|
48
|
+
for (let a = 0; a < e.length; a += 4) {
|
|
49
|
+
const r = e[a], s = e[a + 1], n = e[a + 2], o = e[a + 3];
|
|
50
|
+
this.skipTransparent && o < 128 || t.push([r, s, n]);
|
|
29
51
|
}
|
|
30
52
|
return t;
|
|
31
53
|
});
|
|
32
|
-
|
|
33
|
-
let e = this.initializeCentroids(t),
|
|
34
|
-
for (;
|
|
35
|
-
|
|
36
|
-
const
|
|
54
|
+
i(this, "performKMeans", (t) => {
|
|
55
|
+
let e = this.initializeCentroids(t), a = [], r = 0;
|
|
56
|
+
for (; r < this.maxIterations && !this.hasConverged(e, a); ) {
|
|
57
|
+
a = e.map((n) => [...n]);
|
|
58
|
+
const s = Array.from(
|
|
37
59
|
{ length: this.colorCount },
|
|
38
60
|
() => []
|
|
39
61
|
);
|
|
40
|
-
t.forEach((
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
}), e =
|
|
62
|
+
t.forEach((n) => {
|
|
63
|
+
const o = this.findClosestCentroid(n, e);
|
|
64
|
+
s[o].push(n);
|
|
65
|
+
}), e = s.map((n) => n.length === 0 ? a[e.indexOf(e[0])] : this.calculateCentroid(n)), r++;
|
|
44
66
|
}
|
|
45
67
|
return e;
|
|
46
68
|
});
|
|
47
|
-
|
|
69
|
+
i(this, "initializeCentroids", (t) => {
|
|
48
70
|
const e = [];
|
|
49
71
|
e.push(t[Math.floor(Math.random() * t.length)]);
|
|
50
|
-
for (let
|
|
51
|
-
const
|
|
72
|
+
for (let a = 1; a < this.colorCount; a++) {
|
|
73
|
+
const r = t.map((c) => {
|
|
52
74
|
const h = Math.min(
|
|
53
75
|
...e.map(
|
|
54
|
-
(
|
|
76
|
+
(d) => this.calculateDistance(c, d)
|
|
55
77
|
)
|
|
56
78
|
);
|
|
57
79
|
return h * h;
|
|
58
|
-
}),
|
|
59
|
-
let
|
|
80
|
+
}), s = r.reduce((c, h) => c + h, 0), n = Math.random() * s;
|
|
81
|
+
let o = 0;
|
|
60
82
|
for (let c = 0; c < t.length; c++)
|
|
61
|
-
if (
|
|
83
|
+
if (o += r[c], o >= n) {
|
|
62
84
|
e.push(t[c]);
|
|
63
85
|
break;
|
|
64
86
|
}
|
|
65
87
|
}
|
|
66
88
|
return e;
|
|
67
89
|
});
|
|
68
|
-
|
|
69
|
-
let
|
|
70
|
-
return e.forEach((
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
}),
|
|
90
|
+
i(this, "findClosestCentroid", (t, e) => {
|
|
91
|
+
let a = 1 / 0, r = 0;
|
|
92
|
+
return e.forEach((s, n) => {
|
|
93
|
+
const o = this.calculateDistance(t, s);
|
|
94
|
+
o < a && (a = o, r = n);
|
|
95
|
+
}), r;
|
|
74
96
|
});
|
|
75
|
-
|
|
76
|
-
const [
|
|
97
|
+
i(this, "calculateDistance", (t, e) => {
|
|
98
|
+
const [a, r, s] = t, [n, o, c] = e;
|
|
77
99
|
return Math.sqrt(
|
|
78
|
-
Math.pow(
|
|
100
|
+
Math.pow(a - n, 2) + Math.pow(r - o, 2) + Math.pow(s - c, 2)
|
|
79
101
|
);
|
|
80
102
|
});
|
|
81
|
-
|
|
103
|
+
i(this, "calculateCentroid", (t) => {
|
|
82
104
|
const e = t.reduce(
|
|
83
|
-
(
|
|
105
|
+
(a, r) => [a[0] + r[0], a[1] + r[1], a[2] + r[2]],
|
|
84
106
|
[0, 0, 0]
|
|
85
107
|
);
|
|
86
108
|
return [
|
|
@@ -89,37 +111,88 @@ class p {
|
|
|
89
111
|
Math.round(e[2] / t.length)
|
|
90
112
|
];
|
|
91
113
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
t.forEach((
|
|
96
|
-
const
|
|
97
|
-
n
|
|
114
|
+
i(this, "hasConverged", (t, e) => e.length === 0 ? !1 : t.every((a, r) => this.calculateDistance(a, e[r]) < this.tolerance));
|
|
115
|
+
i(this, "calculateColorFrequencies", (t, e) => {
|
|
116
|
+
const a = new Array(e.length).fill(0);
|
|
117
|
+
t.forEach((s) => {
|
|
118
|
+
const n = this.findClosestCentroid(s, e);
|
|
119
|
+
a[n]++;
|
|
98
120
|
});
|
|
99
|
-
const
|
|
100
|
-
return e.map((
|
|
101
|
-
color:
|
|
102
|
-
hex:
|
|
103
|
-
count: n
|
|
104
|
-
percentage: parseFloat((n
|
|
121
|
+
const r = t.length;
|
|
122
|
+
return e.map((s, n) => ({
|
|
123
|
+
color: s,
|
|
124
|
+
hex: p.rgb(s[0], s[1], s[2]).hex(),
|
|
125
|
+
count: a[n],
|
|
126
|
+
percentage: parseFloat((a[n] / r * 100).toFixed(2))
|
|
105
127
|
}));
|
|
106
128
|
});
|
|
107
|
-
|
|
129
|
+
i(this, "setColorCount", (t) => {
|
|
108
130
|
this.colorCount = Math.max(1, Math.min(t, 20));
|
|
109
131
|
});
|
|
110
|
-
|
|
132
|
+
i(this, "updateOptions", (t) => {
|
|
111
133
|
t.colorCount !== void 0 && this.setColorCount(t.colorCount), t.maxIterations !== void 0 && (this.maxIterations = t.maxIterations), t.tolerance !== void 0 && (this.tolerance = t.tolerance), t.skipTransparent !== void 0 && (this.skipTransparent = t.skipTransparent);
|
|
112
134
|
});
|
|
113
|
-
|
|
135
|
+
i(this, "getOptions", () => ({
|
|
114
136
|
colorCount: this.colorCount,
|
|
115
137
|
maxIterations: this.maxIterations,
|
|
116
138
|
tolerance: this.tolerance,
|
|
117
139
|
skipTransparent: this.skipTransparent
|
|
118
140
|
}));
|
|
119
|
-
|
|
141
|
+
if (!t && !e)
|
|
142
|
+
throw new Error("Either imageData or arrayBuffer must be provided");
|
|
143
|
+
this.imageData = t || null, this.colorCount = a, this.maxIterations = r, this.tolerance = s, this.skipTransparent = n, this.maxImageSize = o, e && !t && (this.arrayBuffer = e);
|
|
144
|
+
}
|
|
145
|
+
async ensureImageData() {
|
|
146
|
+
!this.imageData && this.arrayBuffer && (this.imageData = await this.decodeImageFromArrayBuffer(this.arrayBuffer));
|
|
147
|
+
}
|
|
148
|
+
async decodeImageFromArrayBuffer(t) {
|
|
149
|
+
return new Promise((e, a) => {
|
|
150
|
+
const r = globalThis;
|
|
151
|
+
if (!r.document || !r.Image || !r.URL) {
|
|
152
|
+
a(new Error("Browser environment with Canvas API required"));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const s = new r.Blob([t]), n = r.URL.createObjectURL(s), o = new r.Image();
|
|
156
|
+
o.onload = () => {
|
|
157
|
+
try {
|
|
158
|
+
const c = r.document.createElement("canvas"), h = c.getContext("2d");
|
|
159
|
+
if (!h)
|
|
160
|
+
throw new Error("Failed to create canvas context");
|
|
161
|
+
const d = o.width / o.height;
|
|
162
|
+
let u = o.width, m = o.height;
|
|
163
|
+
Math.max(o.width, o.height) > this.maxImageSize && (o.width > o.height ? (u = this.maxImageSize, m = Math.round(this.maxImageSize / d)) : (m = this.maxImageSize, u = Math.round(this.maxImageSize * d))), c.width = u, c.height = m, h.drawImage(o, 0, 0, u, m);
|
|
164
|
+
const g = h.getImageData(
|
|
165
|
+
0,
|
|
166
|
+
0,
|
|
167
|
+
u,
|
|
168
|
+
m
|
|
169
|
+
), w = {
|
|
170
|
+
data: new Uint8ClampedArray(g.data),
|
|
171
|
+
width: g.width,
|
|
172
|
+
height: g.height
|
|
173
|
+
};
|
|
174
|
+
r.URL.revokeObjectURL(n), e(w);
|
|
175
|
+
} catch (c) {
|
|
176
|
+
r.URL.revokeObjectURL(n), a(c);
|
|
177
|
+
}
|
|
178
|
+
}, o.onerror = () => {
|
|
179
|
+
r.URL.revokeObjectURL(n), a(new Error("Failed to load image"));
|
|
180
|
+
}, o.src = n;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/** Static method for simplified ArrayBuffer usage */
|
|
184
|
+
static async fromArrayBuffer(t, e = {}) {
|
|
185
|
+
return new f({
|
|
186
|
+
arrayBuffer: t,
|
|
187
|
+
...e
|
|
188
|
+
}).extractDominantColorsAsync();
|
|
189
|
+
}
|
|
190
|
+
/** Simplified static method for quick color extraction */
|
|
191
|
+
static async extract(t, e = 5) {
|
|
192
|
+
return this.fromArrayBuffer(t, { colorCount: e });
|
|
120
193
|
}
|
|
121
194
|
}
|
|
122
195
|
export {
|
|
123
|
-
|
|
196
|
+
f as default
|
|
124
197
|
};
|
|
125
198
|
//# sourceMappingURL=dominant-colors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dominant-colors.js","sources":["../../../src/modules/dominant-colors/dominant-colors.ts"],"sourcesContent":["import chroma from 'chroma-js'\nimport {\n Channel,\n HexModel,\n ImageData,\n DominantColorResult,\n DominantColorsOptions,\n} from '@tps/color.types'\n\nexport default class DominantColors {\n private imageData: ImageData\n private colorCount: number\n private maxIterations: number\n private tolerance: number\n private skipTransparent: boolean\n\n constructor({\n imageData,\n colorCount = 5,\n maxIterations = 50,\n tolerance = 0.01,\n skipTransparent = true,\n }: {\n imageData: ImageData\n } & DominantColorsOptions) {\n this.imageData = imageData\n this.colorCount = colorCount\n this.maxIterations = maxIterations\n this.tolerance = tolerance\n this.skipTransparent = skipTransparent\n }\n\n extractDominantColors = (): DominantColorResult[] => {\n const pixels = this.extractPixels()\n if (pixels.length === 0) return []\n\n const clusters = this.performKMeans(pixels)\n const results = this.calculateColorFrequencies(pixels, clusters)\n\n return results.sort((a, b) => b.percentage - a.percentage)\n }\n\n private extractPixels = (): Channel[] => {\n const pixels: Channel[] = []\n const data = this.imageData.data\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i]\n const g = data[i + 1]\n const b = data[i + 2]\n const a = data[i + 3]\n\n if (this.skipTransparent && a < 128) continue\n\n pixels.push([r, g, b])\n }\n\n return pixels\n }\n\n private performKMeans = (pixels: Channel[]): Channel[] => {\n let centroids = this.initializeCentroids(pixels)\n let prevCentroids: Channel[] = []\n let iteration = 0\n\n while (\n iteration < this.maxIterations &&\n !this.hasConverged(centroids, prevCentroids)\n ) {\n prevCentroids = centroids.map((c) => [...c] as Channel)\n\n const clusters: Channel[][] = Array.from(\n { length: this.colorCount },\n () => []\n )\n\n pixels.forEach((pixel) => {\n const closestIndex = this.findClosestCentroid(pixel, centroids)\n clusters[closestIndex].push(pixel)\n })\n\n centroids = clusters.map((cluster) => {\n if (cluster.length === 0)\n return prevCentroids[centroids.indexOf(centroids[0])]\n return this.calculateCentroid(cluster)\n })\n\n iteration++\n }\n\n return centroids\n }\n\n private initializeCentroids = (pixels: Channel[]): Channel[] => {\n const centroids: Channel[] = []\n\n // K-means++ initialization\n centroids.push(pixels[Math.floor(Math.random() * pixels.length)])\n\n for (let i = 1; i < this.colorCount; i++) {\n const distances = pixels.map((pixel) => {\n const minDistance = Math.min(\n ...centroids.map((centroid) =>\n this.calculateDistance(pixel, centroid)\n )\n )\n return minDistance * minDistance\n })\n\n const totalDistance = distances.reduce((sum, d) => sum + d, 0)\n const threshold = Math.random() * totalDistance\n\n let cumulative = 0\n for (let j = 0; j < pixels.length; j++) {\n cumulative += distances[j]\n if (cumulative >= threshold) {\n centroids.push(pixels[j])\n break\n }\n }\n }\n\n return centroids\n }\n\n private findClosestCentroid = (\n pixel: Channel,\n centroids: Channel[]\n ): number => {\n let minDistance = Infinity\n let closestIndex = 0\n\n centroids.forEach((centroid, index) => {\n const distance = this.calculateDistance(pixel, centroid)\n if (distance < minDistance) {\n minDistance = distance\n closestIndex = index\n }\n })\n\n return closestIndex\n }\n\n private calculateDistance = (color1: Channel, color2: Channel): number => {\n const [r1, g1, b1] = color1\n const [r2, g2, b2] = color2\n\n return Math.sqrt(\n Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2)\n )\n }\n\n private calculateCentroid = (cluster: Channel[]): Channel => {\n const sum = cluster.reduce(\n (acc, pixel) => [acc[0] + pixel[0], acc[1] + pixel[1], acc[2] + pixel[2]],\n [0, 0, 0] as Channel\n )\n\n return [\n Math.round(sum[0] / cluster.length),\n Math.round(sum[1] / cluster.length),\n Math.round(sum[2] / cluster.length),\n ]\n }\n\n private hasConverged = (\n centroids: Channel[],\n prevCentroids: Channel[]\n ): boolean => {\n if (prevCentroids.length === 0) return false\n\n return centroids.every((centroid, index) => {\n const distance = this.calculateDistance(centroid, prevCentroids[index])\n return distance < this.tolerance\n })\n }\n\n private calculateColorFrequencies = (\n pixels: Channel[],\n centroids: Channel[]\n ): DominantColorResult[] => {\n const counts = new Array(centroids.length).fill(0)\n\n pixels.forEach((pixel) => {\n const closestIndex = this.findClosestCentroid(pixel, centroids)\n counts[closestIndex]++\n })\n\n const totalPixels = pixels.length\n\n return centroids.map((centroid, index) => ({\n color: centroid,\n hex: chroma.rgb(centroid[0], centroid[1], centroid[2]).hex() as HexModel,\n count: counts[index],\n percentage: parseFloat(((counts[index] / totalPixels) * 100).toFixed(2)),\n }))\n }\n\n setColorCount = (count: number): void => {\n this.colorCount = Math.max(1, Math.min(count, 20))\n }\n\n updateOptions = (options: Partial<DominantColorsOptions>): void => {\n if (options.colorCount !== undefined) this.setColorCount(options.colorCount)\n if (options.maxIterations !== undefined)\n this.maxIterations = options.maxIterations\n if (options.tolerance !== undefined) this.tolerance = options.tolerance\n if (options.skipTransparent !== undefined)\n this.skipTransparent = options.skipTransparent\n }\n\n getOptions = (): DominantColorsOptions => ({\n colorCount: this.colorCount,\n maxIterations: this.maxIterations,\n tolerance: this.tolerance,\n skipTransparent: this.skipTransparent,\n })\n}\n"],"names":["DominantColors","imageData","colorCount","maxIterations","tolerance","skipTransparent","__publicField","pixels","clusters","b","data","i","r","g","a","centroids","prevCentroids","iteration","c","pixel","closestIndex","cluster","distances","minDistance","centroid","totalDistance","sum","d","threshold","cumulative","j","index","distance","color1","color2","r1","g1","b1","r2","g2","b2","acc","counts","totalPixels","chroma","count","options"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dominant-colors.js","sources":["../../../src/modules/dominant-colors/dominant-colors.ts"],"sourcesContent":["import chroma from 'chroma-js'\nimport {\n Channel,\n HexModel,\n ImageData,\n DominantColorResult,\n DominantColorsOptions,\n} from '@tps/color.types'\n\ninterface DominantColorsInput extends DominantColorsOptions {\n imageData?: ImageData\n arrayBuffer?: ArrayBuffer\n maxImageSize?: number\n}\n\nexport default class DominantColors {\n private imageData: ImageData | null = null\n private colorCount: number\n private maxIterations: number\n private tolerance: number\n private skipTransparent: boolean\n private maxImageSize: number\n\n constructor({\n imageData,\n arrayBuffer,\n colorCount = 5,\n maxIterations = 50,\n tolerance = 0.01,\n skipTransparent = true,\n maxImageSize = 200,\n }: DominantColorsInput) {\n if (!imageData && !arrayBuffer) {\n throw new Error('Either imageData or arrayBuffer must be provided')\n }\n\n this.imageData = imageData || null\n this.colorCount = colorCount\n this.maxIterations = maxIterations\n this.tolerance = tolerance\n this.skipTransparent = skipTransparent\n this.maxImageSize = maxImageSize\n\n if (arrayBuffer && !imageData) {\n this.arrayBuffer = arrayBuffer\n }\n }\n\n private arrayBuffer?: ArrayBuffer\n\n private async ensureImageData(): Promise<void> {\n if (!this.imageData && this.arrayBuffer) {\n this.imageData = await this.decodeImageFromArrayBuffer(this.arrayBuffer)\n }\n }\n\n private async decodeImageFromArrayBuffer(\n arrayBuffer: ArrayBuffer\n ): Promise<ImageData> {\n return new Promise((resolve, reject) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const globalWindow = globalThis as any\n\n if (!globalWindow.document || !globalWindow.Image || !globalWindow.URL) {\n reject(new Error('Browser environment with Canvas API required'))\n return\n }\n\n const blob = new globalWindow.Blob([arrayBuffer])\n const url = globalWindow.URL.createObjectURL(blob)\n const img = new globalWindow.Image()\n\n img.onload = () => {\n try {\n const canvas = globalWindow.document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n\n if (!ctx) {\n throw new Error('Failed to create canvas context')\n }\n\n // Resize image if needed\n const aspectRatio = img.width / img.height\n let targetWidth = img.width\n let targetHeight = img.height\n\n if (Math.max(img.width, img.height) > this.maxImageSize) {\n if (img.width > img.height) {\n targetWidth = this.maxImageSize\n targetHeight = Math.round(this.maxImageSize / aspectRatio)\n } else {\n targetHeight = this.maxImageSize\n targetWidth = Math.round(this.maxImageSize * aspectRatio)\n }\n }\n\n canvas.width = targetWidth\n canvas.height = targetHeight\n\n ctx.drawImage(img, 0, 0, targetWidth, targetHeight)\n\n const browserImageData = ctx.getImageData(\n 0,\n 0,\n targetWidth,\n targetHeight\n )\n\n const imageData: ImageData = {\n data: new Uint8ClampedArray(browserImageData.data),\n width: browserImageData.width,\n height: browserImageData.height,\n }\n\n globalWindow.URL.revokeObjectURL(url)\n resolve(imageData)\n } catch (error) {\n globalWindow.URL.revokeObjectURL(url)\n reject(error)\n }\n }\n\n img.onerror = () => {\n globalWindow.URL.revokeObjectURL(url)\n reject(new Error('Failed to load image'))\n }\n\n img.src = url\n })\n }\n\n /** Synchronous extraction for ImageData (backward compatibility) */\n extractDominantColors = (): DominantColorResult[] => {\n if (!this.imageData) {\n throw new Error(\n 'No image data available. Use extractDominantColorsAsync() for ArrayBuffer.'\n )\n }\n\n const pixels = this.extractPixels()\n if (pixels.length === 0) return []\n\n const clusters = this.performKMeans(pixels)\n const results = this.calculateColorFrequencies(pixels, clusters)\n\n return results.sort((a, b) => b.percentage - a.percentage)\n }\n\n /** Asynchronous extraction for ArrayBuffer */\n extractDominantColorsAsync = async (): Promise<DominantColorResult[]> => {\n await this.ensureImageData()\n\n if (!this.imageData) {\n throw new Error(\n 'No image data available. Ensure ArrayBuffer was successfully decoded.'\n )\n }\n\n const pixels = this.extractPixels()\n if (pixels.length === 0) return []\n\n const clusters = this.performKMeans(pixels)\n const results = this.calculateColorFrequencies(pixels, clusters)\n\n return results.sort((a, b) => b.percentage - a.percentage)\n }\n\n private extractPixels = (): Channel[] => {\n if (!this.imageData) {\n throw new Error('No image data available')\n }\n\n const pixels: Channel[] = []\n const data = this.imageData.data\n\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i]\n const g = data[i + 1]\n const b = data[i + 2]\n const a = data[i + 3]\n\n if (this.skipTransparent && a < 128) continue\n\n pixels.push([r, g, b])\n }\n\n return pixels\n }\n\n private performKMeans = (pixels: Channel[]): Channel[] => {\n let centroids = this.initializeCentroids(pixels)\n let prevCentroids: Channel[] = []\n let iteration = 0\n\n while (\n iteration < this.maxIterations &&\n !this.hasConverged(centroids, prevCentroids)\n ) {\n prevCentroids = centroids.map((c) => [...c] as Channel)\n\n const clusters: Channel[][] = Array.from(\n { length: this.colorCount },\n () => []\n )\n\n pixels.forEach((pixel) => {\n const closestIndex = this.findClosestCentroid(pixel, centroids)\n clusters[closestIndex].push(pixel)\n })\n\n centroids = clusters.map((cluster) => {\n if (cluster.length === 0)\n return prevCentroids[centroids.indexOf(centroids[0])]\n return this.calculateCentroid(cluster)\n })\n\n iteration++\n }\n\n return centroids\n }\n\n private initializeCentroids = (pixels: Channel[]): Channel[] => {\n const centroids: Channel[] = []\n\n // K-means++ initialization\n centroids.push(pixels[Math.floor(Math.random() * pixels.length)])\n\n for (let i = 1; i < this.colorCount; i++) {\n const distances = pixels.map((pixel) => {\n const minDistance = Math.min(\n ...centroids.map((centroid) =>\n this.calculateDistance(pixel, centroid)\n )\n )\n return minDistance * minDistance\n })\n\n const totalDistance = distances.reduce((sum, d) => sum + d, 0)\n const threshold = Math.random() * totalDistance\n\n let cumulative = 0\n for (let j = 0; j < pixels.length; j++) {\n cumulative += distances[j]\n if (cumulative >= threshold) {\n centroids.push(pixels[j])\n break\n }\n }\n }\n\n return centroids\n }\n\n private findClosestCentroid = (\n pixel: Channel,\n centroids: Channel[]\n ): number => {\n let minDistance = Infinity\n let closestIndex = 0\n\n centroids.forEach((centroid, index) => {\n const distance = this.calculateDistance(pixel, centroid)\n if (distance < minDistance) {\n minDistance = distance\n closestIndex = index\n }\n })\n\n return closestIndex\n }\n\n private calculateDistance = (color1: Channel, color2: Channel): number => {\n const [r1, g1, b1] = color1\n const [r2, g2, b2] = color2\n\n return Math.sqrt(\n Math.pow(r1 - r2, 2) + Math.pow(g1 - g2, 2) + Math.pow(b1 - b2, 2)\n )\n }\n\n private calculateCentroid = (cluster: Channel[]): Channel => {\n const sum = cluster.reduce(\n (acc, pixel) => [acc[0] + pixel[0], acc[1] + pixel[1], acc[2] + pixel[2]],\n [0, 0, 0] as Channel\n )\n\n return [\n Math.round(sum[0] / cluster.length),\n Math.round(sum[1] / cluster.length),\n Math.round(sum[2] / cluster.length),\n ]\n }\n\n private hasConverged = (\n centroids: Channel[],\n prevCentroids: Channel[]\n ): boolean => {\n if (prevCentroids.length === 0) return false\n\n return centroids.every((centroid, index) => {\n const distance = this.calculateDistance(centroid, prevCentroids[index])\n return distance < this.tolerance\n })\n }\n\n private calculateColorFrequencies = (\n pixels: Channel[],\n centroids: Channel[]\n ): DominantColorResult[] => {\n const counts = new Array(centroids.length).fill(0)\n\n pixels.forEach((pixel) => {\n const closestIndex = this.findClosestCentroid(pixel, centroids)\n counts[closestIndex]++\n })\n\n const totalPixels = pixels.length\n\n return centroids.map((centroid, index) => ({\n color: centroid,\n hex: chroma.rgb(centroid[0], centroid[1], centroid[2]).hex() as HexModel,\n count: counts[index],\n percentage: parseFloat(((counts[index] / totalPixels) * 100).toFixed(2)),\n }))\n }\n\n setColorCount = (count: number): void => {\n this.colorCount = Math.max(1, Math.min(count, 20))\n }\n\n updateOptions = (options: Partial<DominantColorsOptions>): void => {\n if (options.colorCount !== undefined) this.setColorCount(options.colorCount)\n if (options.maxIterations !== undefined)\n this.maxIterations = options.maxIterations\n if (options.tolerance !== undefined) this.tolerance = options.tolerance\n if (options.skipTransparent !== undefined)\n this.skipTransparent = options.skipTransparent\n }\n\n getOptions = (): DominantColorsOptions => ({\n colorCount: this.colorCount,\n maxIterations: this.maxIterations,\n tolerance: this.tolerance,\n skipTransparent: this.skipTransparent,\n })\n\n /** Static method for simplified ArrayBuffer usage */\n static async fromArrayBuffer(\n arrayBuffer: ArrayBuffer,\n options: Omit<DominantColorsInput, 'arrayBuffer' | 'imageData'> = {}\n ): Promise<DominantColorResult[]> {\n const decoder = new DominantColors({\n arrayBuffer,\n ...options,\n })\n\n return decoder.extractDominantColorsAsync()\n }\n\n /** Simplified static method for quick color extraction */\n static async extract(\n arrayBuffer: ArrayBuffer,\n colorCount: number = 5\n ): Promise<DominantColorResult[]> {\n return this.fromArrayBuffer(arrayBuffer, { colorCount })\n }\n}\n"],"names":["DominantColors","imageData","arrayBuffer","colorCount","maxIterations","tolerance","skipTransparent","maxImageSize","__publicField","pixels","clusters","a","b","data","i","g","centroids","prevCentroids","iteration","c","pixel","closestIndex","cluster","distances","minDistance","centroid","totalDistance","sum","d","threshold","cumulative","j","index","distance","color1","color2","r1","g1","b1","r2","g2","b2","acc","counts","totalPixels","chroma","count","options","resolve","reject","globalWindow","blob","url","img","canvas","ctx","aspectRatio","targetWidth","targetHeight","browserImageData","error"],"mappings":"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"}
|
|
@@ -30,7 +30,7 @@ export interface DominantColorsOptions {
|
|
|
30
30
|
tolerance?: number;
|
|
31
31
|
skipTransparent?: boolean;
|
|
32
32
|
}
|
|
33
|
-
export type HarmonyType = '
|
|
33
|
+
export type HarmonyType = 'ANALOGOUS' | 'COMPLEMENTARY' | 'TRIADIC' | 'TETRADIC' | 'SQUARE' | 'COMPOUND';
|
|
34
34
|
export interface ColorHarmonyResult {
|
|
35
35
|
type: HarmonyType;
|
|
36
36
|
baseColor: Channel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color.types.d.ts","sourceRoot":"","sources":["../../src/types/color.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,IAAI,MAAM,EAAE,GAAG,MAAM,CAAA;AAE5C,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,CAAC,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9C,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAE/D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,iBAAiB,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,QAAQ,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,eAAe,GACf,SAAS,GACT,UAAU,GACV,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"color.types.d.ts","sourceRoot":"","sources":["../../src/types/color.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,IAAI,MAAM,EAAE,GAAG,MAAM,CAAA;AAE5C,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,CAAC,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9C,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAE/D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,iBAAiB,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,QAAQ,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,eAAe,GACf,SAAS,GACT,UAAU,GACV,QAAQ,GACR,UAAU,CAAA;AAEd,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,WAAW,CAAA;IACjB,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,QAAQ,CAAA;IACjB,MAAM,EAAE,OAAO,EAAE,CAAA;IACjB,SAAS,EAAE,QAAQ,EAAE,CAAA;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;CACtC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a_ng_d/utils-ui-color-palette",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.7.
|
|
4
|
+
"version": "1.7.3",
|
|
5
5
|
"description": "Core utilities library for UI Color Palette - a color management plugin for design tools. This library provides the foundational color manipulation, contrast calculation, and palette generation features used in the plugin.",
|
|
6
6
|
"repository": "https://github.com/a-ng-d/utils-ui-color-palette",
|
|
7
7
|
"keywords": [
|