color-map 2.2.0 → 2.3.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 (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 +94 -0
  5. package/README.md +71 -8
  6. package/bin/cli-CNBftDBE.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 +29 -0
  268. package/package.json +276 -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 +2 -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,7 @@
1
+ import { Space } from "./types.js";
2
+ /**
3
+ * The CSS `oklch` space, the polar form of `oklab`. Components are lightness in 0 to 1, chroma (about 0 to 0.4) and hue in degrees.
4
+ * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.
5
+ */
6
+ export declare const oklch: Space;
7
+ //# sourceMappingURL=oklch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oklch.d.ts","names":["_$__types_js0.Space"],"sources":["../../src/color/oklch.ts"],"mappings":";;;;;qBAOa,OAAAA"}
@@ -0,0 +1,11 @@
1
+ import { oklab } from "./oklab.js";
2
+ import { polarSpace } from "./polar.js";
3
+ // src/color/oklch.ts
4
+ /**
5
+ * The CSS `oklch` space, the polar form of `oklab`. Components are lightness in 0 to 1, chroma (about 0 to 0.4) and hue in degrees.
6
+ * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.
7
+ */
8
+ const oklch = polarSpace("oklch", oklab);
9
+ export { oklch };
10
+
11
+ //# sourceMappingURL=oklch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oklch.js","names":[],"sources":["../../src/color/oklch.ts"],"sourcesContent":["import { oklab } from './oklab.js'\nimport { polarSpace } from './polar.js'\n\n/**\n * The CSS `oklch` space, the polar form of `oklab`. Components are lightness in 0 to 1, chroma (about 0 to 0.4) and hue in degrees.\n * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.\n */\nexport const oklch = polarSpace('oklch', oklab)\n"],"mappings":";;;;;;;AAOA,MAAa,QAAQ,WAAW,SAAS,KAAK"}
@@ -0,0 +1,9 @@
1
+ import { Color } from "./types.js";
2
+ /**
3
+ * Parses a CSS Color 4 color: hex, named colors, `transparent`, `rgb()`,
4
+ * `hsl()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()` and `color()`.
5
+ * `none` becomes `null`. Values that need a context (`currentcolor`, system
6
+ * colors) throw, because nothing here can resolve them.
7
+ */
8
+ export declare function parse(input: string): Color;
9
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","names":[],"sources":["../../src/color/parse.ts"],"mappings":";;;;;;;wBA4IgB,MAAM,gBAAgB"}
@@ -0,0 +1,452 @@
1
+ import { namedColor } from "./named.js";
2
+ // src/color/parse.ts
3
+ const NUMBER = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?/;
4
+ const UNITS = {
5
+ __proto__: null,
6
+ "": 1,
7
+ deg: 1,
8
+ grad: .9,
9
+ rad: 180 / Math.PI,
10
+ turn: 360
11
+ };
12
+ function fail(input, what, token) {
13
+ throw new Error(`color-map: cannot parse "${input}": ${what}${token === void 0 ? "" : ` "${token}"`}`);
14
+ }
15
+ function channel(token, spec, input) {
16
+ if (token === "none") return null;
17
+ const m = NUMBER.exec(token);
18
+ if (!m) return fail(input, "invalid value", token);
19
+ const n = Number(m[0]);
20
+ const rest = token.slice(m[0].length);
21
+ let value;
22
+ if (spec.hue) {
23
+ const unit = UNITS[rest];
24
+ if (unit === void 0) return fail(input, "invalid angle", token);
25
+ return n * unit;
26
+ }
27
+ if (rest === "%") value = n * spec.pct / 100;
28
+ else if (rest === "") value = n / (spec.div ?? 1);
29
+ else return fail(input, "invalid value", token);
30
+ return Math.min(spec.max ?? Number.POSITIVE_INFINITY, Math.max(spec.min ?? Number.NEGATIVE_INFINITY, value));
31
+ }
32
+ const SRGB = {
33
+ pct: 1,
34
+ div: 255
35
+ };
36
+ const PCT100 = {
37
+ pct: 100,
38
+ min: 0
39
+ };
40
+ const UNIT = { pct: 1 };
41
+ const ALPHA = {
42
+ pct: 1,
43
+ min: 0,
44
+ max: 1
45
+ };
46
+ const HUE = {
47
+ pct: 0,
48
+ hue: true
49
+ };
50
+ const FUNCTIONS = {
51
+ __proto__: null,
52
+ rgb: {
53
+ space: "srgb",
54
+ channels: [
55
+ SRGB,
56
+ SRGB,
57
+ SRGB
58
+ ]
59
+ },
60
+ hsl: {
61
+ space: "hsl",
62
+ channels: [
63
+ HUE,
64
+ PCT100,
65
+ PCT100
66
+ ]
67
+ },
68
+ hwb: {
69
+ space: "hwb",
70
+ channels: [
71
+ HUE,
72
+ PCT100,
73
+ PCT100
74
+ ]
75
+ },
76
+ lab: {
77
+ space: "lab",
78
+ channels: [
79
+ {
80
+ pct: 100,
81
+ min: 0,
82
+ max: 100
83
+ },
84
+ { pct: 125 },
85
+ { pct: 125 }
86
+ ]
87
+ },
88
+ lch: {
89
+ space: "lch",
90
+ channels: [
91
+ {
92
+ pct: 100,
93
+ min: 0,
94
+ max: 100
95
+ },
96
+ {
97
+ pct: 150,
98
+ min: 0
99
+ },
100
+ HUE
101
+ ]
102
+ },
103
+ oklab: {
104
+ space: "oklab",
105
+ channels: [
106
+ {
107
+ pct: 1,
108
+ min: 0,
109
+ max: 1
110
+ },
111
+ { pct: .4 },
112
+ { pct: .4 }
113
+ ]
114
+ },
115
+ oklch: {
116
+ space: "oklch",
117
+ channels: [
118
+ {
119
+ pct: 1,
120
+ min: 0,
121
+ max: 1
122
+ },
123
+ {
124
+ pct: .4,
125
+ min: 0
126
+ },
127
+ HUE
128
+ ]
129
+ }
130
+ };
131
+ /** The spaces `color()` names, by the name it uses: their own, and `xyz` for `xyz-d65`. */
132
+ const COLOR_SPACES = {
133
+ __proto__: null,
134
+ xyz: "xyz-d65"
135
+ };
136
+ for (const id of [
137
+ "srgb",
138
+ "srgb-linear",
139
+ "display-p3",
140
+ "display-p3-linear",
141
+ "a98-rgb",
142
+ "prophoto-rgb",
143
+ "rec2020",
144
+ "xyz-d50",
145
+ "xyz-d65"
146
+ ]) COLOR_SPACES[id] = id;
147
+ /** `currentcolor` and the CSS Color 4 system colors (canvas, canvastext, linktext, buttonface, ...). */
148
+ const VALUES_NEEDING_RESOLVE = /^(?:currentcolor|(?:canvas|field|highlight|selecteditem|mark|accentcolor)(?:text)?|(?:link|visited|active|button|gray)text|button(?:face|border))$/;
149
+ function hex(input) {
150
+ const digits = input.slice(1);
151
+ if (!/^(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$/.test(digits)) return fail(input, "invalid hex color");
152
+ const full = digits.length < 5 ? [...digits].map((d) => d + d).join("") : digits;
153
+ const byte = (i) => Number.parseInt(full.slice(i * 2, i * 2 + 2), 16) / 255;
154
+ const color = {
155
+ colorSpace: "srgb",
156
+ components: [
157
+ byte(0),
158
+ byte(1),
159
+ byte(2)
160
+ ]
161
+ };
162
+ if (full.length === 8) color.alpha = byte(3);
163
+ return color;
164
+ }
165
+ const ALIASES = {
166
+ __proto__: null,
167
+ rgba: "rgb",
168
+ hsla: "hsl"
169
+ };
170
+ function functional(rawName, body, input) {
171
+ const name = ALIASES[rawName] ?? rawName;
172
+ const [main, alphaToken, ...extra] = body.split("/").map((s) => s.trim());
173
+ if (extra.length > 0) return fail(input, "more than one \"/\"");
174
+ const legacy = main.includes(",");
175
+ const tokens = (legacy ? main.split(",") : main.split(/\s+/)).map((s) => s.trim()).filter(Boolean);
176
+ let alpha = alphaToken;
177
+ if (legacy) {
178
+ if (name !== "rgb" && name !== "hsl") return fail(input, "the comma syntax is only for rgb() and hsl()");
179
+ if (alpha !== void 0) return fail(input, "cannot mix \",\" and \"/\"");
180
+ if (tokens.length === 4) alpha = tokens.pop();
181
+ if (tokens.includes("none")) return fail(input, "\"none\" is not allowed in the comma syntax");
182
+ }
183
+ let space;
184
+ let channels;
185
+ if (name === "color") {
186
+ const id = COLOR_SPACES[tokens.shift() ?? ""];
187
+ if (!id) return fail(input, "unknown color space", main.split(/\s+/)[0]);
188
+ space = id;
189
+ channels = [
190
+ UNIT,
191
+ UNIT,
192
+ UNIT
193
+ ];
194
+ } else {
195
+ const fn = FUNCTIONS[name];
196
+ if (!fn) return fail(input, "unknown function", rawName);
197
+ ({space, channels} = fn);
198
+ }
199
+ if (tokens.length !== 3) return fail(input, `expected 3 components, got ${tokens.length}`);
200
+ if (legacy) {
201
+ const percents = tokens.map((t) => t.endsWith("%"));
202
+ if (!(space === "hsl" ? !percents[0] && percents[1] && percents[2] : percents.every((p) => p === percents[0]))) return fail(input, "mixed numbers and percentages", tokens.join(", "));
203
+ }
204
+ const color = {
205
+ colorSpace: space,
206
+ components: tokens.map((t, i) => channel(t, channels[i], input))
207
+ };
208
+ if (alpha !== void 0) color.alpha = channel(alpha, ALPHA, input);
209
+ return color;
210
+ }
211
+ /**
212
+ * Parses a CSS Color 4 color: hex, named colors, `transparent`, `rgb()`,
213
+ * `hsl()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()` and `color()`.
214
+ * `none` becomes `null`. Values that need a context (`currentcolor`, system
215
+ * colors) throw, because nothing here can resolve them.
216
+ */
217
+ function parse(input) {
218
+ const text = input.trim().toLowerCase();
219
+ return scan(text) ?? parseGeneric(input, text);
220
+ }
221
+ /**
222
+ * The regex-based parser: every accepted form, and every error message. `parse`
223
+ * tries {@link scan} first, which takes only the plain valid forms and leaves
224
+ * the rest, including every error, to this.
225
+ */
226
+ function parseGeneric(input, text) {
227
+ if (text.startsWith("#")) return hex(text);
228
+ const fn = /^([a-z]+)\((.*)\)$/s.exec(text);
229
+ if (fn) return functional(fn[1], fn[2], input);
230
+ if (text === "transparent") return {
231
+ colorSpace: "srgb",
232
+ components: [
233
+ 0,
234
+ 0,
235
+ 0
236
+ ],
237
+ alpha: 0
238
+ };
239
+ const named = namedColor(text);
240
+ if (named !== void 0) return {
241
+ colorSpace: "srgb",
242
+ components: [
243
+ (named >> 16) / 255,
244
+ (named >> 8 & 255) / 255,
245
+ (named & 255) / 255
246
+ ]
247
+ };
248
+ if (VALUES_NEEDING_RESOLVE.test(text)) return fail(input, "needs a context to resolve", text);
249
+ return fail(input, "not a color");
250
+ }
251
+ /** A color as given, or parsed with {@link parse} when it is a string. */
252
+ const toColor = (c) => typeof c === "string" ? parse(c) : c;
253
+ const isSpace = (c) => c === 32 || c === 9 || c === 10 || c === 13 || c === 12;
254
+ const isDigit = (c) => c >= 48 && c <= 57;
255
+ const hexValue = (c) => c >= 48 && c <= 57 ? c - 48 : c >= 97 && c <= 102 ? c - 87 : -1;
256
+ let at = 0;
257
+ let percent = false;
258
+ function scanHex(text) {
259
+ const len = text.length;
260
+ if (len !== 4 && len !== 5 && len !== 7 && len !== 9) return void 0;
261
+ const short = len < 6;
262
+ const count = short ? len - 1 : (len - 1) / 2;
263
+ const bytes = [];
264
+ for (let i = 0; i < count; i++) {
265
+ let value;
266
+ if (short) {
267
+ const d = hexValue(text.charCodeAt(1 + i));
268
+ value = d * 17;
269
+ if (d < 0) return void 0;
270
+ } else {
271
+ const hi = hexValue(text.charCodeAt(1 + i * 2));
272
+ const lo = hexValue(text.charCodeAt(2 + i * 2));
273
+ if (hi < 0 || lo < 0) return void 0;
274
+ value = hi * 16 + lo;
275
+ }
276
+ bytes.push(value / 255);
277
+ }
278
+ const color = {
279
+ colorSpace: "srgb",
280
+ components: [
281
+ bytes[0],
282
+ bytes[1],
283
+ bytes[2]
284
+ ]
285
+ };
286
+ if (count === 4) color.alpha = bytes[3];
287
+ return color;
288
+ }
289
+ /** Skips whitespace from `at` up to `end`. */
290
+ function skip(text, end) {
291
+ while (at < end && isSpace(text.charCodeAt(at))) at++;
292
+ }
293
+ /** The end of the token that starts at `at`: it runs to whitespace, a comma, a slash or `end`. */
294
+ function tokenEnd(text, end) {
295
+ let j = at;
296
+ while (j < end) {
297
+ const c = text.charCodeAt(j);
298
+ if (isSpace(c) || c === 44 || c === 47) break;
299
+ j++;
300
+ }
301
+ return j;
302
+ }
303
+ /**
304
+ * Reads the token at `at` as {@link channel} would, or returns `undefined` when
305
+ * it is anything but a plain valid one. Leaves `at` after the token.
306
+ */
307
+ function scanChannel(text, end, spec) {
308
+ const s = at;
309
+ const e = tokenEnd(text, end);
310
+ at = e;
311
+ if (e === s) return void 0;
312
+ if (e - s === 4 && text.startsWith("none", s)) return null;
313
+ let j = s;
314
+ let c = text.charCodeAt(j);
315
+ if (c === 43 || c === 45) c = text.charCodeAt(++j);
316
+ let digits = 0;
317
+ while (isDigit(c)) {
318
+ c = text.charCodeAt(++j);
319
+ digits++;
320
+ }
321
+ if (c === 46) {
322
+ c = text.charCodeAt(++j);
323
+ while (isDigit(c)) {
324
+ c = text.charCodeAt(++j);
325
+ digits++;
326
+ }
327
+ }
328
+ if (digits === 0) return void 0;
329
+ if (c === 101) {
330
+ let k = j + 1;
331
+ let x = text.charCodeAt(k);
332
+ if (x === 43 || x === 45) x = text.charCodeAt(++k);
333
+ if (isDigit(x)) {
334
+ while (isDigit(text.charCodeAt(k))) k++;
335
+ j = k;
336
+ }
337
+ }
338
+ const n = Number(text.slice(s, j));
339
+ if (spec.hue) {
340
+ const unit = j === e ? 1 : UNITS[text.slice(j, e)];
341
+ return unit === void 0 ? void 0 : n * unit;
342
+ }
343
+ let value;
344
+ if (j === e) value = n / (spec.div ?? 1);
345
+ else if (e - j === 1 && text.charCodeAt(j) === 37) {
346
+ percent = true;
347
+ value = n * spec.pct / 100;
348
+ } else return void 0;
349
+ return Math.min(spec.max ?? Number.POSITIVE_INFINITY, Math.max(spec.min ?? Number.NEGATIVE_INFINITY, value));
350
+ }
351
+ /**
352
+ * Parses the plain valid forms (hex, and the comma or space forms of the
353
+ * functions) by char code, with no regex, split or per-token array. Anything
354
+ * else returns `undefined`, so that {@link parseGeneric} handles it and says
355
+ * why it is wrong.
356
+ */
357
+ function scan(text) {
358
+ if (text.charCodeAt(0) === 35) return scanHex(text);
359
+ const end = text.length - 1;
360
+ if (text.charCodeAt(end) !== 41) return void 0;
361
+ let open = 0;
362
+ while (open < end) {
363
+ const c = text.charCodeAt(open);
364
+ if (c < 97 || c > 122) break;
365
+ open++;
366
+ }
367
+ if (open === 0 || text.charCodeAt(open) !== 40) return void 0;
368
+ const rawName = text.slice(0, open);
369
+ const name = ALIASES[rawName] ?? rawName;
370
+ let space;
371
+ let channels;
372
+ at = open + 1;
373
+ skip(text, end);
374
+ if (name === "color") {
375
+ const s = at;
376
+ while (at < end && !isSpace(text.charCodeAt(at))) at++;
377
+ const id = COLOR_SPACES[text.slice(s, at)];
378
+ if (!id) return void 0;
379
+ space = id;
380
+ channels = [
381
+ UNIT,
382
+ UNIT,
383
+ UNIT
384
+ ];
385
+ skip(text, end);
386
+ } else {
387
+ const fn = FUNCTIONS[name];
388
+ if (!fn) return void 0;
389
+ ({space, channels} = fn);
390
+ }
391
+ percent = false;
392
+ const c0 = scanChannel(text, end, channels[0]);
393
+ if (c0 === void 0) return void 0;
394
+ const p0 = percent;
395
+ skip(text, end);
396
+ const comma = text.charCodeAt(at) === 44;
397
+ if (comma && name !== "rgb" && name !== "hsl") return void 0;
398
+ let alpha;
399
+ let c1;
400
+ let c2;
401
+ let p1 = false;
402
+ let p2 = false;
403
+ if (comma) {
404
+ at++;
405
+ skip(text, end);
406
+ percent = false;
407
+ c1 = scanChannel(text, end, channels[1]);
408
+ p1 = percent;
409
+ skip(text, end);
410
+ if (text.charCodeAt(at++) !== 44) return void 0;
411
+ skip(text, end);
412
+ percent = false;
413
+ c2 = scanChannel(text, end, channels[2]);
414
+ p2 = percent;
415
+ skip(text, end);
416
+ if (c0 === null || c1 === void 0 || c1 === null || c2 === void 0 || c2 === null) return void 0;
417
+ if (!(space === "hsl" ? !p0 && p1 && p2 : p0 === p1 && p1 === p2)) return void 0;
418
+ if (at < end) {
419
+ if (text.charCodeAt(at++) !== 44) return void 0;
420
+ skip(text, end);
421
+ alpha = scanChannel(text, end, ALPHA);
422
+ if (alpha === void 0 || alpha === null) return void 0;
423
+ skip(text, end);
424
+ }
425
+ } else {
426
+ c1 = scanChannel(text, end, channels[1]);
427
+ skip(text, end);
428
+ c2 = scanChannel(text, end, channels[2]);
429
+ skip(text, end);
430
+ if (at < end) {
431
+ if (text.charCodeAt(at++) !== 47) return void 0;
432
+ skip(text, end);
433
+ alpha = scanChannel(text, end, ALPHA);
434
+ if (alpha === void 0) return void 0;
435
+ skip(text, end);
436
+ }
437
+ }
438
+ if (at !== end || c1 === void 0 || c2 === void 0) return void 0;
439
+ const color = {
440
+ colorSpace: space,
441
+ components: [
442
+ c0,
443
+ c1,
444
+ c2
445
+ ]
446
+ };
447
+ if (alpha !== void 0) color.alpha = alpha;
448
+ return color;
449
+ }
450
+ export { ALPHA, COLOR_SPACES, FUNCTIONS, NUMBER, SRGB, UNIT, UNITS, VALUES_NEEDING_RESOLVE, channel, fail, parse, parseGeneric, toColor };
451
+
452
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","names":[],"sources":["../../src/color/parse.ts"],"sourcesContent":["import { namedColor } from './named.js'\nimport type { Color, ColorSpaceId, Component } from './types.js'\n\nexport const NUMBER = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?/\n// Tables keyed by text a caller wrote have no prototype (`__proto__: null`), so `constructor` or `toString` is an unknown name, not Object.prototype's.\nexport const UNITS: Record<string, number> = {\n\t__proto__: null as never,\n\t'': 1,\n\tdeg: 1,\n\tgrad: 0.9,\n\trad: 180 / Math.PI,\n\tturn: 360\n}\n\n/** How one channel reads: what 100% means, and the allowed range. */\nexport interface Channel {\n\t/** The value of 100%. Also the factor applied to a plain number, usually 1. */\n\tpct: number\n\t/** A plain number is divided by this (255 for sRGB channels). */\n\tdiv?: number\n\tmin?: number\n\tmax?: number\n\thue?: boolean\n}\n\nexport function fail(input: string, what: string, token?: string): never {\n\tthrow new Error(`color-map: cannot parse \"${input}\": ${what}${token === undefined ? '' : ` \"${token}\"`}`)\n}\n\nexport function channel(token: string, spec: Channel, input: string): Component {\n\tif (token === 'none') return null\n\tconst m = NUMBER.exec(token)\n\tif (!m) return fail(input, 'invalid value', token)\n\tconst n = Number(m[0])\n\tconst rest = token.slice(m[0].length)\n\tlet value: number\n\tif (spec.hue) {\n\t\tconst unit = UNITS[rest]\n\t\tif (unit === undefined) return fail(input, 'invalid angle', token)\n\t\treturn n * unit\n\t}\n\tif (rest === '%') value = (n * spec.pct) / 100\n\telse if (rest === '') value = n / (spec.div ?? 1)\n\telse return fail(input, 'invalid value', token)\n\treturn Math.min(spec.max ?? Number.POSITIVE_INFINITY, Math.max(spec.min ?? Number.NEGATIVE_INFINITY, value))\n}\n\nexport const SRGB: Channel = { pct: 1, div: 255 }\nconst PCT100: Channel = { pct: 100, min: 0 }\nexport const UNIT: Channel = { pct: 1 }\nexport const ALPHA: Channel = { pct: 1, min: 0, max: 1 }\nconst HUE: Channel = { pct: 0, hue: true }\n\nexport const FUNCTIONS: Record<string, { space: ColorSpaceId; channels: [Channel, Channel, Channel] }> = {\n\t__proto__: null as never,\n\trgb: { space: 'srgb', channels: [SRGB, SRGB, SRGB] },\n\thsl: { space: 'hsl', channels: [HUE, PCT100, PCT100] },\n\thwb: { space: 'hwb', channels: [HUE, PCT100, PCT100] },\n\tlab: { space: 'lab', channels: [{ pct: 100, min: 0, max: 100 }, { pct: 125 }, { pct: 125 }] },\n\tlch: { space: 'lch', channels: [{ pct: 100, min: 0, max: 100 }, { pct: 150, min: 0 }, HUE] },\n\toklab: { space: 'oklab', channels: [{ pct: 1, min: 0, max: 1 }, { pct: 0.4 }, { pct: 0.4 }] },\n\toklch: { space: 'oklch', channels: [{ pct: 1, min: 0, max: 1 }, { pct: 0.4, min: 0 }, HUE] }\n}\n\n/** The spaces `color()` names, by the name it uses: their own, and `xyz` for `xyz-d65`. */\nexport const COLOR_SPACES: Record<string, ColorSpaceId> = { __proto__: null as never, xyz: 'xyz-d65' }\nfor (const id of [\n\t'srgb',\n\t'srgb-linear',\n\t'display-p3',\n\t'display-p3-linear',\n\t'a98-rgb',\n\t'prophoto-rgb',\n\t'rec2020',\n\t'xyz-d50',\n\t'xyz-d65'\n] as const)\n\tCOLOR_SPACES[id] = id\n\n/** `currentcolor` and the CSS Color 4 system colors (canvas, canvastext, linktext, buttonface, ...). */\nexport const VALUES_NEEDING_RESOLVE =\n\t/^(?:currentcolor|(?:canvas|field|highlight|selecteditem|mark|accentcolor)(?:text)?|(?:link|visited|active|button|gray)text|button(?:face|border))$/\n\nfunction hex(input: string): Color {\n\tconst digits = input.slice(1)\n\tif (!/^(?:[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/.test(digits)) return fail(input, 'invalid hex color')\n\tconst full = digits.length < 5 ? [...digits].map((d) => d + d).join('') : digits\n\tconst byte = (i: number): number => Number.parseInt(full.slice(i * 2, i * 2 + 2), 16) / 255\n\tconst color: Color = { colorSpace: 'srgb', components: [byte(0), byte(1), byte(2)] }\n\tif (full.length === 8) color.alpha = byte(3)\n\treturn color\n}\n\nconst ALIASES: Record<string, string> = { __proto__: null as never, rgba: 'rgb', hsla: 'hsl' }\n\nfunction functional(rawName: string, body: string, input: string): Color {\n\tconst name = ALIASES[rawName] ?? rawName\n\tconst [main, alphaToken, ...extra] = body.split('/').map((s) => s.trim())\n\tif (extra.length > 0) return fail(input, 'more than one \"/\"')\n\tconst legacy = main.includes(',')\n\tconst tokens = (legacy ? main.split(',') : main.split(/\\s+/)).map((s) => s.trim()).filter(Boolean)\n\tlet alpha = alphaToken\n\tif (legacy) {\n\t\tif (name !== 'rgb' && name !== 'hsl') return fail(input, 'the comma syntax is only for rgb() and hsl()')\n\t\tif (alpha !== undefined) return fail(input, 'cannot mix \",\" and \"/\"')\n\t\tif (tokens.length === 4) alpha = tokens.pop() as string\n\t\tif (tokens.includes('none')) return fail(input, '\"none\" is not allowed in the comma syntax')\n\t}\n\tlet space: ColorSpaceId\n\tlet channels: [Channel, Channel, Channel]\n\tif (name === 'color') {\n\t\tconst id = COLOR_SPACES[tokens.shift() ?? '']\n\t\tif (!id) return fail(input, 'unknown color space', main.split(/\\s+/)[0])\n\t\tspace = id\n\t\tchannels = [UNIT, UNIT, UNIT]\n\t} else {\n\t\tconst fn = FUNCTIONS[name]\n\t\tif (!fn) return fail(input, 'unknown function', rawName)\n\t\t;({ space, channels } = fn)\n\t}\n\tif (tokens.length !== 3) return fail(input, `expected 3 components, got ${tokens.length}`)\n\tif (legacy) {\n\t\tconst percents = tokens.map((t) => t.endsWith('%'))\n\t\tconst ok = space === 'hsl' ? !percents[0] && percents[1] && percents[2] : percents.every((p) => p === percents[0])\n\t\tif (!ok) return fail(input, 'mixed numbers and percentages', tokens.join(', '))\n\t}\n\tconst color: Color = {\n\t\tcolorSpace: space,\n\t\tcomponents: tokens.map((t, i) => channel(t, channels[i], input))\n\t}\n\tif (alpha !== undefined) color.alpha = channel(alpha, ALPHA, input)\n\treturn color\n}\n\n/**\n * Parses a CSS Color 4 color: hex, named colors, `transparent`, `rgb()`,\n * `hsl()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()` and `color()`.\n * `none` becomes `null`. Values that need a context (`currentcolor`, system\n * colors) throw, because nothing here can resolve them.\n */\nexport function parse(input: string): Color {\n\tconst text = input.trim().toLowerCase()\n\treturn scan(text) ?? parseGeneric(input, text)\n}\n\n/**\n * The regex-based parser: every accepted form, and every error message. `parse`\n * tries {@link scan} first, which takes only the plain valid forms and leaves\n * the rest, including every error, to this.\n */\nexport function parseGeneric(input: string, text: string): Color {\n\tif (text.startsWith('#')) return hex(text)\n\tconst fn = /^([a-z]+)\\((.*)\\)$/s.exec(text)\n\tif (fn) return functional(fn[1], fn[2], input)\n\tif (text === 'transparent') return { colorSpace: 'srgb', components: [0, 0, 0], alpha: 0 }\n\tconst named = namedColor(text)\n\tif (named !== undefined) {\n\t\treturn { colorSpace: 'srgb', components: [(named >> 16) / 255, ((named >> 8) & 255) / 255, (named & 255) / 255] }\n\t}\n\tif (VALUES_NEEDING_RESOLVE.test(text)) return fail(input, 'needs a context to resolve', text)\n\treturn fail(input, 'not a color')\n}\n\n/** A color as given, or parsed with {@link parse} when it is a string. */\nexport const toColor = (c: Color | string): Color => (typeof c === 'string' ? parse(c) : c)\n\n// --- The scanner: a char-code fast path for hex and the functional forms ---\n\nconst isSpace = (c: number): boolean => c === 32 || c === 9 || c === 10 || c === 13 || c === 12\nconst isDigit = (c: number): boolean => c >= 48 && c <= 57\nconst hexValue = (c: number): number => (c >= 48 && c <= 57 ? c - 48 : c >= 97 && c <= 102 ? c - 87 : -1)\n\n// Scanner state, shared across calls: `parse` is synchronous and does not re-enter.\nlet at = 0\nlet percent = false\n\nfunction scanHex(text: string): Color | undefined {\n\tconst len = text.length\n\tif (len !== 4 && len !== 5 && len !== 7 && len !== 9) return undefined\n\tconst short = len < 6\n\tconst count = short ? len - 1 : (len - 1) / 2\n\tconst bytes: number[] = []\n\tfor (let i = 0; i < count; i++) {\n\t\tlet value: number\n\t\tif (short) {\n\t\t\tconst d = hexValue(text.charCodeAt(1 + i))\n\t\t\tvalue = d * 17\n\t\t\tif (d < 0) return undefined\n\t\t} else {\n\t\t\tconst hi = hexValue(text.charCodeAt(1 + i * 2))\n\t\t\tconst lo = hexValue(text.charCodeAt(2 + i * 2))\n\t\t\tif (hi < 0 || lo < 0) return undefined\n\t\t\tvalue = hi * 16 + lo\n\t\t}\n\t\tbytes.push(value / 255)\n\t}\n\tconst color: Color = { colorSpace: 'srgb', components: [bytes[0], bytes[1], bytes[2]] }\n\tif (count === 4) color.alpha = bytes[3]\n\treturn color\n}\n\n/** Skips whitespace from `at` up to `end`. */\nfunction skip(text: string, end: number): void {\n\twhile (at < end && isSpace(text.charCodeAt(at))) at++\n}\n\n/** The end of the token that starts at `at`: it runs to whitespace, a comma, a slash or `end`. */\nfunction tokenEnd(text: string, end: number): number {\n\tlet j = at\n\twhile (j < end) {\n\t\tconst c = text.charCodeAt(j)\n\t\tif (isSpace(c) || c === 44 || c === 47) break\n\t\tj++\n\t}\n\treturn j\n}\n\n/**\n * Reads the token at `at` as {@link channel} would, or returns `undefined` when\n * it is anything but a plain valid one. Leaves `at` after the token.\n */\nfunction scanChannel(text: string, end: number, spec: Channel): Component | undefined {\n\tconst s = at\n\tconst e = tokenEnd(text, end)\n\tat = e\n\tif (e === s) return undefined\n\tif (e - s === 4 && text.startsWith('none', s)) return null\n\tlet j = s\n\tlet c = text.charCodeAt(j)\n\tif (c === 43 || c === 45) c = text.charCodeAt(++j)\n\tlet digits = 0\n\twhile (isDigit(c)) {\n\t\tc = text.charCodeAt(++j)\n\t\tdigits++\n\t}\n\tif (c === 46) {\n\t\tc = text.charCodeAt(++j)\n\t\twhile (isDigit(c)) {\n\t\t\tc = text.charCodeAt(++j)\n\t\t\tdigits++\n\t\t}\n\t}\n\tif (digits === 0) return undefined\n\tif (c === 101) {\n\t\tlet k = j + 1\n\t\tlet x = text.charCodeAt(k)\n\t\tif (x === 43 || x === 45) x = text.charCodeAt(++k)\n\t\tif (isDigit(x)) {\n\t\t\twhile (isDigit(text.charCodeAt(k))) k++\n\t\t\tj = k\n\t\t}\n\t}\n\tconst n = Number(text.slice(s, j))\n\tif (spec.hue) {\n\t\tconst unit = j === e ? 1 : UNITS[text.slice(j, e)]\n\t\treturn unit === undefined ? undefined : n * unit\n\t}\n\tlet value: number\n\tif (j === e) value = n / (spec.div ?? 1)\n\telse if (e - j === 1 && text.charCodeAt(j) === 37) {\n\t\tpercent = true\n\t\tvalue = (n * spec.pct) / 100\n\t} else return undefined\n\treturn Math.min(spec.max ?? Number.POSITIVE_INFINITY, Math.max(spec.min ?? Number.NEGATIVE_INFINITY, value))\n}\n\n/**\n * Parses the plain valid forms (hex, and the comma or space forms of the\n * functions) by char code, with no regex, split or per-token array. Anything\n * else returns `undefined`, so that {@link parseGeneric} handles it and says\n * why it is wrong.\n */\nfunction scan(text: string): Color | undefined {\n\tif (text.charCodeAt(0) === 35) return scanHex(text)\n\tconst end = text.length - 1\n\tif (text.charCodeAt(end) !== 41) return undefined\n\tlet open = 0\n\twhile (open < end) {\n\t\tconst c = text.charCodeAt(open)\n\t\tif (c < 97 || c > 122) break\n\t\topen++\n\t}\n\tif (open === 0 || text.charCodeAt(open) !== 40) return undefined\n\tconst rawName = text.slice(0, open)\n\tconst name = ALIASES[rawName] ?? rawName\n\tlet space: ColorSpaceId\n\tlet channels: [Channel, Channel, Channel]\n\tat = open + 1\n\tskip(text, end)\n\tif (name === 'color') {\n\t\tconst s = at\n\t\twhile (at < end && !isSpace(text.charCodeAt(at))) at++\n\t\tconst id = COLOR_SPACES[text.slice(s, at)]\n\t\tif (!id) return undefined\n\t\tspace = id\n\t\tchannels = [UNIT, UNIT, UNIT]\n\t\tskip(text, end)\n\t} else {\n\t\tconst fn = FUNCTIONS[name]\n\t\tif (!fn) return undefined\n\t\t;({ space, channels } = fn)\n\t}\n\tpercent = false\n\tconst c0 = scanChannel(text, end, channels[0])\n\tif (c0 === undefined) return undefined\n\tconst p0 = percent\n\tskip(text, end)\n\tconst comma = text.charCodeAt(at) === 44\n\tif (comma && name !== 'rgb' && name !== 'hsl') return undefined\n\tlet alpha: Component | undefined\n\tlet c1: Component | undefined\n\tlet c2: Component | undefined\n\tlet p1 = false\n\tlet p2 = false\n\tif (comma) {\n\t\tat++\n\t\tskip(text, end)\n\t\tpercent = false\n\t\tc1 = scanChannel(text, end, channels[1])\n\t\tp1 = percent\n\t\tskip(text, end)\n\t\tif (text.charCodeAt(at++) !== 44) return undefined\n\t\tskip(text, end)\n\t\tpercent = false\n\t\tc2 = scanChannel(text, end, channels[2])\n\t\tp2 = percent\n\t\tskip(text, end)\n\t\tif (c0 === null || c1 === undefined || c1 === null || c2 === undefined || c2 === null) return undefined\n\t\tconst ok = space === 'hsl' ? !p0 && p1 && p2 : p0 === p1 && p1 === p2\n\t\tif (!ok) return undefined\n\t\tif (at < end) {\n\t\t\tif (text.charCodeAt(at++) !== 44) return undefined\n\t\t\tskip(text, end)\n\t\t\talpha = scanChannel(text, end, ALPHA)\n\t\t\tif (alpha === undefined || alpha === null) return undefined\n\t\t\tskip(text, end)\n\t\t}\n\t} else {\n\t\tc1 = scanChannel(text, end, channels[1])\n\t\tskip(text, end)\n\t\tc2 = scanChannel(text, end, channels[2])\n\t\tskip(text, end)\n\t\tif (at < end) {\n\t\t\tif (text.charCodeAt(at++) !== 47) return undefined\n\t\t\tskip(text, end)\n\t\t\talpha = scanChannel(text, end, ALPHA)\n\t\t\tif (alpha === undefined) return undefined\n\t\t\tskip(text, end)\n\t\t}\n\t}\n\tif (at !== end || c1 === undefined || c2 === undefined) return undefined\n\tconst color: Color = { colorSpace: space, components: [c0, c1, c2] }\n\tif (alpha !== undefined) color.alpha = alpha\n\treturn color\n}\n"],"mappings":";;AAGA,MAAa,SAAS;AAEtB,MAAa,QAAgC;CAC5C,WAAW;CACX,IAAI;CACJ,KAAK;CACL,MAAM;CACN,KAAK,MAAM,KAAK;CAChB,MAAM;AACP;AAaA,SAAgB,KAAK,OAAe,MAAc,OAAuB;CACxE,MAAM,IAAI,MAAM,4BAA4B,MAAM,KAAK,OAAO,UAAU,KAAA,IAAY,KAAK,KAAK,MAAM,IAAI;AACzG;AAEA,SAAgB,QAAQ,OAAe,MAAe,OAA0B;CAC/E,IAAI,UAAU,QAAQ,OAAO;CAC7B,MAAM,IAAI,OAAO,KAAK,KAAK;CAC3B,IAAI,CAAC,GAAG,OAAO,KAAK,OAAO,iBAAiB,KAAK;CACjD,MAAM,IAAI,OAAO,EAAE,EAAE;CACrB,MAAM,OAAO,MAAM,MAAM,EAAE,EAAE,CAAC,MAAM;CACpC,IAAI;CACJ,IAAI,KAAK,KAAK;EACb,MAAM,OAAO,MAAM;EACnB,IAAI,SAAS,KAAA,GAAW,OAAO,KAAK,OAAO,iBAAiB,KAAK;EACjE,OAAO,IAAI;CACZ;CACA,IAAI,SAAS,KAAK,QAAS,IAAI,KAAK,MAAO;MACtC,IAAI,SAAS,IAAI,QAAQ,KAAK,KAAK,OAAO;MAC1C,OAAO,KAAK,OAAO,iBAAiB,KAAK;CAC9C,OAAO,KAAK,IAAI,KAAK,OAAO,OAAO,mBAAmB,KAAK,IAAI,KAAK,OAAO,OAAO,mBAAmB,KAAK,CAAC;AAC5G;AAEA,MAAa,OAAgB;CAAE,KAAK;CAAG,KAAK;AAAI;AAChD,MAAM,SAAkB;CAAE,KAAK;CAAK,KAAK;AAAE;AAC3C,MAAa,OAAgB,EAAE,KAAK,EAAE;AACtC,MAAa,QAAiB;CAAE,KAAK;CAAG,KAAK;CAAG,KAAK;AAAE;AACvD,MAAM,MAAe;CAAE,KAAK;CAAG,KAAK;AAAK;AAEzC,MAAa,YAA4F;CACxG,WAAW;CACX,KAAK;EAAE,OAAO;EAAQ,UAAU;GAAC;GAAM;GAAM;EAAI;CAAE;CACnD,KAAK;EAAE,OAAO;EAAO,UAAU;GAAC;GAAK;GAAQ;EAAM;CAAE;CACrD,KAAK;EAAE,OAAO;EAAO,UAAU;GAAC;GAAK;GAAQ;EAAM;CAAE;CACrD,KAAK;EAAE,OAAO;EAAO,UAAU;GAAC;IAAE,KAAK;IAAK,KAAK;IAAG,KAAK;GAAI;GAAG,EAAE,KAAK,IAAI;GAAG,EAAE,KAAK,IAAI;EAAC;CAAE;CAC5F,KAAK;EAAE,OAAO;EAAO,UAAU;GAAC;IAAE,KAAK;IAAK,KAAK;IAAG,KAAK;GAAI;GAAG;IAAE,KAAK;IAAK,KAAK;GAAE;GAAG;EAAG;CAAE;CAC3F,OAAO;EAAE,OAAO;EAAS,UAAU;GAAC;IAAE,KAAK;IAAG,KAAK;IAAG,KAAK;GAAE;GAAG,EAAE,KAAK,GAAI;GAAG,EAAE,KAAK,GAAI;EAAC;CAAE;CAC5F,OAAO;EAAE,OAAO;EAAS,UAAU;GAAC;IAAE,KAAK;IAAG,KAAK;IAAG,KAAK;GAAE;GAAG;IAAE,KAAK;IAAK,KAAK;GAAE;GAAG;EAAG;CAAE;AAC5F;;AAGA,MAAa,eAA6C;CAAE,WAAW;CAAe,KAAK;AAAU;AACrG,KAAK,MAAM,MAAM;CAChB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,GACC,aAAa,MAAM;;AAGpB,MAAa,yBACZ;AAED,SAAS,IAAI,OAAsB;CAClC,MAAM,SAAS,MAAM,MAAM,CAAC;CAC5B,IAAI,CAAC,2CAA2C,KAAK,MAAM,GAAG,OAAO,KAAK,OAAO,mBAAmB;CACpG,MAAM,OAAO,OAAO,SAAS,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI;CAC1E,MAAM,QAAQ,MAAsB,OAAO,SAAS,KAAK,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI;CACxF,MAAM,QAAe;EAAE,YAAY;EAAQ,YAAY;GAAC,KAAK,CAAC;GAAG,KAAK,CAAC;GAAG,KAAK,CAAC;EAAC;CAAE;CACnF,IAAI,KAAK,WAAW,GAAG,MAAM,QAAQ,KAAK,CAAC;CAC3C,OAAO;AACR;AAEA,MAAM,UAAkC;CAAE,WAAW;CAAe,MAAM;CAAO,MAAM;AAAM;AAE7F,SAAS,WAAW,SAAiB,MAAc,OAAsB;CACxE,MAAM,OAAO,QAAQ,YAAY;CACjC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;CACxE,IAAI,MAAM,SAAS,GAAG,OAAO,KAAK,OAAO,qBAAmB;CAC5D,MAAM,SAAS,KAAK,SAAS,GAAG;CAChC,MAAM,UAAU,SAAS,KAAK,MAAM,GAAG,IAAI,KAAK,MAAM,KAAK,EAAA,CAAG,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO;CACjG,IAAI,QAAQ;CACZ,IAAI,QAAQ;EACX,IAAI,SAAS,SAAS,SAAS,OAAO,OAAO,KAAK,OAAO,8CAA8C;EACvG,IAAI,UAAU,KAAA,GAAW,OAAO,KAAK,OAAO,4BAAwB;EACpE,IAAI,OAAO,WAAW,GAAG,QAAQ,OAAO,IAAI;EAC5C,IAAI,OAAO,SAAS,MAAM,GAAG,OAAO,KAAK,OAAO,6CAA2C;CAC5F;CACA,IAAI;CACJ,IAAI;CACJ,IAAI,SAAS,SAAS;EACrB,MAAM,KAAK,aAAa,OAAO,MAAM,KAAK;EAC1C,IAAI,CAAC,IAAI,OAAO,KAAK,OAAO,uBAAuB,KAAK,MAAM,KAAK,CAAC,CAAC,EAAE;EACvE,QAAQ;EACR,WAAW;GAAC;GAAM;GAAM;EAAI;CAC7B,OAAO;EACN,MAAM,KAAK,UAAU;EACrB,IAAI,CAAC,IAAI,OAAO,KAAK,OAAO,oBAAoB,OAAO;EACtD,CAAC,CAAE,OAAO,YAAa;CACzB;CACA,IAAI,OAAO,WAAW,GAAG,OAAO,KAAK,OAAO,8BAA8B,OAAO,QAAQ;CACzF,IAAI,QAAQ;EACX,MAAM,WAAW,OAAO,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC;EAElD,IAAI,EADO,UAAU,QAAQ,CAAC,SAAS,MAAM,SAAS,MAAM,SAAS,KAAK,SAAS,OAAO,MAAM,MAAM,SAAS,EAAE,IACxG,OAAO,KAAK,OAAO,iCAAiC,OAAO,KAAK,IAAI,CAAC;CAC/E;CACA,MAAM,QAAe;EACpB,YAAY;EACZ,YAAY,OAAO,KAAK,GAAG,MAAM,QAAQ,GAAG,SAAS,IAAI,KAAK,CAAC;CAChE;CACA,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ,QAAQ,OAAO,OAAO,KAAK;CAClE,OAAO;AACR;;;;;;;AAQA,SAAgB,MAAM,OAAsB;CAC3C,MAAM,OAAO,MAAM,KAAK,CAAC,CAAC,YAAY;CACtC,OAAO,KAAK,IAAI,KAAK,aAAa,OAAO,IAAI;AAC9C;;;;;;AAOA,SAAgB,aAAa,OAAe,MAAqB;CAChE,IAAI,KAAK,WAAW,GAAG,GAAG,OAAO,IAAI,IAAI;CACzC,MAAM,KAAK,sBAAsB,KAAK,IAAI;CAC1C,IAAI,IAAI,OAAO,WAAW,GAAG,IAAI,GAAG,IAAI,KAAK;CAC7C,IAAI,SAAS,eAAe,OAAO;EAAE,YAAY;EAAQ,YAAY;GAAC;GAAG;GAAG;EAAC;EAAG,OAAO;CAAE;CACzF,MAAM,QAAQ,WAAW,IAAI;CAC7B,IAAI,UAAU,KAAA,GACb,OAAO;EAAE,YAAY;EAAQ,YAAY;IAAE,SAAS,MAAM;IAAO,SAAS,IAAK,OAAO;IAAM,QAAQ,OAAO;EAAG;CAAE;CAEjH,IAAI,uBAAuB,KAAK,IAAI,GAAG,OAAO,KAAK,OAAO,8BAA8B,IAAI;CAC5F,OAAO,KAAK,OAAO,aAAa;AACjC;;AAGA,MAAa,WAAW,MAA8B,OAAO,MAAM,WAAW,MAAM,CAAC,IAAI;AAIzF,MAAM,WAAW,MAAuB,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM;AAC7F,MAAM,WAAW,MAAuB,KAAK,MAAM,KAAK;AACxD,MAAM,YAAY,MAAuB,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK;AAGtG,IAAI,KAAK;AACT,IAAI,UAAU;AAEd,SAAS,QAAQ,MAAiC;CACjD,MAAM,MAAM,KAAK;CACjB,IAAI,QAAQ,KAAK,QAAQ,KAAK,QAAQ,KAAK,QAAQ,GAAG,OAAO,KAAA;CAC7D,MAAM,QAAQ,MAAM;CACpB,MAAM,QAAQ,QAAQ,MAAM,KAAK,MAAM,KAAK;CAC5C,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;EAC/B,IAAI;EACJ,IAAI,OAAO;GACV,MAAM,IAAI,SAAS,KAAK,WAAW,IAAI,CAAC,CAAC;GACzC,QAAQ,IAAI;GACZ,IAAI,IAAI,GAAG,OAAO,KAAA;EACnB,OAAO;GACN,MAAM,KAAK,SAAS,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC;GAC9C,MAAM,KAAK,SAAS,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC;GAC9C,IAAI,KAAK,KAAK,KAAK,GAAG,OAAO,KAAA;GAC7B,QAAQ,KAAK,KAAK;EACnB;EACA,MAAM,KAAK,QAAQ,GAAG;CACvB;CACA,MAAM,QAAe;EAAE,YAAY;EAAQ,YAAY;GAAC,MAAM;GAAI,MAAM;GAAI,MAAM;EAAE;CAAE;CACtF,IAAI,UAAU,GAAG,MAAM,QAAQ,MAAM;CACrC,OAAO;AACR;;AAGA,SAAS,KAAK,MAAc,KAAmB;CAC9C,OAAO,KAAK,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC,GAAG;AAClD;;AAGA,SAAS,SAAS,MAAc,KAAqB;CACpD,IAAI,IAAI;CACR,OAAO,IAAI,KAAK;EACf,MAAM,IAAI,KAAK,WAAW,CAAC;EAC3B,IAAI,QAAQ,CAAC,KAAK,MAAM,MAAM,MAAM,IAAI;EACxC;CACD;CACA,OAAO;AACR;;;;;AAMA,SAAS,YAAY,MAAc,KAAa,MAAsC;CACrF,MAAM,IAAI;CACV,MAAM,IAAI,SAAS,MAAM,GAAG;CAC5B,KAAK;CACL,IAAI,MAAM,GAAG,OAAO,KAAA;CACpB,IAAI,IAAI,MAAM,KAAK,KAAK,WAAW,QAAQ,CAAC,GAAG,OAAO;CACtD,IAAI,IAAI;CACR,IAAI,IAAI,KAAK,WAAW,CAAC;CACzB,IAAI,MAAM,MAAM,MAAM,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;CACjD,IAAI,SAAS;CACb,OAAO,QAAQ,CAAC,GAAG;EAClB,IAAI,KAAK,WAAW,EAAE,CAAC;EACvB;CACD;CACA,IAAI,MAAM,IAAI;EACb,IAAI,KAAK,WAAW,EAAE,CAAC;EACvB,OAAO,QAAQ,CAAC,GAAG;GAClB,IAAI,KAAK,WAAW,EAAE,CAAC;GACvB;EACD;CACD;CACA,IAAI,WAAW,GAAG,OAAO,KAAA;CACzB,IAAI,MAAM,KAAK;EACd,IAAI,IAAI,IAAI;EACZ,IAAI,IAAI,KAAK,WAAW,CAAC;EACzB,IAAI,MAAM,MAAM,MAAM,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;EACjD,IAAI,QAAQ,CAAC,GAAG;GACf,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,GAAG;GACpC,IAAI;EACL;CACD;CACA,MAAM,IAAI,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC;CACjC,IAAI,KAAK,KAAK;EACb,MAAM,OAAO,MAAM,IAAI,IAAI,MAAM,KAAK,MAAM,GAAG,CAAC;EAChD,OAAO,SAAS,KAAA,IAAY,KAAA,IAAY,IAAI;CAC7C;CACA,IAAI;CACJ,IAAI,MAAM,GAAG,QAAQ,KAAK,KAAK,OAAO;MACjC,IAAI,IAAI,MAAM,KAAK,KAAK,WAAW,CAAC,MAAM,IAAI;EAClD,UAAU;EACV,QAAS,IAAI,KAAK,MAAO;CAC1B,OAAO,OAAO,KAAA;CACd,OAAO,KAAK,IAAI,KAAK,OAAO,OAAO,mBAAmB,KAAK,IAAI,KAAK,OAAO,OAAO,mBAAmB,KAAK,CAAC;AAC5G;;;;;;;AAQA,SAAS,KAAK,MAAiC;CAC9C,IAAI,KAAK,WAAW,CAAC,MAAM,IAAI,OAAO,QAAQ,IAAI;CAClD,MAAM,MAAM,KAAK,SAAS;CAC1B,IAAI,KAAK,WAAW,GAAG,MAAM,IAAI,OAAO,KAAA;CACxC,IAAI,OAAO;CACX,OAAO,OAAO,KAAK;EAClB,MAAM,IAAI,KAAK,WAAW,IAAI;EAC9B,IAAI,IAAI,MAAM,IAAI,KAAK;EACvB;CACD;CACA,IAAI,SAAS,KAAK,KAAK,WAAW,IAAI,MAAM,IAAI,OAAO,KAAA;CACvD,MAAM,UAAU,KAAK,MAAM,GAAG,IAAI;CAClC,MAAM,OAAO,QAAQ,YAAY;CACjC,IAAI;CACJ,IAAI;CACJ,KAAK,OAAO;CACZ,KAAK,MAAM,GAAG;CACd,IAAI,SAAS,SAAS;EACrB,MAAM,IAAI;EACV,OAAO,KAAK,OAAO,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC,GAAG;EAClD,MAAM,KAAK,aAAa,KAAK,MAAM,GAAG,EAAE;EACxC,IAAI,CAAC,IAAI,OAAO,KAAA;EAChB,QAAQ;EACR,WAAW;GAAC;GAAM;GAAM;EAAI;EAC5B,KAAK,MAAM,GAAG;CACf,OAAO;EACN,MAAM,KAAK,UAAU;EACrB,IAAI,CAAC,IAAI,OAAO,KAAA;EACf,CAAC,CAAE,OAAO,YAAa;CACzB;CACA,UAAU;CACV,MAAM,KAAK,YAAY,MAAM,KAAK,SAAS,EAAE;CAC7C,IAAI,OAAO,KAAA,GAAW,OAAO,KAAA;CAC7B,MAAM,KAAK;CACX,KAAK,MAAM,GAAG;CACd,MAAM,QAAQ,KAAK,WAAW,EAAE,MAAM;CACtC,IAAI,SAAS,SAAS,SAAS,SAAS,OAAO,OAAO,KAAA;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,KAAK;CACT,IAAI,KAAK;CACT,IAAI,OAAO;EACV;EACA,KAAK,MAAM,GAAG;EACd,UAAU;EACV,KAAK,YAAY,MAAM,KAAK,SAAS,EAAE;EACvC,KAAK;EACL,KAAK,MAAM,GAAG;EACd,IAAI,KAAK,WAAW,IAAI,MAAM,IAAI,OAAO,KAAA;EACzC,KAAK,MAAM,GAAG;EACd,UAAU;EACV,KAAK,YAAY,MAAM,KAAK,SAAS,EAAE;EACvC,KAAK;EACL,KAAK,MAAM,GAAG;EACd,IAAI,OAAO,QAAQ,OAAO,KAAA,KAAa,OAAO,QAAQ,OAAO,KAAA,KAAa,OAAO,MAAM,OAAO,KAAA;EAE9F,IAAI,EADO,UAAU,QAAQ,CAAC,MAAM,MAAM,KAAK,OAAO,MAAM,OAAO,KAC1D,OAAO,KAAA;EAChB,IAAI,KAAK,KAAK;GACb,IAAI,KAAK,WAAW,IAAI,MAAM,IAAI,OAAO,KAAA;GACzC,KAAK,MAAM,GAAG;GACd,QAAQ,YAAY,MAAM,KAAK,KAAK;GACpC,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO,KAAA;GAClD,KAAK,MAAM,GAAG;EACf;CACD,OAAO;EACN,KAAK,YAAY,MAAM,KAAK,SAAS,EAAE;EACvC,KAAK,MAAM,GAAG;EACd,KAAK,YAAY,MAAM,KAAK,SAAS,EAAE;EACvC,KAAK,MAAM,GAAG;EACd,IAAI,KAAK,KAAK;GACb,IAAI,KAAK,WAAW,IAAI,MAAM,IAAI,OAAO,KAAA;GACzC,KAAK,MAAM,GAAG;GACd,QAAQ,YAAY,MAAM,KAAK,KAAK;GACpC,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;GAChC,KAAK,MAAM,GAAG;EACf;CACD;CACA,IAAI,OAAO,OAAO,OAAO,KAAA,KAAa,OAAO,KAAA,GAAW,OAAO,KAAA;CAC/D,MAAM,QAAe;EAAE,YAAY;EAAO,YAAY;GAAC;GAAI;GAAI;EAAE;CAAE;CACnE,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;CACvC,OAAO;AACR"}
@@ -0,0 +1,27 @@
1
+ import { normalizeHue } from "./math.js";
2
+ // src/color/polar.ts
3
+ /** Wraps a rectangular Lab-like space as its polar (LCH-like) twin. */
4
+ function polarSpace(id, base) {
5
+ return {
6
+ id,
7
+ toXyz: ([l, c, h]) => {
8
+ const r = h * Math.PI / 180;
9
+ return base.toXyz([
10
+ l,
11
+ c * Math.cos(r),
12
+ c * Math.sin(r)
13
+ ]);
14
+ },
15
+ fromXyz: (xyz) => {
16
+ const [l, a, b] = base.fromXyz(xyz);
17
+ return [
18
+ l,
19
+ Math.hypot(a, b),
20
+ normalizeHue(Math.atan2(b, a) * 180 / Math.PI)
21
+ ];
22
+ }
23
+ };
24
+ }
25
+ export { polarSpace };
26
+
27
+ //# sourceMappingURL=polar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polar.js","names":[],"sources":["../../src/color/polar.ts"],"sourcesContent":["import { normalizeHue } from './math.js'\nimport type { Space } from './types.js'\n\n/** Wraps a rectangular Lab-like space as its polar (LCH-like) twin. */\nexport function polarSpace(id: 'lch' | 'oklch', base: Space): Space {\n\treturn {\n\t\tid,\n\t\ttoXyz: ([l, c, h]) => {\n\t\t\tconst r = (h * Math.PI) / 180\n\t\t\treturn base.toXyz([l, c * Math.cos(r), c * Math.sin(r)])\n\t\t},\n\t\tfromXyz: (xyz) => {\n\t\t\tconst [l, a, b] = base.fromXyz(xyz)\n\t\t\treturn [l, Math.hypot(a, b), normalizeHue((Math.atan2(b, a) * 180) / Math.PI)]\n\t\t}\n\t}\n}\n"],"mappings":";;;AAIA,SAAgB,WAAW,IAAqB,MAAoB;CACnE,OAAO;EACN;EACA,QAAQ,CAAC,GAAG,GAAG,OAAO;GACrB,MAAM,IAAK,IAAI,KAAK,KAAM;GAC1B,OAAO,KAAK,MAAM;IAAC;IAAG,IAAI,KAAK,IAAI,CAAC;IAAG,IAAI,KAAK,IAAI,CAAC;GAAC,CAAC;EACxD;EACA,UAAU,QAAQ;GACjB,MAAM,CAAC,GAAG,GAAG,KAAK,KAAK,QAAQ,GAAG;GAClC,OAAO;IAAC;IAAG,KAAK,MAAM,GAAG,CAAC;IAAG,aAAc,KAAK,MAAM,GAAG,CAAC,IAAI,MAAO,KAAK,EAAE;GAAC;EAC9E;CACD;AACD"}
@@ -0,0 +1,7 @@
1
+ import { Space } from "./types.js";
2
+ /**
3
+ * The CSS `prophoto-rgb` space. Components are red, green and blue in 0 to 1. It is defined against a D50 white and converted through `xyzD50`.
4
+ * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.
5
+ */
6
+ export declare const prophotoRgb: Space;
7
+ //# sourceMappingURL=prophoto-rgb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prophoto-rgb.d.ts","names":[],"sources":["../../src/color/prophoto-rgb.ts"],"mappings":";;;;;qBAaa,aAAa"}
@@ -0,0 +1,18 @@
1
+ import { prophotoToXyzD50, xyzD50ToProphoto } from "./matrices.js";
2
+ import { rgbSpace } from "./rgb.js";
3
+ import { prophotoToGamma, prophotoToLinear } from "./transfer.js";
4
+ import { xyzD50 } from "./xyz-d50.js";
5
+ // src/color/prophoto-rgb.ts
6
+ const d50 = rgbSpace("prophoto-rgb", prophotoToLinear, prophotoToGamma, prophotoToXyzD50, xyzD50ToProphoto);
7
+ /**
8
+ * The CSS `prophoto-rgb` space. Components are red, green and blue in 0 to 1. It is defined against a D50 white and converted through `xyzD50`.
9
+ * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.
10
+ */
11
+ const prophotoRgb = {
12
+ id: "prophoto-rgb",
13
+ toXyz: (c) => xyzD50.toXyz(d50.toXyz(c)),
14
+ fromXyz: (xyz) => d50.fromXyz(xyzD50.fromXyz(xyz))
15
+ };
16
+ export { prophotoRgb };
17
+
18
+ //# sourceMappingURL=prophoto-rgb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prophoto-rgb.js","names":[],"sources":["../../src/color/prophoto-rgb.ts"],"sourcesContent":["import { prophotoToXyzD50, xyzD50ToProphoto } from './matrices.js'\nimport { rgbSpace } from './rgb.js'\nimport { prophotoToGamma, prophotoToLinear } from './transfer.js'\nimport type { Space } from './types.js'\nimport { xyzD50 } from './xyz-d50.js'\n\n// ProPhoto's matrices lead to XYZ-D50, so it goes through that space on the way to the hub.\nconst d50 = rgbSpace('prophoto-rgb', prophotoToLinear, prophotoToGamma, prophotoToXyzD50, xyzD50ToProphoto)\n\n/**\n * The CSS `prophoto-rgb` space. Components are red, green and blue in 0 to 1. It is defined against a D50 white and converted through `xyzD50`.\n * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.\n */\nexport const prophotoRgb: Space = {\n\tid: 'prophoto-rgb',\n\ttoXyz: (c) => xyzD50.toXyz(d50.toXyz(c)),\n\tfromXyz: (xyz) => d50.fromXyz(xyzD50.fromXyz(xyz))\n}\n"],"mappings":";;;;;AAOA,MAAM,MAAM,SAAS,gBAAgB,kBAAkB,iBAAiB,kBAAkB,gBAAgB;;;;;AAM1G,MAAa,cAAqB;CACjC,IAAI;CACJ,QAAQ,MAAM,OAAO,MAAM,IAAI,MAAM,CAAC,CAAC;CACvC,UAAU,QAAQ,IAAI,QAAQ,OAAO,QAAQ,GAAG,CAAC;AAClD"}
@@ -0,0 +1,7 @@
1
+ import { Space } from "./types.js";
2
+ /**
3
+ * The CSS `rec2020` space. Components are red, green and blue in 0 to 1, with a 2.4 power transfer curve.
4
+ * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.
5
+ */
6
+ export declare const rec2020: Space;
7
+ //# sourceMappingURL=rec2020.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rec2020.d.ts","names":["_$__types_js0.Space"],"sources":["../../src/color/rec2020.ts"],"mappings":";;;;;qBAUa,SAAAA"}
@@ -0,0 +1,13 @@
1
+ import { rec2020ToXyz, xyzToRec2020 } from "./matrices.js";
2
+ import { rgbSpace } from "./rgb.js";
3
+ import { power } from "./transfer.js";
4
+ // src/color/rec2020.ts
5
+ const [toLinear, toGamma] = power(2.4);
6
+ /**
7
+ * The CSS `rec2020` space. Components are red, green and blue in 0 to 1, with a 2.4 power transfer curve.
8
+ * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.
9
+ */
10
+ const rec2020 = rgbSpace("rec2020", toLinear, toGamma, rec2020ToXyz, xyzToRec2020);
11
+ export { rec2020 };
12
+
13
+ //# sourceMappingURL=rec2020.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rec2020.js","names":[],"sources":["../../src/color/rec2020.ts"],"sourcesContent":["import { rec2020ToXyz, xyzToRec2020 } from './matrices.js'\nimport { rgbSpace } from './rgb.js'\nimport { power } from './transfer.js'\n\nconst [toLinear, toGamma] = power(2.4)\n\n/**\n * The CSS `rec2020` space. Components are red, green and blue in 0 to 1, with a 2.4 power transfer curve.\n * Pass it to `createConverter` and to the narrow helpers such as `createMix` and `createToGamut`.\n */\nexport const rec2020 = rgbSpace('rec2020', toLinear, toGamma, rec2020ToXyz, xyzToRec2020)\n"],"mappings":";;;;AAIA,MAAM,CAAC,UAAU,WAAW,MAAM,GAAG;;;;;AAMrC,MAAa,UAAU,SAAS,WAAW,UAAU,SAAS,cAAc,YAAY"}
@@ -0,0 +1,18 @@
1
+ import { ColorExpr } from "./expr.js";
2
+ import { Color } from "./types.js";
3
+ /** What `resolve` needs from its surroundings to settle `currentcolor`, `light-dark()` and system colors. */
4
+ export interface ResolveContext {
5
+ /** What `currentcolor` means. */
6
+ currentColor?: string | ColorExpr;
7
+ /** Which side `light-dark()` takes. Default `light`. */
8
+ colorScheme?: 'light' | 'dark';
9
+ /** What each system color (`canvas`, `buttontext`, ...) means, by lowercase name. */
10
+ systemColors?: Record<string, string | ColorExpr>;
11
+ }
12
+ /**
13
+ * Turns a color, a CSS string or a {@link ColorExpr} into a concrete {@link Color}.
14
+ * `currentcolor`, system colors and `light-dark()` read `context`; nothing is
15
+ * guessed, so a missing entry throws and names the value.
16
+ */
17
+ export declare function resolve(input: string | ColorExpr, context?: ResolveContext): Color;
18
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","names":[],"sources":["../../src/color/resolve.ts"],"mappings":";;;iBASiB;;EAEhB,wBAAwB;;EAExB;;EAEA,eAAe,wBAAwB;;;;;;;wBA2DxB,QAAQ,gBAAgB,WAAW,UAAS,iBAAsB"}