color-map 2.2.0 → 2.3.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 (366) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/.codex-plugin/plugin.json +12 -0
  3. package/.cursor-plugin/plugin.json +12 -0
  4. package/CHANGELOG.md +100 -0
  5. package/README.md +71 -8
  6. package/bin/cli-CELmx3Y9.js +6414 -0
  7. package/bin/color-map.js +9 -0
  8. package/bin/index.js +1 -0
  9. package/cjs/color/index.d.ts +5 -0
  10. package/cjs/color/index.js +52 -0
  11. package/cjs/color-wNrkrhC7.js +374 -0
  12. package/cjs/color-wNrkrhC7.js.map +1 -0
  13. package/cjs/contrast-XjF5Rwui.js +293 -0
  14. package/cjs/contrast-XjF5Rwui.js.map +1 -0
  15. package/cjs/gamut-CG1J2aat.d.ts +158 -0
  16. package/cjs/gamut-CG1J2aat.d.ts.map +1 -0
  17. package/cjs/index-BcEqCPHz.d.ts +137 -0
  18. package/cjs/index-BcEqCPHz.d.ts.map +1 -0
  19. package/cjs/index-CGKCqRqD.d.ts +111 -0
  20. package/cjs/index-CGKCqRqD.d.ts.map +1 -0
  21. package/cjs/index-Cv3iUUYE.d.ts +171 -0
  22. package/cjs/index-Cv3iUUYE.d.ts.map +1 -0
  23. package/cjs/index-Dw43Hj4v.d.ts +41 -0
  24. package/cjs/index-Dw43Hj4v.d.ts.map +1 -0
  25. package/cjs/index-Dy8UARqO.d.ts +72 -0
  26. package/cjs/index-Dy8UARqO.d.ts.map +1 -0
  27. package/cjs/index.d.ts +26 -36
  28. package/cjs/index.d.ts.map +1 -1
  29. package/cjs/index.js +83 -62
  30. package/cjs/index.js.map +1 -1
  31. package/cjs/legacy/index.d.ts +2 -0
  32. package/cjs/legacy/index.js +75 -0
  33. package/cjs/legacy/index.js.map +1 -0
  34. package/cjs/mix-Cs4owSbW.js +158 -0
  35. package/cjs/mix-Cs4owSbW.js.map +1 -0
  36. package/cjs/mix-DGlKoUw4.d.ts +31 -0
  37. package/cjs/mix-DGlKoUw4.d.ts.map +1 -0
  38. package/cjs/palette/index.d.ts +3 -0
  39. package/cjs/palette/index.js +8 -0
  40. package/cjs/palette-DyFV_KoJ.js +332 -0
  41. package/cjs/palette-DyFV_KoJ.js.map +1 -0
  42. package/cjs/parse-8mt2OMKf.js +1508 -0
  43. package/cjs/parse-8mt2OMKf.js.map +1 -0
  44. package/cjs/scale/index.d.ts +2 -0
  45. package/cjs/scale/index.js +11 -0
  46. package/cjs/scale-Cq9pXrc1.js +318 -0
  47. package/cjs/scale-Cq9pXrc1.js.map +1 -0
  48. package/cjs/semantic-CrEIo8tS.d.ts +52 -0
  49. package/cjs/semantic-CrEIo8tS.d.ts.map +1 -0
  50. package/cjs/serialize-C69DAmoE.d.ts +25 -0
  51. package/cjs/serialize-C69DAmoE.d.ts.map +1 -0
  52. package/cjs/serialize-Ci2X0cPN.js +103 -0
  53. package/cjs/serialize-Ci2X0cPN.js.map +1 -0
  54. package/cjs/tokens/index.d.ts +2 -0
  55. package/cjs/tokens/index.js +6 -0
  56. package/cjs/tokens-CzXxaMgM.js +168 -0
  57. package/cjs/tokens-CzXxaMgM.js.map +1 -0
  58. package/cjs/tone-BAhu-QzQ.js +118 -0
  59. package/cjs/tone-BAhu-QzQ.js.map +1 -0
  60. package/dist/color-map.es5.js.map +1 -1
  61. package/esm/color/a98-rgb.d.ts +7 -0
  62. package/esm/color/a98-rgb.d.ts.map +1 -0
  63. package/esm/color/a98-rgb.js +13 -0
  64. package/esm/color/a98-rgb.js.map +1 -0
  65. package/esm/color/argb.d.ts +6 -0
  66. package/esm/color/argb.d.ts.map +1 -0
  67. package/esm/color/argb.js +25 -0
  68. package/esm/color/argb.js.map +1 -0
  69. package/esm/color/calc.js +82 -0
  70. package/esm/color/calc.js.map +1 -0
  71. package/esm/color/compare.d.ts +20 -0
  72. package/esm/color/compare.d.ts.map +1 -0
  73. package/esm/color/compare.js +46 -0
  74. package/esm/color/compare.js.map +1 -0
  75. package/esm/color/contrast.d.ts +107 -0
  76. package/esm/color/contrast.d.ts.map +1 -0
  77. package/esm/color/contrast.js +242 -0
  78. package/esm/color/contrast.js.map +1 -0
  79. package/esm/color/convert.d.ts +9 -0
  80. package/esm/color/convert.d.ts.map +1 -0
  81. package/esm/color/convert.js +45 -0
  82. package/esm/color/convert.js.map +1 -0
  83. package/esm/color/display-p3-linear.d.ts +7 -0
  84. package/esm/color/display-p3-linear.d.ts.map +1 -0
  85. package/esm/color/display-p3-linear.js +12 -0
  86. package/esm/color/display-p3-linear.js.map +1 -0
  87. package/esm/color/display-p3.d.ts +7 -0
  88. package/esm/color/display-p3.d.ts.map +1 -0
  89. package/esm/color/display-p3.js +12 -0
  90. package/esm/color/display-p3.js.map +1 -0
  91. package/esm/color/expr.d.ts +43 -0
  92. package/esm/color/expr.d.ts.map +1 -0
  93. package/esm/color/expr.js +160 -0
  94. package/esm/color/expr.js.map +1 -0
  95. package/esm/color/gamut.d.ts +31 -0
  96. package/esm/color/gamut.d.ts.map +1 -0
  97. package/esm/color/gamut.js +210 -0
  98. package/esm/color/gamut.js.map +1 -0
  99. package/esm/color/hsl.d.ts +7 -0
  100. package/esm/color/hsl.d.ts.map +1 -0
  101. package/esm/color/hsl.js +67 -0
  102. package/esm/color/hsl.js.map +1 -0
  103. package/esm/color/hwb.d.ts +7 -0
  104. package/esm/color/hwb.d.ts.map +1 -0
  105. package/esm/color/hwb.js +40 -0
  106. package/esm/color/hwb.js.map +1 -0
  107. package/esm/color/index.d.ts +28 -0
  108. package/esm/color/index.js +27 -0
  109. package/esm/color/lab.d.ts +7 -0
  110. package/esm/color/lab.d.ts.map +1 -0
  111. package/esm/color/lab.js +33 -0
  112. package/esm/color/lab.js.map +1 -0
  113. package/esm/color/lch.d.ts +7 -0
  114. package/esm/color/lch.d.ts.map +1 -0
  115. package/esm/color/lch.js +11 -0
  116. package/esm/color/lch.js.map +1 -0
  117. package/esm/color/math.js +32 -0
  118. package/esm/color/math.js.map +1 -0
  119. package/esm/color/matrices.js +180 -0
  120. package/esm/color/matrices.js.map +1 -0
  121. package/esm/color/mix.d.ts +30 -0
  122. package/esm/color/mix.d.ts.map +1 -0
  123. package/esm/color/mix.js +152 -0
  124. package/esm/color/mix.js.map +1 -0
  125. package/esm/color/named.js +11 -0
  126. package/esm/color/named.js.map +1 -0
  127. package/esm/color/oklab.d.ts +7 -0
  128. package/esm/color/oklab.d.ts.map +1 -0
  129. package/esm/color/oklab.js +21 -0
  130. package/esm/color/oklab.js.map +1 -0
  131. package/esm/color/oklch.d.ts +7 -0
  132. package/esm/color/oklch.d.ts.map +1 -0
  133. package/esm/color/oklch.js +11 -0
  134. package/esm/color/oklch.js.map +1 -0
  135. package/esm/color/parse.d.ts +9 -0
  136. package/esm/color/parse.d.ts.map +1 -0
  137. package/esm/color/parse.js +452 -0
  138. package/esm/color/parse.js.map +1 -0
  139. package/esm/color/polar.js +27 -0
  140. package/esm/color/polar.js.map +1 -0
  141. package/esm/color/prophoto-rgb.d.ts +7 -0
  142. package/esm/color/prophoto-rgb.d.ts.map +1 -0
  143. package/esm/color/prophoto-rgb.js +18 -0
  144. package/esm/color/prophoto-rgb.js.map +1 -0
  145. package/esm/color/rec2020.d.ts +7 -0
  146. package/esm/color/rec2020.d.ts.map +1 -0
  147. package/esm/color/rec2020.js +13 -0
  148. package/esm/color/rec2020.js.map +1 -0
  149. package/esm/color/resolve.d.ts +18 -0
  150. package/esm/color/resolve.d.ts.map +1 -0
  151. package/esm/color/resolve.js +98 -0
  152. package/esm/color/resolve.js.map +1 -0
  153. package/esm/color/rgb.js +20 -0
  154. package/esm/color/rgb.js.map +1 -0
  155. package/esm/color/serialize.d.ts +24 -0
  156. package/esm/color/serialize.d.ts.map +1 -0
  157. package/esm/color/serialize.js +88 -0
  158. package/esm/color/serialize.js.map +1 -0
  159. package/esm/color/spaces.d.ts +6 -0
  160. package/esm/color/spaces.d.ts.map +1 -0
  161. package/esm/color/spaces.js +42 -0
  162. package/esm/color/spaces.js.map +1 -0
  163. package/esm/color/srgb-linear.d.ts +7 -0
  164. package/esm/color/srgb-linear.d.ts.map +1 -0
  165. package/esm/color/srgb-linear.js +12 -0
  166. package/esm/color/srgb-linear.js.map +1 -0
  167. package/esm/color/srgb.d.ts +7 -0
  168. package/esm/color/srgb.d.ts.map +1 -0
  169. package/esm/color/srgb.js +12 -0
  170. package/esm/color/srgb.js.map +1 -0
  171. package/esm/color/transfer.js +11 -0
  172. package/esm/color/transfer.js.map +1 -0
  173. package/esm/color/types.d.ts +23 -0
  174. package/esm/color/types.d.ts.map +1 -0
  175. package/esm/color/unknown-name.js +16 -0
  176. package/esm/color/unknown-name.js.map +1 -0
  177. package/esm/color/xyz-d50.d.ts +7 -0
  178. package/esm/color/xyz-d50.d.ts.map +1 -0
  179. package/esm/color/xyz-d50.js +15 -0
  180. package/esm/color/xyz-d50.js.map +1 -0
  181. package/esm/color/xyz-d65.d.ts +4 -0
  182. package/esm/color/xyz-d65.d.ts.map +1 -0
  183. package/esm/color/xyz-d65.js +10 -0
  184. package/esm/color/xyz-d65.js.map +1 -0
  185. package/esm/index.d.ts +63 -6
  186. package/esm/index.d.ts.map +1 -0
  187. package/esm/index.js +54 -5
  188. package/esm/index.js.map +1 -0
  189. package/esm/legacy/createColors.d.ts +9 -0
  190. package/esm/legacy/createColors.d.ts.map +1 -0
  191. package/esm/{createColors.js → legacy/createColors.js} +7 -2
  192. package/esm/legacy/createColors.js.map +1 -0
  193. package/esm/legacy/createColorsFromMap.d.ts +9 -0
  194. package/esm/legacy/createColorsFromMap.d.ts.map +1 -0
  195. package/esm/{createColorsFromMap.js → legacy/createColorsFromMap.js} +4 -2
  196. package/esm/legacy/createColorsFromMap.js.map +1 -0
  197. package/esm/legacy/index.d.ts +6 -0
  198. package/esm/legacy/index.js +5 -0
  199. package/esm/legacy/interfaces.d.ts +19 -0
  200. package/esm/legacy/interfaces.d.ts.map +1 -0
  201. package/esm/{rgbHex.d.ts → legacy/rgbHex.d.ts} +1 -4
  202. package/esm/legacy/rgbHex.d.ts.map +1 -0
  203. package/esm/{rgbHex.js → legacy/rgbHex.js} +1 -2
  204. package/esm/legacy/rgbHex.js.map +1 -0
  205. package/esm/legacy/rgbaString.d.ts +4 -0
  206. package/esm/{rgbaString.d.ts.map → legacy/rgbaString.d.ts.map} +1 -1
  207. package/esm/legacy/rgbaString.js +8 -0
  208. package/esm/legacy/rgbaString.js.map +1 -0
  209. package/esm/palette/dark.d.ts +23 -0
  210. package/esm/palette/dark.d.ts.map +1 -0
  211. package/esm/palette/dark.js +54 -0
  212. package/esm/palette/dark.js.map +1 -0
  213. package/esm/palette/harmony.d.ts +56 -0
  214. package/esm/palette/harmony.d.ts.map +1 -0
  215. package/esm/palette/harmony.js +115 -0
  216. package/esm/palette/harmony.js.map +1 -0
  217. package/esm/palette/index.d.ts +5 -0
  218. package/esm/palette/index.js +5 -0
  219. package/esm/palette/semantic.d.ts +53 -0
  220. package/esm/palette/semantic.d.ts.map +1 -0
  221. package/esm/palette/semantic.js +96 -0
  222. package/esm/palette/semantic.js.map +1 -0
  223. package/esm/palette/validate.d.ts +39 -0
  224. package/esm/palette/validate.d.ts.map +1 -0
  225. package/esm/palette/validate.js +56 -0
  226. package/esm/palette/validate.js.map +1 -0
  227. package/esm/scale/brand.d.ts +21 -0
  228. package/esm/scale/brand.d.ts.map +1 -0
  229. package/esm/scale/brand.js +63 -0
  230. package/esm/scale/brand.js.map +1 -0
  231. package/esm/scale/contrast-scale.d.ts +33 -0
  232. package/esm/scale/contrast-scale.d.ts.map +1 -0
  233. package/esm/scale/contrast-scale.js +26 -0
  234. package/esm/scale/contrast-scale.js.map +1 -0
  235. package/esm/scale/gradient.d.ts +38 -0
  236. package/esm/scale/gradient.d.ts.map +1 -0
  237. package/esm/scale/gradient.js +73 -0
  238. package/esm/scale/gradient.js.map +1 -0
  239. package/esm/scale/index.d.ts +6 -0
  240. package/esm/scale/index.js +6 -0
  241. package/esm/scale/scale.d.ts +31 -0
  242. package/esm/scale/scale.d.ts.map +1 -0
  243. package/esm/scale/scale.js +152 -0
  244. package/esm/scale/scale.js.map +1 -0
  245. package/esm/scale/tone.d.ts +25 -0
  246. package/esm/scale/tone.d.ts.map +1 -0
  247. package/esm/scale/tone.js +96 -0
  248. package/esm/scale/tone.js.map +1 -0
  249. package/esm/tokens/css.d.ts +18 -0
  250. package/esm/tokens/css.d.ts.map +1 -0
  251. package/esm/tokens/css.js +23 -0
  252. package/esm/tokens/css.js.map +1 -0
  253. package/esm/tokens/dtcg.d.ts +33 -0
  254. package/esm/tokens/dtcg.d.ts.map +1 -0
  255. package/esm/tokens/dtcg.js +42 -0
  256. package/esm/tokens/dtcg.js.map +1 -0
  257. package/esm/tokens/index.d.ts +5 -0
  258. package/esm/tokens/index.js +4 -0
  259. package/esm/tokens/tailwind.d.ts +19 -0
  260. package/esm/tokens/tailwind.d.ts.map +1 -0
  261. package/esm/tokens/tailwind.js +19 -0
  262. package/esm/tokens/tailwind.js.map +1 -0
  263. package/esm/tokens/tokens.d.ts +11 -0
  264. package/esm/tokens/tokens.d.ts.map +1 -0
  265. package/esm/tokens/tokens.js +77 -0
  266. package/esm/tokens/tokens.js.map +1 -0
  267. package/llms.txt +48 -0
  268. package/package.json +277 -64
  269. package/plugin.json +18 -0
  270. package/schemas/contrast.schema.json +24 -0
  271. package/schemas/convert.schema.json +60 -0
  272. package/schemas/export.schema.json +106 -0
  273. package/schemas/find-contrast.schema.json +51 -0
  274. package/schemas/harmony.schema.json +58 -0
  275. package/schemas/mix.schema.json +72 -0
  276. package/schemas/palette.schema.json +56 -0
  277. package/schemas/scale.schema.json +86 -0
  278. package/skills/color-map/SKILL.md +38 -0
  279. package/src/cli/bin.ts +11 -0
  280. package/src/cli/cli.ts +40 -0
  281. package/src/cli/commands/contrast.ts +36 -0
  282. package/src/cli/commands/convert.ts +37 -0
  283. package/src/cli/commands/export.ts +102 -0
  284. package/src/cli/commands/find-contrast.ts +37 -0
  285. package/src/cli/commands/harmony.ts +30 -0
  286. package/src/cli/commands/mix.ts +29 -0
  287. package/src/cli/commands/palette.ts +66 -0
  288. package/src/cli/commands/scale.ts +75 -0
  289. package/src/cli/index.ts +3 -0
  290. package/src/cli/schema-command.ts +31 -0
  291. package/src/cli/schemas.ts +86 -0
  292. package/src/cli/shared.ts +72 -0
  293. package/src/cli/testing.ts +27 -0
  294. package/src/color/a98-rgb.ts +11 -0
  295. package/src/color/argb.ts +21 -0
  296. package/src/color/calc.ts +84 -0
  297. package/src/color/compare.ts +53 -0
  298. package/src/color/contrast.ts +277 -0
  299. package/src/color/convert.ts +43 -0
  300. package/src/color/display-p3-linear.ts +9 -0
  301. package/src/color/display-p3.ts +9 -0
  302. package/src/color/expr.ts +158 -0
  303. package/src/color/gamut.ts +215 -0
  304. package/src/color/hsl.ts +57 -0
  305. package/src/color/hwb.ts +26 -0
  306. package/src/color/index.ts +43 -0
  307. package/src/color/lab.ts +29 -0
  308. package/src/color/lch.ts +8 -0
  309. package/src/color/math.ts +30 -0
  310. package/src/color/matrices.ts +91 -0
  311. package/src/color/mix.ts +158 -0
  312. package/src/color/named.ts +13 -0
  313. package/src/color/oklab.ts +19 -0
  314. package/src/color/oklch.ts +8 -0
  315. package/src/color/parse.ts +355 -0
  316. package/src/color/polar.ts +17 -0
  317. package/src/color/prophoto-rgb.ts +18 -0
  318. package/src/color/rec2020.ts +11 -0
  319. package/src/color/resolve.ts +87 -0
  320. package/src/color/rgb.ts +20 -0
  321. package/src/color/serialize.ts +96 -0
  322. package/src/color/spaces.ts +42 -0
  323. package/src/color/srgb-linear.ts +9 -0
  324. package/src/color/srgb.ts +9 -0
  325. package/src/color/test-utils.ts +10 -0
  326. package/src/color/transfer.ts +14 -0
  327. package/src/color/types.ts +41 -0
  328. package/src/color/unknown-name.ts +15 -0
  329. package/src/color/xyz-d50.ts +13 -0
  330. package/src/color/xyz-d65.ts +8 -0
  331. package/src/index.ts +37 -0
  332. package/{ts → src/legacy}/createColors.ts +6 -0
  333. package/{ts → src/legacy}/createColorsFromMap.ts +3 -0
  334. package/{ts → src/legacy}/interfaces.ts +4 -0
  335. package/{ts → src/legacy}/rgbaString.ts +1 -0
  336. package/src/palette/dark.ts +55 -0
  337. package/src/palette/harmony.ts +107 -0
  338. package/src/palette/index.ts +18 -0
  339. package/src/palette/semantic.ts +120 -0
  340. package/src/palette/validate.ts +82 -0
  341. package/src/scale/brand.ts +50 -0
  342. package/src/scale/contrast-scale.ts +48 -0
  343. package/src/scale/gradient.ts +91 -0
  344. package/src/scale/index.ts +5 -0
  345. package/src/scale/scale.ts +127 -0
  346. package/src/scale/tone.ts +69 -0
  347. package/src/tokens/css.ts +32 -0
  348. package/src/tokens/dtcg.ts +62 -0
  349. package/src/tokens/index.ts +11 -0
  350. package/src/tokens/tailwind.ts +24 -0
  351. package/src/tokens/tokens.ts +82 -0
  352. package/esm/createColors.d.ts +0 -6
  353. package/esm/createColors.d.ts.map +0 -1
  354. package/esm/createColors.js.map +0 -1
  355. package/esm/createColorsFromMap.d.ts +0 -9
  356. package/esm/createColorsFromMap.d.ts.map +0 -1
  357. package/esm/createColorsFromMap.js.map +0 -1
  358. package/esm/interfaces.d.ts +0 -18
  359. package/esm/interfaces.d.ts.map +0 -1
  360. package/esm/rgbHex.d.ts.map +0 -1
  361. package/esm/rgbHex.js.map +0 -1
  362. package/esm/rgbaString.d.ts +0 -6
  363. package/esm/rgbaString.js +0 -8
  364. package/esm/rgbaString.js.map +0 -1
  365. /package/{ts → src/legacy}/index.ts +0 -0
  366. /package/{ts → src/legacy}/rgbHex.ts +0 -0
@@ -0,0 +1,293 @@
1
+ const require_parse = require("./parse-8mt2OMKf.js");
2
+ // src/color/contrast.ts
3
+ /** Relative luminance (WCAG 2): the Y of the color in XYZ-D65, with white at 1. */
4
+ function luminance(componentsIn, color) {
5
+ return Math.max(0, componentsIn(color, "xyz-d65")[1]);
6
+ }
7
+ /** Lays a translucent color over `bg`, in `srgb`, the way a browser paints it. */
8
+ function flatten(componentsIn, fg, bg) {
9
+ const alpha = fg.alpha === null ? 0 : fg.alpha ?? 1;
10
+ if (alpha >= 1) return fg;
11
+ const f = componentsIn(fg, "srgb");
12
+ const b = componentsIn(bg, "srgb");
13
+ return {
14
+ colorSpace: "srgb",
15
+ components: f.map((x, i) => x * alpha + b[i] * (1 - alpha))
16
+ };
17
+ }
18
+ /**
19
+ * WCAG 2 contrast ratio, 1 to 21. A translucent `fg` is laid over `bg` first;
20
+ * `bg` is taken as opaque.
21
+ */
22
+ const wcag2 = /* @__PURE__ */ wcag2Over(require_parse.componentsIn);
23
+ /** WCAG 2 over the spaces `componentsIn` knows, which must include `srgb` and `xyz-d65`. */
24
+ function wcag2Over(componentsIn) {
25
+ return Object.assign((fg, bg) => {
26
+ const a = luminance(componentsIn, flatten(componentsIn, fg, bg)) + .05;
27
+ const b = luminance(componentsIn, bg) + .05;
28
+ return a > b ? a / b : b / a;
29
+ }, {
30
+ algorithm: "wcag2",
31
+ thresholds: {
32
+ AA: 4.5,
33
+ "AA-large": 3,
34
+ AAA: 7,
35
+ "AAA-large": 4.5,
36
+ "non-text": 3
37
+ },
38
+ polarity: "symmetric"
39
+ });
40
+ }
41
+ /** The measure `algo` names: `wcag2` or a function; anything else is an unknown name. */
42
+ function pick(algo) {
43
+ return pickFrom(wcag2, algo);
44
+ }
45
+ /** {@link pick}, with `builtin` as what `wcag2` names. */
46
+ function pickFrom(builtin, algo) {
47
+ if (algo === "wcag2") return builtin;
48
+ if (typeof algo !== "function") throw require_parse.unknownName("contrast algorithm", algo, ["wcag2"]);
49
+ return algo;
50
+ }
51
+ /** A {@link ContrastKit} over `needed` and `spaces`. */
52
+ function contrastKit(needed, spaces) {
53
+ const over = require_parse.componentsOver([...needed, ...spaces]);
54
+ return {
55
+ componentsIn: over,
56
+ wcag2: wcag2Over(over)
57
+ };
58
+ }
59
+ /**
60
+ * Contrast of `fg` on `bg`. Colors may be CSS strings. The default is WCAG 2;
61
+ * pass a {@link ContrastFn} to use another measure (see the APCA recipe).
62
+ */
63
+ function contrast(fg, bg, algo = "wcag2") {
64
+ return pick(algo)(require_parse.toColor(fg), require_parse.toColor(bg));
65
+ }
66
+ /**
67
+ * Builds {@link contrast} over the spaces given, plus `srgb` and `xyz-d65`,
68
+ * which WCAG 2 works in, so a bundle contains only those. It takes color
69
+ * objects, not strings, so it does not carry `parse`. A color in a space not
70
+ * given throws, naming that space.
71
+ */
72
+ function createContrast(...spaces) {
73
+ const kit = contrastKit([require_parse.srgb, require_parse.xyzD65], spaces);
74
+ return (fg, bg, algo = "wcag2") => pickFrom(kit.wcag2, algo)(fg, bg);
75
+ }
76
+ /**
77
+ * True when `fg` on `bg` reaches `level`: a number, or a name from the
78
+ * algorithm's thresholds (WCAG 2: `AA`, `AA-large`, `AAA`, `AAA-large`,
79
+ * `non-text`). A signed measure such as APCA is compared by magnitude.
80
+ */
81
+ function meets(fg, bg, level, algo = "wcag2") {
82
+ const fn = pick(algo);
83
+ const target = levelOf(fn, level);
84
+ return Math.abs(fn(require_parse.toColor(fg), require_parse.toColor(bg))) >= target;
85
+ }
86
+ /**
87
+ * Builds {@link meets} over the spaces given, plus `srgb` and `xyz-d65`, which
88
+ * WCAG 2 works in, so a bundle contains only those. It takes color objects,
89
+ * not strings, so it does not carry `parse`. A color in a space not given
90
+ * throws, naming that space.
91
+ */
92
+ function createMeets(...spaces) {
93
+ const kit = contrastKit([require_parse.srgb, require_parse.xyzD65], spaces);
94
+ return (fg, bg, level, algo = "wcag2") => {
95
+ const fn = pickFrom(kit.wcag2, algo);
96
+ return Math.abs(fn(fg, bg)) >= levelOf(fn, level);
97
+ };
98
+ }
99
+ /** The contrast `level` stands for under `fn`: the number itself, or one of its thresholds by name. */
100
+ function levelOf(fn, level) {
101
+ const named = typeof level === "number" ? level : fn.thresholds?.[level];
102
+ const target = typeof named === "number" ? named : void 0;
103
+ if (target === void 0) throw require_parse.unknownName("contrast level", level, Object.keys(fn.thresholds ?? {}));
104
+ return target;
105
+ }
106
+ const STEPS = 32;
107
+ /**
108
+ * Finds the color closest in lightness to `bg` (OKLCH L, at the given hue and
109
+ * chroma) that reaches `target` contrast against it, by binary search. It looks
110
+ * the preferred way first, then the other. The returned `contrast` is measured
111
+ * on the final, gamut-mapped color, and `met` says whether it reaches `target`.
112
+ */
113
+ function findContrast(bg, target, options = {}) {
114
+ return findContrastWith({
115
+ componentsIn: require_parse.componentsIn,
116
+ wcag2
117
+ }, require_parse.toColor(bg), target, options);
118
+ }
119
+ /**
120
+ * Builds {@link findContrast} over the spaces given, plus `srgb`, `xyz-d65`,
121
+ * `oklch` and `oklab`, which WCAG 2 and gamut mapping work in, so a bundle
122
+ * contains only those. It takes a color object, not a string, so it does not
123
+ * carry `parse`. A color in a space not given throws, naming that space.
124
+ */
125
+ function createFindContrast(...spaces) {
126
+ const kit = contrastKit([
127
+ require_parse.srgb,
128
+ require_parse.xyzD65,
129
+ require_parse.oklch,
130
+ require_parse.oklab
131
+ ], spaces);
132
+ return (bg, target, options = {}) => findContrastWith(kit, bg, target, options);
133
+ }
134
+ function findContrastWith({ componentsIn, wcag2 }, back, target, options) {
135
+ const fn = pickFrom(wcag2, options.contrast ?? "wcag2");
136
+ const lch = componentsIn(back, "oklch");
137
+ const l0 = lch[0];
138
+ const hue = options.hue ?? lch[2];
139
+ const chroma = options.chroma ?? 0;
140
+ const at = (l) => {
141
+ const color = require_parse.toGamutWith(componentsIn, {
142
+ colorSpace: "oklch",
143
+ components: [
144
+ l,
145
+ chroma,
146
+ hue
147
+ ]
148
+ }, {});
149
+ const value = fn(color, back);
150
+ return {
151
+ color,
152
+ contrast: value,
153
+ met: Math.abs(value) >= target
154
+ };
155
+ };
156
+ const first = options.direction ?? (l0 > .5 ? "darker" : "lighter");
157
+ let best;
158
+ for (const side of [first, first === "darker" ? "lighter" : "darker"]) {
159
+ const far = side === "darker" ? 0 : 1;
160
+ const end = at(far);
161
+ if (!end.met) {
162
+ if (!best || Math.abs(end.contrast) > Math.abs(best.contrast)) best = end;
163
+ continue;
164
+ }
165
+ let [lo, hi] = [l0, far];
166
+ let found = end;
167
+ for (let i = 0; i < STEPS; i++) {
168
+ const mid = (lo + hi) / 2;
169
+ const candidate = at(mid);
170
+ if (candidate.met) {
171
+ hi = mid;
172
+ found = candidate;
173
+ } else lo = mid;
174
+ }
175
+ return found;
176
+ }
177
+ return {
178
+ ...best,
179
+ met: false
180
+ };
181
+ }
182
+ /**
183
+ * The text color for `bg`, by the Radix rule: white, unless white's contrast
184
+ * on `bg` is under `target`, then a near-black tinted with the hue of `bg`
185
+ * (OKLCH lightness 0.2). When neither reaches `target`, whichever contrasts more.
186
+ */
187
+ function onColor(bg, options = {}) {
188
+ return onColorWith({
189
+ componentsIn: require_parse.componentsIn,
190
+ wcag2
191
+ }, require_parse.toColor(bg), options);
192
+ }
193
+ /**
194
+ * Builds {@link onColor} over the spaces given, plus `srgb`, `xyz-d65`,
195
+ * `oklch` and `oklab`, which WCAG 2 and gamut mapping work in, so a bundle
196
+ * contains only those. It takes a color object, not a string, so it does not
197
+ * carry `parse`. A color in a space not given throws, naming that space.
198
+ */
199
+ function createOnColor(...spaces) {
200
+ const kit = contrastKit([
201
+ require_parse.srgb,
202
+ require_parse.xyzD65,
203
+ require_parse.oklch,
204
+ require_parse.oklab
205
+ ], spaces);
206
+ return (bg, options = {}) => onColorWith(kit, bg, options);
207
+ }
208
+ function onColorWith({ componentsIn, wcag2 }, back, options) {
209
+ const fn = pickFrom(wcag2, options.contrast ?? "wcag2");
210
+ const target = options.target ?? 4.5;
211
+ const white = {
212
+ colorSpace: "srgb",
213
+ components: [
214
+ 1,
215
+ 1,
216
+ 1
217
+ ]
218
+ };
219
+ const whiteScore = Math.abs(fn(white, back));
220
+ if (whiteScore >= target) return white;
221
+ const hue = componentsIn(back, "oklch")[2];
222
+ const dark = require_parse.toGamutWith(componentsIn, {
223
+ colorSpace: "oklch",
224
+ components: [
225
+ .2,
226
+ options.chroma ?? .03,
227
+ hue
228
+ ]
229
+ }, {});
230
+ return Math.abs(fn(dark, back)) >= whiteScore ? dark : white;
231
+ }
232
+ Object.defineProperty(exports, "contrast", {
233
+ enumerable: true,
234
+ get: function() {
235
+ return contrast;
236
+ }
237
+ });
238
+ Object.defineProperty(exports, "createContrast", {
239
+ enumerable: true,
240
+ get: function() {
241
+ return createContrast;
242
+ }
243
+ });
244
+ Object.defineProperty(exports, "createFindContrast", {
245
+ enumerable: true,
246
+ get: function() {
247
+ return createFindContrast;
248
+ }
249
+ });
250
+ Object.defineProperty(exports, "createMeets", {
251
+ enumerable: true,
252
+ get: function() {
253
+ return createMeets;
254
+ }
255
+ });
256
+ Object.defineProperty(exports, "createOnColor", {
257
+ enumerable: true,
258
+ get: function() {
259
+ return createOnColor;
260
+ }
261
+ });
262
+ Object.defineProperty(exports, "findContrast", {
263
+ enumerable: true,
264
+ get: function() {
265
+ return findContrast;
266
+ }
267
+ });
268
+ Object.defineProperty(exports, "meets", {
269
+ enumerable: true,
270
+ get: function() {
271
+ return meets;
272
+ }
273
+ });
274
+ Object.defineProperty(exports, "onColor", {
275
+ enumerable: true,
276
+ get: function() {
277
+ return onColor;
278
+ }
279
+ });
280
+ Object.defineProperty(exports, "pick", {
281
+ enumerable: true,
282
+ get: function() {
283
+ return pick;
284
+ }
285
+ });
286
+ Object.defineProperty(exports, "wcag2", {
287
+ enumerable: true,
288
+ get: function() {
289
+ return wcag2;
290
+ }
291
+ });
292
+
293
+ //# sourceMappingURL=contrast-XjF5Rwui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contrast-XjF5Rwui.js","names":["componentsIn","unknownName","componentsOver","toColor","srgb","xyzD65","oklch","oklab","toGamutWith"],"sources":["../src/color/contrast.ts"],"sourcesContent":["import { type ComponentsIn, componentsOver } from './convert.js'\nimport { toGamutWith } from './gamut.js'\nimport { oklab } from './oklab.js'\nimport { oklch } from './oklch.js'\nimport { toColor } from './parse.js'\nimport { componentsIn } from './spaces.js'\nimport { srgb } from './srgb.js'\nimport type { Color, Space } from './types.js'\nimport { unknownName } from './unknown-name.js'\nimport { xyzD65 } from './xyz-d65.js'\n\n/**\n * A contrast measure: `(fg, bg) => number`, plus what a caller needs to use it\n * without knowing the algorithm. Any plain `(fg, bg) => number` also works\n * wherever a `ContrastFn` is taken; the extra fields are optional.\n */\nexport interface ContrastFn {\n\t(fg: Color, bg: Color): number\n\t/** A label for messages and output, for example `wcag2`. */\n\treadonly algorithm?: string\n\t/** Named targets, for example `{ AA: 4.5 }`, which `meets` accepts as a level. */\n\treadonly thresholds?: Readonly<Record<string, number>>\n\t/** `symmetric` when swapping fg and bg gives the same number; `signed` when the sign says which is lighter. */\n\treadonly polarity?: 'symmetric' | 'signed'\n}\n\n/** The contrast algorithms built in. */\nexport type ContrastAlgorithm = 'wcag2'\n\n/** Either a built-in name or a {@link ContrastFn}. */\nexport type ContrastOption = ContrastAlgorithm | ContrastFn\n\ntype ColorInput = Color | string\n\n/** Relative luminance (WCAG 2): the Y of the color in XYZ-D65, with white at 1. */\nfunction luminance(componentsIn: ComponentsIn, color: Color): number {\n\treturn Math.max(0, componentsIn(color, 'xyz-d65')[1] as number)\n}\n\n/** Lays a translucent color over `bg`, in `srgb`, the way a browser paints it. */\nfunction flatten(componentsIn: ComponentsIn, fg: Color, bg: Color): Color {\n\tconst alpha = fg.alpha === null ? 0 : (fg.alpha ?? 1)\n\tif (alpha >= 1) return fg\n\tconst f = componentsIn(fg, 'srgb')\n\tconst b = componentsIn(bg, 'srgb')\n\treturn { colorSpace: 'srgb', components: f.map((x, i) => (x as number) * alpha + (b[i] as number) * (1 - alpha)) }\n}\n\n/**\n * WCAG 2 contrast ratio, 1 to 21. A translucent `fg` is laid over `bg` first;\n * `bg` is taken as opaque.\n */\nexport const wcag2: ContrastFn = /* @__PURE__ */ wcag2Over(componentsIn)\n\n/** WCAG 2 over the spaces `componentsIn` knows, which must include `srgb` and `xyz-d65`. */\nfunction wcag2Over(componentsIn: ComponentsIn): ContrastFn {\n\treturn Object.assign(\n\t\t(fg: Color, bg: Color): number => {\n\t\t\tconst a = luminance(componentsIn, flatten(componentsIn, fg, bg)) + 0.05\n\t\t\tconst b = luminance(componentsIn, bg) + 0.05\n\t\t\treturn a > b ? a / b : b / a\n\t\t},\n\t\t{\n\t\t\talgorithm: 'wcag2',\n\t\t\tthresholds: { AA: 4.5, 'AA-large': 3, AAA: 7, 'AAA-large': 4.5, 'non-text': 3 },\n\t\t\tpolarity: 'symmetric'\n\t\t} as const\n\t)\n}\n\n/** The measure `algo` names: `wcag2` or a function; anything else is an unknown name. */\nexport function pick(algo: ContrastOption): ContrastFn {\n\treturn pickFrom(wcag2, algo)\n}\n\n/** {@link pick}, with `builtin` as what `wcag2` names. */\nfunction pickFrom(builtin: ContrastFn, algo: ContrastOption): ContrastFn {\n\tif (algo === 'wcag2') return builtin\n\tif (typeof algo !== 'function') throw unknownName('contrast algorithm', algo, ['wcag2'])\n\treturn algo\n}\n\n/** What a narrow contrast helper works over: its spaces and its own `wcag2`. */\ninterface ContrastKit {\n\tcomponentsIn: ComponentsIn\n\twcag2: ContrastFn\n}\n\n/** A {@link ContrastKit} over `needed` and `spaces`. */\nfunction contrastKit(needed: Space[], spaces: Space[]): ContrastKit {\n\tconst over = componentsOver([...needed, ...spaces])\n\treturn { componentsIn: over, wcag2: wcag2Over(over) }\n}\n\n/**\n * Contrast of `fg` on `bg`. Colors may be CSS strings. The default is WCAG 2;\n * pass a {@link ContrastFn} to use another measure (see the APCA recipe).\n */\nexport function contrast(fg: ColorInput, bg: ColorInput, algo: ContrastOption = 'wcag2'): number {\n\treturn pick(algo)(toColor(fg), toColor(bg))\n}\n\n/**\n * Builds {@link contrast} over the spaces given, plus `srgb` and `xyz-d65`,\n * which WCAG 2 works in, so a bundle contains only those. It takes color\n * objects, not strings, so it does not carry `parse`. A color in a space not\n * given throws, naming that space.\n */\nexport function createContrast(...spaces: Space[]): (fg: Color, bg: Color, algo?: ContrastOption) => number {\n\tconst kit = contrastKit([srgb, xyzD65], spaces)\n\treturn (fg, bg, algo = 'wcag2') => pickFrom(kit.wcag2, algo)(fg, bg)\n}\n\n/**\n * True when `fg` on `bg` reaches `level`: a number, or a name from the\n * algorithm's thresholds (WCAG 2: `AA`, `AA-large`, `AAA`, `AAA-large`,\n * `non-text`). A signed measure such as APCA is compared by magnitude.\n */\nexport function meets(fg: ColorInput, bg: ColorInput, level: number | string, algo: ContrastOption = 'wcag2'): boolean {\n\tconst fn = pick(algo)\n\tconst target = levelOf(fn, level)\n\treturn Math.abs(fn(toColor(fg), toColor(bg))) >= target\n}\n\n/**\n * Builds {@link meets} over the spaces given, plus `srgb` and `xyz-d65`, which\n * WCAG 2 works in, so a bundle contains only those. It takes color objects,\n * not strings, so it does not carry `parse`. A color in a space not given\n * throws, naming that space.\n */\nexport function createMeets(\n\t...spaces: Space[]\n): (fg: Color, bg: Color, level: number | string, algo?: ContrastOption) => boolean {\n\tconst kit = contrastKit([srgb, xyzD65], spaces)\n\treturn (fg, bg, level, algo = 'wcag2') => {\n\t\tconst fn = pickFrom(kit.wcag2, algo)\n\t\treturn Math.abs(fn(fg, bg)) >= levelOf(fn, level)\n\t}\n}\n\n/** The contrast `level` stands for under `fn`: the number itself, or one of its thresholds by name. */\nfunction levelOf(fn: ContrastFn, level: number | string): number {\n\tconst named = typeof level === 'number' ? level : fn.thresholds?.[level]\n\t// A name that is not the algorithm's own (`constructor`) finds something that is not a number.\n\tconst target = typeof named === 'number' ? named : undefined\n\tif (target === undefined) throw unknownName('contrast level', level, Object.keys(fn.thresholds ?? {}))\n\treturn target\n}\n\n/** Options for `findContrast` and the function `createFindContrast` returns. */\nexport interface FindContrastOptions {\n\t/** Hue of the result, in OKLCH degrees. Default: the hue of `bg`. */\n\thue?: number\n\t/** Chroma of the result, in OKLCH. Default 0. The result is mapped into the gamut. */\n\tchroma?: number\n\t/** Which way to look first from `bg`. Default: darker on a light `bg`, lighter on a dark one. */\n\tdirection?: 'lighter' | 'darker'\n\t/** Default `wcag2`. */\n\tcontrast?: ContrastOption\n}\n\n/** What `findContrast` returns: the color it found and whether it reached the target. */\nexport interface FoundContrast {\n\t/** The color, in `srgb` and inside the gamut. */\n\tcolor: Color\n\t/** The contrast it achieves against `bg`, as the algorithm reports it. */\n\tcontrast: number\n\t/** False when no lightness reaches `target`; `color` is then the best one found. */\n\tmet: boolean\n}\n\nconst STEPS = 32\n\n/**\n * Finds the color closest in lightness to `bg` (OKLCH L, at the given hue and\n * chroma) that reaches `target` contrast against it, by binary search. It looks\n * the preferred way first, then the other. The returned `contrast` is measured\n * on the final, gamut-mapped color, and `met` says whether it reaches `target`.\n */\nexport function findContrast(bg: ColorInput, target: number, options: FindContrastOptions = {}): FoundContrast {\n\treturn findContrastWith({ componentsIn, wcag2 }, toColor(bg), target, options)\n}\n\n/**\n * Builds {@link findContrast} over the spaces given, plus `srgb`, `xyz-d65`,\n * `oklch` and `oklab`, which WCAG 2 and gamut mapping work in, so a bundle\n * contains only those. It takes a color object, not a string, so it does not\n * carry `parse`. A color in a space not given throws, naming that space.\n */\nexport function createFindContrast(\n\t...spaces: Space[]\n): (bg: Color, target: number, options?: FindContrastOptions) => FoundContrast {\n\tconst kit = contrastKit([srgb, xyzD65, oklch, oklab], spaces)\n\treturn (bg, target, options = {}) => findContrastWith(kit, bg, target, options)\n}\n\nfunction findContrastWith(\n\t{ componentsIn, wcag2 }: ContrastKit,\n\tback: Color,\n\ttarget: number,\n\toptions: FindContrastOptions\n): FoundContrast {\n\tconst fn = pickFrom(wcag2, options.contrast ?? 'wcag2')\n\tconst lch = componentsIn(back, 'oklch')\n\tconst l0 = lch[0] as number\n\tconst hue = options.hue ?? (lch[2] as number)\n\tconst chroma = options.chroma ?? 0\n\tconst at = (l: number): FoundContrast => {\n\t\tconst color = toGamutWith(componentsIn, { colorSpace: 'oklch', components: [l, chroma, hue] }, {})\n\t\tconst value = fn(color, back)\n\t\treturn { color, contrast: value, met: Math.abs(value) >= target }\n\t}\n\tconst first = options.direction ?? (l0 > 0.5 ? 'darker' : 'lighter')\n\tlet best: FoundContrast | undefined\n\tfor (const side of [first, first === 'darker' ? 'lighter' : 'darker']) {\n\t\tconst far = side === 'darker' ? 0 : 1\n\t\tconst end = at(far)\n\t\tif (!end.met) {\n\t\t\tif (!best || Math.abs(end.contrast) > Math.abs(best.contrast)) best = end\n\t\t\tcontinue\n\t\t}\n\t\t// `lo` is on the bg side and fails or is the bg itself; `hi` always passes.\n\t\tlet [lo, hi] = [l0, far]\n\t\tlet found = end\n\t\tfor (let i = 0; i < STEPS; i++) {\n\t\t\tconst mid = (lo + hi) / 2\n\t\t\tconst candidate = at(mid)\n\t\t\tif (candidate.met) {\n\t\t\t\thi = mid\n\t\t\t\tfound = candidate\n\t\t\t} else lo = mid\n\t\t}\n\t\treturn found\n\t}\n\treturn { ...(best as FoundContrast), met: false }\n}\n\n/** Options for `onColor` and the function `createOnColor` returns. */\nexport interface OnColorOptions {\n\t/** The contrast the text needs. Default 4.5 for WCAG 2. */\n\ttarget?: number\n\t/** How much of the background's hue the dark text carries, as OKLCH chroma. Default 0.03. */\n\tchroma?: number\n\t/** Default `wcag2`. */\n\tcontrast?: ContrastOption\n}\n\n/**\n * The text color for `bg`, by the Radix rule: white, unless white's contrast\n * on `bg` is under `target`, then a near-black tinted with the hue of `bg`\n * (OKLCH lightness 0.2). When neither reaches `target`, whichever contrasts more.\n */\nexport function onColor(bg: ColorInput, options: OnColorOptions = {}): Color {\n\treturn onColorWith({ componentsIn, wcag2 }, toColor(bg), options)\n}\n\n/**\n * Builds {@link onColor} over the spaces given, plus `srgb`, `xyz-d65`,\n * `oklch` and `oklab`, which WCAG 2 and gamut mapping work in, so a bundle\n * contains only those. It takes a color object, not a string, so it does not\n * carry `parse`. A color in a space not given throws, naming that space.\n */\nexport function createOnColor(...spaces: Space[]): (bg: Color, options?: OnColorOptions) => Color {\n\tconst kit = contrastKit([srgb, xyzD65, oklch, oklab], spaces)\n\treturn (bg, options = {}) => onColorWith(kit, bg, options)\n}\n\nfunction onColorWith({ componentsIn, wcag2 }: ContrastKit, back: Color, options: OnColorOptions): Color {\n\tconst fn = pickFrom(wcag2, options.contrast ?? 'wcag2')\n\tconst target = options.target ?? 4.5\n\tconst white: Color = { colorSpace: 'srgb', components: [1, 1, 1] }\n\tconst whiteScore = Math.abs(fn(white, back))\n\tif (whiteScore >= target) return white\n\tconst hue = componentsIn(back, 'oklch')[2] as number\n\tconst dark = toGamutWith(componentsIn, { colorSpace: 'oklch', components: [0.2, options.chroma ?? 0.03, hue] }, {})\n\treturn Math.abs(fn(dark, back)) >= whiteScore ? dark : white\n}\n"],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ /** The spaces a {@link Color} can be in. Names are the CSS ones. */
2
+ type ColorSpaceId = 'srgb' | 'srgb-linear' | 'hsl' | 'hwb' | 'lab' | 'lch' | 'oklab' | 'oklch' | 'display-p3' | 'display-p3-linear' | 'a98-rgb' | 'prophoto-rgb' | 'rec2020' | 'xyz-d50' | 'xyz-d65';
3
+ /** A component value. `null` stands for the CSS keyword `none`. */
4
+ type Component = number | null;
5
+ /**
6
+ * A color as plain JSON. Component ranges follow CSS: `srgb` is 0 to 1, `hsl`
7
+ * and `hwb` take hue in degrees and the rest in 0 to 100, `lab` and `lch` take
8
+ * L in 0 to 100, `oklab` and `oklch` take L in 0 to 1. A missing `alpha` is 1.
9
+ */
10
+ interface Color {
11
+ colorSpace: ColorSpaceId;
12
+ components: Component[];
13
+ alpha?: Component;
14
+ }
15
+ /** Three numbers: the components of a color without alpha, or a point in XYZ. */
16
+ type Vec3 = [number, number, number];
17
+ /** A color space, defined by its conversion to and from the XYZ-D65 hub. */
18
+ interface Space {
19
+ id: ColorSpaceId;
20
+ toXyz(c: Vec3): Vec3;
21
+ fromXyz(xyz: Vec3): Vec3;
22
+ }
23
+ /**
24
+ * A contrast measure: `(fg, bg) => number`, plus what a caller needs to use it
25
+ * without knowing the algorithm. Any plain `(fg, bg) => number` also works
26
+ * wherever a `ContrastFn` is taken; the extra fields are optional.
27
+ */
28
+ interface ContrastFn {
29
+ (fg: Color, bg: Color): number;
30
+ /** A label for messages and output, for example `wcag2`. */
31
+ readonly algorithm?: string;
32
+ /** Named targets, for example `{ AA: 4.5 }`, which `meets` accepts as a level. */
33
+ readonly thresholds?: Readonly<Record<string, number>>;
34
+ /** `symmetric` when swapping fg and bg gives the same number; `signed` when the sign says which is lighter. */
35
+ readonly polarity?: 'symmetric' | 'signed';
36
+ }
37
+ /** The contrast algorithms built in. */
38
+ type ContrastAlgorithm = 'wcag2';
39
+ /** Either a built-in name or a {@link ContrastFn}. */
40
+ type ContrastOption = ContrastAlgorithm | ContrastFn;
41
+ type ColorInput = Color | string;
42
+ /**
43
+ * WCAG 2 contrast ratio, 1 to 21. A translucent `fg` is laid over `bg` first;
44
+ * `bg` is taken as opaque.
45
+ */
46
+ declare const wcag2: ContrastFn;
47
+ /**
48
+ * Contrast of `fg` on `bg`. Colors may be CSS strings. The default is WCAG 2;
49
+ * pass a {@link ContrastFn} to use another measure (see the APCA recipe).
50
+ */
51
+ declare function contrast(fg: ColorInput, bg: ColorInput, algo?: ContrastOption): number;
52
+ /**
53
+ * Builds {@link contrast} over the spaces given, plus `srgb` and `xyz-d65`,
54
+ * which WCAG 2 works in, so a bundle contains only those. It takes color
55
+ * objects, not strings, so it does not carry `parse`. A color in a space not
56
+ * given throws, naming that space.
57
+ */
58
+ declare function createContrast(...spaces: Space[]): (fg: Color, bg: Color, algo?: ContrastOption) => number;
59
+ /**
60
+ * True when `fg` on `bg` reaches `level`: a number, or a name from the
61
+ * algorithm's thresholds (WCAG 2: `AA`, `AA-large`, `AAA`, `AAA-large`,
62
+ * `non-text`). A signed measure such as APCA is compared by magnitude.
63
+ */
64
+ declare function meets(fg: ColorInput, bg: ColorInput, level: number | string, algo?: ContrastOption): boolean;
65
+ /**
66
+ * Builds {@link meets} over the spaces given, plus `srgb` and `xyz-d65`, which
67
+ * WCAG 2 works in, so a bundle contains only those. It takes color objects,
68
+ * not strings, so it does not carry `parse`. A color in a space not given
69
+ * throws, naming that space.
70
+ */
71
+ declare function createMeets(...spaces: Space[]): (fg: Color, bg: Color, level: number | string, algo?: ContrastOption) => boolean;
72
+ /** Options for `findContrast` and the function `createFindContrast` returns. */
73
+ interface FindContrastOptions {
74
+ /** Hue of the result, in OKLCH degrees. Default: the hue of `bg`. */
75
+ hue?: number;
76
+ /** Chroma of the result, in OKLCH. Default 0. The result is mapped into the gamut. */
77
+ chroma?: number;
78
+ /** Which way to look first from `bg`. Default: darker on a light `bg`, lighter on a dark one. */
79
+ direction?: 'lighter' | 'darker';
80
+ /** Default `wcag2`. */
81
+ contrast?: ContrastOption;
82
+ }
83
+ /** What `findContrast` returns: the color it found and whether it reached the target. */
84
+ interface FoundContrast {
85
+ /** The color, in `srgb` and inside the gamut. */
86
+ color: Color;
87
+ /** The contrast it achieves against `bg`, as the algorithm reports it. */
88
+ contrast: number;
89
+ /** False when no lightness reaches `target`; `color` is then the best one found. */
90
+ met: boolean;
91
+ }
92
+ /**
93
+ * Finds the color closest in lightness to `bg` (OKLCH L, at the given hue and
94
+ * chroma) that reaches `target` contrast against it, by binary search. It looks
95
+ * the preferred way first, then the other. The returned `contrast` is measured
96
+ * on the final, gamut-mapped color, and `met` says whether it reaches `target`.
97
+ */
98
+ declare function findContrast(bg: ColorInput, target: number, options?: FindContrastOptions): FoundContrast;
99
+ /**
100
+ * Builds {@link findContrast} over the spaces given, plus `srgb`, `xyz-d65`,
101
+ * `oklch` and `oklab`, which WCAG 2 and gamut mapping work in, so a bundle
102
+ * contains only those. It takes a color object, not a string, so it does not
103
+ * carry `parse`. A color in a space not given throws, naming that space.
104
+ */
105
+ declare function createFindContrast(...spaces: Space[]): (bg: Color, target: number, options?: FindContrastOptions) => FoundContrast;
106
+ /** Options for `onColor` and the function `createOnColor` returns. */
107
+ interface OnColorOptions {
108
+ /** The contrast the text needs. Default 4.5 for WCAG 2. */
109
+ target?: number;
110
+ /** How much of the background's hue the dark text carries, as OKLCH chroma. Default 0.03. */
111
+ chroma?: number;
112
+ /** Default `wcag2`. */
113
+ contrast?: ContrastOption;
114
+ }
115
+ /**
116
+ * The text color for `bg`, by the Radix rule: white, unless white's contrast
117
+ * on `bg` is under `target`, then a near-black tinted with the hue of `bg`
118
+ * (OKLCH lightness 0.2). When neither reaches `target`, whichever contrasts more.
119
+ */
120
+ declare function onColor(bg: ColorInput, options?: OnColorOptions): Color;
121
+ /**
122
+ * Builds {@link onColor} over the spaces given, plus `srgb`, `xyz-d65`,
123
+ * `oklch` and `oklab`, which WCAG 2 and gamut mapping work in, so a bundle
124
+ * contains only those. It takes a color object, not a string, so it does not
125
+ * carry `parse`. A color in a space not given throws, naming that space.
126
+ */
127
+ declare function createOnColor(...spaces: Space[]): (bg: Color, options?: OnColorOptions) => Color;
128
+ /** The bounded RGB spaces a color can be tested or mapped against. */
129
+ type GamutId = 'srgb' | 'srgb-linear' | 'display-p3' | 'display-p3-linear' | 'a98-rgb' | 'prophoto-rgb' | 'rec2020';
130
+ /** True when every channel of `color`, seen in `gamut`, is within 0 to 1 (± `epsilon`). */
131
+ declare function inGamut(color: Color, gamut?: GamutId, epsilon?: number): boolean;
132
+ /**
133
+ * Builds {@link inGamut} over the spaces given, plus `srgb`, so a bundle
134
+ * contains only those. Give the gamut too when it is not `srgb`. A color or
135
+ * gamut in a space not given throws, naming that space.
136
+ */
137
+ declare function createInGamut(...spaces: Space[]): (color: Color, gamut?: GamutId, epsilon?: number) => boolean;
138
+ /** Options for `toGamut` and the function `createToGamut` returns. */
139
+ interface ToGamutOptions {
140
+ /** The gamut to fit into. Default `srgb`. */
141
+ gamut?: GamutId;
142
+ /** `css` is the CSS Color 4 OKLCH chroma reduction. `clip` clamps each channel. Default `css`. */
143
+ method?: 'css' | 'clip';
144
+ }
145
+ /**
146
+ * Maps a color into a gamut and returns it in its original space. `css` follows
147
+ * CSS Color 4 section 13.2: reduce OKLCH chroma until the clipped color is
148
+ * within a just-noticeable ΔEOK of 0.02.
149
+ */
150
+ declare function toGamut(color: Color, options?: ToGamutOptions): Color;
151
+ /**
152
+ * Builds {@link toGamut} over the spaces given, plus `srgb`, `oklch` and
153
+ * `oklab`, which the CSS method works in. Give the gamut too when it is not
154
+ * `srgb`. A color or gamut in a space not given throws, naming that space.
155
+ */
156
+ declare function createToGamut(...spaces: Space[]): (color: Color, options?: ToGamutOptions) => Color;
157
+ export { ColorSpaceId as C, Vec3 as E, Color as S, Space as T, createOnColor as _, inGamut as a, onColor as b, ContrastFn as c, FoundContrast as d, OnColorOptions as f, createMeets as g, createFindContrast as h, createToGamut as i, ContrastOption as l, createContrast as m, ToGamutOptions as n, toGamut as o, contrast as p, createInGamut as r, ContrastAlgorithm as s, GamutId as t, FindContrastOptions as u, findContrast as v, Component as w, wcag2 as x, meets as y };
158
+ //# sourceMappingURL=gamut-CG1J2aat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gamut-CG1J2aat.d.ts","names":[],"sources":["../src/color/types.ts","../src/color/contrast.ts","../src/color/gamut.ts"],"mappings":";KACY;;KAkBA;;;;;;UAOK;EAChB,YAAY;EACZ,YAAY;EACZ,QAAQ;;;KAIG;;UAGK;EAChB,IAAI;EACJ,MAAM,GAAG,OAAO;EAChB,QAAQ,KAAK,OAAO;;;;;;;UCvBJ;GACf,IAAI,OAAO,IAAI;;WAEP;;WAEA,aAAa,SAAS;;WAEtB;;;KAIE;;KAGA,iBAAiB,oBAAoB;KAE5C,aAAa;;;;;cAoBL,OAAO;;;;;iBA8CJ,SAAS,IAAI,YAAY,IAAI,YAAY,OAAM;;;;;;;iBAU/C,kBAAkB,QAAQ,WAAW,IAAI,OAAO,IAAI,OAAO,OAAO;;;;;;iBAUlE,MAAM,IAAI,YAAY,IAAI,YAAY,wBAAwB,OAAM;;;;;;;iBAYpE,eACZ,QAAQ,WACR,IAAI,OAAO,IAAI,OAAO,wBAAwB,OAAO;;UAkBxC;;EAEhB;;EAEA;;EAEA;;EAEA,WAAW;;;UAIK;;EAEhB,OAAO;;EAEP;;EAEA;;;;;;;;iBAWe,aAAa,IAAI,YAAY,gBAAgB,UAAS,sBAA2B;;;;;;;iBAUjF,sBACZ,QAAQ,WACR,IAAI,OAAO,gBAAgB,UAAU,wBAAwB;;UA+ChD;;EAEhB;;EAEA;;EAEA,WAAW;;;;;;;iBAQI,QAAQ,IAAI,YAAY,UAAS,iBAAsB;;;;;;;iBAUvD,iBAAiB,QAAQ,WAAW,IAAI,OAAO,UAAU,mBAAmB;;KC1PhF;;iBAaI,QAAQ,OAAO,OAAO,QAAO,SAAkB;;;;;;iBAS/C,iBAAiB,QAAQ,WAAW,OAAO,OAAO,QAAQ,SAAS;;UAMlE;;EAEhB,QAAQ;;EAER;;;;;;;iBAgBe,QAAQ,OAAO,OAAO,UAAS,iBAAsB;;;;;;iBASrD,iBAAiB,QAAQ,WAAW,OAAO,OAAO,UAAU,mBAAmB"}
@@ -0,0 +1,137 @@
1
+ import { S as Color, l as ContrastOption, t as GamutId } from "./gamut-CG1J2aat.js";
2
+ import { n as MixOptions } from "./mix-DGlKoUw4.js";
3
+ /** Options for `scaleFromBrand`. */
4
+ interface BrandScaleOptions {
5
+ /** `light` runs from a near-white step 1 to dark text; `dark` the other way. Default `light`. */
6
+ mode?: 'light' | 'dark';
7
+ /** The page background, whose lightness step 1 takes. Default near-white, or near-black in `dark`. */
8
+ background?: Color | string;
9
+ /** The gamut steps other than 9 must fit. Default `srgb`. */
10
+ gamut?: GamutId;
11
+ }
12
+ /**
13
+ * A 12-step UI scale from one brand color, after Radix's palette generator:
14
+ * the brand color is step 9 exactly (returned as given, never remapped), steps
15
+ * 1 to 8 run from the background to it, step 10 is its hover state, and steps
16
+ * 11 and 12 are low- and high-contrast text. Hue is the brand's throughout.
17
+ * Radix's generator also borrows the shape of the nearest of its hand-tuned
18
+ * scales; this one uses a single fixed shape instead.
19
+ */
20
+ declare function scaleFromBrand(brand: Color | string, options?: BrandScaleOptions): Color[];
21
+ /** Options for `createContrastScale`. */
22
+ interface ContrastScaleOptions {
23
+ /** The color the scale is built around: its hue and chroma carry to every step. */
24
+ seed: Color | string;
25
+ /** What every step is measured against. */
26
+ background: Color | string;
27
+ /** Target contrast per step, in order, or a record of named targets (`{ text: 7, border: 3 }`). */
28
+ targets: number[] | Record<string, number>;
29
+ /** Default `wcag2`. */
30
+ contrast?: ContrastOption;
31
+ /** Which way to look first from the background. Default: darker on a light background, lighter on a dark one. */
32
+ direction?: 'lighter' | 'darker';
33
+ }
34
+ /** One step of a contrast scale: the target it was given and the color and contrast it got. */
35
+ interface ContrastStep {
36
+ /** The key in a record of targets; otherwise the step's index as a string. */
37
+ name: string;
38
+ target: number;
39
+ color: Color;
40
+ /** The contrast the color achieves, measured on the color itself. */
41
+ contrast: number;
42
+ /** False when no lightness reaches `target`; `color` is then the best one found. */
43
+ met: boolean;
44
+ }
45
+ /**
46
+ * A Leonardo-style scale: each step is the color nearest the background's
47
+ * lightness, at the seed's hue and chroma, that reaches its target contrast.
48
+ * Contrast is the same across hues, which a fixed-lightness scale cannot give.
49
+ */
50
+ declare function createContrastScale(options: ContrastScaleOptions): ContrastStep[];
51
+ /** A color at a position on the gradient line. */
52
+ interface GradientStop {
53
+ /** A CSS color string or a color object. Its alpha is the stop's alpha. */
54
+ color: Color | string;
55
+ /**
56
+ * Where the stop sits, with 0 the start and 1 the end; it may fall outside
57
+ * 0 to 1. Leave it out to spread the stop evenly between its neighbors, as
58
+ * CSS gradients do.
59
+ */
60
+ at?: number;
61
+ }
62
+ /** `in` and `hue` work as they do in `mix()`. The default space is `oklab`. */
63
+ type GradientOptions = MixOptions;
64
+ /**
65
+ * Builds `count` colors, evenly spaced from 0 to 1 along a gradient through
66
+ * `stops`, the way a CSS gradient blends them: each pair of neighboring stops
67
+ * is mixed with `mix()`, so `in` and `hue` work as they do there. A stop is
68
+ * `{ color, at? }`, or a bare color when it needs no position. Before the
69
+ * first stop and after the last, the color holds; where two stops share a
70
+ * position, the color changes there and the sample at that position takes the
71
+ * later stop. Colors come back in the `in` space, default `oklab`.
72
+ *
73
+ * Alpha comes from each stop's color, 1 when the color has none, so
74
+ * `rgb(0 0 255 / 0.2)` is a stop at alpha 0.2. Alpha is interpolated linearly
75
+ * between stops, and the other components are premultiplied by it, so a
76
+ * transparent stop does not pull its neighbor's color toward its own. A color
77
+ * whose alpha is 1 has no `alpha` key; a `none` alpha takes the neighboring
78
+ * stop's.
79
+ *
80
+ * ```ts
81
+ * createGradient([{ color: 'blue', at: 0 }, { color: 'lime', at: 0.6 }, { color: 'yellow', at: 1 }], 72)
82
+ * createGradient(['blue', 'lime'], 5, { in: 'oklch' })
83
+ * ```
84
+ */
85
+ declare function createGradient(stops: readonly (GradientStop | Color | string)[], count: number, options?: GradientOptions): Color[];
86
+ /** The built-in step curves. */
87
+ type ScalePreset = 'tailwind-11' | 'radix-12' | 'tone-13' | 'even';
88
+ /** Options for `createScale`. Only `seed` is required. */
89
+ interface ScaleOptions {
90
+ /** The color the scale is built around. Its hue and chroma set the anchor step. */
91
+ seed: Color | string;
92
+ /**
93
+ * A preset, or a number of steps for an even scale. Default `tailwind-11`.
94
+ * `tone-13` steps are CIE L* tones, so any two steps whose tones differ by
95
+ * 40 reach contrast 3 and by 50 about 4.5.
96
+ */
97
+ steps?: ScalePreset | number;
98
+ /** Overrides the curve's lightness, one per step: OKLCH L 0 to 1 (L* tones 0 to 100 for `tone-13`). */
99
+ lightness?: number[];
100
+ /** Overrides chroma, as a multiplier of the seed's chroma, one per step. */
101
+ chroma?: number[];
102
+ /** Overrides hue drift, as degrees added to the seed's hue, one per step; a number is applied to every step. */
103
+ hueShift?: number[] | number;
104
+ /** The gamut every step must fit. Default `srgb`. */
105
+ gamut?: GamutId;
106
+ }
107
+ /**
108
+ * Builds a scale from light to dark around `seed`: one color per step, in
109
+ * OKLCH, mapped into `gamut`. The preset gives each step's lightness, chroma
110
+ * (relative to the seed's) and hue drift; pass `lightness`, `chroma` or
111
+ * `hueShift` to replace any of them.
112
+ */
113
+ declare function createScale(options: ScaleOptions): Color[];
114
+ /** CIE L* (0 to 100) of a color: its relative luminance on the CIELAB lightness curve. */
115
+ declare function lstar(color: Color): number;
116
+ /** Material's tones: 0 is black, 100 is white. */
117
+ declare const MATERIAL_TONES: readonly number[];
118
+ /** Options for `tonalPalette`. */
119
+ interface TonalPaletteOptions {
120
+ /** The gamut the colors must fit. Default `srgb`. */
121
+ gamut?: GamutId;
122
+ }
123
+ /**
124
+ * The color at CIE L* `tone` with the given OKLCH hue and chroma, mapped into
125
+ * the gamut. OKLCH lightness is searched until the *mapped* color lands on
126
+ * `tone`, so chroma tapers where the gamut narrows and the tone stays true.
127
+ */
128
+ declare function toneColor(tone: number, chroma: number, hue: number, gamut?: GamutId): Color;
129
+ /**
130
+ * A tonal palette, as in Material: one OKLCH hue and chroma held across L*
131
+ * tones. Two colors whose tones differ by 40 or more reach WCAG 2 contrast 3,
132
+ * and by 50 or more about 4.5 (4.48 at the worst pair, 100 against 50), so a
133
+ * pair can be picked by tone alone. Default tones are Material's 13.
134
+ */
135
+ declare function tonalPalette(hue: number, chroma: number, tones?: readonly number[], options?: TonalPaletteOptions): Color[];
136
+ export { toneColor as a, createScale as c, createGradient as d, ContrastScaleOptions as f, scaleFromBrand as g, BrandScaleOptions as h, tonalPalette as i, GradientOptions as l, createContrastScale as m, TonalPaletteOptions as n, ScaleOptions as o, ContrastStep as p, lstar as r, ScalePreset as s, MATERIAL_TONES as t, GradientStop as u };
137
+ //# sourceMappingURL=index-BcEqCPHz.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BcEqCPHz.d.ts","names":[],"sources":["../src/scale/brand.ts","../src/scale/contrast-scale.ts","../src/scale/gradient.ts","../src/scale/scale.ts","../src/scale/tone.ts"],"mappings":";;;UAQiB;;EAEhB;;EAEA,aAAa;;EAEb,QAAQ;;;;;;;;;;iBAgBO,eAAe,OAAO,gBAAgB,UAAS,oBAAyB;;UCxBvE;;EAEhB,MAAM;;EAEN,YAAY;;EAEZ,oBAAoB;;EAEpB,WAAW;;EAEX;;;UAIgB;;EAEhB;EACA;EACA,OAAO;;EAEP;;EAEA;;;;;;;iBAQe,oBAAoB,SAAS,uBAAuB;;UC/BnD;;EAEhB,OAAO;;;;;;EAMP;;;KAIW,kBAAkB;;;;;;;;;;;;;;;;;;;;;;iBAqDd,eACf,iBAAiB,eAAe,mBAChC,eACA,UAAS,kBACP;;KCjES;;UA2DK;;EAEhB,MAAM;;;;;;EAMN,QAAQ;;EAER;;EAEA;;EAEA;;EAEA,QAAQ;;;;;;;;iBAoBO,YAAY,SAAS,eAAe;;iBCnGpC,MAAM,OAAO;;cAMhB;;UAGI;;EAEhB,QAAQ;;;;;;;iBAQO,UAAU,cAAc,gBAAgB,aAAa,QAAO,UAAmB;;;;;;;iBAqC/E,aACf,aACA,gBACA,2BACA,UAAS,sBACP"}