@react-stately/color 3.5.4-nightly.4547 → 3.5.4-nightly.4551

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 (177) hide show
  1. package/dist/ar-AE.main.js +30 -1
  2. package/dist/ar-AE.main.js.map +1 -1
  3. package/dist/ar-AE.mjs +30 -1
  4. package/dist/ar-AE.module.js +30 -1
  5. package/dist/ar-AE.module.js.map +1 -1
  6. package/dist/bg-BG.main.js +30 -1
  7. package/dist/bg-BG.main.js.map +1 -1
  8. package/dist/bg-BG.mjs +30 -1
  9. package/dist/bg-BG.module.js +30 -1
  10. package/dist/bg-BG.module.js.map +1 -1
  11. package/dist/cs-CZ.main.js +30 -1
  12. package/dist/cs-CZ.main.js.map +1 -1
  13. package/dist/cs-CZ.mjs +30 -1
  14. package/dist/cs-CZ.module.js +30 -1
  15. package/dist/cs-CZ.module.js.map +1 -1
  16. package/dist/da-DK.main.js +30 -1
  17. package/dist/da-DK.main.js.map +1 -1
  18. package/dist/da-DK.mjs +30 -1
  19. package/dist/da-DK.module.js +30 -1
  20. package/dist/da-DK.module.js.map +1 -1
  21. package/dist/de-DE.main.js +30 -1
  22. package/dist/de-DE.main.js.map +1 -1
  23. package/dist/de-DE.mjs +30 -1
  24. package/dist/de-DE.module.js +30 -1
  25. package/dist/de-DE.module.js.map +1 -1
  26. package/dist/el-GR.main.js +30 -1
  27. package/dist/el-GR.main.js.map +1 -1
  28. package/dist/el-GR.mjs +30 -1
  29. package/dist/el-GR.module.js +30 -1
  30. package/dist/el-GR.module.js.map +1 -1
  31. package/dist/en-US.main.js +30 -1
  32. package/dist/en-US.main.js.map +1 -1
  33. package/dist/en-US.mjs +30 -1
  34. package/dist/en-US.module.js +30 -1
  35. package/dist/en-US.module.js.map +1 -1
  36. package/dist/es-ES.main.js +30 -1
  37. package/dist/es-ES.main.js.map +1 -1
  38. package/dist/es-ES.mjs +30 -1
  39. package/dist/es-ES.module.js +30 -1
  40. package/dist/es-ES.module.js.map +1 -1
  41. package/dist/et-EE.main.js +30 -1
  42. package/dist/et-EE.main.js.map +1 -1
  43. package/dist/et-EE.mjs +30 -1
  44. package/dist/et-EE.module.js +30 -1
  45. package/dist/et-EE.module.js.map +1 -1
  46. package/dist/fi-FI.main.js +30 -1
  47. package/dist/fi-FI.main.js.map +1 -1
  48. package/dist/fi-FI.mjs +30 -1
  49. package/dist/fi-FI.module.js +30 -1
  50. package/dist/fi-FI.module.js.map +1 -1
  51. package/dist/fr-FR.main.js +30 -1
  52. package/dist/fr-FR.main.js.map +1 -1
  53. package/dist/fr-FR.mjs +30 -1
  54. package/dist/fr-FR.module.js +30 -1
  55. package/dist/fr-FR.module.js.map +1 -1
  56. package/dist/he-IL.main.js +30 -1
  57. package/dist/he-IL.main.js.map +1 -1
  58. package/dist/he-IL.mjs +30 -1
  59. package/dist/he-IL.module.js +30 -1
  60. package/dist/he-IL.module.js.map +1 -1
  61. package/dist/hr-HR.main.js +30 -1
  62. package/dist/hr-HR.main.js.map +1 -1
  63. package/dist/hr-HR.mjs +30 -1
  64. package/dist/hr-HR.module.js +30 -1
  65. package/dist/hr-HR.module.js.map +1 -1
  66. package/dist/hu-HU.main.js +30 -1
  67. package/dist/hu-HU.main.js.map +1 -1
  68. package/dist/hu-HU.mjs +30 -1
  69. package/dist/hu-HU.module.js +30 -1
  70. package/dist/hu-HU.module.js.map +1 -1
  71. package/dist/import.mjs +215 -1
  72. package/dist/it-IT.main.js +30 -1
  73. package/dist/it-IT.main.js.map +1 -1
  74. package/dist/it-IT.mjs +30 -1
  75. package/dist/it-IT.module.js +30 -1
  76. package/dist/it-IT.module.js.map +1 -1
  77. package/dist/ja-JP.main.js +30 -1
  78. package/dist/ja-JP.main.js.map +1 -1
  79. package/dist/ja-JP.mjs +30 -1
  80. package/dist/ja-JP.module.js +30 -1
  81. package/dist/ja-JP.module.js.map +1 -1
  82. package/dist/ko-KR.main.js +30 -1
  83. package/dist/ko-KR.main.js.map +1 -1
  84. package/dist/ko-KR.mjs +30 -1
  85. package/dist/ko-KR.module.js +30 -1
  86. package/dist/ko-KR.module.js.map +1 -1
  87. package/dist/lt-LT.main.js +30 -1
  88. package/dist/lt-LT.main.js.map +1 -1
  89. package/dist/lt-LT.mjs +30 -1
  90. package/dist/lt-LT.module.js +30 -1
  91. package/dist/lt-LT.module.js.map +1 -1
  92. package/dist/lv-LV.main.js +30 -1
  93. package/dist/lv-LV.main.js.map +1 -1
  94. package/dist/lv-LV.mjs +30 -1
  95. package/dist/lv-LV.module.js +30 -1
  96. package/dist/lv-LV.module.js.map +1 -1
  97. package/dist/main.js +214 -0
  98. package/dist/main.js.map +1 -1
  99. package/dist/module.js +215 -1
  100. package/dist/module.js.map +1 -1
  101. package/dist/nb-NO.main.js +30 -1
  102. package/dist/nb-NO.main.js.map +1 -1
  103. package/dist/nb-NO.mjs +30 -1
  104. package/dist/nb-NO.module.js +30 -1
  105. package/dist/nb-NO.module.js.map +1 -1
  106. package/dist/nl-NL.main.js +30 -1
  107. package/dist/nl-NL.main.js.map +1 -1
  108. package/dist/nl-NL.mjs +30 -1
  109. package/dist/nl-NL.module.js +30 -1
  110. package/dist/nl-NL.module.js.map +1 -1
  111. package/dist/pl-PL.main.js +30 -1
  112. package/dist/pl-PL.main.js.map +1 -1
  113. package/dist/pl-PL.mjs +30 -1
  114. package/dist/pl-PL.module.js +30 -1
  115. package/dist/pl-PL.module.js.map +1 -1
  116. package/dist/pt-BR.main.js +30 -1
  117. package/dist/pt-BR.main.js.map +1 -1
  118. package/dist/pt-BR.mjs +30 -1
  119. package/dist/pt-BR.module.js +30 -1
  120. package/dist/pt-BR.module.js.map +1 -1
  121. package/dist/pt-PT.main.js +30 -1
  122. package/dist/pt-PT.main.js.map +1 -1
  123. package/dist/pt-PT.mjs +30 -1
  124. package/dist/pt-PT.module.js +30 -1
  125. package/dist/pt-PT.module.js.map +1 -1
  126. package/dist/ro-RO.main.js +30 -1
  127. package/dist/ro-RO.main.js.map +1 -1
  128. package/dist/ro-RO.mjs +30 -1
  129. package/dist/ro-RO.module.js +30 -1
  130. package/dist/ro-RO.module.js.map +1 -1
  131. package/dist/ru-RU.main.js +30 -1
  132. package/dist/ru-RU.main.js.map +1 -1
  133. package/dist/ru-RU.mjs +30 -1
  134. package/dist/ru-RU.module.js +30 -1
  135. package/dist/ru-RU.module.js.map +1 -1
  136. package/dist/sk-SK.main.js +30 -1
  137. package/dist/sk-SK.main.js.map +1 -1
  138. package/dist/sk-SK.mjs +30 -1
  139. package/dist/sk-SK.module.js +30 -1
  140. package/dist/sk-SK.module.js.map +1 -1
  141. package/dist/sl-SI.main.js +30 -1
  142. package/dist/sl-SI.main.js.map +1 -1
  143. package/dist/sl-SI.mjs +30 -1
  144. package/dist/sl-SI.module.js +30 -1
  145. package/dist/sl-SI.module.js.map +1 -1
  146. package/dist/sr-SP.main.js +30 -1
  147. package/dist/sr-SP.main.js.map +1 -1
  148. package/dist/sr-SP.mjs +30 -1
  149. package/dist/sr-SP.module.js +30 -1
  150. package/dist/sr-SP.module.js.map +1 -1
  151. package/dist/sv-SE.main.js +30 -1
  152. package/dist/sv-SE.main.js.map +1 -1
  153. package/dist/sv-SE.mjs +30 -1
  154. package/dist/sv-SE.module.js +30 -1
  155. package/dist/sv-SE.module.js.map +1 -1
  156. package/dist/tr-TR.main.js +30 -1
  157. package/dist/tr-TR.main.js.map +1 -1
  158. package/dist/tr-TR.mjs +30 -1
  159. package/dist/tr-TR.module.js +30 -1
  160. package/dist/tr-TR.module.js.map +1 -1
  161. package/dist/uk-UA.main.js +30 -1
  162. package/dist/uk-UA.main.js.map +1 -1
  163. package/dist/uk-UA.mjs +30 -1
  164. package/dist/uk-UA.module.js +30 -1
  165. package/dist/uk-UA.module.js.map +1 -1
  166. package/dist/zh-CN.main.js +30 -1
  167. package/dist/zh-CN.main.js.map +1 -1
  168. package/dist/zh-CN.mjs +30 -1
  169. package/dist/zh-CN.module.js +30 -1
  170. package/dist/zh-CN.module.js.map +1 -1
  171. package/dist/zh-TW.main.js +30 -1
  172. package/dist/zh-TW.main.js.map +1 -1
  173. package/dist/zh-TW.mjs +30 -1
  174. package/dist/zh-TW.module.js +30 -1
  175. package/dist/zh-TW.module.js.map +1 -1
  176. package/package.json +9 -8
  177. package/src/Color.ts +203 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-stately/color",
3
- "version": "3.5.4-nightly.4547+8269d9fca",
3
+ "version": "3.5.4-nightly.4551+17751bb75",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,12 +22,13 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@internationalized/number": "3.5.2-nightly.4547+8269d9fca",
26
- "@internationalized/string": "3.2.2-nightly.4547+8269d9fca",
27
- "@react-stately/form": "3.0.2-nightly.4547+8269d9fca",
28
- "@react-stately/slider": "3.5.3-nightly.4547+8269d9fca",
29
- "@react-stately/utils": "3.0.0-nightly.2835+8269d9fca",
30
- "@react-types/color": "3.0.0-nightly.4547+8269d9fca",
25
+ "@internationalized/number": "3.5.2-nightly.4551+17751bb75",
26
+ "@internationalized/string": "3.2.2-nightly.4551+17751bb75",
27
+ "@react-aria/i18n": "3.0.0-nightly.2839+17751bb75",
28
+ "@react-stately/form": "3.0.2-nightly.4551+17751bb75",
29
+ "@react-stately/slider": "3.5.3-nightly.4551+17751bb75",
30
+ "@react-stately/utils": "3.0.0-nightly.2839+17751bb75",
31
+ "@react-types/color": "3.0.0-nightly.4551+17751bb75",
31
32
  "@swc/helpers": "^0.5.0"
32
33
  },
33
34
  "peerDependencies": {
@@ -36,5 +37,5 @@
36
37
  "publishConfig": {
37
38
  "access": "public"
38
39
  },
39
- "gitHead": "8269d9fca8460df96545592d60c6476eade8da0f"
40
+ "gitHead": "17751bb75cf4b0500e86abe9e1b4561d140f9486"
40
41
  }
package/src/Color.ts CHANGED
@@ -14,7 +14,7 @@ import {clamp, toFixedNumber} from '@react-stately/utils';
14
14
  import {ColorAxes, ColorChannel, ColorChannelRange, ColorFormat, Color as IColor} from '@react-types/color';
15
15
  // @ts-ignore
16
16
  import intlMessages from '../intl/*.json';
17
- import {LocalizedStringDictionary} from '@internationalized/string';
17
+ import {LocalizedStringDictionary, LocalizedStringFormatter} from '@internationalized/string';
18
18
  import {NumberFormatter} from '@internationalized/number';
19
19
 
20
20
  let dictionary = new LocalizedStringDictionary(intlMessages);
@@ -37,6 +37,25 @@ export function normalizeColor(v: string | IColor) {
37
37
  }
38
38
  }
39
39
 
40
+ // Lightness threshold between orange and brown.
41
+ const ORANGE_LIGHTNESS_THRESHOLD = 0.68;
42
+ // The maximum lightness considered to be "dark".
43
+ const MAX_DARK_LIGHTNESS = 0.55;
44
+ // The chroma threshold between gray and color.
45
+ const GRAY_THRESHOLD = 0.001;
46
+ const OKLCH_HUES: [number, string][] = [
47
+ [0, 'pink'],
48
+ [15, 'red'],
49
+ [48, 'orange'],
50
+ [94, 'yellow'],
51
+ [124, 'green'],
52
+ [180, 'cyan'],
53
+ [264, 'blue'],
54
+ [284, 'purple'],
55
+ [320, 'magenta'],
56
+ [349, 'pink']
57
+ ];
58
+
40
59
  abstract class Color implements IColor {
41
60
  abstract toFormat(format: ColorFormat): IColor;
42
61
  abstract toString(format: ColorFormat | 'css'): string;
@@ -80,8 +99,113 @@ abstract class Color implements IColor {
80
99
 
81
100
  return {xChannel: xCh, yChannel: yCh, zChannel: zCh};
82
101
  }
102
+
83
103
  abstract getColorChannels(): [ColorChannel, ColorChannel, ColorChannel]
104
+
105
+ getColorName(locale: string): string {
106
+ // Convert to oklch color space, which has perceptually uniform lightness across all hues.
107
+ let [l, c, h] = toOKLCH(this);
108
+
109
+ let strings = LocalizedStringDictionary.getGlobalDictionaryForPackage('@react-stately/color') || dictionary;
110
+ if (l > 0.999) {
111
+ return strings.getStringForLocale('white', locale);
112
+ }
113
+
114
+ if (l < 0.001) {
115
+ return strings.getStringForLocale('black', locale);
116
+ }
117
+
118
+ let hue: string;
119
+ [hue, l] = this.getOklchHue(l, c, h, locale);
120
+
121
+ let lightness = '';
122
+ let chroma = '';
123
+ if (c <= 0.1 && c >= GRAY_THRESHOLD) {
124
+ if (l >= 0.7) {
125
+ chroma = 'pale';
126
+ } else {
127
+ chroma = 'grayish';
128
+ }
129
+ } else if (c >= 0.15) {
130
+ chroma = 'vibrant';
131
+ }
132
+
133
+ if (l < 0.3) {
134
+ lightness = 'very dark';
135
+ } else if (l < MAX_DARK_LIGHTNESS) {
136
+ lightness = 'dark';
137
+ } else if (l < 0.7) {
138
+ // none
139
+ } else if (l < 0.85) {
140
+ lightness = 'light';
141
+ } else {
142
+ lightness = 'very light';
143
+ }
144
+
145
+ if (chroma) {
146
+ chroma = strings.getStringForLocale(chroma, locale);
147
+ }
148
+
149
+ if (lightness) {
150
+ lightness = strings.getStringForLocale(lightness, locale);
151
+ }
152
+
153
+ let alpha = this.getChannelValue('alpha');
154
+ let formatter = new LocalizedStringFormatter(locale, strings);
155
+ let transparency = '';
156
+ if (alpha < 1) {
157
+ let percent = new NumberFormatter(locale, {style: 'percent'}).format(1 - alpha);
158
+ transparency = formatter.format('transparency', {percent});
159
+ }
160
+
161
+ return formatter.format('colorName', {
162
+ lightness,
163
+ chroma,
164
+ hue,
165
+ transparency
166
+ }).replace(/\s+/g, ' ').trim();
167
+ }
168
+
169
+ private getOklchHue(l: number, c: number, h: number, locale: string): [string, number] {
170
+ let strings = LocalizedStringDictionary.getGlobalDictionaryForPackage('@react-stately/color') || dictionary;
171
+ if (c < GRAY_THRESHOLD) {
172
+ return [strings.getStringForLocale('gray', locale), l];
173
+ }
174
+
175
+ for (let i = 0; i < OKLCH_HUES.length; i++) {
176
+ let [hue, hueName] = OKLCH_HUES[i];
177
+ let [nextHue, nextHueName] = OKLCH_HUES[i + 1] || [360, 'pink'];
178
+ if (h >= hue && h < nextHue) {
179
+ // Split orange hue into brown/orange depending on lightness.
180
+ if (hueName === 'orange') {
181
+ if (l < ORANGE_LIGHTNESS_THRESHOLD) {
182
+ hueName = 'brown';
183
+ } else {
184
+ // Adjust lightness.
185
+ l = (l - ORANGE_LIGHTNESS_THRESHOLD) + MAX_DARK_LIGHTNESS;
186
+ }
187
+ }
188
+
189
+ // If the hue is at least halfway to the next hue, add the next hue name as well.
190
+ if (h > hue + (nextHue - hue) / 2 && hueName !== nextHueName) {
191
+ hueName = `${hueName} ${nextHueName}`;
192
+ }
193
+
194
+ let name = strings.getStringForLocale(hueName, locale).toLocaleLowerCase(locale);
195
+ return [name, l];
196
+ }
197
+ }
198
+
199
+ throw new Error('Unexpected hue');
200
+ }
201
+
202
+ getHueName(locale: string): string {
203
+ let [l, c, h] = toOKLCH(this);
204
+ let [name] = this.getOklchHue(l, c, h, locale);
205
+ return name;
206
+ }
84
207
  }
208
+
85
209
  class RGBColor extends Color {
86
210
  constructor(private red: number, private green: number, private blue: number, private alpha: number) {
87
211
  super();
@@ -108,7 +232,6 @@ class RGBColor extends Color {
108
232
  return colors.length < 3 ? undefined : new RGBColor(colors[0], colors[1], colors[2], colors[3] ?? 1);
109
233
  }
110
234
 
111
-
112
235
  toString(format: ColorFormat | 'css') {
113
236
  switch (format) {
114
237
  case 'hex':
@@ -551,3 +674,81 @@ class HSLColor extends Color {
551
674
  return HSLColor.colorChannels;
552
675
  }
553
676
  }
677
+
678
+ // https://www.w3.org/TR/css-color-4/#color-conversion-code
679
+ function toOKLCH(color: Color) {
680
+ let rgb = color.toFormat('rgb');
681
+ let red = rgb.getChannelValue('red') / 255;
682
+ let green = rgb.getChannelValue('green') / 255;
683
+ let blue = rgb.getChannelValue('blue') / 255;
684
+ [red, green, blue] = lin_sRGB(red, green, blue);
685
+ let [x, y, z] = lin_sRGB_to_XYZ(red, green, blue);
686
+ let [l, a, b] = XYZ_to_OKLab(x, y, z);
687
+ return OKLab_to_OKLCH(l, a, b);
688
+ }
689
+
690
+ function OKLab_to_OKLCH(l: number, a: number, b: number): [number, number, number] {
691
+ var hue = Math.atan2(b, a) * 180 / Math.PI;
692
+ return [
693
+ l,
694
+ Math.sqrt(a ** 2 + b ** 2), // Chroma
695
+ hue >= 0 ? hue : hue + 360 // Hue, in degrees [0 to 360)
696
+ ];
697
+ }
698
+
699
+ function lin_sRGB(r: number, g: number, b: number): [number, number, number] {
700
+ // convert an array of sRGB values
701
+ // where in-gamut values are in the range [0 - 1]
702
+ // to linear light (un-companded) form.
703
+ // https://en.wikipedia.org/wiki/SRGB
704
+ // Extended transfer function:
705
+ // for negative values, linear portion is extended on reflection of axis,
706
+ // then reflected power function is used.
707
+ return [lin_sRGB_component(r), lin_sRGB_component(g), lin_sRGB_component(b)];
708
+ }
709
+
710
+ function lin_sRGB_component(val: number) {
711
+ let sign = val < 0 ? -1 : 1;
712
+ let abs = Math.abs(val);
713
+
714
+ if (abs <= 0.04045) {
715
+ return val / 12.92;
716
+ }
717
+
718
+ return sign * (Math.pow((abs + 0.055) / 1.055, 2.4));
719
+ }
720
+
721
+ function lin_sRGB_to_XYZ(r: number, g: number, b: number) {
722
+ // convert an array of linear-light sRGB values to CIE XYZ
723
+ // using sRGB's own white, D65 (no chromatic adaptation)
724
+ const M = [
725
+ 506752 / 1228815, 87881 / 245763, 12673 / 70218,
726
+ 87098 / 409605, 175762 / 245763, 12673 / 175545,
727
+ 7918 / 409605, 87881 / 737289, 1001167 / 1053270
728
+ ];
729
+ return multiplyMatrix(M, r, g, b);
730
+ }
731
+
732
+ function XYZ_to_OKLab(x: number, y: number, z: number) {
733
+ // Given XYZ relative to D65, convert to OKLab
734
+ const XYZtoLMS = [
735
+ 0.8190224379967030, 0.3619062600528904, -0.1288737815209879,
736
+ 0.0329836539323885, 0.9292868615863434, 0.0361446663506424,
737
+ 0.0481771893596242, 0.2642395317527308, 0.6335478284694309
738
+ ];
739
+ const LMStoOKLab = [
740
+ 0.2104542683093140, 0.7936177747023054, -0.0040720430116193,
741
+ 1.9779985324311684, -2.4285922420485799, 0.4505937096174110,
742
+ 0.0259040424655478, 0.7827717124575296, -0.8086757549230774
743
+ ];
744
+
745
+ let [a, b, c] = multiplyMatrix(XYZtoLMS, x, y, z);
746
+ return multiplyMatrix(LMStoOKLab, Math.cbrt(a), Math.cbrt(b), Math.cbrt(c));
747
+ }
748
+
749
+ function multiplyMatrix(m: number[], x: number, y: number, z: number): [number, number, number] {
750
+ let a = m[0] * x + m[1] * y + m[2] * z;
751
+ let b = m[3] * x + m[4] * y + m[5] * z;
752
+ let c = m[6] * x + m[7] * y + m[8] * z;
753
+ return [a, b, c];
754
+ }