@xivdyetools/core 2.7.0 → 4.0.1

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.
Files changed (156) hide show
  1. package/README.md +85 -67
  2. package/dist/blending/blending.d.ts +22 -0
  3. package/dist/blending/blending.d.ts.map +1 -0
  4. package/dist/blending/blending.js +129 -0
  5. package/dist/blending/blending.js.map +1 -0
  6. package/dist/blending/conversions.d.ts +53 -0
  7. package/dist/blending/conversions.d.ts.map +1 -0
  8. package/dist/blending/conversions.js +256 -0
  9. package/dist/blending/conversions.js.map +1 -0
  10. package/dist/blending/index.d.ts +8 -0
  11. package/dist/blending/index.d.ts.map +1 -0
  12. package/dist/blending/index.js +3 -0
  13. package/dist/blending/index.js.map +1 -0
  14. package/dist/blending/types.d.ts +36 -0
  15. package/dist/blending/types.d.ts.map +1 -0
  16. package/dist/blending/types.js +21 -0
  17. package/dist/blending/types.js.map +1 -0
  18. package/dist/config/band-calibration.d.ts +68 -0
  19. package/dist/config/band-calibration.d.ts.map +1 -0
  20. package/dist/config/band-calibration.js +196 -0
  21. package/dist/config/band-calibration.js.map +1 -0
  22. package/dist/config/band-vocabulary.d.ts +82 -0
  23. package/dist/config/band-vocabulary.d.ts.map +1 -0
  24. package/dist/config/band-vocabulary.js +117 -0
  25. package/dist/config/band-vocabulary.js.map +1 -0
  26. package/dist/config/consolidated-ids.js +2 -2
  27. package/dist/config/consolidated-ids.js.map +1 -1
  28. package/dist/config/dye-vocabulary.d.ts +45 -0
  29. package/dist/config/dye-vocabulary.d.ts.map +1 -0
  30. package/dist/config/dye-vocabulary.js +58 -0
  31. package/dist/config/dye-vocabulary.js.map +1 -0
  32. package/dist/config/facewear.d.ts +24 -0
  33. package/dist/config/facewear.d.ts.map +1 -0
  34. package/dist/config/facewear.js +35 -0
  35. package/dist/config/facewear.js.map +1 -0
  36. package/dist/config/learn-links.d.ts +70 -0
  37. package/dist/config/learn-links.d.ts.map +1 -0
  38. package/dist/config/learn-links.js +171 -0
  39. package/dist/config/learn-links.js.map +1 -0
  40. package/dist/config/product-links.d.ts +44 -0
  41. package/dist/config/product-links.d.ts.map +1 -0
  42. package/dist/config/product-links.js +44 -0
  43. package/dist/config/product-links.js.map +1 -0
  44. package/dist/constants/index.d.ts +14 -1
  45. package/dist/constants/index.d.ts.map +1 -1
  46. package/dist/constants/index.js +38 -22
  47. package/dist/constants/index.js.map +1 -1
  48. package/dist/data/character_colors/race_specific/hair_colors.json +1 -1
  49. package/dist/data/character_colors/race_specific/skin_colors.json +1 -1
  50. package/dist/data/dyes.json +1127 -0
  51. package/dist/data/facewear_colors.json +57 -0
  52. package/dist/data/locales/de.json +4 -50
  53. package/dist/data/locales/en.json +4 -50
  54. package/dist/data/locales/fr.json +4 -50
  55. package/dist/data/locales/ja.json +4 -50
  56. package/dist/data/locales/ko.json +4 -50
  57. package/dist/data/locales/zh.json +4 -50
  58. package/dist/data/presets.json +59 -301
  59. package/dist/index.d.ts +156 -17
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +114 -10
  62. package/dist/index.js.map +1 -1
  63. package/dist/services/APIService.d.ts +7 -61
  64. package/dist/services/APIService.d.ts.map +1 -1
  65. package/dist/services/APIService.js +43 -154
  66. package/dist/services/APIService.js.map +1 -1
  67. package/dist/services/CharacterColorService.d.ts +4 -36
  68. package/dist/services/CharacterColorService.d.ts.map +1 -1
  69. package/dist/services/CharacterColorService.js +16 -68
  70. package/dist/services/CharacterColorService.js.map +1 -1
  71. package/dist/services/ColorService.d.ts +55 -68
  72. package/dist/services/ColorService.d.ts.map +1 -1
  73. package/dist/services/ColorService.js +86 -94
  74. package/dist/services/ColorService.js.map +1 -1
  75. package/dist/services/DyeService.d.ts +10 -103
  76. package/dist/services/DyeService.d.ts.map +1 -1
  77. package/dist/services/DyeService.js +13 -156
  78. package/dist/services/DyeService.js.map +1 -1
  79. package/dist/services/LocalizationService.d.ts +1 -33
  80. package/dist/services/LocalizationService.d.ts.map +1 -1
  81. package/dist/services/LocalizationService.js +0 -44
  82. package/dist/services/LocalizationService.js.map +1 -1
  83. package/dist/services/PaletteService.d.ts +8 -9
  84. package/dist/services/PaletteService.d.ts.map +1 -1
  85. package/dist/services/PaletteService.js +2 -21
  86. package/dist/services/PaletteService.js.map +1 -1
  87. package/dist/services/PresetService.d.ts +2 -34
  88. package/dist/services/PresetService.d.ts.map +1 -1
  89. package/dist/services/PresetService.js +12 -59
  90. package/dist/services/PresetService.js.map +1 -1
  91. package/dist/services/chara/chara-models.d.ts +68 -0
  92. package/dist/services/chara/chara-models.d.ts.map +1 -0
  93. package/dist/services/chara/chara-models.js +87 -0
  94. package/dist/services/chara/chara-models.js.map +1 -0
  95. package/dist/services/chara/chara-parser.d.ts +95 -0
  96. package/dist/services/chara/chara-parser.d.ts.map +1 -0
  97. package/dist/services/chara/chara-parser.js +299 -0
  98. package/dist/services/chara/chara-parser.js.map +1 -0
  99. package/dist/services/chara/chara-resolver.d.ts +103 -0
  100. package/dist/services/chara/chara-resolver.d.ts.map +1 -0
  101. package/dist/services/chara/chara-resolver.js +233 -0
  102. package/dist/services/chara/chara-resolver.js.map +1 -0
  103. package/dist/services/color/ColorConverter.d.ts +107 -35
  104. package/dist/services/color/ColorConverter.d.ts.map +1 -1
  105. package/dist/services/color/ColorConverter.js +159 -48
  106. package/dist/services/color/ColorConverter.js.map +1 -1
  107. package/dist/services/color/ColorManipulator.d.ts +11 -0
  108. package/dist/services/color/ColorManipulator.d.ts.map +1 -1
  109. package/dist/services/color/ColorManipulator.js +14 -0
  110. package/dist/services/color/ColorManipulator.js.map +1 -1
  111. package/dist/services/color/ColorblindnessSimulator.d.ts +17 -0
  112. package/dist/services/color/ColorblindnessSimulator.d.ts.map +1 -1
  113. package/dist/services/color/ColorblindnessSimulator.js +53 -1
  114. package/dist/services/color/ColorblindnessSimulator.js.map +1 -1
  115. package/dist/services/color/SpectralMixer.d.ts +0 -34
  116. package/dist/services/color/SpectralMixer.d.ts.map +1 -1
  117. package/dist/services/color/SpectralMixer.js +0 -73
  118. package/dist/services/color/SpectralMixer.js.map +1 -1
  119. package/dist/services/dye/DyeDatabase.d.ts +0 -21
  120. package/dist/services/dye/DyeDatabase.d.ts.map +1 -1
  121. package/dist/services/dye/DyeDatabase.js +78 -103
  122. package/dist/services/dye/DyeDatabase.js.map +1 -1
  123. package/dist/services/dye/DyeSearch.d.ts +17 -31
  124. package/dist/services/dye/DyeSearch.d.ts.map +1 -1
  125. package/dist/services/dye/DyeSearch.js +31 -67
  126. package/dist/services/dye/DyeSearch.js.map +1 -1
  127. package/dist/services/dye/HarmonyGenerator.d.ts +11 -18
  128. package/dist/services/dye/HarmonyGenerator.d.ts.map +1 -1
  129. package/dist/services/dye/HarmonyGenerator.js +24 -35
  130. package/dist/services/dye/HarmonyGenerator.js.map +1 -1
  131. package/dist/services/localization/LocaleLoader.d.ts.map +1 -1
  132. package/dist/services/localization/LocaleLoader.js +0 -1
  133. package/dist/services/localization/LocaleLoader.js.map +1 -1
  134. package/dist/services/localization/TranslationProvider.d.ts +1 -42
  135. package/dist/services/localization/TranslationProvider.d.ts.map +1 -1
  136. package/dist/services/localization/TranslationProvider.js +4 -82
  137. package/dist/services/localization/TranslationProvider.js.map +1 -1
  138. package/dist/types/index.d.ts +39 -52
  139. package/dist/types/index.d.ts.map +1 -1
  140. package/dist/types/index.js +50 -10
  141. package/dist/types/index.js.map +1 -1
  142. package/dist/utils/index.d.ts +35 -122
  143. package/dist/utils/index.d.ts.map +1 -1
  144. package/dist/utils/index.js +45 -422
  145. package/dist/utils/index.js.map +1 -1
  146. package/dist/utils/kd-tree.d.ts +0 -4
  147. package/dist/utils/kd-tree.d.ts.map +1 -1
  148. package/dist/utils/kd-tree.js +0 -6
  149. package/dist/utils/kd-tree.js.map +1 -1
  150. package/package.json +19 -10
  151. package/dist/data/character_colors/index.json +0 -40
  152. package/dist/data/colors_xiv.json +0 -3538
  153. package/dist/version.d.ts +0 -11
  154. package/dist/version.d.ts.map +0 -1
  155. package/dist/version.js +0 -11
  156. package/dist/version.js.map +0 -1
@@ -0,0 +1,256 @@
1
+ import { clamp } from '../utils/index.js';
2
+ // ============================================================================
3
+ // CIELAB (D65 illuminant)
4
+ // ============================================================================
5
+ /**
6
+ * RGB to CIELAB conversion.
7
+ * Exported for use in SVG generators that display LAB values.
8
+ */
9
+ export function rgbToLab(rgb) {
10
+ let r = rgb.r / 255;
11
+ let g = rgb.g / 255;
12
+ let b = rgb.b / 255;
13
+ // sRGB to linear
14
+ r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
15
+ g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
16
+ b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
17
+ // Convert to XYZ (D65 illuminant)
18
+ let x = (r * 0.4124564 + g * 0.3575761 + b * 0.1804375) / 0.95047;
19
+ let y = r * 0.2126729 + g * 0.7151522 + b * 0.072175;
20
+ let z = (r * 0.0193339 + g * 0.119192 + b * 0.9503041) / 1.08883;
21
+ // XYZ to LAB
22
+ x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
23
+ y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
24
+ z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
25
+ return {
26
+ l: 116 * y - 16,
27
+ a: 500 * (x - y),
28
+ b: 200 * (y - z),
29
+ };
30
+ }
31
+ export function labToRgb(lab) {
32
+ let y = (lab.l + 16) / 116;
33
+ let x = lab.a / 500 + y;
34
+ let z = y - lab.b / 200;
35
+ const y3 = y * y * y;
36
+ const x3 = x * x * x;
37
+ const z3 = z * z * z;
38
+ y = y3 > 0.008856 ? y3 : (y - 16 / 116) / 7.787;
39
+ x = x3 > 0.008856 ? x3 : (x - 16 / 116) / 7.787;
40
+ z = z3 > 0.008856 ? z3 : (z - 16 / 116) / 7.787;
41
+ x *= 0.95047;
42
+ z *= 1.08883;
43
+ let r = x * 3.2404542 + y * -1.5371385 + z * -0.4985314;
44
+ let g = x * -0.969266 + y * 1.8760108 + z * 0.041556;
45
+ let b = x * 0.0556434 + y * -0.2040259 + z * 1.0572252;
46
+ // Linear to sRGB
47
+ r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
48
+ g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
49
+ b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
50
+ return {
51
+ r: Math.round(clamp(r * 255, 0, 255)),
52
+ g: Math.round(clamp(g * 255, 0, 255)),
53
+ b: Math.round(clamp(b * 255, 0, 255)),
54
+ };
55
+ }
56
+ // ============================================================================
57
+ // OKLAB (Björn Ottosson, 2020)
58
+ // ============================================================================
59
+ export function rgbToOklab(rgb) {
60
+ let r = rgb.r / 255;
61
+ let g = rgb.g / 255;
62
+ let b = rgb.b / 255;
63
+ // sRGB to linear
64
+ r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
65
+ g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
66
+ b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
67
+ // Linear RGB to LMS
68
+ const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
69
+ const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
70
+ const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
71
+ const l_ = Math.cbrt(l);
72
+ const m_ = Math.cbrt(m);
73
+ const s_ = Math.cbrt(s);
74
+ return {
75
+ L: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
76
+ a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
77
+ b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
78
+ };
79
+ }
80
+ export function oklabToRgb(oklab) {
81
+ const l_ = oklab.L + 0.3963377774 * oklab.a + 0.2158037573 * oklab.b;
82
+ const m_ = oklab.L - 0.1055613458 * oklab.a - 0.0638541728 * oklab.b;
83
+ const s_ = oklab.L - 0.0894841775 * oklab.a - 1.291485548 * oklab.b;
84
+ const l = l_ * l_ * l_;
85
+ const m = m_ * m_ * m_;
86
+ const s = s_ * s_ * s_;
87
+ let r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
88
+ let g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
89
+ let b = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
90
+ // Linear to sRGB
91
+ r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
92
+ g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
93
+ b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
94
+ return {
95
+ r: Math.round(clamp(r * 255, 0, 255)),
96
+ g: Math.round(clamp(g * 255, 0, 255)),
97
+ b: Math.round(clamp(b * 255, 0, 255)),
98
+ };
99
+ }
100
+ // ============================================================================
101
+ // RYB (Red-Yellow-Blue, approximate)
102
+ // ============================================================================
103
+ export function rgbToRyb(rgb) {
104
+ const r = rgb.r / 255;
105
+ const g = rgb.g / 255;
106
+ const b = rgb.b / 255;
107
+ const w = Math.min(r, g, b);
108
+ const r_ = r - w;
109
+ const g_ = g - w;
110
+ const b_ = b - w;
111
+ const mg = Math.max(r_, g_, b_);
112
+ const y = Math.min(r_, g_);
113
+ const r__ = r_ - y;
114
+ const b__ = (b_ + (g_ - y)) / 2;
115
+ const n = Math.max(r__, y, b__) / Math.max(mg, 0.001);
116
+ return {
117
+ r: r__ / Math.max(n, 0.001) + w,
118
+ y: y / Math.max(n, 0.001) + w,
119
+ b: b__ / Math.max(n, 0.001) + w,
120
+ };
121
+ }
122
+ export function rybToRgb(ryb) {
123
+ const r = ryb.r;
124
+ const y = ryb.y;
125
+ const b = ryb.b;
126
+ const w = Math.min(r, y, b);
127
+ const r_ = r - w;
128
+ const y_ = y - w;
129
+ const b_ = b - w;
130
+ const my = Math.max(r_, y_, b_);
131
+ let g = Math.min(y_, b_);
132
+ const y__ = y_ - g;
133
+ const b__ = b_ - g;
134
+ const r__ = r_ + y__;
135
+ g = g + y__;
136
+ const n = Math.max(r__, g, b__) / Math.max(my, 0.001);
137
+ return {
138
+ r: Math.round(clamp((r__ / Math.max(n, 0.001) + w) * 255, 0, 255)),
139
+ g: Math.round(clamp((g / Math.max(n, 0.001) + w) * 255, 0, 255)),
140
+ b: Math.round(clamp((b__ / Math.max(n, 0.001) + w) * 255, 0, 255)),
141
+ };
142
+ }
143
+ // ============================================================================
144
+ // HSL
145
+ // ============================================================================
146
+ export function rgbToHsl(rgb) {
147
+ const r = rgb.r / 255;
148
+ const g = rgb.g / 255;
149
+ const b = rgb.b / 255;
150
+ const max = Math.max(r, g, b);
151
+ const min = Math.min(r, g, b);
152
+ const l = (max + min) / 2;
153
+ if (max === min) {
154
+ return { h: 0, s: 0, l };
155
+ }
156
+ const d = max - min;
157
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
158
+ let h = 0;
159
+ switch (max) {
160
+ case r:
161
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
162
+ break;
163
+ case g:
164
+ h = ((b - r) / d + 2) / 6;
165
+ break;
166
+ case b:
167
+ h = ((r - g) / d + 4) / 6;
168
+ break;
169
+ }
170
+ return { h: h * 360, s, l };
171
+ }
172
+ export function hslToRgb(hsl) {
173
+ const h = hsl.h / 360;
174
+ const s = hsl.s;
175
+ const l = hsl.l;
176
+ if (s === 0) {
177
+ const v = Math.round(l * 255);
178
+ return { r: v, g: v, b: v };
179
+ }
180
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
181
+ const p = 2 * l - q;
182
+ const hue2rgb = (p, q, t) => {
183
+ if (t < 0)
184
+ t += 1;
185
+ if (t > 1)
186
+ t -= 1;
187
+ if (t < 1 / 6)
188
+ return p + (q - p) * 6 * t;
189
+ if (t < 1 / 2)
190
+ return q;
191
+ if (t < 2 / 3)
192
+ return p + (q - p) * (2 / 3 - t) * 6;
193
+ return p;
194
+ };
195
+ return {
196
+ r: Math.round(hue2rgb(p, q, h + 1 / 3) * 255),
197
+ g: Math.round(hue2rgb(p, q, h) * 255),
198
+ b: Math.round(hue2rgb(p, q, h - 1 / 3) * 255),
199
+ };
200
+ }
201
+ // ============================================================================
202
+ // Kubelka-Munk (Spectral)
203
+ // ============================================================================
204
+ export function rgbToReflectance(rgb) {
205
+ return { r: rgb.r / 255, g: rgb.g / 255, b: rgb.b / 255 };
206
+ }
207
+ export function reflectanceToRgb(ref) {
208
+ return {
209
+ r: Math.round(clamp(ref.r * 255, 0, 255)),
210
+ g: Math.round(clamp(ref.g * 255, 0, 255)),
211
+ b: Math.round(clamp(ref.b * 255, 0, 255)),
212
+ };
213
+ }
214
+ export function reflectanceToKS(r) {
215
+ // K/S = (1-R)² / (2R)
216
+ const R = Math.max(0.001, Math.min(0.999, r));
217
+ return ((1 - R) * (1 - R)) / (2 * R);
218
+ }
219
+ export function ksToReflectance(ks) {
220
+ // R = 1 + K/S - √((K/S)² + 2·K/S)
221
+ return 1 + ks - Math.sqrt(ks * ks + 2 * ks);
222
+ }
223
+ // ============================================================================
224
+ // Utility
225
+ // ============================================================================
226
+ /**
227
+ * Parse a hex color string into RGB channels.
228
+ *
229
+ * REFACTOR-005 (2026-07-18 audit): local implementation replacing the sole use
230
+ * of `@xivdyetools/core`'s ColorService — the entire core package (dye
231
+ * database, k-d tree, i18n) was a dependency for these ~10 lines. Matches
232
+ * core's strict behavior: throws on malformed input; accepts #RGB and #RRGGBB
233
+ * (leading # optional).
234
+ */
235
+ export function hexToRgb(hex) {
236
+ const clean = hex.startsWith('#') ? hex.slice(1) : hex;
237
+ if (!/^(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(clean)) {
238
+ throw new Error(`Invalid hex color: ${hex}. Use format #RRGGBB or #RGB`);
239
+ }
240
+ const full = clean.length === 3
241
+ ? clean
242
+ .split('')
243
+ .map((c) => c + c)
244
+ .join('')
245
+ : clean;
246
+ return {
247
+ r: parseInt(full.substring(0, 2), 16),
248
+ g: parseInt(full.substring(2, 4), 16),
249
+ b: parseInt(full.substring(4, 6), 16),
250
+ };
251
+ }
252
+ export function rgbToHex(rgb) {
253
+ const toHex = (n) => n.toString(16).padStart(2, '0');
254
+ return `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`;
255
+ }
256
+ //# sourceMappingURL=conversions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversions.js","sourceRoot":"","sources":["../../src/blending/conversions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type {
2
+ /** @public */ RGB,
3
+ /** @public */ LAB,
4
+ /** @public */ HSL,
5
+ /** @public */ BlendResult, BlendingMode, } from './types.js';
6
+ export { BLENDING_MODES, isValidBlendingMode } from './types.js';
7
+ export { blendColors } from './blending.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blending/index.ts"],"names":[],"mappings":"AAAA,YAAY;AACV,cAAc,CAAC,GAAG;AAClB,cAAc,CAAC,GAAG;AAClB,cAAc,CAAC,GAAG;AAClB,cAAc,CAAC,WAAW,EAC1B,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { BLENDING_MODES, isValidBlendingMode } from './types.js';
2
+ export { blendColors } from './blending.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/blending/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Available color blending algorithms.
3
+ */
4
+ export type BlendingMode = 'rgb' | 'lab' | 'oklab' | 'ryb' | 'hsl' | 'spectral';
5
+ /**
6
+ * All blending modes with display metadata.
7
+ */
8
+ export declare const BLENDING_MODES: Array<{
9
+ value: BlendingMode;
10
+ name: string;
11
+ description: string;
12
+ }>;
13
+ /**
14
+ * Type guard: check if a string is a valid blending mode.
15
+ */
16
+ export declare function isValidBlendingMode(mode: string): mode is BlendingMode;
17
+ export interface RGB {
18
+ r: number;
19
+ g: number;
20
+ b: number;
21
+ }
22
+ export interface LAB {
23
+ l: number;
24
+ a: number;
25
+ b: number;
26
+ }
27
+ export interface HSL {
28
+ h: number;
29
+ s: number;
30
+ l: number;
31
+ }
32
+ export interface BlendResult {
33
+ hex: string;
34
+ rgb: RGB;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/blending/types.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAO5F,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,YAAY,CAEtE;AAMD,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,GAAG,CAAC;CACV"}
@@ -0,0 +1,21 @@
1
+ // ============================================================================
2
+ // Blending Mode
3
+ // ============================================================================
4
+ /**
5
+ * All blending modes with display metadata.
6
+ */
7
+ export const BLENDING_MODES = [
8
+ { value: 'rgb', name: 'RGB', description: 'Additive channel averaging (default)' },
9
+ { value: 'lab', name: 'LAB', description: 'Perceptually uniform CIELAB blending' },
10
+ { value: 'oklab', name: 'OKLAB', description: 'Modern perceptual (fixes LAB blue→purple)' },
11
+ { value: 'ryb', name: 'RYB', description: "Traditional artist's color wheel" },
12
+ { value: 'hsl', name: 'HSL', description: 'Hue-Saturation-Lightness interpolation' },
13
+ { value: 'spectral', name: 'Spectral', description: 'Kubelka-Munk physics simulation' },
14
+ ];
15
+ /**
16
+ * Type guard: check if a string is a valid blending mode.
17
+ */
18
+ export function isValidBlendingMode(mode) {
19
+ return BLENDING_MODES.some((m) => m.value === mode);
20
+ }
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/blending/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAO/E;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsE;IAC/F,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,sCAAsC,EAAE;IAClF,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,sCAAsC,EAAE;IAClF,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,2CAA2C,EAAE;IAC3F,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,kCAAkC,EAAE;IAC9E,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,wCAAwC,EAAE;IACpF,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,iCAAiC,EAAE;CACxF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Band calibration — the algorithm behind the 5.0 band vocabulary.
3
+ *
4
+ * Port of the confirmed calibration study (`Band Calibration.dc.html`,
5
+ * confirmed 2026-08-07): for each context boundary, choose the per-method
6
+ * threshold that maximises tier agreement with ΔE2000's settled tiers over
7
+ * every real dye pair, round it to the method's display precision, and
8
+ * re-score on rounded values (the tier-on-the-displayed-value rule).
9
+ * Quantile-matched thresholds are computed beside as a stability check.
10
+ *
11
+ * Corpora:
12
+ * - MATCH / HARMONY calibrate on all real dye pairs.
13
+ * - SEPARATION calibrates on the pooled lens corpus — normal + protanopia +
14
+ * deuteranopia + tritanopia + achromatopsia, Machado severity-1.0 matrices
15
+ * applied in linear RGB (achromatopsia as linear-luminance grey) — because
16
+ * separation verdicts print on simulated pairs.
17
+ * - RATIO (WCAG contrast, not a distance) is calibrated anyway: against MATCH
18
+ * tiers for Comparison and SEPARATION tiers for Accessibility, with the
19
+ * Accessibility top band anchored at 3:1 (the 1.4.11 figure).
20
+ *
21
+ * The shipped numbers live in `band-vocabulary.ts`; the parity test recomputes
22
+ * them through this module. Per the confirmed decision, the shipped numbers
23
+ * come from core's own primitives (ColorConverter, ColorblindnessSimulator,
24
+ * ColorAccessibility), not from the design page's inline copies.
25
+ */
26
+ /** Methods calibrated against ΔE2000 (DISTINGUISH % derives from RGB DIST). */
27
+ export type CalibratedMethodId = 'oklab' | 'cie76' | 'redmean' | 'rgb';
28
+ export interface CalibratedMethodBands {
29
+ /** Accuracy-optimal cuts, display-rounded, ordering enforced (ascending) */
30
+ cuts: [number, number, number];
31
+ /** Quantile-matched cuts (stability cross-check, not shipped) */
32
+ quantile: [number, number, number];
33
+ /** Tier agreement with ΔE2000 on display-rounded values (0-1) */
34
+ agreement: number;
35
+ /** Agreement of the quantile cuts (0-1) */
36
+ quantileAgreement: number;
37
+ }
38
+ export interface RatioCalibration {
39
+ cuts: [number, number, number];
40
+ agreement: number;
41
+ }
42
+ export interface BandCalibrationResult {
43
+ realPairCount: number;
44
+ pooledPairCount: number;
45
+ match: Record<CalibratedMethodId, CalibratedMethodBands>;
46
+ harmony: Record<CalibratedMethodId, CalibratedMethodBands>;
47
+ separation: Record<CalibratedMethodId, CalibratedMethodBands>;
48
+ ratio: {
49
+ comparison: RatioCalibration;
50
+ accessibility: RatioCalibration;
51
+ /** Accessibility cuts with the top band anchored at 3:1 (1.4.11) */
52
+ accessibilityAnchored: RatioCalibration;
53
+ };
54
+ }
55
+ /** ΔE2000 settled ground-truth boundaries (ascending) */
56
+ export declare const DE2000_GROUND_TRUTH: {
57
+ readonly match: readonly [5, 10, 20];
58
+ readonly harmony: readonly [6, 12, 20];
59
+ readonly separation: readonly [8, 15, 30];
60
+ };
61
+ /**
62
+ * Run the full band calibration over a dye list (hex strings).
63
+ *
64
+ * Deterministic and pure; used by the parity test and the
65
+ * `calibrate-bands` script that regenerates `band-vocabulary.ts`'s numbers.
66
+ */
67
+ export declare function calibrateBandVocabulary(hexes: readonly string[]): BandCalibrationResult;
68
+ //# sourceMappingURL=band-calibration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"band-calibration.d.ts","sourceRoot":"","sources":["../../src/config/band-calibration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,CAAC;AAEvE,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;IACzD,OAAO,EAAE,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;IAC3D,UAAU,EAAE,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;IAC9D,KAAK,EAAE;QACL,UAAU,EAAE,gBAAgB,CAAC;QAC7B,aAAa,EAAE,gBAAgB,CAAC;QAChC,oEAAoE;QACpE,qBAAqB,EAAE,gBAAgB,CAAC;KACzC,CAAC;CACH;AAED,yDAAyD;AACzD,eAAO,MAAM,mBAAmB;;;;CAItB,CAAC;AA4IX;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,qBAAqB,CA4CvF"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Band calibration — the algorithm behind the 5.0 band vocabulary.
3
+ *
4
+ * Port of the confirmed calibration study (`Band Calibration.dc.html`,
5
+ * confirmed 2026-08-07): for each context boundary, choose the per-method
6
+ * threshold that maximises tier agreement with ΔE2000's settled tiers over
7
+ * every real dye pair, round it to the method's display precision, and
8
+ * re-score on rounded values (the tier-on-the-displayed-value rule).
9
+ * Quantile-matched thresholds are computed beside as a stability check.
10
+ *
11
+ * Corpora:
12
+ * - MATCH / HARMONY calibrate on all real dye pairs.
13
+ * - SEPARATION calibrates on the pooled lens corpus — normal + protanopia +
14
+ * deuteranopia + tritanopia + achromatopsia, Machado severity-1.0 matrices
15
+ * applied in linear RGB (achromatopsia as linear-luminance grey) — because
16
+ * separation verdicts print on simulated pairs.
17
+ * - RATIO (WCAG contrast, not a distance) is calibrated anyway: against MATCH
18
+ * tiers for Comparison and SEPARATION tiers for Accessibility, with the
19
+ * Accessibility top band anchored at 3:1 (the 1.4.11 figure).
20
+ *
21
+ * The shipped numbers live in `band-vocabulary.ts`; the parity test recomputes
22
+ * them through this module. Per the confirmed decision, the shipped numbers
23
+ * come from core's own primitives (ColorConverter, ColorblindnessSimulator,
24
+ * ColorAccessibility), not from the design page's inline copies.
25
+ */
26
+ import { ColorConverter } from '../services/color/ColorConverter.js';
27
+ import { ColorblindnessSimulator } from '../services/color/ColorblindnessSimulator.js';
28
+ import { ColorAccessibility } from '../services/color/ColorAccessibility.js';
29
+ import { BAND_METHOD_DP } from './band-vocabulary.js';
30
+ /** ΔE2000 settled ground-truth boundaries (ascending) */
31
+ export const DE2000_GROUND_TRUTH = {
32
+ match: [5, 10, 20],
33
+ harmony: [6, 12, 20],
34
+ separation: [8, 15, 30],
35
+ };
36
+ const LENSES = ['protanopia', 'deuteranopia', 'tritanopia', 'achromatopsia'];
37
+ function roundTo(value, dp) {
38
+ const f = Math.pow(10, dp);
39
+ return Math.round(value * f) / f;
40
+ }
41
+ function tierOf(value, bands) {
42
+ return value < bands[0] ? 0 : value < bands[1] ? 1 : value < bands[2] ? 2 : 3;
43
+ }
44
+ /**
45
+ * Best threshold for a binary split (label true = "should read below the
46
+ * cut"), evaluated on display-rounded midpoints. Verbatim port of the study's
47
+ * `bestCut`, including its behaviour of never placing the cut below the
48
+ * smallest observed value.
49
+ */
50
+ function bestCut(vals, labels, dp) {
51
+ const idx = vals.map((_, i) => i).sort((x, y) => vals[x] - vals[y]);
52
+ let negTotal = 0;
53
+ for (const l of labels)
54
+ if (!l)
55
+ negTotal++;
56
+ let below = 0;
57
+ let negBelow = 0;
58
+ let bestAgree = -1;
59
+ let bestT = 0;
60
+ for (let k = 0; k < idx.length; k++) {
61
+ if (labels[idx[k]])
62
+ below++;
63
+ else
64
+ negBelow++;
65
+ const v = vals[idx[k]];
66
+ const next = k + 1 < idx.length ? vals[idx[k + 1]] : v + 1;
67
+ if (next === v)
68
+ continue;
69
+ const agree = below + (negTotal - negBelow);
70
+ if (agree > bestAgree) {
71
+ bestAgree = agree;
72
+ bestT = roundTo((v + next) / 2, dp);
73
+ }
74
+ }
75
+ return bestT;
76
+ }
77
+ /** Quantile-matched threshold: cut where the positive count falls. */
78
+ function quantileCut(vals, labels, dp) {
79
+ let pos = 0;
80
+ for (const l of labels)
81
+ if (l)
82
+ pos++;
83
+ const sorted = [...vals].sort((a, b) => a - b);
84
+ const i = Math.min(sorted.length - 1, Math.max(0, pos - 1));
85
+ return roundTo((sorted[i] + sorted[Math.min(sorted.length - 1, i + 1)]) / 2, dp);
86
+ }
87
+ /** Fraction of pairs whose display-rounded tier matches the reference tier. */
88
+ function jointAgree(vals, refTiers, bands, dp) {
89
+ let ok = 0;
90
+ for (let i = 0; i < vals.length; i++) {
91
+ if (tierOf(roundTo(vals[i], dp), bands) === refTiers[i])
92
+ ok++;
93
+ }
94
+ return ok / vals.length;
95
+ }
96
+ function pairRows(hexes) {
97
+ const rows = { ciede2000: [], oklab: [], cie76: [], redmean: [], rgb: [], ratio: [] };
98
+ for (let i = 0; i < hexes.length; i++) {
99
+ for (let j = i + 1; j < hexes.length; j++) {
100
+ const a = hexes[i];
101
+ const b = hexes[j];
102
+ rows.ciede2000.push(ColorConverter.getDeltaE(a, b, 'cie2000'));
103
+ rows.oklab.push(ColorConverter.getDeltaE_Oklab(a, b));
104
+ rows.cie76.push(ColorConverter.getDeltaE(a, b, 'cie76'));
105
+ rows.redmean.push(ColorConverter.getRedmeanDistance(a, b));
106
+ rows.rgb.push(ColorConverter.getColorDistance(a, b));
107
+ rows.ratio.push(ColorAccessibility.getContrastRatio(a, b));
108
+ }
109
+ }
110
+ return rows;
111
+ }
112
+ function calibrateContext(rows, refBands) {
113
+ const refTiers = rows.ciede2000.map((v) => tierOf(roundTo(v, 1), refBands));
114
+ const result = {};
115
+ for (const id of ['oklab', 'cie76', 'redmean', 'rgb']) {
116
+ const dp = BAND_METHOD_DP[id];
117
+ const vals = rows[id];
118
+ const cuts = [];
119
+ const quantile = [];
120
+ for (let k = 0; k < 3; k++) {
121
+ const labels = refTiers.map((t) => t <= k);
122
+ cuts.push(bestCut(vals, labels, dp));
123
+ quantile.push(quantileCut(vals, labels, dp));
124
+ }
125
+ for (let k = 1; k < 3; k++) {
126
+ if (cuts[k] < cuts[k - 1])
127
+ cuts[k] = cuts[k - 1];
128
+ if (quantile[k] < quantile[k - 1])
129
+ quantile[k] = quantile[k - 1];
130
+ }
131
+ result[id] = {
132
+ cuts: cuts,
133
+ quantile: quantile,
134
+ agreement: jointAgree(vals, refTiers, cuts, dp),
135
+ quantileAgreement: jointAgree(vals, refTiers, quantile, dp),
136
+ };
137
+ }
138
+ return result;
139
+ }
140
+ function calibrateRatio(rows, refBands) {
141
+ const refTiers = rows.ciede2000.map((v) => tierOf(roundTo(v, 1), refBands));
142
+ const cuts = [];
143
+ for (let k = 0; k < 3; k++) {
144
+ cuts.push(bestCut(rows.ratio, refTiers.map((t) => t <= k), 2));
145
+ }
146
+ for (let k = 1; k < 3; k++)
147
+ if (cuts[k] < cuts[k - 1])
148
+ cuts[k] = cuts[k - 1];
149
+ return {
150
+ cuts: cuts,
151
+ agreement: jointAgree(rows.ratio, refTiers, cuts, 2),
152
+ };
153
+ }
154
+ /**
155
+ * Run the full band calibration over a dye list (hex strings).
156
+ *
157
+ * Deterministic and pure; used by the parity test and the
158
+ * `calibrate-bands` script that regenerates `band-vocabulary.ts`'s numbers.
159
+ */
160
+ export function calibrateBandVocabulary(hexes) {
161
+ const normal = pairRows(hexes);
162
+ const pooled = {
163
+ ciede2000: [...normal.ciede2000],
164
+ oklab: [...normal.oklab],
165
+ cie76: [...normal.cie76],
166
+ redmean: [...normal.redmean],
167
+ rgb: [...normal.rgb],
168
+ ratio: [...normal.ratio],
169
+ };
170
+ for (const lens of LENSES) {
171
+ const simulated = hexes.map((hex) => ColorblindnessSimulator.simulateColorblindnessMachadoHex(hex, lens));
172
+ const rows = pairRows(simulated);
173
+ for (const key of Object.keys(pooled)) {
174
+ pooled[key].push(...rows[key]);
175
+ }
176
+ }
177
+ const accessibility = calibrateRatio(pooled, DE2000_GROUND_TRUTH.separation);
178
+ const anchoredCuts = [accessibility.cuts[0], accessibility.cuts[1], 3.0].map((v, i, a) => i > 0 && v < a[i - 1] ? a[i - 1] : v);
179
+ const refTiersSep = pooled.ciede2000.map((v) => tierOf(roundTo(v, 1), DE2000_GROUND_TRUTH.separation));
180
+ return {
181
+ realPairCount: normal.ciede2000.length,
182
+ pooledPairCount: pooled.ciede2000.length,
183
+ match: calibrateContext(normal, DE2000_GROUND_TRUTH.match),
184
+ harmony: calibrateContext(normal, DE2000_GROUND_TRUTH.harmony),
185
+ separation: calibrateContext(pooled, DE2000_GROUND_TRUTH.separation),
186
+ ratio: {
187
+ comparison: calibrateRatio(normal, DE2000_GROUND_TRUTH.match),
188
+ accessibility,
189
+ accessibilityAnchored: {
190
+ cuts: anchoredCuts,
191
+ agreement: jointAgree(pooled.ratio, refTiersSep, anchoredCuts, 2),
192
+ },
193
+ },
194
+ };
195
+ }
196
+ //# sourceMappingURL=band-calibration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"band-calibration.js","sourceRoot":"","sources":["../../src/config/band-calibration.ts"],"names":[],"mappings":"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"}