@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 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 square color harmonies
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('triadic')
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,CAexD;IAED,eAAe,QAAO,kBAAkB,EAAE,CAQzC;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
+ {"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 = (n, e, t) => e in n ? i(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var r = (n, e, t) => u(n, typeof e != "symbol" ? e + "" : e, t);
4
- import { c as o } from "../../index-Beb8qoyd.js";
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
- r(this, "baseColor");
12
- r(this, "analogousSpread");
13
- r(this, "returnFormat");
14
- r(this, "generateAnalogous", () => {
15
- const e = o(this.baseColor).hsl(), t = e[0] || 0, s = [
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("analogous", s);
28
+ return this.formatResult("ANALOGOUS", s);
29
29
  });
30
- r(this, "generateComplementary", () => {
31
- const e = o(this.baseColor).hsl(), t = e[0] || 0, s = [
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("complementary", s);
35
+ return this.formatResult("COMPLEMENTARY", s);
36
36
  });
37
- r(this, "generateTriadic", () => {
38
- const e = o(this.baseColor).hsl(), t = e[0] || 0, s = [
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("triadic", s);
43
+ return this.formatResult("TRIADIC", s);
44
44
  });
45
- r(this, "generateTetradic", () => {
46
- const e = o(this.baseColor).hsl(), t = e[0] || 0, s = [
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("tetradic", s);
52
+ return this.formatResult("TETRADIC", s);
53
53
  });
54
- r(this, "generateSquare", () => {
55
- const e = o(this.baseColor).hsl(), t = e[0] || 0, s = [
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("square", s);
61
+ return this.formatResult("SQUARE", s);
62
62
  });
63
- r(this, "generateHarmony", (e) => {
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 "analogous":
73
+ case "ANALOGOUS":
66
74
  return this.generateAnalogous();
67
- case "complementary":
75
+ case "COMPLEMENTARY":
68
76
  return this.generateComplementary();
69
- case "triadic":
77
+ case "TRIADIC":
70
78
  return this.generateTriadic();
71
- case "tetradic":
79
+ case "TETRADIC":
72
80
  return this.generateTetradic();
73
- case "square":
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
- r(this, "getAllHarmonies", () => [
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
- r(this, "normalizeHue", (e) => {
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
- r(this, "hueToRgb", (e, t, s) => {
92
- const h = o.hsl(e, t, s).rgb();
93
- return [Math.round(h[0]), Math.round(h[1]), Math.round(h[2])];
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
- r(this, "formatResult", (e, t) => {
106
+ o(this, "formatResult", (e, t) => {
96
107
  const s = t.map(
97
- (a) => [
98
- Math.round(a[0]),
99
- Math.round(a[1]),
100
- Math.round(a[2])
108
+ (n) => [
109
+ Math.round(n[0]),
110
+ Math.round(n[1]),
111
+ Math.round(n[2])
101
112
  ]
102
- ), h = s.map(
103
- (a) => o.rgb(a[0], a[1], a[2]).hex()
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: o.rgb(this.baseColor[0], this.baseColor[1], this.baseColor[2]).hex(),
123
+ baseHex: r.rgb(this.baseColor[0], this.baseColor[1], this.baseColor[2]).hex(),
113
124
  colors: s,
114
- hexColors: h
125
+ hexColors: a
115
126
  };
116
127
  });
117
- r(this, "setBaseColor", (e) => {
128
+ o(this, "setBaseColor", (e) => {
118
129
  this.baseColor = e;
119
130
  });
120
- r(this, "setAnalogousSpread", (e) => {
131
+ o(this, "setAnalogousSpread", (e) => {
121
132
  this.analogousSpread = Math.max(1, Math.min(e, 180));
122
133
  });
123
- r(this, "updateOptions", (e) => {
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
- r(this, "getOptions", () => ({
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
- constructor({ imageData, colorCount, maxIterations, tolerance, skipTransparent, }: {
10
- imageData: ImageData;
11
- } & DominantColorsOptions);
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,CAAW;IAC5B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,eAAe,CAAS;gBAEpB,EACV,SAAS,EACT,UAAc,EACd,aAAkB,EAClB,SAAgB,EAChB,eAAsB,GACvB,EAAE;QACD,SAAS,EAAE,SAAS,CAAA;KACrB,GAAG,qBAAqB;IAQzB,qBAAqB,QAAO,mBAAmB,EAAE,CAQhD;IAED,OAAO,CAAC,aAAa,CAgBpB;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;CACH"}
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 d = Object.defineProperty;
2
- var m = (l, t, e) => t in l ? d(l, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[t] = e;
3
- var o = (l, t, e) => m(l, typeof t != "symbol" ? t + "" : t, e);
4
- import { c as f } from "../../index-Beb8qoyd.js";
5
- class p {
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
- colorCount: e = 5,
9
- maxIterations: n = 50,
10
- tolerance: a = 0.01,
11
- skipTransparent: r = !0
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
- o(this, "imageData");
14
- o(this, "colorCount");
15
- o(this, "maxIterations");
16
- o(this, "tolerance");
17
- o(this, "skipTransparent");
18
- o(this, "extractDominantColors", () => {
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((a, r) => r.percentage - a.percentage);
42
+ return this.calculateColorFrequencies(t, e).sort((r, s) => s.percentage - r.percentage);
23
43
  });
24
- o(this, "extractPixels", () => {
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 n = 0; n < e.length; n += 4) {
27
- const a = e[n], r = e[n + 1], s = e[n + 2], i = e[n + 3];
28
- this.skipTransparent && i < 128 || t.push([a, r, s]);
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
- o(this, "performKMeans", (t) => {
33
- let e = this.initializeCentroids(t), n = [], a = 0;
34
- for (; a < this.maxIterations && !this.hasConverged(e, n); ) {
35
- n = e.map((s) => [...s]);
36
- const r = Array.from(
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((s) => {
41
- const i = this.findClosestCentroid(s, e);
42
- r[i].push(s);
43
- }), e = r.map((s) => s.length === 0 ? n[e.indexOf(e[0])] : this.calculateCentroid(s)), a++;
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
- o(this, "initializeCentroids", (t) => {
69
+ i(this, "initializeCentroids", (t) => {
48
70
  const e = [];
49
71
  e.push(t[Math.floor(Math.random() * t.length)]);
50
- for (let n = 1; n < this.colorCount; n++) {
51
- const a = t.map((c) => {
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
- (u) => this.calculateDistance(c, u)
76
+ (d) => this.calculateDistance(c, d)
55
77
  )
56
78
  );
57
79
  return h * h;
58
- }), r = a.reduce((c, h) => c + h, 0), s = Math.random() * r;
59
- let i = 0;
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 (i += a[c], i >= s) {
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
- o(this, "findClosestCentroid", (t, e) => {
69
- let n = 1 / 0, a = 0;
70
- return e.forEach((r, s) => {
71
- const i = this.calculateDistance(t, r);
72
- i < n && (n = i, a = s);
73
- }), a;
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
- o(this, "calculateDistance", (t, e) => {
76
- const [n, a, r] = t, [s, i, c] = e;
97
+ i(this, "calculateDistance", (t, e) => {
98
+ const [a, r, s] = t, [n, o, c] = e;
77
99
  return Math.sqrt(
78
- Math.pow(n - s, 2) + Math.pow(a - i, 2) + Math.pow(r - c, 2)
100
+ Math.pow(a - n, 2) + Math.pow(r - o, 2) + Math.pow(s - c, 2)
79
101
  );
80
102
  });
81
- o(this, "calculateCentroid", (t) => {
103
+ i(this, "calculateCentroid", (t) => {
82
104
  const e = t.reduce(
83
- (n, a) => [n[0] + a[0], n[1] + a[1], n[2] + a[2]],
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
- o(this, "hasConverged", (t, e) => e.length === 0 ? !1 : t.every((n, a) => this.calculateDistance(n, e[a]) < this.tolerance));
93
- o(this, "calculateColorFrequencies", (t, e) => {
94
- const n = new Array(e.length).fill(0);
95
- t.forEach((r) => {
96
- const s = this.findClosestCentroid(r, e);
97
- n[s]++;
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 a = t.length;
100
- return e.map((r, s) => ({
101
- color: r,
102
- hex: f.rgb(r[0], r[1], r[2]).hex(),
103
- count: n[s],
104
- percentage: parseFloat((n[s] / a * 100).toFixed(2))
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
- o(this, "setColorCount", (t) => {
129
+ i(this, "setColorCount", (t) => {
108
130
  this.colorCount = Math.max(1, Math.min(t, 20));
109
131
  });
110
- o(this, "updateOptions", (t) => {
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
- o(this, "getOptions", () => ({
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
- this.imageData = t, this.colorCount = e, this.maxIterations = n, this.tolerance = a, this.skipTransparent = r;
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
- p as default
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 = 'analogous' | 'complementary' | 'triadic' | 'tetradic' | 'square';
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;AAEZ,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"}
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.1",
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": [