@xivdyetools/core 1.12.4 → 1.12.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Spectral Color Mixer
3
+ *
4
+ * Wrapper for spectral.js library that provides Kubelka-Munk theory-based
5
+ * realistic pigment/paint mixing. This produces results that closely match
6
+ * how actual paints and pigments mix in the physical world.
7
+ *
8
+ * Key characteristics:
9
+ * - Based on Kubelka-Munk light absorption/scattering theory
10
+ * - Simulates how pigments interact with light
11
+ * - Blue + Yellow = Green (like real paint!)
12
+ * - Uses spectral reflectance curves (380-750nm)
13
+ *
14
+ * @module services/color/SpectralMixer
15
+ */
16
+ // @ts-expect-error - spectral.js has no type definitions
17
+ import * as spectral from 'spectral.js';
18
+ import { ColorConverter } from './ColorConverter.js';
19
+ /**
20
+ * Spectral Color Mixer using Kubelka-Munk theory
21
+ *
22
+ * Provides realistic paint/pigment color mixing by simulating
23
+ * how light interacts with pigmented materials.
24
+ */
25
+ export class SpectralMixer {
26
+ /**
27
+ * Mix two colors using Kubelka-Munk spectral mixing
28
+ *
29
+ * This produces results similar to mixing physical paints:
30
+ * - Blue + Yellow = Green (like mixing paints)
31
+ * - More realistic tinting and shading
32
+ * - Handles complementary colors naturally
33
+ *
34
+ * @param hex1 First hex color
35
+ * @param hex2 Second hex color
36
+ * @param ratio Mix ratio (0 = all hex1, 0.5 = equal mix, 1 = all hex2). Default: 0.5
37
+ * @returns Mixed color as hex
38
+ *
39
+ * @example
40
+ * // Mix blue and yellow to get green
41
+ * SpectralMixer.mixColors('#0000FF', '#FFFF00') // Returns green-ish color
42
+ */
43
+ static mixColors(hex1, hex2, ratio = 0.5) {
44
+ // Clamp ratio to valid range
45
+ ratio = Math.max(0, Math.min(1, ratio));
46
+ // Create spectral Color objects
47
+ const color1 = new spectral.Color(hex1);
48
+ const color2 = new spectral.Color(hex2);
49
+ // Mix using Kubelka-Munk theory
50
+ // The mix function takes [color, concentration] pairs
51
+ // We use (1 - ratio) for color1 and ratio for color2
52
+ const mixed = spectral.mix([color1, 1 - ratio], [color2, ratio]);
53
+ // Convert to hex string
54
+ // toString returns hex format by default with gamut mapping
55
+ const hexResult = mixed.toString({ format: 'hex', method: 'map' });
56
+ // Normalize to our HexColor format
57
+ return ColorConverter.normalizeHex(hexResult);
58
+ }
59
+ /**
60
+ * Mix multiple colors using Kubelka-Munk spectral mixing
61
+ *
62
+ * @param colors Array of hex colors to mix
63
+ * @param weights Optional array of weights (defaults to equal weights)
64
+ * @returns Mixed color as hex
65
+ *
66
+ * @example
67
+ * // Mix three colors
68
+ * SpectralMixer.mixMultiple(['#FF0000', '#00FF00', '#0000FF'])
69
+ */
70
+ static mixMultiple(colors, weights) {
71
+ if (colors.length === 0) {
72
+ throw new Error('At least one color is required');
73
+ }
74
+ if (colors.length === 1) {
75
+ return ColorConverter.normalizeHex(colors[0]);
76
+ }
77
+ // Use equal weights if not provided
78
+ const effectiveWeights = weights ?? colors.map(() => 1 / colors.length);
79
+ // Normalize weights to sum to 1
80
+ const totalWeight = effectiveWeights.reduce((sum, w) => sum + w, 0);
81
+ const normalizedWeights = effectiveWeights.map((w) => w / totalWeight);
82
+ // Create spectral Color objects with weights
83
+ const colorPairs = colors.map((hex, i) => [
84
+ new spectral.Color(hex),
85
+ normalizedWeights[i],
86
+ ]);
87
+ // Mix using Kubelka-Munk theory
88
+ const mixed = spectral.mix(...colorPairs);
89
+ // Convert to hex string
90
+ const hexResult = mixed.toString({ format: 'hex', method: 'map' });
91
+ return ColorConverter.normalizeHex(hexResult);
92
+ }
93
+ /**
94
+ * Generate a gradient palette using spectral mixing
95
+ *
96
+ * Creates a series of colors that transition smoothly between
97
+ * two colors using Kubelka-Munk theory for realistic blending.
98
+ *
99
+ * @param hex1 Starting color
100
+ * @param hex2 Ending color
101
+ * @param steps Number of colors in the gradient (including start and end)
102
+ * @returns Array of hex colors
103
+ *
104
+ * @example
105
+ * // Generate a 5-step gradient from red to blue
106
+ * SpectralMixer.gradient('#FF0000', '#0000FF', 5)
107
+ */
108
+ static gradient(hex1, hex2, steps) {
109
+ if (steps < 2) {
110
+ throw new Error('Gradient requires at least 2 steps');
111
+ }
112
+ const result = [];
113
+ for (let i = 0; i < steps; i++) {
114
+ const ratio = i / (steps - 1);
115
+ result.push(this.mixColors(hex1, hex2, ratio));
116
+ }
117
+ return result;
118
+ }
119
+ /**
120
+ * Check if the spectral.js library is available
121
+ *
122
+ * @returns true if spectral.js is loaded and functional
123
+ */
124
+ static isAvailable() {
125
+ try {
126
+ return typeof spectral.Color === 'function' && typeof spectral.mix === 'function';
127
+ }
128
+ catch {
129
+ return false;
130
+ }
131
+ }
132
+ }
133
+ //# sourceMappingURL=SpectralMixer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpectralMixer.js","sourceRoot":"","sources":["../../../src/services/color/SpectralMixer.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,7 @@ export { NoOpLogger, ConsoleLogger } from '@xivdyetools/logger/library';
20
20
  /**
21
21
  * @deprecated Removed in v2.0.0. Import directly from '@xivdyetools/types' instead.
22
22
  */
23
- export type { RGB, HSV, LAB, HexColor, DyeId, Hue, Saturation } from '@xivdyetools/types';
23
+ export type { RGB, HSV, LAB, OKLAB, OKLCH, LCH, HSL, HexColor, DyeId, Hue, Saturation } from '@xivdyetools/types';
24
24
  /**
25
25
  * @deprecated Removed in v2.0.0. Import directly from '@xivdyetools/types' instead.
26
26
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,YAAY,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAMxE;;GAEG;AACH,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC1F;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC9F;;GAEG;AACH,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEpF;;GAEG;AACH,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE1F;;GAEG;AACH,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,OAAO,EACP,MAAM,EACN,IAAI,GACL,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3F;;GAEG;AACH,YAAY,EACV,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,6BAA6B,EAC7B,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,4BAA4B,EAC5B,qBAAqB,EACrB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,YAAY,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,MAAM,EACN,eAAe,EACf,OAAO,EACP,OAAO,EACP,UAAU,EACV,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzD;;GAEG;AACH,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAClF;;GAEG;AACH,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,YAAY,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAMxE;;GAEG;AACH,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAClH;;GAEG;AACH,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC9F;;GAEG;AACH,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEpF;;GAEG;AACH,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE1F;;GAEG;AACH,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,OAAO,EACP,MAAM,EACN,IAAI,GACL,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3F;;GAEG;AACH,YAAY,EACV,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,6BAA6B,EAC7B,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,YAAY,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,4BAA4B,EAC5B,qBAAqB,EACrB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,YAAY,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,SAAS,EACT,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,MAAM,EACN,eAAe,EACf,OAAO,EACP,OAAO,EACP,UAAU,EACV,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzD;;GAEG;AACH,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAClF;;GAEG;AACH,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/version.d.ts CHANGED
@@ -7,5 +7,5 @@
7
7
  * Current library version
8
8
  * Automatically synced with package.json version
9
9
  */
10
- export declare const VERSION = "1.12.4";
10
+ export declare const VERSION = "1.12.5";
11
11
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -7,5 +7,5 @@
7
7
  * Current library version
8
8
  * Automatically synced with package.json version
9
9
  */
10
- export const VERSION = '1.12.4';
10
+ export const VERSION = '1.12.5';
11
11
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xivdyetools/core",
3
- "version": "1.12.4",
3
+ "version": "1.12.5",
4
4
  "description": "Core color algorithms and dye database for XIV Dye Tools",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -77,7 +77,8 @@
77
77
  },
78
78
  "dependencies": {
79
79
  "@xivdyetools/logger": "^1.0.2",
80
- "@xivdyetools/types": "^1.6.1"
80
+ "@xivdyetools/types": "^1.6.1",
81
+ "spectral.js": "^3.0.0"
81
82
  },
82
83
  "lint-staged": {
83
84
  "*.ts": [
@@ -85,4 +86,4 @@
85
86
  "prettier --write"
86
87
  ]
87
88
  }
88
- }
89
+ }