@xivdyetools/core 4.3.0 → 5.2.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.
Files changed (100) hide show
  1. package/NOTICE +26 -0
  2. package/README.md +3 -1
  3. package/dist/blending/blending.d.ts +26 -6
  4. package/dist/blending/blending.d.ts.map +1 -1
  5. package/dist/blending/blending.js +79 -32
  6. package/dist/blending/blending.js.map +1 -1
  7. package/dist/blending/conversions.d.ts +0 -12
  8. package/dist/blending/conversions.d.ts.map +1 -1
  9. package/dist/blending/conversions.js +25 -28
  10. package/dist/blending/conversions.js.map +1 -1
  11. package/dist/blending/index.d.ts +4 -1
  12. package/dist/blending/index.d.ts.map +1 -1
  13. package/dist/blending/index.js.map +1 -1
  14. package/dist/blending/types.d.ts +38 -0
  15. package/dist/blending/types.d.ts.map +1 -1
  16. package/dist/config/band-vocabulary.d.ts +9 -0
  17. package/dist/config/band-vocabulary.d.ts.map +1 -1
  18. package/dist/config/band-vocabulary.js +12 -3
  19. package/dist/config/band-vocabulary.js.map +1 -1
  20. package/dist/data/locales/de.json +8 -1
  21. package/dist/data/locales/en.json +8 -1
  22. package/dist/data/locales/fr.json +8 -1
  23. package/dist/data/locales/ja.json +8 -1
  24. package/dist/data/locales/ko.json +8 -1
  25. package/dist/data/locales/zh.json +8 -1
  26. package/dist/data/munsell-hues.json +175 -0
  27. package/dist/data/oklch-hue-table.json +297 -0
  28. package/dist/index.d.ts +18 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +9 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/services/ColorService.d.ts +37 -15
  33. package/dist/services/ColorService.d.ts.map +1 -1
  34. package/dist/services/ColorService.js +70 -69
  35. package/dist/services/ColorService.js.map +1 -1
  36. package/dist/services/DyeService.d.ts +35 -0
  37. package/dist/services/DyeService.d.ts.map +1 -1
  38. package/dist/services/DyeService.js +35 -0
  39. package/dist/services/DyeService.js.map +1 -1
  40. package/dist/services/LocalizationService.d.ts +5 -1
  41. package/dist/services/LocalizationService.d.ts.map +1 -1
  42. package/dist/services/LocalizationService.js +8 -0
  43. package/dist/services/LocalizationService.js.map +1 -1
  44. package/dist/services/color/ColorConverter.d.ts +67 -35
  45. package/dist/services/color/ColorConverter.d.ts.map +1 -1
  46. package/dist/services/color/ColorConverter.js +236 -85
  47. package/dist/services/color/ColorConverter.js.map +1 -1
  48. package/dist/services/dye/HarmonyGenerator.d.ts +22 -2
  49. package/dist/services/dye/HarmonyGenerator.d.ts.map +1 -1
  50. package/dist/services/dye/HarmonyGenerator.js +39 -5
  51. package/dist/services/dye/HarmonyGenerator.js.map +1 -1
  52. package/dist/services/dye/HarmonySelector.d.ts +15 -1
  53. package/dist/services/dye/HarmonySelector.d.ts.map +1 -1
  54. package/dist/services/dye/HarmonySelector.js +20 -8
  55. package/dist/services/dye/HarmonySelector.js.map +1 -1
  56. package/dist/services/dye/wheels/ColorWheel.d.ts +29 -0
  57. package/dist/services/dye/wheels/ColorWheel.d.ts.map +1 -0
  58. package/dist/services/dye/wheels/ColorWheel.js +63 -0
  59. package/dist/services/dye/wheels/ColorWheel.js.map +1 -0
  60. package/dist/services/dye/wheels/hue-warp.d.ts +40 -0
  61. package/dist/services/dye/wheels/hue-warp.d.ts.map +1 -0
  62. package/dist/services/dye/wheels/hue-warp.js +144 -0
  63. package/dist/services/dye/wheels/hue-warp.js.map +1 -0
  64. package/dist/services/dye/wheels/munsell.d.ts +17 -0
  65. package/dist/services/dye/wheels/munsell.d.ts.map +1 -0
  66. package/dist/services/dye/wheels/munsell.js +18 -0
  67. package/dist/services/dye/wheels/munsell.js.map +1 -0
  68. package/dist/services/dye/wheels/oklch-hue.d.ts +22 -0
  69. package/dist/services/dye/wheels/oklch-hue.d.ts.map +1 -0
  70. package/dist/services/dye/wheels/oklch-hue.js +23 -0
  71. package/dist/services/dye/wheels/oklch-hue.js.map +1 -0
  72. package/dist/services/dye/wheels/oklch-lightness.d.ts +24 -0
  73. package/dist/services/dye/wheels/oklch-lightness.d.ts.map +1 -0
  74. package/dist/services/dye/wheels/oklch-lightness.js +65 -0
  75. package/dist/services/dye/wheels/oklch-lightness.js.map +1 -0
  76. package/dist/services/dye/wheels/rgb-ryb.d.ts +18 -0
  77. package/dist/services/dye/wheels/rgb-ryb.d.ts.map +1 -0
  78. package/dist/services/dye/wheels/rgb-ryb.js +47 -0
  79. package/dist/services/dye/wheels/rgb-ryb.js.map +1 -0
  80. package/dist/services/dye/wheels/types.d.ts +40 -0
  81. package/dist/services/dye/wheels/types.d.ts.map +1 -0
  82. package/dist/services/dye/wheels/types.js +11 -0
  83. package/dist/services/dye/wheels/types.js.map +1 -0
  84. package/dist/services/localization/TranslationProvider.d.ts +6 -1
  85. package/dist/services/localization/TranslationProvider.d.ts.map +1 -1
  86. package/dist/services/localization/TranslationProvider.js +8 -0
  87. package/dist/services/localization/TranslationProvider.js.map +1 -1
  88. package/dist/types/index.d.ts +3 -2
  89. package/dist/types/index.d.ts.map +1 -1
  90. package/dist/types/index.js +2 -2
  91. package/dist/types/index.js.map +1 -1
  92. package/package.json +8 -3
  93. package/dist/services/color/RybColorMixer.d.ts +0 -102
  94. package/dist/services/color/RybColorMixer.d.ts.map +0 -1
  95. package/dist/services/color/RybColorMixer.js +0 -362
  96. package/dist/services/color/RybColorMixer.js.map +0 -1
  97. package/dist/services/color/SpectralMixer.d.ts +0 -43
  98. package/dist/services/color/SpectralMixer.d.ts.map +0 -1
  99. package/dist/services/color/SpectralMixer.js +0 -59
  100. package/dist/services/color/SpectralMixer.js.map +0 -1
@@ -19,6 +19,11 @@ export type HarmonyMatchingAlgorithm = 'hue' | 'deltaE';
19
19
  * - 'oklch': OKLCH perceptual color space (Björn Ottosson, 2020) - perceptually uniform hue
20
20
  * - 'lch': CIELCHab cylindrical perceptual space - traditional color science standard
21
21
  * - 'hsl': HSL hue-saturation-lightness - similar to HSV with different lightness mapping
22
+ *
23
+ * @deprecated Since 5.2.0. Rotates hue at fixed L/C in a space that does not
24
+ * carry the base's saturation and value; now gamut-maps for `oklch`, while
25
+ * `lch`/`hsl` still clip. Still prefer `generateHarmonySlots(…, { wheel })`
26
+ * and `getColorWheel(id)`. Kept for published-API compatibility only.
22
27
  */
23
28
  export type HarmonyColorSpace = 'hsv' | 'oklch' | 'lch' | 'hsl';
24
29
  /**
@@ -35,11 +40,16 @@ export interface HarmonyOptions {
35
40
  * When set to a non-HSV space, target colors are generated by rotating
36
41
  * the hue in that space and matching via k-d tree (perceptual distance).
37
42
  * @default 'hsv'
43
+ *
44
+ * @deprecated Since 5.2.0. Rotates hue at fixed L/C in a space that does not
45
+ * carry the base's saturation and value; now gamut-maps for `oklch`, while
46
+ * `lch`/`hsl` still clip. Still prefer `generateHarmonySlots(…, { wheel })`
47
+ * and `getColorWheel(id)`. Kept for published-API compatibility only.
38
48
  */
39
49
  colorSpace?: HarmonyColorSpace;
40
50
  /**
41
51
  * DeltaE formula (only used when algorithm is 'deltaE')
42
- * @default 'cie76'
52
+ * @default 'ciede2000' (was `'cie76'` before 5.1.0 — see DEFAULT_HARMONY_DELTA_E)
43
53
  */
44
54
  deltaEFormula?: DeltaEFormula;
45
55
  /**
@@ -53,7 +63,7 @@ export interface HarmonyOptions {
53
63
  * Only used when algorithm is 'deltaE'
54
64
  * Higher values return more matches but less precise
55
65
  * @default per formula — 40 cie76, 25 ciede2000 (and its 'cie2000'
56
- * alias), 0.13 oklab. OKLAB deltaE runs on a ~0-1 scale, so the CIE76
66
+ * alias), 0.21 oklab. OKLAB deltaE runs on a ~0-1 scale, so the CIE76
57
67
  * number is not a usable default for it (BUG-059).
58
68
  */
59
69
  deltaETolerance?: number;
@@ -180,6 +190,16 @@ export declare class HarmonyGenerator {
180
190
  /**
181
191
  * Rotate a color's hue by an offset in the specified color space
182
192
  * Keeps the other components (chroma/saturation, lightness/value) unchanged
193
+ *
194
+ * @deprecated Since 5.2.0. Rotates hue at fixed L/C in a space that does not
195
+ * carry the base's S/V; now gamut-maps for `oklch`; still prefer
196
+ * `generateHarmonySlots(…, { wheel })` and `getColorWheel(id)`. Kept for
197
+ * published-API compatibility only.
198
+ *
199
+ * `lch` (and `hsl`) still CLIP per channel, which changes hue on any
200
+ * out-of-gamut rotation — CIELAB has no in-package gamut mapper, and adding
201
+ * one to a deprecated path is not the trade. `oklch` does not: it bisects
202
+ * chroma at constant L and h (CSS Color 4), the same mapping the wheels use.
183
203
  */
184
204
  private rotateHueInSpace;
185
205
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"HarmonyGenerator.d.ts","sourceRoot":"","sources":["../../../src/services/dye/HarmonyGenerator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAO,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,KAAK,GAAG,QAAQ,CAAC;AA4CxD;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,wBAAwB,CAAC;IAErC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAE/B;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;gBADN,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,SAAS;IAG3B;;;;;OAKG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,GAAG,IAAI;IAkCxE;;;;;;OAMG;IACH,OAAO,CAAC,yBAAyB;IAKjC;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAKnF;;;;;;;;;OASG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAI7D;;;;;;;;OAQG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAI5D;;;;;;;;OAQG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAK9D;;;;;;;;;;;OAWG;IACH,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAKtE;;;;;;;OAOG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAmEtF;;;;;;;;OAQG;IACH,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAIxE;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,wBAAwB;IAkEhC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAsC5B"}
1
+ {"version":3,"file":"HarmonyGenerator.d.ts","sourceRoot":"","sources":["../../../src/services/dye/HarmonyGenerator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAO,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAqExD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,SAAS,CAAC,EAAE,wBAAwB,CAAC;IAErC;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAE/B;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;gBADN,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,SAAS;IAG3B;;;;;OAKG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,GAAG,IAAI;IAkCxE;;;;;;OAMG;IACH,OAAO,CAAC,yBAAyB;IAKjC;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAKnF;;;;;;;;;OASG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAI7D;;;;;;;;OAQG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAI5D;;;;;;;;OAQG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAK9D;;;;;;;;;;;OAWG;IACH,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAKtE;;;;;;;OAOG;IACH,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAmEtF;;;;;;;;OAQG;IACH,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,EAAE;IAIxE;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,wBAAwB;IAkEhC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAsC5B"}
@@ -5,6 +5,24 @@
5
5
  */
6
6
  import { ColorManipulator } from '../color/ColorManipulator.js';
7
7
  import { ColorConverter, normalizeDeltaEFormula, } from '../color/ColorConverter.js';
8
+ /**
9
+ * The ΔE formula these per-type harmony methods rank by when a caller does not
10
+ * say. Was hard-coded `'cie76'`, which meant harmony ranked by a metric that
11
+ * disagrees with `ciede2000` — the suite default every other tool uses — on
12
+ * about 31% of dye pairs.
13
+ *
14
+ * ⚠️ Changing this is CORRECT but it is NOT the fix the 2026-09-03 fact-check
15
+ * described, because the live harmony path moved out from under it. Since the
16
+ * harmony convergence (PR #159) every surface — web app, Discord bot,
17
+ * og-worker — goes through `HarmonySelector.generateHarmonySlots`, which takes
18
+ * `matchingMethod` as a REQUIRED config field and is given `ciede2000`
19
+ * explicitly by all three. The `find*Dyes()` methods below are reached only
20
+ * through the `DyeService` façade, which nothing in this monorepo calls; they
21
+ * survive as published npm API. So this default was already unreachable in
22
+ * production, and aligning it changes no shipped behaviour — it stops the
23
+ * published API contradicting the documented suite default.
24
+ */
25
+ const DEFAULT_HARMONY_DELTA_E = 'ciede2000';
8
26
  /**
9
27
  * Default ΔE tolerance per formula.
10
28
  *
@@ -12,13 +30,19 @@ import { ColorConverter, normalizeDeltaEFormula, } from '../color/ColorConverter
12
30
  * silently gave `'oklab'` CIE76's tolerance. OKLAB ΔE runs roughly 0-1, so 40
13
31
  * admitted the entire dye set. Each value sits just outside its formula's
14
32
  * widest calibrated `harmony` band cut in `config/band-vocabulary.ts`
15
- * (ciede2000 20, cie76 26.2, oklab 0.107), which is the relationship the
33
+ * (ciede2000 20, cie76 26.2, oklab 0.174), which is the relationship the
16
34
  * original two already had.
35
+ *
36
+ * The oklab value moved 0.13 -> 0.21 in 5.1.0, when `getDeltaE_Oklab` became
37
+ * ΔEOK2 and its widest harmony cut moved 0.107 -> 0.174. The ratio to that cut
38
+ * is preserved (~1.21), so the tolerance still means the same thing relative
39
+ * to the bands; leaving 0.13 behind would have quietly tightened oklab harmony
40
+ * matching to roughly half its intended reach.
17
41
  */
18
42
  const DEFAULT_DELTA_E_TOLERANCE = {
19
43
  ciede2000: 25,
20
44
  cie76: 40,
21
- oklab: 0.13,
45
+ oklab: 0.21,
22
46
  };
23
47
  /**
24
48
  * ΔE between two colours under a canonical formula.
@@ -182,7 +206,7 @@ export class HarmonyGenerator {
182
206
  // DeltaE-based monochromatic search
183
207
  if (options?.algorithm === 'deltaE') {
184
208
  const baseLab = ColorConverter.hexToLab(baseDye.hex);
185
- const formula = normalizeDeltaEFormula(options.deltaEFormula ?? 'cie76');
209
+ const formula = normalizeDeltaEFormula(options.deltaEFormula ?? DEFAULT_HARMONY_DELTA_E);
186
210
  const tolerance = options.deltaETolerance ?? DEFAULT_DELTA_E_TOLERANCE[formula];
187
211
  const results = [];
188
212
  for (const dye of dyes) {
@@ -311,12 +335,22 @@ export class HarmonyGenerator {
311
335
  /**
312
336
  * Rotate a color's hue by an offset in the specified color space
313
337
  * Keeps the other components (chroma/saturation, lightness/value) unchanged
338
+ *
339
+ * @deprecated Since 5.2.0. Rotates hue at fixed L/C in a space that does not
340
+ * carry the base's S/V; now gamut-maps for `oklch`; still prefer
341
+ * `generateHarmonySlots(…, { wheel })` and `getColorWheel(id)`. Kept for
342
+ * published-API compatibility only.
343
+ *
344
+ * `lch` (and `hsl`) still CLIP per channel, which changes hue on any
345
+ * out-of-gamut rotation — CIELAB has no in-package gamut mapper, and adding
346
+ * one to a deprecated path is not the trade. `oklch` does not: it bisects
347
+ * chroma at constant L and h (CSS Color 4), the same mapping the wheels use.
314
348
  */
315
349
  rotateHueInSpace(hex, offset, space) {
316
350
  switch (space) {
317
351
  case 'oklch': {
318
352
  const oklch = ColorConverter.hexToOklch(hex);
319
- return ColorConverter.oklchToHex(oklch.L, oklch.C, (oklch.h + offset + 360) % 360);
353
+ return ColorConverter.gamutMapOklch(oklch.L, oklch.C, (oklch.h + offset + 360) % 360);
320
354
  }
321
355
  case 'lch': {
322
356
  const lch = ColorConverter.hexToLch(hex);
@@ -337,7 +371,7 @@ export class HarmonyGenerator {
337
371
  * @param options - DeltaE options (formula, tolerance)
338
372
  */
339
373
  findClosestByDeltaE(targetHex, excludeIds, options) {
340
- const formula = normalizeDeltaEFormula(options.deltaEFormula ?? 'cie76');
374
+ const formula = normalizeDeltaEFormula(options.deltaEFormula ?? DEFAULT_HARMONY_DELTA_E);
341
375
  const tolerance = options.deltaETolerance ?? DEFAULT_DELTA_E_TOLERANCE[formula];
342
376
  const targetLab = ColorConverter.hexToLab(targetHex);
343
377
  let bestMatch = null;
@@ -1 +1 @@
1
- {"version":3,"file":"HarmonyGenerator.js","sourceRoot":"","sources":["../../../src/services/dye/HarmonyGenerator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HarmonyGenerator.js","sourceRoot":"","sources":["../../../src/services/dye/HarmonyGenerator.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@
26
26
  *
27
27
  * @module services/dye/HarmonySelector
28
28
  */
29
- import type { Dye } from '@xivdyetools/types';
29
+ import type { ColorWheelId, Dye } from '@xivdyetools/types';
30
30
  import type { MatchingMethod } from '../../types/index.js';
31
31
  /** How a caller wants harmony slots chosen. */
32
32
  export interface HarmonySelectionConfig {
@@ -34,6 +34,10 @@ export interface HarmonySelectionConfig {
34
34
  * Rank by the configured ΔE against an S/V-preserving target (`true`), or by
35
35
  * plain angular hue distance (`false`). The web app's "strict matching"
36
36
  * toggle, on by default.
37
+ *
38
+ * Forced on for wheels that do not carry the base's S/V
39
+ * (`oklch-lightness`): hue-only ranking would discard the very property that
40
+ * wheel exists for.
37
41
  */
38
42
  usePerceptualMatching: boolean;
39
43
  /** Which ΔE the ranking uses. Ignored when `usePerceptualMatching` is false. */
@@ -42,6 +46,11 @@ export interface HarmonySelectionConfig {
42
46
  companionCount?: number;
43
47
  /** Never show one dye in two slots. Default `false`. */
44
48
  preventDuplicates?: boolean;
49
+ /**
50
+ * Which colour wheel the offsets are measured on. Default `'rgb'`, which is
51
+ * today's behaviour bit for bit. See `wheels/ColorWheel.ts`.
52
+ */
53
+ wheel?: ColorWheelId;
45
54
  }
46
55
  /** One position in a harmony: its ideal, the dye chosen for it, and runners-up. */
47
56
  export interface HarmonySlot {
@@ -51,6 +60,11 @@ export interface HarmonySlot {
51
60
  offset: number;
52
61
  /** The absolute ideal hue in degrees, 0–359. */
53
62
  targetHue: number;
63
+ /**
64
+ * The slot's angle on the SELECTED wheel's ring, 0–359 — where a node is
65
+ * drawn. Equals `targetHue` on the RGB wheel and differs on every other.
66
+ */
67
+ wheelHue: number;
54
68
  /**
55
69
  * The ideal colour for this slot: the base's saturation and value on the
56
70
  * target hue. This is what a card outlines next to the dye it actually found.
@@ -1 +1 @@
1
- {"version":3,"file":"HarmonySelector.d.ts","sourceRoot":"","sources":["../../../src/services/dye/HarmonySelector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,+CAA+C;AAC/C,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gFAAgF;IAChF,cAAc,EAAE,cAAc,CAAC;IAC/B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,EAAE,GAAG,EAAE,CAAC;CACnB;AAQD,kEAAkE;AAClE,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AA0CD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,SAAS,GAAG,EAAE,EAC1B,MAAM,EAAE,sBAAsB,EAC9B,OAAO,CAAC,EAAE,uBAAuB,GAChC,WAAW,EAAE,CA2Ff"}
1
+ {"version":3,"file":"HarmonySelector.d.ts","sourceRoot":"","sources":["../../../src/services/dye/HarmonySelector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,+CAA+C;AAC/C,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;OAQG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gFAAgF;IAChF,cAAc,EAAE,cAAc,CAAC;IAC/B,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,UAAU,EAAE,GAAG,EAAE,CAAC;CACnB;AAQD,kEAAkE;AAClE,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AA0CD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,SAAS,GAAG,EAAE,EAC1B,MAAM,EAAE,sBAAsB,EAC9B,OAAO,CAAC,EAAE,uBAAuB,GAChC,WAAW,EAAE,CAsGf"}
@@ -28,6 +28,7 @@
28
28
  */
29
29
  import { HARMONY_OFFSETS } from '../../constants/index.js';
30
30
  import { ColorService } from '../ColorService.js';
31
+ import { DEFAULT_COLOR_WHEEL, getColorWheel } from './wheels/ColorWheel.js';
31
32
  /**
32
33
  * The single definition of "how far is this dye from the slot's target".
33
34
  *
@@ -91,7 +92,17 @@ export function generateHarmonySlots(baseHex, harmonyType, candidates, config, o
91
92
  if (!isKnownHarmonyType(harmonyType))
92
93
  return [];
93
94
  const offsets = HARMONY_OFFSETS[harmonyType];
94
- const baseHsv = ColorService.hexToHsv(baseHex);
95
+ const wheel = getColorWheel(config.wheel ?? DEFAULT_COLOR_WHEEL);
96
+ // A wheel that keeps the base's OKLab L and C instead of its HSV S/V has no
97
+ // meaningful hue-distance ranking: scoring by degrees against `targetHue`
98
+ // throws away the lightness the wheel was chosen for, and returns a partner
99
+ // at some other lightness entirely. Built once, used for every scoring call
100
+ // below (pins included) so a slot can never be scored in different units
101
+ // from its neighbours — the BUG-064 rule.
102
+ const effective = wheel.carriesBaseHsv
103
+ ? config
104
+ : { ...config, usePerceptualMatching: true };
105
+ const baseWheelHue = wheel.hueOf(baseHex);
95
106
  const companionCount = config.companionCount ?? 0;
96
107
  const preventDuplicates = config.preventDuplicates ?? false;
97
108
  // Two different questions, and they were one set until 2026-09-03.
@@ -116,12 +127,12 @@ export function generateHarmonySlots(baseHex, harmonyType, candidates, config, o
116
127
  const slots = [];
117
128
  offsets.forEach((offset, index) => {
118
129
  const normalisedOffset = ((offset % 360) + 360) % 360;
119
- const targetHue = (baseHsv.h + normalisedOffset) % 360;
120
- // The ideal carries the BASE's saturation and value onto the rotated hue.
121
- // That is the whole reason a desaturated base finds desaturated dyes, and
122
- // the single biggest difference from the per-type find*Dyes() methods.
123
- const targetHex = ColorService.hsvToHex(targetHue, baseHsv.s, baseHsv.v);
124
- const ranked = rankCandidates(candidates, targetHue, targetHex, config);
130
+ const wheelHue = (baseWheelHue + normalisedOffset) % 360;
131
+ // The wheel builds the ideal. Warp wheels carry the BASE's saturation and
132
+ // value onto the mapped hue — the whole reason a desaturated base finds
133
+ // desaturated dyes; the constant-lightness wheel carries L and C instead.
134
+ const { targetHex, targetHue } = wheel.target(baseHex, wheelHue);
135
+ const ranked = rankCandidates(candidates, targetHue, targetHex, effective);
125
136
  const pin = options?.pinned?.get(index);
126
137
  // Every branch below assigns, so no initialiser: an unread `= null` here
127
138
  // would be one more place for a future edit to leave a slot silently empty.
@@ -129,7 +140,7 @@ export function generateHarmonySlots(baseHex, harmonyType, candidates, config, o
129
140
  if (pin) {
130
141
  // An explicit hand-swap wins its slot outright, exclusions included: the
131
142
  // user naming a dye outranks our guess about which dyes are eligible.
132
- chosen = { dye: pin, deviance: devianceFor(pin, targetHue, targetHex, config) };
143
+ chosen = { dye: pin, deviance: devianceFor(pin, targetHue, targetHex, effective) };
133
144
  }
134
145
  else if (preventDuplicates) {
135
146
  // First eligible-and-unused, else the nearest eligible even if already
@@ -165,6 +176,7 @@ export function generateHarmonySlots(baseHex, harmonyType, candidates, config, o
165
176
  index,
166
177
  offset: normalisedOffset,
167
178
  targetHue,
179
+ wheelHue,
168
180
  targetHex,
169
181
  dye: chosen?.dye ?? null,
170
182
  deviance: chosen?.deviance ?? 0,
@@ -1 +1 @@
1
- {"version":3,"file":"HarmonySelector.js","sourceRoot":"","sources":["../../../src/services/dye/HarmonySelector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HarmonySelector.js","sourceRoot":"","sources":["../../../src/services/dye/HarmonySelector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The colour-wheel registry — the ONE list every surface reads.
3
+ *
4
+ * @module services/dye/wheels/ColorWheel
5
+ */
6
+ import type { ColorWheelId } from '@xivdyetools/types';
7
+ import type { ColorWheel } from './types.js';
8
+ export type { ColorWheel } from './types.js';
9
+ /** Display order. `rgb` first, and the default. */
10
+ export declare const COLOR_WHEEL_IDS: readonly ["rgb", "ryb", "munsell", "oklch-hue", "oklch-lightness"];
11
+ export declare const DEFAULT_COLOR_WHEEL: ColorWheelId;
12
+ export declare function isColorWheelId(value: unknown): value is ColorWheelId;
13
+ /** Lower-cased, trimmed id when recognised; undefined for anything else (absent, empty, unknown). */
14
+ export declare function parseColorWheelId(value: unknown): ColorWheelId | undefined;
15
+ /** `parseColorWheelId(value) ?? DEFAULT_COLOR_WHEEL` — "absent or unknown means rgb", in one place. */
16
+ export declare function normalizeColorWheelId(value: unknown): ColorWheelId;
17
+ /**
18
+ * The short tag each wheel prints in a card footer. Identifiers, never
19
+ * localised — the OG footer tag sits beside `algoTag`, which is the same kind
20
+ * of token, and a translated one would make two cards of the same wheel
21
+ * unrecognisable as such.
22
+ */
23
+ export declare const COLOR_WHEEL_TAGS: Record<ColorWheelId, string>;
24
+ /**
25
+ * Own-property lookup: the id arrives from a share URL, and
26
+ * `WHEELS['toString']` would be truthy under a plain index.
27
+ */
28
+ export declare function getColorWheel(id: ColorWheelId): ColorWheel;
29
+ //# sourceMappingURL=ColorWheel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorWheel.d.ts","sourceRoot":"","sources":["../../../../src/services/dye/wheels/ColorWheel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,mDAAmD;AACnD,eAAO,MAAM,eAAe,oEAMgB,CAAC;AAE7C,eAAO,MAAM,mBAAmB,EAAE,YAAoB,CAAC;AAEvD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAI1E;AAED,uGAAuG;AACvG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAElE;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAMzD,CAAC;AAUF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,UAAU,CAK1D"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The colour-wheel registry — the ONE list every surface reads.
3
+ *
4
+ * @module services/dye/wheels/ColorWheel
5
+ */
6
+ import { MUNSELL_WHEEL } from './munsell.js';
7
+ import { OKLCH_HUE_WHEEL } from './oklch-hue.js';
8
+ import { OKLCH_LIGHTNESS_WHEEL } from './oklch-lightness.js';
9
+ import { RGB_WHEEL, RYB_WHEEL } from './rgb-ryb.js';
10
+ /** Display order. `rgb` first, and the default. */
11
+ export const COLOR_WHEEL_IDS = [
12
+ 'rgb',
13
+ 'ryb',
14
+ 'munsell',
15
+ 'oklch-hue',
16
+ 'oklch-lightness',
17
+ ];
18
+ export const DEFAULT_COLOR_WHEEL = 'rgb';
19
+ export function isColorWheelId(value) {
20
+ return typeof value === 'string' && COLOR_WHEEL_IDS.includes(value);
21
+ }
22
+ /** Lower-cased, trimmed id when recognised; undefined for anything else (absent, empty, unknown). */
23
+ export function parseColorWheelId(value) {
24
+ if (typeof value !== 'string')
25
+ return undefined;
26
+ const v = value.trim().toLowerCase();
27
+ return isColorWheelId(v) ? v : undefined;
28
+ }
29
+ /** `parseColorWheelId(value) ?? DEFAULT_COLOR_WHEEL` — "absent or unknown means rgb", in one place. */
30
+ export function normalizeColorWheelId(value) {
31
+ return parseColorWheelId(value) ?? DEFAULT_COLOR_WHEEL;
32
+ }
33
+ /**
34
+ * The short tag each wheel prints in a card footer. Identifiers, never
35
+ * localised — the OG footer tag sits beside `algoTag`, which is the same kind
36
+ * of token, and a translated one would make two cards of the same wheel
37
+ * unrecognisable as such.
38
+ */
39
+ export const COLOR_WHEEL_TAGS = {
40
+ rgb: 'RGB',
41
+ ryb: 'RYB',
42
+ munsell: 'MUNSELL',
43
+ 'oklch-hue': 'OKLCH·H',
44
+ 'oklch-lightness': 'OKLCH·L',
45
+ };
46
+ const WHEELS = {
47
+ rgb: RGB_WHEEL,
48
+ ryb: RYB_WHEEL,
49
+ munsell: MUNSELL_WHEEL,
50
+ 'oklch-hue': OKLCH_HUE_WHEEL,
51
+ 'oklch-lightness': OKLCH_LIGHTNESS_WHEEL,
52
+ };
53
+ /**
54
+ * Own-property lookup: the id arrives from a share URL, and
55
+ * `WHEELS['toString']` would be truthy under a plain index.
56
+ */
57
+ export function getColorWheel(id) {
58
+ if (!Object.hasOwn(WHEELS, id)) {
59
+ throw new RangeError(`Unknown colour wheel: ${String(id)}`);
60
+ }
61
+ return WHEELS[id];
62
+ }
63
+ //# sourceMappingURL=ColorWheel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorWheel.js","sourceRoot":"","sources":["../../../../src/services/dye/wheels/ColorWheel.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAKpD,mDAAmD;AACnD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,KAAK;IACL,KAAK;IACL,SAAS;IACT,WAAW;IACX,iBAAiB;CACyB,CAAC;AAE7C,MAAM,CAAC,MAAM,mBAAmB,GAAiB,KAAK,CAAC;AAEvD,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,eAAqC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7F,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,OAAO,iBAAiB,CAAC,KAAK,CAAC,IAAI,mBAAmB,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAiC;IAC5D,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,SAAS;IACtB,iBAAiB,EAAE,SAAS;CAC7B,CAAC;AAEF,MAAM,MAAM,GAA+C;IACzD,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;IACd,OAAO,EAAE,aAAa;IACtB,WAAW,EAAE,eAAe;IAC5B,iBAAiB,EAAE,qBAAqB;CACzC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAAgB;IAC5C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,UAAU,CAAC,yBAAyB,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Hue-warp wheels: a monotone piecewise-linear bijection between sRGB/HSV hue
3
+ * and a wheel angle. RGB (identity), RYB, Munsell and OKLCH-hue are all this.
4
+ *
5
+ * The target keeps the BASE's HSV saturation and value on the mapped hue —
6
+ * the contract the 2026-09-03 harmony convergence rests on — so on the
7
+ * identity table this reproduces today's output bit for bit.
8
+ *
9
+ * @module services/dye/wheels/hue-warp
10
+ */
11
+ import type { ColorWheel, ColorWheelId, WarpTable } from './types.js';
12
+ /**
13
+ * Every table must be strictly increasing in both columns and run exactly
14
+ * from `[0,0]` to `[360,360]`; otherwise the inverse is ambiguous and a
15
+ * linear-search inverse returns a hue wrong by far more than the dent
16
+ * (research 05 §7: a 0.16° reversal produced a 13° error, silently).
17
+ */
18
+ export declare function assertMonotoneTable(table: WarpTable, id: string): void;
19
+ /** sRGB/HSV hue → wheel angle. */
20
+ export declare function toWheelHue(table: WarpTable, hsvHue: number): number;
21
+ /** Wheel angle → sRGB/HSV hue. */
22
+ export declare function fromWheelHue(table: WarpTable, wheelHue: number): number;
23
+ export interface NormalizeOptions {
24
+ /** Largest running-max correction tolerated, in degrees. Default 1. */
25
+ maxCorrectionDeg?: number;
26
+ }
27
+ /**
28
+ * Turn measured `[wheelAngle, hsvHue]` pairs — in any order, with the wheel
29
+ * column wrapping wherever the measurement put its zero — into a valid
30
+ * {@link WarpTable}: sorted by HSV hue, wheel column unwrapped, small dents
31
+ * monotonised with a running maximum, re-zeroed so HSV 0° ↦ wheel 0°, and
32
+ * closed with `[0,0]` and `[360,360]`.
33
+ *
34
+ * Every warp wheel is zeroed at sRGB red, so wheels differ in SPACING only;
35
+ * that is what lets the ring, the nodes and the base spoke share one origin.
36
+ */
37
+ export declare function normalizeWarpTable(raw: ReadonlyArray<readonly [number, number]>, id: string, options?: NormalizeOptions): WarpTable;
38
+ /** Build a wheel from a table. Throws at construction on a bad table. */
39
+ export declare function hueWarpWheel(id: ColorWheelId, table: WarpTable): ColorWheel;
40
+ //# sourceMappingURL=hue-warp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hue-warp.d.ts","sourceRoot":"","sources":["../../../../src/services/dye/wheels/hue-warp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAItE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAiBtE;AAkBD,kCAAkC;AAClC,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,kCAAkC;AAClC,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC7C,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,gBAAqB,GAC7B,SAAS,CAoDX;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CAuB3E"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Hue-warp wheels: a monotone piecewise-linear bijection between sRGB/HSV hue
3
+ * and a wheel angle. RGB (identity), RYB, Munsell and OKLCH-hue are all this.
4
+ *
5
+ * The target keeps the BASE's HSV saturation and value on the mapped hue —
6
+ * the contract the 2026-09-03 harmony convergence rests on — so on the
7
+ * identity table this reproduces today's output bit for bit.
8
+ *
9
+ * @module services/dye/wheels/hue-warp
10
+ */
11
+ import { ColorConverter } from '../../color/ColorConverter.js';
12
+ const mod360 = (x) => (x >= 0 && x < 360 ? x : ((x % 360) + 360) % 360);
13
+ /**
14
+ * Every table must be strictly increasing in both columns and run exactly
15
+ * from `[0,0]` to `[360,360]`; otherwise the inverse is ambiguous and a
16
+ * linear-search inverse returns a hue wrong by far more than the dent
17
+ * (research 05 §7: a 0.16° reversal produced a 13° error, silently).
18
+ */
19
+ export function assertMonotoneTable(table, id) {
20
+ if (table.length < 2) {
21
+ throw new Error(`ColorWheel ${id}: table needs at least two pairs`);
22
+ }
23
+ const first = table[0];
24
+ const last = table[table.length - 1];
25
+ if (first[0] !== 0 || first[1] !== 0) {
26
+ throw new Error(`ColorWheel ${id}: table must start at [0,0]`);
27
+ }
28
+ if (last[0] !== 360 || last[1] !== 360) {
29
+ throw new Error(`ColorWheel ${id}: table must end at [360,360]`);
30
+ }
31
+ for (let i = 1; i < table.length; i++) {
32
+ if (!(table[i][0] > table[i - 1][0]) || !(table[i][1] > table[i - 1][1])) {
33
+ throw new Error(`ColorWheel ${id}: table is not strictly increasing at row ${i}`);
34
+ }
35
+ }
36
+ }
37
+ /** Piecewise-linear map of `x` from column `from` to column `to`. */
38
+ function interpolate(table, x, from, to) {
39
+ const v = mod360(x);
40
+ let lo = 0;
41
+ let hi = table.length - 1;
42
+ while (hi - lo > 1) {
43
+ const mid = (lo + hi) >> 1;
44
+ if (table[mid][from] <= v)
45
+ lo = mid;
46
+ else
47
+ hi = mid;
48
+ }
49
+ const a = table[lo];
50
+ const b = table[hi];
51
+ const t = (v - a[from]) / (b[from] - a[from]);
52
+ return mod360(a[to] + t * (b[to] - a[to]));
53
+ }
54
+ /** sRGB/HSV hue → wheel angle. */
55
+ export function toWheelHue(table, hsvHue) {
56
+ return table.length === 2 ? mod360(hsvHue) : interpolate(table, hsvHue, 1, 0);
57
+ }
58
+ /** Wheel angle → sRGB/HSV hue. */
59
+ export function fromWheelHue(table, wheelHue) {
60
+ return table.length === 2 ? mod360(wheelHue) : interpolate(table, wheelHue, 0, 1);
61
+ }
62
+ /**
63
+ * Turn measured `[wheelAngle, hsvHue]` pairs — in any order, with the wheel
64
+ * column wrapping wherever the measurement put its zero — into a valid
65
+ * {@link WarpTable}: sorted by HSV hue, wheel column unwrapped, small dents
66
+ * monotonised with a running maximum, re-zeroed so HSV 0° ↦ wheel 0°, and
67
+ * closed with `[0,0]` and `[360,360]`.
68
+ *
69
+ * Every warp wheel is zeroed at sRGB red, so wheels differ in SPACING only;
70
+ * that is what lets the ring, the nodes and the base spoke share one origin.
71
+ */
72
+ export function normalizeWarpTable(raw, id, options = {}) {
73
+ const maxCorrection = options.maxCorrectionDeg ?? 1;
74
+ if (raw.length < 3) {
75
+ throw new Error(`ColorWheel ${id}: need at least three measured pairs`);
76
+ }
77
+ const sorted = raw
78
+ .map(([w, h]) => [mod360(w), mod360(h)])
79
+ .sort((a, b) => a[1] - b[1]);
80
+ // Unwrap the wheel column: a backward step larger than half a turn is the
81
+ // measurement's own zero crossing, not a dent.
82
+ const unwrapped = [];
83
+ let offset = 0;
84
+ for (let i = 0; i < sorted.length; i++) {
85
+ let w = sorted[i][0] + offset;
86
+ if (i > 0 && w < unwrapped[i - 1][0] - 180) {
87
+ offset += 360;
88
+ w += 360;
89
+ }
90
+ unwrapped.push([w, sorted[i][1]]);
91
+ }
92
+ // Monotonise small dents; refuse large ones.
93
+ for (let i = 1; i < unwrapped.length; i++) {
94
+ const prev = unwrapped[i - 1][0];
95
+ if (unwrapped[i][0] <= prev) {
96
+ const correction = prev - unwrapped[i][0];
97
+ if (correction > maxCorrection) {
98
+ throw new Error(`ColorWheel ${id}: wheel column reverses by ${correction.toFixed(3)}° at HSV ` +
99
+ `${unwrapped[i][1].toFixed(2)}°, more than the ${maxCorrection}° tolerance`);
100
+ }
101
+ unwrapped[i][0] = prev + 1e-6;
102
+ }
103
+ }
104
+ // Wheel angle at HSV 0°, by interpolating across the wrap-around segment.
105
+ const [wFirst, hFirst] = unwrapped[0];
106
+ const [wLast, hLast] = unwrapped[unwrapped.length - 1];
107
+ const t = (360 - hLast) / (hFirst + 360 - hLast);
108
+ const w0 = wLast + t * (wFirst + 360 - wLast);
109
+ const table = [[0, 0]];
110
+ for (const [w, h] of unwrapped) {
111
+ const shifted = w - w0 + 360; // wFirst ≥ w0 − 360 by construction
112
+ if (h > 0 && shifted > 0 && shifted < 360)
113
+ table.push([shifted, h]);
114
+ }
115
+ table.push([360, 360]);
116
+ assertMonotoneTable(table, id);
117
+ return table;
118
+ }
119
+ /** Build a wheel from a table. Throws at construction on a bad table. */
120
+ export function hueWarpWheel(id, table) {
121
+ assertMonotoneTable(table, id);
122
+ return {
123
+ id,
124
+ // Every warp wheel's target is the base's own S/V on a re-spaced hue, so
125
+ // angular hue distance to `targetHue` is a meaningful ranking here.
126
+ carriesBaseHsv: true,
127
+ hueOf(hex) {
128
+ return toWheelHue(table, ColorConverter.hexToHsv(hex).h);
129
+ },
130
+ target(baseHex, wheelHue) {
131
+ const base = ColorConverter.hexToHsv(baseHex);
132
+ const targetHue = fromWheelHue(table, wheelHue);
133
+ return { targetHex: ColorConverter.hsvToHex(targetHue, base.s, base.v), targetHue };
134
+ },
135
+ ringStops(count) {
136
+ const stops = [];
137
+ for (let i = 0; i < count; i++) {
138
+ stops.push(ColorConverter.hsvToHex(fromWheelHue(table, (i * 360) / count), 100, 100));
139
+ }
140
+ return stops;
141
+ },
142
+ };
143
+ }
144
+ //# sourceMappingURL=hue-warp.js.map