@al8b/palette 0.1.0

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.
@@ -0,0 +1,255 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/core/palette.ts
5
+ import { APIErrorCode, reportRuntimeError } from "@al8b/diagnostics";
6
+ var HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;
7
+ var Palette = class _Palette {
8
+ static {
9
+ __name(this, "Palette");
10
+ }
11
+ colors;
12
+ name;
13
+ rgbCache;
14
+ runtime;
15
+ constructor(options = {}, runtime) {
16
+ this.runtime = runtime;
17
+ if ("colors" in options && Array.isArray(options.colors)) {
18
+ if (!this.validatePaletteFormat(options.colors)) {
19
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, {
20
+ format: "invalid color array"
21
+ });
22
+ this.colors = [];
23
+ this.name = "Invalid";
24
+ } else {
25
+ this.colors = [
26
+ ...options.colors
27
+ ];
28
+ this.name = options.name || "Custom";
29
+ }
30
+ } else {
31
+ this.colors = [];
32
+ this.name = "Empty";
33
+ }
34
+ this.rgbCache = /* @__PURE__ */ new Map();
35
+ }
36
+ /**
37
+ * Validate palette format
38
+ */
39
+ validatePaletteFormat(colors) {
40
+ if (!Array.isArray(colors)) return false;
41
+ return colors.every((color) => typeof color === "string" && HEX_COLOR_REGEX.test(color));
42
+ }
43
+ /**
44
+ * Get color by index
45
+ */
46
+ get(index) {
47
+ if (!isFinite(index) || index < 0) {
48
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7073, {
49
+ index,
50
+ maxIndex: this.colors.length - 1
51
+ });
52
+ return "#000000";
53
+ }
54
+ if (this.colors.length === 0) {
55
+ return "#000000";
56
+ }
57
+ return this.colors[index % this.colors.length] || "#000000";
58
+ }
59
+ /**
60
+ * Get color as RGB object
61
+ */
62
+ getRGB(index) {
63
+ if (this.rgbCache.has(index)) {
64
+ return this.rgbCache.get(index);
65
+ }
66
+ const hex = this.get(index);
67
+ const rgb = this.hexToRGB(hex);
68
+ this.rgbCache.set(index, rgb);
69
+ return rgb;
70
+ }
71
+ /**
72
+ * Get all colors
73
+ */
74
+ getAll() {
75
+ return [
76
+ ...this.colors
77
+ ];
78
+ }
79
+ /**
80
+ * Get palette size
81
+ */
82
+ get size() {
83
+ return this.colors.length;
84
+ }
85
+ /**
86
+ * Get palette name
87
+ */
88
+ get paletteName() {
89
+ return this.name;
90
+ }
91
+ /**
92
+ * Set color at index (expands palette if needed)
93
+ */
94
+ set(index, color) {
95
+ if (!isFinite(index) || index < 0) {
96
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7073, {
97
+ index,
98
+ maxIndex: this.colors.length - 1
99
+ });
100
+ return;
101
+ }
102
+ if (!HEX_COLOR_REGEX.test(color)) {
103
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, {
104
+ format: color
105
+ });
106
+ return;
107
+ }
108
+ while (this.colors.length <= index) {
109
+ this.colors.push("#000000");
110
+ }
111
+ this.colors[index] = color;
112
+ this.rgbCache.delete(index);
113
+ }
114
+ /**
115
+ * Add color to palette
116
+ */
117
+ add(color) {
118
+ this.colors.push(color);
119
+ return this.colors.length - 1;
120
+ }
121
+ /**
122
+ * Remove color at index
123
+ */
124
+ remove(index) {
125
+ if (index >= 0 && index < this.colors.length) {
126
+ this.colors.splice(index, 1);
127
+ this.rgbCache.clear();
128
+ }
129
+ }
130
+ /**
131
+ * Replace entire palette
132
+ */
133
+ setPalette(colors) {
134
+ if (!this.validatePaletteFormat(colors)) {
135
+ reportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, {
136
+ format: "invalid color array"
137
+ });
138
+ return;
139
+ }
140
+ this.colors = [
141
+ ...colors
142
+ ];
143
+ this.rgbCache.clear();
144
+ }
145
+ /**
146
+ * Reset to original colors
147
+ */
148
+ reset(paletteData) {
149
+ if (paletteData) {
150
+ this.colors = [
151
+ ...paletteData.colors
152
+ ];
153
+ this.name = paletteData.name;
154
+ }
155
+ this.rgbCache.clear();
156
+ }
157
+ /**
158
+ * Convert hex to RGB
159
+ */
160
+ hexToRGB(hex) {
161
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
162
+ return result ? {
163
+ r: Number.parseInt(result[1], 16),
164
+ g: Number.parseInt(result[2], 16),
165
+ b: Number.parseInt(result[3], 16)
166
+ } : {
167
+ r: 0,
168
+ g: 0,
169
+ b: 0
170
+ };
171
+ }
172
+ /**
173
+ * Convert RGB to hex
174
+ */
175
+ static rgbToHex(r, g, b) {
176
+ return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
177
+ }
178
+ /**
179
+ * Find closest color in palette
180
+ */
181
+ findClosest(targetHex) {
182
+ const target = this.hexToRGB(targetHex);
183
+ let closestIndex = 0;
184
+ let closestDistance = Number.POSITIVE_INFINITY;
185
+ for (let i = 0; i < this.colors.length; i++) {
186
+ const color = this.getRGB(i);
187
+ const distance = (target.r - color.r) ** 2 + (target.g - color.g) ** 2 + (target.b - color.b) ** 2;
188
+ if (distance < closestDistance) {
189
+ closestDistance = distance;
190
+ closestIndex = i;
191
+ }
192
+ }
193
+ return closestIndex;
194
+ }
195
+ /**
196
+ * Create a gradient between two palette colors
197
+ */
198
+ gradient(startIndex, endIndex, steps) {
199
+ const start = this.getRGB(startIndex);
200
+ const end = this.getRGB(endIndex);
201
+ const gradient = [];
202
+ for (let i = 0; i < steps; i++) {
203
+ const t = i / (steps - 1);
204
+ const r = Math.round(start.r + (end.r - start.r) * t);
205
+ const g = Math.round(start.g + (end.g - start.g) * t);
206
+ const b = Math.round(start.b + (end.b - start.b) * t);
207
+ gradient.push(_Palette.rgbToHex(r, g, b));
208
+ }
209
+ return gradient;
210
+ }
211
+ /**
212
+ * Lighten a color
213
+ */
214
+ lighten(index, amount = 0.2) {
215
+ const color = this.getRGB(index);
216
+ const r = Math.min(255, Math.round(color.r + (255 - color.r) * amount));
217
+ const g = Math.min(255, Math.round(color.g + (255 - color.g) * amount));
218
+ const b = Math.min(255, Math.round(color.b + (255 - color.b) * amount));
219
+ return _Palette.rgbToHex(r, g, b);
220
+ }
221
+ /**
222
+ * Darken a color
223
+ */
224
+ darken(index, amount = 0.2) {
225
+ const color = this.getRGB(index);
226
+ const r = Math.max(0, Math.round(color.r * (1 - amount)));
227
+ const g = Math.max(0, Math.round(color.g * (1 - amount)));
228
+ const b = Math.max(0, Math.round(color.b * (1 - amount)));
229
+ return _Palette.rgbToHex(r, g, b);
230
+ }
231
+ /**
232
+ * Mix two colors
233
+ */
234
+ mix(index1, index2, ratio = 0.5) {
235
+ const color1 = this.getRGB(index1);
236
+ const color2 = this.getRGB(index2);
237
+ const r = Math.round(color1.r + (color2.r - color1.r) * ratio);
238
+ const g = Math.round(color1.g + (color2.g - color1.g) * ratio);
239
+ const b = Math.round(color1.b + (color2.b - color1.b) * ratio);
240
+ return _Palette.rgbToHex(r, g, b);
241
+ }
242
+ /**
243
+ * Export palette data
244
+ */
245
+ toData() {
246
+ return {
247
+ name: this.name,
248
+ colors: this.getAll()
249
+ };
250
+ }
251
+ };
252
+ export {
253
+ Palette
254
+ };
255
+ //# sourceMappingURL=palette.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/palette.ts"],"sourcesContent":["/**\n * Palette - Color palette management\n */\n\nimport { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\nimport type { ColorHex, ColorRGB, PaletteData } from \"../types\";\n\n/** Matches a valid 6-digit hex color string, e.g. \"#1A2B3C\" */\nconst HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;\n\nexport interface PaletteOptions {\n\tcolors?: ColorHex[];\n\tname?: string;\n}\n\nexport class Palette {\n\tprivate colors: ColorHex[];\n\tprivate name: string;\n\tprivate rgbCache: Map<number, ColorRGB>;\n\tprivate runtime?: any;\n\n\tconstructor(options: PaletteOptions | PaletteData = {}, runtime?: any) {\n\t\tthis.runtime = runtime;\n\n\t\tif (\"colors\" in options && Array.isArray(options.colors)) {\n\t\t\t// Validate palette format to ensure all colors are valid hex strings\n\t\t\tif (!this.validatePaletteFormat(options.colors)) {\n\t\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, { format: \"invalid color array\" });\n\t\t\t\tthis.colors = [];\n\t\t\t\tthis.name = \"Invalid\";\n\t\t\t} else {\n\t\t\t\tthis.colors = [...options.colors];\n\t\t\t\tthis.name = options.name || \"Custom\";\n\t\t\t}\n\t\t} else {\n\t\t\t// Initialize with empty palette when no valid colors provided\n\t\t\tthis.colors = [];\n\t\t\tthis.name = \"Empty\";\n\t\t}\n\n\t\tthis.rgbCache = new Map();\n\t}\n\n\t/**\n\t * Validate palette format\n\t */\n\tprivate validatePaletteFormat(colors: any[]): boolean {\n\t\tif (!Array.isArray(colors)) return false;\n\t\treturn colors.every((color) => typeof color === \"string\" && HEX_COLOR_REGEX.test(color));\n\t}\n\n\t/**\n\t * Get color by index\n\t */\n\tget(index: number): ColorHex {\n\t\t// Validate color index is a finite, non-negative number\n\t\tif (!isFinite(index) || index < 0) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7073, { index, maxIndex: this.colors.length - 1 });\n\t\t\treturn \"#000000\";\n\t\t}\n\n\t\tif (this.colors.length === 0) {\n\t\t\treturn \"#000000\";\n\t\t}\n\n\t\treturn this.colors[index % this.colors.length] || \"#000000\";\n\t}\n\n\t/**\n\t * Get color as RGB object\n\t */\n\tgetRGB(index: number): ColorRGB {\n\t\tif (this.rgbCache.has(index)) {\n\t\t\treturn this.rgbCache.get(index)!;\n\t\t}\n\n\t\tconst hex = this.get(index);\n\t\tconst rgb = this.hexToRGB(hex);\n\t\tthis.rgbCache.set(index, rgb);\n\t\treturn rgb;\n\t}\n\n\t/**\n\t * Get all colors\n\t */\n\tgetAll(): ColorHex[] {\n\t\treturn [...this.colors];\n\t}\n\n\t/**\n\t * Get palette size\n\t */\n\tget size(): number {\n\t\treturn this.colors.length;\n\t}\n\n\t/**\n\t * Get palette name\n\t */\n\tget paletteName(): string {\n\t\treturn this.name;\n\t}\n\n\t/**\n\t * Set color at index (expands palette if needed)\n\t */\n\tset(index: number, color: ColorHex): void {\n\t\t// Validate color index is a finite, non-negative number\n\t\tif (!isFinite(index) || index < 0) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7073, { index, maxIndex: this.colors.length - 1 });\n\t\t\treturn;\n\t\t}\n\n\t\t// Validate color format matches hex pattern (#RRGGBB)\n\t\tif (!HEX_COLOR_REGEX.test(color)) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, { format: color });\n\t\t\treturn;\n\t\t}\n\n\t\t// Expand palette with black (#000000) if index exceeds current size\n\t\twhile (this.colors.length <= index) {\n\t\t\tthis.colors.push(\"#000000\");\n\t\t}\n\t\tthis.colors[index] = color;\n\t\tthis.rgbCache.delete(index);\n\t}\n\n\t/**\n\t * Add color to palette\n\t */\n\tadd(color: ColorHex): number {\n\t\tthis.colors.push(color);\n\t\treturn this.colors.length - 1;\n\t}\n\n\t/**\n\t * Remove color at index\n\t */\n\tremove(index: number): void {\n\t\tif (index >= 0 && index < this.colors.length) {\n\t\t\tthis.colors.splice(index, 1);\n\t\t\tthis.rgbCache.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Replace entire palette\n\t */\n\tsetPalette(colors: ColorHex[]): void {\n\t\t// Validate palette format to ensure all colors are valid hex strings\n\t\tif (!this.validatePaletteFormat(colors)) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, { format: \"invalid color array\" });\n\t\t\treturn;\n\t\t}\n\n\t\tthis.colors = [...colors];\n\t\tthis.rgbCache.clear();\n\t}\n\n\t/**\n\t * Reset to original colors\n\t */\n\treset(paletteData?: PaletteData): void {\n\t\tif (paletteData) {\n\t\t\tthis.colors = [...paletteData.colors];\n\t\t\tthis.name = paletteData.name;\n\t\t}\n\t\tthis.rgbCache.clear();\n\t}\n\n\t/**\n\t * Convert hex to RGB\n\t */\n\tprivate hexToRGB(hex: ColorHex): ColorRGB {\n\t\tconst result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\t\treturn result\n\t\t\t? {\n\t\t\t\t\tr: Number.parseInt(result[1], 16),\n\t\t\t\t\tg: Number.parseInt(result[2], 16),\n\t\t\t\t\tb: Number.parseInt(result[3], 16),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tr: 0,\n\t\t\t\t\tg: 0,\n\t\t\t\t\tb: 0,\n\t\t\t\t};\n\t}\n\n\t/**\n\t * Convert RGB to hex\n\t */\n\tstatic rgbToHex(r: number, g: number, b: number): ColorHex {\n\t\treturn \"#\" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();\n\t}\n\n\t/**\n\t * Find closest color in palette\n\t */\n\tfindClosest(targetHex: ColorHex): number {\n\t\tconst target = this.hexToRGB(targetHex);\n\t\tlet closestIndex = 0;\n\t\tlet closestDistance = Number.POSITIVE_INFINITY;\n\n\t\tfor (let i = 0; i < this.colors.length; i++) {\n\t\t\tconst color = this.getRGB(i);\n\t\t\tconst distance = (target.r - color.r) ** 2 + (target.g - color.g) ** 2 + (target.b - color.b) ** 2;\n\n\t\t\tif (distance < closestDistance) {\n\t\t\t\tclosestDistance = distance;\n\t\t\t\tclosestIndex = i;\n\t\t\t}\n\t\t}\n\n\t\treturn closestIndex;\n\t}\n\n\t/**\n\t * Create a gradient between two palette colors\n\t */\n\tgradient(startIndex: number, endIndex: number, steps: number): ColorHex[] {\n\t\tconst start = this.getRGB(startIndex);\n\t\tconst end = this.getRGB(endIndex);\n\t\tconst gradient: ColorHex[] = [];\n\n\t\tfor (let i = 0; i < steps; i++) {\n\t\t\tconst t = i / (steps - 1);\n\t\t\tconst r = Math.round(start.r + (end.r - start.r) * t);\n\t\t\tconst g = Math.round(start.g + (end.g - start.g) * t);\n\t\t\tconst b = Math.round(start.b + (end.b - start.b) * t);\n\t\t\tgradient.push(Palette.rgbToHex(r, g, b));\n\t\t}\n\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * Lighten a color\n\t */\n\tlighten(index: number, amount: number = 0.2): ColorHex {\n\t\tconst color = this.getRGB(index);\n\t\tconst r = Math.min(255, Math.round(color.r + (255 - color.r) * amount));\n\t\tconst g = Math.min(255, Math.round(color.g + (255 - color.g) * amount));\n\t\tconst b = Math.min(255, Math.round(color.b + (255 - color.b) * amount));\n\t\treturn Palette.rgbToHex(r, g, b);\n\t}\n\n\t/**\n\t * Darken a color\n\t */\n\tdarken(index: number, amount: number = 0.2): ColorHex {\n\t\tconst color = this.getRGB(index);\n\t\tconst r = Math.max(0, Math.round(color.r * (1 - amount)));\n\t\tconst g = Math.max(0, Math.round(color.g * (1 - amount)));\n\t\tconst b = Math.max(0, Math.round(color.b * (1 - amount)));\n\t\treturn Palette.rgbToHex(r, g, b);\n\t}\n\n\t/**\n\t * Mix two colors\n\t */\n\tmix(index1: number, index2: number, ratio: number = 0.5): ColorHex {\n\t\tconst color1 = this.getRGB(index1);\n\t\tconst color2 = this.getRGB(index2);\n\t\tconst r = Math.round(color1.r + (color2.r - color1.r) * ratio);\n\t\tconst g = Math.round(color1.g + (color2.g - color1.g) * ratio);\n\t\tconst b = Math.round(color1.b + (color2.b - color1.b) * ratio);\n\t\treturn Palette.rgbToHex(r, g, b);\n\t}\n\n\t/**\n\t * Export palette data\n\t */\n\ttoData(): PaletteData {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tcolors: this.getAll(),\n\t\t};\n\t}\n}\n"],"mappings":";;;;AAIA,SAASA,cAAcC,0BAA0B;AAIjD,IAAMC,kBAAkB;AAOjB,IAAMC,UAAN,MAAMA,SAAAA;EAfb,OAeaA;;;EACJC;EACAC;EACAC;EACAC;EAER,YAAYC,UAAwC,CAAC,GAAGD,SAAe;AACtE,SAAKA,UAAUA;AAEf,QAAI,YAAYC,WAAWC,MAAMC,QAAQF,QAAQJ,MAAM,GAAG;AAEzD,UAAI,CAAC,KAAKO,sBAAsBH,QAAQJ,MAAM,GAAG;AAChDQ,2BAAmB,KAAKL,SAASM,UAAUC,aAAaC,OAAO;UAAEC,QAAQ;QAAsB,CAAA;AAC/F,aAAKZ,SAAS,CAAA;AACd,aAAKC,OAAO;MACb,OAAO;AACN,aAAKD,SAAS;aAAII,QAAQJ;;AAC1B,aAAKC,OAAOG,QAAQH,QAAQ;MAC7B;IACD,OAAO;AAEN,WAAKD,SAAS,CAAA;AACd,WAAKC,OAAO;IACb;AAEA,SAAKC,WAAW,oBAAIW,IAAAA;EACrB;;;;EAKQN,sBAAsBP,QAAwB;AACrD,QAAI,CAACK,MAAMC,QAAQN,MAAAA,EAAS,QAAO;AACnC,WAAOA,OAAOc,MAAM,CAACC,UAAU,OAAOA,UAAU,YAAYjB,gBAAgBkB,KAAKD,KAAAA,CAAAA;EAClF;;;;EAKAE,IAAIC,OAAyB;AAE5B,QAAI,CAACC,SAASD,KAAAA,KAAUA,QAAQ,GAAG;AAClCV,yBAAmB,KAAKL,SAASM,UAAUC,aAAaU,OAAO;QAAEF;QAAOG,UAAU,KAAKrB,OAAOsB,SAAS;MAAE,CAAA;AACzG,aAAO;IACR;AAEA,QAAI,KAAKtB,OAAOsB,WAAW,GAAG;AAC7B,aAAO;IACR;AAEA,WAAO,KAAKtB,OAAOkB,QAAQ,KAAKlB,OAAOsB,MAAM,KAAK;EACnD;;;;EAKAC,OAAOL,OAAyB;AAC/B,QAAI,KAAKhB,SAASsB,IAAIN,KAAAA,GAAQ;AAC7B,aAAO,KAAKhB,SAASe,IAAIC,KAAAA;IAC1B;AAEA,UAAMO,MAAM,KAAKR,IAAIC,KAAAA;AACrB,UAAMQ,MAAM,KAAKC,SAASF,GAAAA;AAC1B,SAAKvB,SAAS0B,IAAIV,OAAOQ,GAAAA;AACzB,WAAOA;EACR;;;;EAKAG,SAAqB;AACpB,WAAO;SAAI,KAAK7B;;EACjB;;;;EAKA,IAAI8B,OAAe;AAClB,WAAO,KAAK9B,OAAOsB;EACpB;;;;EAKA,IAAIS,cAAsB;AACzB,WAAO,KAAK9B;EACb;;;;EAKA2B,IAAIV,OAAeH,OAAuB;AAEzC,QAAI,CAACI,SAASD,KAAAA,KAAUA,QAAQ,GAAG;AAClCV,yBAAmB,KAAKL,SAASM,UAAUC,aAAaU,OAAO;QAAEF;QAAOG,UAAU,KAAKrB,OAAOsB,SAAS;MAAE,CAAA;AACzG;IACD;AAGA,QAAI,CAACxB,gBAAgBkB,KAAKD,KAAAA,GAAQ;AACjCP,yBAAmB,KAAKL,SAASM,UAAUC,aAAaC,OAAO;QAAEC,QAAQG;MAAM,CAAA;AAC/E;IACD;AAGA,WAAO,KAAKf,OAAOsB,UAAUJ,OAAO;AACnC,WAAKlB,OAAOgC,KAAK,SAAA;IAClB;AACA,SAAKhC,OAAOkB,KAAAA,IAASH;AACrB,SAAKb,SAAS+B,OAAOf,KAAAA;EACtB;;;;EAKAgB,IAAInB,OAAyB;AAC5B,SAAKf,OAAOgC,KAAKjB,KAAAA;AACjB,WAAO,KAAKf,OAAOsB,SAAS;EAC7B;;;;EAKAa,OAAOjB,OAAqB;AAC3B,QAAIA,SAAS,KAAKA,QAAQ,KAAKlB,OAAOsB,QAAQ;AAC7C,WAAKtB,OAAOoC,OAAOlB,OAAO,CAAA;AAC1B,WAAKhB,SAASmC,MAAK;IACpB;EACD;;;;EAKAC,WAAWtC,QAA0B;AAEpC,QAAI,CAAC,KAAKO,sBAAsBP,MAAAA,GAAS;AACxCQ,yBAAmB,KAAKL,SAASM,UAAUC,aAAaC,OAAO;QAAEC,QAAQ;MAAsB,CAAA;AAC/F;IACD;AAEA,SAAKZ,SAAS;SAAIA;;AAClB,SAAKE,SAASmC,MAAK;EACpB;;;;EAKAE,MAAMC,aAAiC;AACtC,QAAIA,aAAa;AAChB,WAAKxC,SAAS;WAAIwC,YAAYxC;;AAC9B,WAAKC,OAAOuC,YAAYvC;IACzB;AACA,SAAKC,SAASmC,MAAK;EACpB;;;;EAKQV,SAASF,KAAyB;AACzC,UAAMgB,SAAS,4CAA4CC,KAAKjB,GAAAA;AAChE,WAAOgB,SACJ;MACAE,GAAGC,OAAOC,SAASJ,OAAO,CAAA,GAAI,EAAA;MAC9BK,GAAGF,OAAOC,SAASJ,OAAO,CAAA,GAAI,EAAA;MAC9BM,GAAGH,OAAOC,SAASJ,OAAO,CAAA,GAAI,EAAA;IAC/B,IACC;MACAE,GAAG;MACHG,GAAG;MACHC,GAAG;IACJ;EACH;;;;EAKA,OAAOC,SAASL,GAAWG,GAAWC,GAAqB;AAC1D,WAAO,QAAQ,KAAK,OAAOJ,KAAK,OAAOG,KAAK,KAAKC,GAAGE,SAAS,EAAA,EAAIC,MAAM,CAAA,EAAGC,YAAW;EACtF;;;;EAKAC,YAAYC,WAA6B;AACxC,UAAMC,SAAS,KAAK3B,SAAS0B,SAAAA;AAC7B,QAAIE,eAAe;AACnB,QAAIC,kBAAkBZ,OAAOa;AAE7B,aAASC,IAAI,GAAGA,IAAI,KAAK1D,OAAOsB,QAAQoC,KAAK;AAC5C,YAAM3C,QAAQ,KAAKQ,OAAOmC,CAAAA;AAC1B,YAAMC,YAAYL,OAAOX,IAAI5B,MAAM4B,MAAM,KAAKW,OAAOR,IAAI/B,MAAM+B,MAAM,KAAKQ,OAAOP,IAAIhC,MAAMgC,MAAM;AAEjG,UAAIY,WAAWH,iBAAiB;AAC/BA,0BAAkBG;AAClBJ,uBAAeG;MAChB;IACD;AAEA,WAAOH;EACR;;;;EAKAK,SAASC,YAAoBC,UAAkBC,OAA2B;AACzE,UAAMC,QAAQ,KAAKzC,OAAOsC,UAAAA;AAC1B,UAAMI,MAAM,KAAK1C,OAAOuC,QAAAA;AACxB,UAAMF,WAAuB,CAAA;AAE7B,aAASF,IAAI,GAAGA,IAAIK,OAAOL,KAAK;AAC/B,YAAMQ,IAAIR,KAAKK,QAAQ;AACvB,YAAMpB,IAAIwB,KAAKC,MAAMJ,MAAMrB,KAAKsB,IAAItB,IAAIqB,MAAMrB,KAAKuB,CAAAA;AACnD,YAAMpB,IAAIqB,KAAKC,MAAMJ,MAAMlB,KAAKmB,IAAInB,IAAIkB,MAAMlB,KAAKoB,CAAAA;AACnD,YAAMnB,IAAIoB,KAAKC,MAAMJ,MAAMjB,KAAKkB,IAAIlB,IAAIiB,MAAMjB,KAAKmB,CAAAA;AACnDN,eAAS5B,KAAKjC,SAAQiD,SAASL,GAAGG,GAAGC,CAAAA,CAAAA;IACtC;AAEA,WAAOa;EACR;;;;EAKAS,QAAQnD,OAAeoD,SAAiB,KAAe;AACtD,UAAMvD,QAAQ,KAAKQ,OAAOL,KAAAA;AAC1B,UAAMyB,IAAIwB,KAAKI,IAAI,KAAKJ,KAAKC,MAAMrD,MAAM4B,KAAK,MAAM5B,MAAM4B,KAAK2B,MAAAA,CAAAA;AAC/D,UAAMxB,IAAIqB,KAAKI,IAAI,KAAKJ,KAAKC,MAAMrD,MAAM+B,KAAK,MAAM/B,MAAM+B,KAAKwB,MAAAA,CAAAA;AAC/D,UAAMvB,IAAIoB,KAAKI,IAAI,KAAKJ,KAAKC,MAAMrD,MAAMgC,KAAK,MAAMhC,MAAMgC,KAAKuB,MAAAA,CAAAA;AAC/D,WAAOvE,SAAQiD,SAASL,GAAGG,GAAGC,CAAAA;EAC/B;;;;EAKAyB,OAAOtD,OAAeoD,SAAiB,KAAe;AACrD,UAAMvD,QAAQ,KAAKQ,OAAOL,KAAAA;AAC1B,UAAMyB,IAAIwB,KAAKM,IAAI,GAAGN,KAAKC,MAAMrD,MAAM4B,KAAK,IAAI2B,OAAK,CAAA;AACrD,UAAMxB,IAAIqB,KAAKM,IAAI,GAAGN,KAAKC,MAAMrD,MAAM+B,KAAK,IAAIwB,OAAK,CAAA;AACrD,UAAMvB,IAAIoB,KAAKM,IAAI,GAAGN,KAAKC,MAAMrD,MAAMgC,KAAK,IAAIuB,OAAK,CAAA;AACrD,WAAOvE,SAAQiD,SAASL,GAAGG,GAAGC,CAAAA;EAC/B;;;;EAKA2B,IAAIC,QAAgBC,QAAgBC,QAAgB,KAAe;AAClE,UAAMC,SAAS,KAAKvD,OAAOoD,MAAAA;AAC3B,UAAMI,SAAS,KAAKxD,OAAOqD,MAAAA;AAC3B,UAAMjC,IAAIwB,KAAKC,MAAMU,OAAOnC,KAAKoC,OAAOpC,IAAImC,OAAOnC,KAAKkC,KAAAA;AACxD,UAAM/B,IAAIqB,KAAKC,MAAMU,OAAOhC,KAAKiC,OAAOjC,IAAIgC,OAAOhC,KAAK+B,KAAAA;AACxD,UAAM9B,IAAIoB,KAAKC,MAAMU,OAAO/B,KAAKgC,OAAOhC,IAAI+B,OAAO/B,KAAK8B,KAAAA;AACxD,WAAO9E,SAAQiD,SAASL,GAAGG,GAAGC,CAAAA;EAC/B;;;;EAKAiC,SAAsB;AACrB,WAAO;MACN/E,MAAM,KAAKA;MACXD,QAAQ,KAAK6B,OAAM;IACpB;EACD;AACD;","names":["APIErrorCode","reportRuntimeError","HEX_COLOR_REGEX","Palette","colors","name","rgbCache","runtime","options","Array","isArray","validatePaletteFormat","reportRuntimeError","listener","APIErrorCode","E7072","format","Map","every","color","test","get","index","isFinite","E7073","maxIndex","length","getRGB","has","hex","rgb","hexToRGB","set","getAll","size","paletteName","push","delete","add","remove","splice","clear","setPalette","reset","paletteData","result","exec","r","Number","parseInt","g","b","rgbToHex","toString","slice","toUpperCase","findClosest","targetHex","target","closestIndex","closestDistance","POSITIVE_INFINITY","i","distance","gradient","startIndex","endIndex","steps","start","end","t","Math","round","lighten","amount","min","darken","max","mix","index1","index2","ratio","color1","color2","toData"]}
@@ -0,0 +1,2 @@
1
+ export { Palette, PaletteOptions } from './core/palette.mjs';
2
+ export { ColorHex, ColorRGB, PaletteData } from './types/index.mjs';
@@ -0,0 +1,2 @@
1
+ export { Palette, PaletteOptions } from './core/palette.js';
2
+ export { ColorHex, ColorRGB, PaletteData } from './types/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ Palette: () => Palette
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/core/palette.ts
29
+ var import_diagnostics = require("@al8b/diagnostics");
30
+ var HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;
31
+ var Palette = class _Palette {
32
+ static {
33
+ __name(this, "Palette");
34
+ }
35
+ colors;
36
+ name;
37
+ rgbCache;
38
+ runtime;
39
+ constructor(options = {}, runtime) {
40
+ this.runtime = runtime;
41
+ if ("colors" in options && Array.isArray(options.colors)) {
42
+ if (!this.validatePaletteFormat(options.colors)) {
43
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7072, {
44
+ format: "invalid color array"
45
+ });
46
+ this.colors = [];
47
+ this.name = "Invalid";
48
+ } else {
49
+ this.colors = [
50
+ ...options.colors
51
+ ];
52
+ this.name = options.name || "Custom";
53
+ }
54
+ } else {
55
+ this.colors = [];
56
+ this.name = "Empty";
57
+ }
58
+ this.rgbCache = /* @__PURE__ */ new Map();
59
+ }
60
+ /**
61
+ * Validate palette format
62
+ */
63
+ validatePaletteFormat(colors) {
64
+ if (!Array.isArray(colors)) return false;
65
+ return colors.every((color) => typeof color === "string" && HEX_COLOR_REGEX.test(color));
66
+ }
67
+ /**
68
+ * Get color by index
69
+ */
70
+ get(index) {
71
+ if (!isFinite(index) || index < 0) {
72
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7073, {
73
+ index,
74
+ maxIndex: this.colors.length - 1
75
+ });
76
+ return "#000000";
77
+ }
78
+ if (this.colors.length === 0) {
79
+ return "#000000";
80
+ }
81
+ return this.colors[index % this.colors.length] || "#000000";
82
+ }
83
+ /**
84
+ * Get color as RGB object
85
+ */
86
+ getRGB(index) {
87
+ if (this.rgbCache.has(index)) {
88
+ return this.rgbCache.get(index);
89
+ }
90
+ const hex = this.get(index);
91
+ const rgb = this.hexToRGB(hex);
92
+ this.rgbCache.set(index, rgb);
93
+ return rgb;
94
+ }
95
+ /**
96
+ * Get all colors
97
+ */
98
+ getAll() {
99
+ return [
100
+ ...this.colors
101
+ ];
102
+ }
103
+ /**
104
+ * Get palette size
105
+ */
106
+ get size() {
107
+ return this.colors.length;
108
+ }
109
+ /**
110
+ * Get palette name
111
+ */
112
+ get paletteName() {
113
+ return this.name;
114
+ }
115
+ /**
116
+ * Set color at index (expands palette if needed)
117
+ */
118
+ set(index, color) {
119
+ if (!isFinite(index) || index < 0) {
120
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7073, {
121
+ index,
122
+ maxIndex: this.colors.length - 1
123
+ });
124
+ return;
125
+ }
126
+ if (!HEX_COLOR_REGEX.test(color)) {
127
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7072, {
128
+ format: color
129
+ });
130
+ return;
131
+ }
132
+ while (this.colors.length <= index) {
133
+ this.colors.push("#000000");
134
+ }
135
+ this.colors[index] = color;
136
+ this.rgbCache.delete(index);
137
+ }
138
+ /**
139
+ * Add color to palette
140
+ */
141
+ add(color) {
142
+ this.colors.push(color);
143
+ return this.colors.length - 1;
144
+ }
145
+ /**
146
+ * Remove color at index
147
+ */
148
+ remove(index) {
149
+ if (index >= 0 && index < this.colors.length) {
150
+ this.colors.splice(index, 1);
151
+ this.rgbCache.clear();
152
+ }
153
+ }
154
+ /**
155
+ * Replace entire palette
156
+ */
157
+ setPalette(colors) {
158
+ if (!this.validatePaletteFormat(colors)) {
159
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7072, {
160
+ format: "invalid color array"
161
+ });
162
+ return;
163
+ }
164
+ this.colors = [
165
+ ...colors
166
+ ];
167
+ this.rgbCache.clear();
168
+ }
169
+ /**
170
+ * Reset to original colors
171
+ */
172
+ reset(paletteData) {
173
+ if (paletteData) {
174
+ this.colors = [
175
+ ...paletteData.colors
176
+ ];
177
+ this.name = paletteData.name;
178
+ }
179
+ this.rgbCache.clear();
180
+ }
181
+ /**
182
+ * Convert hex to RGB
183
+ */
184
+ hexToRGB(hex) {
185
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
186
+ return result ? {
187
+ r: Number.parseInt(result[1], 16),
188
+ g: Number.parseInt(result[2], 16),
189
+ b: Number.parseInt(result[3], 16)
190
+ } : {
191
+ r: 0,
192
+ g: 0,
193
+ b: 0
194
+ };
195
+ }
196
+ /**
197
+ * Convert RGB to hex
198
+ */
199
+ static rgbToHex(r, g, b) {
200
+ return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
201
+ }
202
+ /**
203
+ * Find closest color in palette
204
+ */
205
+ findClosest(targetHex) {
206
+ const target = this.hexToRGB(targetHex);
207
+ let closestIndex = 0;
208
+ let closestDistance = Number.POSITIVE_INFINITY;
209
+ for (let i = 0; i < this.colors.length; i++) {
210
+ const color = this.getRGB(i);
211
+ const distance = (target.r - color.r) ** 2 + (target.g - color.g) ** 2 + (target.b - color.b) ** 2;
212
+ if (distance < closestDistance) {
213
+ closestDistance = distance;
214
+ closestIndex = i;
215
+ }
216
+ }
217
+ return closestIndex;
218
+ }
219
+ /**
220
+ * Create a gradient between two palette colors
221
+ */
222
+ gradient(startIndex, endIndex, steps) {
223
+ const start = this.getRGB(startIndex);
224
+ const end = this.getRGB(endIndex);
225
+ const gradient = [];
226
+ for (let i = 0; i < steps; i++) {
227
+ const t = i / (steps - 1);
228
+ const r = Math.round(start.r + (end.r - start.r) * t);
229
+ const g = Math.round(start.g + (end.g - start.g) * t);
230
+ const b = Math.round(start.b + (end.b - start.b) * t);
231
+ gradient.push(_Palette.rgbToHex(r, g, b));
232
+ }
233
+ return gradient;
234
+ }
235
+ /**
236
+ * Lighten a color
237
+ */
238
+ lighten(index, amount = 0.2) {
239
+ const color = this.getRGB(index);
240
+ const r = Math.min(255, Math.round(color.r + (255 - color.r) * amount));
241
+ const g = Math.min(255, Math.round(color.g + (255 - color.g) * amount));
242
+ const b = Math.min(255, Math.round(color.b + (255 - color.b) * amount));
243
+ return _Palette.rgbToHex(r, g, b);
244
+ }
245
+ /**
246
+ * Darken a color
247
+ */
248
+ darken(index, amount = 0.2) {
249
+ const color = this.getRGB(index);
250
+ const r = Math.max(0, Math.round(color.r * (1 - amount)));
251
+ const g = Math.max(0, Math.round(color.g * (1 - amount)));
252
+ const b = Math.max(0, Math.round(color.b * (1 - amount)));
253
+ return _Palette.rgbToHex(r, g, b);
254
+ }
255
+ /**
256
+ * Mix two colors
257
+ */
258
+ mix(index1, index2, ratio = 0.5) {
259
+ const color1 = this.getRGB(index1);
260
+ const color2 = this.getRGB(index2);
261
+ const r = Math.round(color1.r + (color2.r - color1.r) * ratio);
262
+ const g = Math.round(color1.g + (color2.g - color1.g) * ratio);
263
+ const b = Math.round(color1.b + (color2.b - color1.b) * ratio);
264
+ return _Palette.rgbToHex(r, g, b);
265
+ }
266
+ /**
267
+ * Export palette data
268
+ */
269
+ toData() {
270
+ return {
271
+ name: this.name,
272
+ colors: this.getAll()
273
+ };
274
+ }
275
+ };
276
+ // Annotate the CommonJS export names for ESM import in node:
277
+ 0 && (module.exports = {
278
+ Palette
279
+ });
280
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/palette.ts"],"sourcesContent":["/**\n * @al8b/palette - Color palette management system\n *\n * Architecture:\n * - core/: Palette class + helpers\n * - types/: Shared color types\n */\n\nexport {\n\tPalette,\n\ttype PaletteOptions,\n} from \"./core/palette\";\nexport type {\n\tColorHex,\n\tColorRGB,\n\tPaletteData,\n} from \"./types\";\n","/**\n * Palette - Color palette management\n */\n\nimport { APIErrorCode, reportRuntimeError } from \"@al8b/diagnostics\";\nimport type { ColorHex, ColorRGB, PaletteData } from \"../types\";\n\n/** Matches a valid 6-digit hex color string, e.g. \"#1A2B3C\" */\nconst HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;\n\nexport interface PaletteOptions {\n\tcolors?: ColorHex[];\n\tname?: string;\n}\n\nexport class Palette {\n\tprivate colors: ColorHex[];\n\tprivate name: string;\n\tprivate rgbCache: Map<number, ColorRGB>;\n\tprivate runtime?: any;\n\n\tconstructor(options: PaletteOptions | PaletteData = {}, runtime?: any) {\n\t\tthis.runtime = runtime;\n\n\t\tif (\"colors\" in options && Array.isArray(options.colors)) {\n\t\t\t// Validate palette format to ensure all colors are valid hex strings\n\t\t\tif (!this.validatePaletteFormat(options.colors)) {\n\t\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, { format: \"invalid color array\" });\n\t\t\t\tthis.colors = [];\n\t\t\t\tthis.name = \"Invalid\";\n\t\t\t} else {\n\t\t\t\tthis.colors = [...options.colors];\n\t\t\t\tthis.name = options.name || \"Custom\";\n\t\t\t}\n\t\t} else {\n\t\t\t// Initialize with empty palette when no valid colors provided\n\t\t\tthis.colors = [];\n\t\t\tthis.name = \"Empty\";\n\t\t}\n\n\t\tthis.rgbCache = new Map();\n\t}\n\n\t/**\n\t * Validate palette format\n\t */\n\tprivate validatePaletteFormat(colors: any[]): boolean {\n\t\tif (!Array.isArray(colors)) return false;\n\t\treturn colors.every((color) => typeof color === \"string\" && HEX_COLOR_REGEX.test(color));\n\t}\n\n\t/**\n\t * Get color by index\n\t */\n\tget(index: number): ColorHex {\n\t\t// Validate color index is a finite, non-negative number\n\t\tif (!isFinite(index) || index < 0) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7073, { index, maxIndex: this.colors.length - 1 });\n\t\t\treturn \"#000000\";\n\t\t}\n\n\t\tif (this.colors.length === 0) {\n\t\t\treturn \"#000000\";\n\t\t}\n\n\t\treturn this.colors[index % this.colors.length] || \"#000000\";\n\t}\n\n\t/**\n\t * Get color as RGB object\n\t */\n\tgetRGB(index: number): ColorRGB {\n\t\tif (this.rgbCache.has(index)) {\n\t\t\treturn this.rgbCache.get(index)!;\n\t\t}\n\n\t\tconst hex = this.get(index);\n\t\tconst rgb = this.hexToRGB(hex);\n\t\tthis.rgbCache.set(index, rgb);\n\t\treturn rgb;\n\t}\n\n\t/**\n\t * Get all colors\n\t */\n\tgetAll(): ColorHex[] {\n\t\treturn [...this.colors];\n\t}\n\n\t/**\n\t * Get palette size\n\t */\n\tget size(): number {\n\t\treturn this.colors.length;\n\t}\n\n\t/**\n\t * Get palette name\n\t */\n\tget paletteName(): string {\n\t\treturn this.name;\n\t}\n\n\t/**\n\t * Set color at index (expands palette if needed)\n\t */\n\tset(index: number, color: ColorHex): void {\n\t\t// Validate color index is a finite, non-negative number\n\t\tif (!isFinite(index) || index < 0) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7073, { index, maxIndex: this.colors.length - 1 });\n\t\t\treturn;\n\t\t}\n\n\t\t// Validate color format matches hex pattern (#RRGGBB)\n\t\tif (!HEX_COLOR_REGEX.test(color)) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, { format: color });\n\t\t\treturn;\n\t\t}\n\n\t\t// Expand palette with black (#000000) if index exceeds current size\n\t\twhile (this.colors.length <= index) {\n\t\t\tthis.colors.push(\"#000000\");\n\t\t}\n\t\tthis.colors[index] = color;\n\t\tthis.rgbCache.delete(index);\n\t}\n\n\t/**\n\t * Add color to palette\n\t */\n\tadd(color: ColorHex): number {\n\t\tthis.colors.push(color);\n\t\treturn this.colors.length - 1;\n\t}\n\n\t/**\n\t * Remove color at index\n\t */\n\tremove(index: number): void {\n\t\tif (index >= 0 && index < this.colors.length) {\n\t\t\tthis.colors.splice(index, 1);\n\t\t\tthis.rgbCache.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Replace entire palette\n\t */\n\tsetPalette(colors: ColorHex[]): void {\n\t\t// Validate palette format to ensure all colors are valid hex strings\n\t\tif (!this.validatePaletteFormat(colors)) {\n\t\t\treportRuntimeError(this.runtime?.listener, APIErrorCode.E7072, { format: \"invalid color array\" });\n\t\t\treturn;\n\t\t}\n\n\t\tthis.colors = [...colors];\n\t\tthis.rgbCache.clear();\n\t}\n\n\t/**\n\t * Reset to original colors\n\t */\n\treset(paletteData?: PaletteData): void {\n\t\tif (paletteData) {\n\t\t\tthis.colors = [...paletteData.colors];\n\t\t\tthis.name = paletteData.name;\n\t\t}\n\t\tthis.rgbCache.clear();\n\t}\n\n\t/**\n\t * Convert hex to RGB\n\t */\n\tprivate hexToRGB(hex: ColorHex): ColorRGB {\n\t\tconst result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\t\treturn result\n\t\t\t? {\n\t\t\t\t\tr: Number.parseInt(result[1], 16),\n\t\t\t\t\tg: Number.parseInt(result[2], 16),\n\t\t\t\t\tb: Number.parseInt(result[3], 16),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tr: 0,\n\t\t\t\t\tg: 0,\n\t\t\t\t\tb: 0,\n\t\t\t\t};\n\t}\n\n\t/**\n\t * Convert RGB to hex\n\t */\n\tstatic rgbToHex(r: number, g: number, b: number): ColorHex {\n\t\treturn \"#\" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();\n\t}\n\n\t/**\n\t * Find closest color in palette\n\t */\n\tfindClosest(targetHex: ColorHex): number {\n\t\tconst target = this.hexToRGB(targetHex);\n\t\tlet closestIndex = 0;\n\t\tlet closestDistance = Number.POSITIVE_INFINITY;\n\n\t\tfor (let i = 0; i < this.colors.length; i++) {\n\t\t\tconst color = this.getRGB(i);\n\t\t\tconst distance = (target.r - color.r) ** 2 + (target.g - color.g) ** 2 + (target.b - color.b) ** 2;\n\n\t\t\tif (distance < closestDistance) {\n\t\t\t\tclosestDistance = distance;\n\t\t\t\tclosestIndex = i;\n\t\t\t}\n\t\t}\n\n\t\treturn closestIndex;\n\t}\n\n\t/**\n\t * Create a gradient between two palette colors\n\t */\n\tgradient(startIndex: number, endIndex: number, steps: number): ColorHex[] {\n\t\tconst start = this.getRGB(startIndex);\n\t\tconst end = this.getRGB(endIndex);\n\t\tconst gradient: ColorHex[] = [];\n\n\t\tfor (let i = 0; i < steps; i++) {\n\t\t\tconst t = i / (steps - 1);\n\t\t\tconst r = Math.round(start.r + (end.r - start.r) * t);\n\t\t\tconst g = Math.round(start.g + (end.g - start.g) * t);\n\t\t\tconst b = Math.round(start.b + (end.b - start.b) * t);\n\t\t\tgradient.push(Palette.rgbToHex(r, g, b));\n\t\t}\n\n\t\treturn gradient;\n\t}\n\n\t/**\n\t * Lighten a color\n\t */\n\tlighten(index: number, amount: number = 0.2): ColorHex {\n\t\tconst color = this.getRGB(index);\n\t\tconst r = Math.min(255, Math.round(color.r + (255 - color.r) * amount));\n\t\tconst g = Math.min(255, Math.round(color.g + (255 - color.g) * amount));\n\t\tconst b = Math.min(255, Math.round(color.b + (255 - color.b) * amount));\n\t\treturn Palette.rgbToHex(r, g, b);\n\t}\n\n\t/**\n\t * Darken a color\n\t */\n\tdarken(index: number, amount: number = 0.2): ColorHex {\n\t\tconst color = this.getRGB(index);\n\t\tconst r = Math.max(0, Math.round(color.r * (1 - amount)));\n\t\tconst g = Math.max(0, Math.round(color.g * (1 - amount)));\n\t\tconst b = Math.max(0, Math.round(color.b * (1 - amount)));\n\t\treturn Palette.rgbToHex(r, g, b);\n\t}\n\n\t/**\n\t * Mix two colors\n\t */\n\tmix(index1: number, index2: number, ratio: number = 0.5): ColorHex {\n\t\tconst color1 = this.getRGB(index1);\n\t\tconst color2 = this.getRGB(index2);\n\t\tconst r = Math.round(color1.r + (color2.r - color1.r) * ratio);\n\t\tconst g = Math.round(color1.g + (color2.g - color1.g) * ratio);\n\t\tconst b = Math.round(color1.b + (color2.b - color1.b) * ratio);\n\t\treturn Palette.rgbToHex(r, g, b);\n\t}\n\n\t/**\n\t * Export palette data\n\t */\n\ttoData(): PaletteData {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tcolors: this.getAll(),\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["HEX_COLOR_REGEX","Palette","colors","name","rgbCache","runtime","options","Array","isArray","validatePaletteFormat","reportRuntimeError","listener","APIErrorCode","E7072","format","Map","every","color","test","get","index","isFinite","E7073","maxIndex","length","getRGB","has","hex","rgb","hexToRGB","set","getAll","size","paletteName","push","delete","add","remove","splice","clear","setPalette","reset","paletteData","result","exec","r","Number","parseInt","g","b","rgbToHex","toString","slice","toUpperCase","findClosest","targetHex","target","closestIndex","closestDistance","POSITIVE_INFINITY","i","distance","gradient","startIndex","endIndex","steps","start","end","t","Math","round","lighten","amount","min","darken","max","mix","index1","index2","ratio","color1","color2","toData"]}