@sportsdataverse/sdvplot 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +109 -0
  3. package/README.md +984 -2
  4. package/dist/_web-D7Aa5Rd8.d.ts +69 -0
  5. package/dist/aaf-GJ3SH34T.js +13 -0
  6. package/dist/aaf-HCYN5T6Y.js +37 -0
  7. package/dist/aaf-ZAE5KS2Y.js +13 -0
  8. package/dist/ahl-E66MDVCU.js +66 -0
  9. package/dist/ahl-NPQQWZEV.js +249 -0
  10. package/dist/ahl-QRDU73XX.js +309 -0
  11. package/dist/axis-CraWQRUJ.d.ts +49 -0
  12. package/dist/bins.d.ts +174 -0
  13. package/dist/bins.js +4 -0
  14. package/dist/bins.js.map +1 -0
  15. package/dist/cfb-F42SVS4X.js +5000 -0
  16. package/dist/cfb-P3SHEYRZ.js +692 -0
  17. package/dist/cfb-WXRZANLP.js +10226 -0
  18. package/dist/chartjs-surface.d.ts +42 -0
  19. package/dist/chartjs-surface.js +65 -0
  20. package/dist/chartjs-surface.js.map +1 -0
  21. package/dist/chartjs.d.ts +162 -0
  22. package/dist/chartjs.js +342 -0
  23. package/dist/chartjs.js.map +1 -0
  24. package/dist/chunk-4C3GX6QO.js +92 -0
  25. package/dist/chunk-4C3GX6QO.js.map +1 -0
  26. package/dist/chunk-57WFSI4Q.js +128 -0
  27. package/dist/chunk-57WFSI4Q.js.map +1 -0
  28. package/dist/chunk-7ULOCCFL.js +313 -0
  29. package/dist/chunk-7ULOCCFL.js.map +1 -0
  30. package/dist/chunk-AMXASQHT.js +120 -0
  31. package/dist/chunk-AMXASQHT.js.map +1 -0
  32. package/dist/chunk-B2MP37SR.js +175 -0
  33. package/dist/chunk-B2MP37SR.js.map +1 -0
  34. package/dist/chunk-C2CDY5OG.js +137 -0
  35. package/dist/chunk-C2CDY5OG.js.map +1 -0
  36. package/dist/chunk-DYMUVE6K.js +127 -0
  37. package/dist/chunk-DYMUVE6K.js.map +1 -0
  38. package/dist/chunk-E7G7VSLV.js +43 -0
  39. package/dist/chunk-E7G7VSLV.js.map +1 -0
  40. package/dist/chunk-H2C3FMMA.js +300 -0
  41. package/dist/chunk-H2C3FMMA.js.map +1 -0
  42. package/dist/chunk-J4P4HDBF.js +175 -0
  43. package/dist/chunk-J4P4HDBF.js.map +1 -0
  44. package/dist/chunk-J6R2LEJ7.js +58 -0
  45. package/dist/chunk-J6R2LEJ7.js.map +1 -0
  46. package/dist/chunk-M3XD2OSN.js +132 -0
  47. package/dist/chunk-M3XD2OSN.js.map +1 -0
  48. package/dist/chunk-OIILARXI.js +30 -0
  49. package/dist/chunk-OIILARXI.js.map +1 -0
  50. package/dist/chunk-RPVVJY74.js +170 -0
  51. package/dist/chunk-RPVVJY74.js.map +1 -0
  52. package/dist/chunk-UL5M6KDE.js +205 -0
  53. package/dist/chunk-UL5M6KDE.js.map +1 -0
  54. package/dist/chunk-WQT4IVLX.js +10 -0
  55. package/dist/chunk-WQT4IVLX.js.map +1 -0
  56. package/dist/chunk-ZAEQXFJM.js +556 -0
  57. package/dist/chunk-ZAEQXFJM.js.map +1 -0
  58. package/dist/cricket-KPCYG2HL.js +493 -0
  59. package/dist/cricket-NDXLE25B.js +116 -0
  60. package/dist/cricket-YUUF7P6M.js +160 -0
  61. package/dist/cytoscape.d.ts +188 -0
  62. package/dist/cytoscape.js +219 -0
  63. package/dist/cytoscape.js.map +1 -0
  64. package/dist/d3.d.ts +234 -0
  65. package/dist/d3.js +198 -0
  66. package/dist/d3.js.map +1 -0
  67. package/dist/deckgl.d.ts +232 -0
  68. package/dist/deckgl.js +197 -0
  69. package/dist/deckgl.js.map +1 -0
  70. package/dist/echarts.d.ts +121 -0
  71. package/dist/echarts.js +228 -0
  72. package/dist/echarts.js.map +1 -0
  73. package/dist/echl-3CR4RGFC.js +241 -0
  74. package/dist/echl-NPC32C23.js +107 -0
  75. package/dist/echl-PI33DGJC.js +64 -0
  76. package/dist/export.d.ts +130 -0
  77. package/dist/export.js +258 -0
  78. package/dist/export.js.map +1 -0
  79. package/dist/g2.d.ts +251 -0
  80. package/dist/g2.js +102 -0
  81. package/dist/g2.js.map +1 -0
  82. package/dist/headshots-B2J_LOO8.d.ts +40 -0
  83. package/dist/index.d.ts +183 -0
  84. package/dist/index.js +9 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/interact.d.ts +567 -0
  87. package/dist/interact.js +809 -0
  88. package/dist/interact.js.map +1 -0
  89. package/dist/lightweight-charts.d.ts +217 -0
  90. package/dist/lightweight-charts.js +155 -0
  91. package/dist/lightweight-charts.js.map +1 -0
  92. package/dist/maplibre.d.ts +271 -0
  93. package/dist/maplibre.js +175 -0
  94. package/dist/maplibre.js.map +1 -0
  95. package/dist/marks-DH-tQIP-.d.ts +75 -0
  96. package/dist/mbb-3TRLVW3H.js +3619 -0
  97. package/dist/mbb-DQUHCHZP.js +5111 -0
  98. package/dist/mbb-PRAIO2P5.js +371 -0
  99. package/dist/milb-6IQ6NCEW.js +291 -0
  100. package/dist/milb-EYY5MD4T.js +1752 -0
  101. package/dist/milb-EYZ4SZLI.js +797 -0
  102. package/dist/mlb-4PBUJSVQ.js +35 -0
  103. package/dist/mlb-FHPY3GQJ.js +701 -0
  104. package/dist/mlb-REVGL3N2.js +665 -0
  105. package/dist/mui.d.ts +338 -0
  106. package/dist/mui.js +184 -0
  107. package/dist/mui.js.map +1 -0
  108. package/dist/nba-ATT775GS.js +485 -0
  109. package/dist/nba-LKM4UHVU.js +482 -0
  110. package/dist/nba-YX7PXM3R.js +35 -0
  111. package/dist/nbagl-3WGZCZ4S.js +37 -0
  112. package/dist/nbagl-LP4XJRAL.js +229 -0
  113. package/dist/nbagl-VTTOU7LN.js +499 -0
  114. package/dist/ncaa_baseball-UV75LNVR.js +2670 -0
  115. package/dist/ncaa_baseball-VD5J5C72.js +419 -0
  116. package/dist/ncaa_baseball-YRBS32D6.js +4592 -0
  117. package/dist/ncaa_mhockey-IMYHS7QS.js +1033 -0
  118. package/dist/ncaa_mhockey-TXTKWHE3.js +115 -0
  119. package/dist/ncaa_mhockey-U3MFW5VT.js +663 -0
  120. package/dist/ncaa_softball-6WR6KS64.js +420 -0
  121. package/dist/ncaa_softball-RZCTIE56.js +2654 -0
  122. package/dist/ncaa_softball-VOD4PVGY.js +4599 -0
  123. package/dist/ncaa_whockey-6XXGUTBK.js +607 -0
  124. package/dist/ncaa_whockey-AKKYKY67.js +53 -0
  125. package/dist/ncaa_whockey-KBEKXFBB.js +293 -0
  126. package/dist/nfl-BDB2HYAR.js +625 -0
  127. package/dist/nfl-EHYHDLJD.js +37 -0
  128. package/dist/nfl-VF4NJCHY.js +514 -0
  129. package/dist/nfl_gsis-UY64JO37.js +4 -0
  130. package/dist/nhl-6WPHME7H.js +511 -0
  131. package/dist/nhl-EMIJFZHY.js +884 -0
  132. package/dist/nhl-ISFUKRFU.js +37 -0
  133. package/dist/nivo.d.ts +193 -0
  134. package/dist/nivo.js +8 -0
  135. package/dist/nivo.js.map +1 -0
  136. package/dist/ohl-2FEM554G.js +113 -0
  137. package/dist/ohl-C5Q4W6JB.js +32 -0
  138. package/dist/ohl-TQ4J46VC.js +66 -0
  139. package/dist/perspective.d.ts +198 -0
  140. package/dist/perspective.js +171 -0
  141. package/dist/perspective.js.map +1 -0
  142. package/dist/phf-H7POU2KW.js +32 -0
  143. package/dist/phf-K5IFMZUM.js +13 -0
  144. package/dist/phf-TWJI3BOW.js +20 -0
  145. package/dist/placement-UWkqUzpa.d.ts +32 -0
  146. package/dist/plot.d.ts +451 -0
  147. package/dist/plot.js +712 -0
  148. package/dist/plot.js.map +1 -0
  149. package/dist/plotly.d.ts +129 -0
  150. package/dist/plotly.js +360 -0
  151. package/dist/plotly.js.map +1 -0
  152. package/dist/pwhl-OX3BO4JI.js +53 -0
  153. package/dist/pwhl-W44OC3C6.js +17 -0
  154. package/dist/pwhl-ZJGG3H7W.js +23 -0
  155. package/dist/qmjhl-5HISEHLL.js +35 -0
  156. package/dist/qmjhl-DA3UHKE5.js +125 -0
  157. package/dist/qmjhl-YG4BOQPF.js +614 -0
  158. package/dist/react.d.ts +377 -0
  159. package/dist/react.js +522 -0
  160. package/dist/react.js.map +1 -0
  161. package/dist/recharts.d.ts +162 -0
  162. package/dist/recharts.js +8 -0
  163. package/dist/recharts.js.map +1 -0
  164. package/dist/resolve-CQW-jzvr.d.ts +28 -0
  165. package/dist/selection-D4T3PkRt.d.ts +140 -0
  166. package/dist/shadcn.d.ts +83 -0
  167. package/dist/shadcn.js +88 -0
  168. package/dist/shadcn.js.map +1 -0
  169. package/dist/shots.d.ts +364 -0
  170. package/dist/shots.js +86 -0
  171. package/dist/shots.js.map +1 -0
  172. package/dist/soccer-7BH3ZLVL.js +7898 -0
  173. package/dist/soccer-MRU25OGE.js +2636 -0
  174. package/dist/soccer-PF4IPPVA.js +12342 -0
  175. package/dist/surface-TR7YFJW3.js +4 -0
  176. package/dist/surface-TR7YFJW3.js.map +1 -0
  177. package/dist/surfaces-MIG7HOFU.js +6 -0
  178. package/dist/surfaces-MIG7HOFU.js.map +1 -0
  179. package/dist/surfaces-W-odWLpT.d.ts +47 -0
  180. package/dist/svelte/HeadshotMark.svelte +25 -0
  181. package/dist/svelte/HeadshotMark.svelte.d.ts +10 -0
  182. package/dist/svelte/HeadshotMark.svelte.d.ts.map +1 -0
  183. package/dist/svelte/LogoMark.svelte +25 -0
  184. package/dist/svelte/LogoMark.svelte.d.ts +10 -0
  185. package/dist/svelte/LogoMark.svelte.d.ts.map +1 -0
  186. package/dist/svelte/Marks.svelte +25 -0
  187. package/dist/svelte/Marks.svelte.d.ts +10 -0
  188. package/dist/svelte/Marks.svelte.d.ts.map +1 -0
  189. package/dist/svelte/Surface.svelte +29 -0
  190. package/dist/svelte/Surface.svelte.d.ts +9 -0
  191. package/dist/svelte/Surface.svelte.d.ts.map +1 -0
  192. package/dist/svelte/SurfaceBackdrop.svelte +26 -0
  193. package/dist/svelte/SurfaceBackdrop.svelte.d.ts +11 -0
  194. package/dist/svelte/SurfaceBackdrop.svelte.d.ts.map +1 -0
  195. package/dist/svelte/index.d.ts +13 -0
  196. package/dist/svelte/index.d.ts.map +1 -0
  197. package/dist/svelte/index.js +11 -0
  198. package/dist/svelte-core.d.ts +139 -0
  199. package/dist/svelte-core.js +123 -0
  200. package/dist/svelte-core.js.map +1 -0
  201. package/dist/tanstack.d.ts +240 -0
  202. package/dist/tanstack.js +110 -0
  203. package/dist/tanstack.js.map +1 -0
  204. package/dist/testing.d.ts +75 -0
  205. package/dist/testing.js +239 -0
  206. package/dist/testing.js.map +1 -0
  207. package/dist/three.d.ts +223 -0
  208. package/dist/three.js +50 -0
  209. package/dist/three.js.map +1 -0
  210. package/dist/tiers-BN4md-GB.d.ts +65 -0
  211. package/dist/types-C7n6gJF3.d.ts +62 -0
  212. package/dist/ufl-7VLZTLTT.js +143 -0
  213. package/dist/ufl-CCMBLPSW.js +100 -0
  214. package/dist/ufl-F2BJRXME.js +16 -0
  215. package/dist/unovis.d.ts +127 -0
  216. package/dist/unovis.js +108 -0
  217. package/dist/unovis.js.map +1 -0
  218. package/dist/uplot.d.ts +120 -0
  219. package/dist/uplot.js +110 -0
  220. package/dist/uplot.js.map +1 -0
  221. package/dist/usfl-4CR5RMZJ.js +32 -0
  222. package/dist/usfl-LD7HP2YK.js +14 -0
  223. package/dist/usfl-VU4YSJQD.js +19 -0
  224. package/dist/ushl-CPG2LB4L.js +73 -0
  225. package/dist/ushl-PQL6HJAD.js +88 -0
  226. package/dist/ushl-ZT2ATPHK.js +22 -0
  227. package/dist/vega.d.ts +85 -0
  228. package/dist/vega.js +362 -0
  229. package/dist/vega.js.map +1 -0
  230. package/dist/victory.d.ts +107 -0
  231. package/dist/victory.js +38 -0
  232. package/dist/victory.js.map +1 -0
  233. package/dist/wbb-3KHCDYTK.js +5087 -0
  234. package/dist/wbb-BMX53Q3Q.js +369 -0
  235. package/dist/wbb-QNRN2CJJ.js +3620 -0
  236. package/dist/whl-4ATYZWUB.js +97 -0
  237. package/dist/whl-RVFPL6MH.js +79 -0
  238. package/dist/whl-Y7ASKYMM.js +28 -0
  239. package/dist/wnba-FWX5SFVI.js +232 -0
  240. package/dist/wnba-GX6HZR4B.js +220 -0
  241. package/dist/wnba-NTMWIPP6.js +20 -0
  242. package/dist/xfl-43R2JMJK.js +30 -0
  243. package/dist/xfl-H3BXQPZZ.js +16 -0
  244. package/dist/xfl-XON7A7FI.js +69 -0
  245. package/package.json +366 -3
@@ -0,0 +1,58 @@
1
+ import { InputError } from './chunk-E7G7VSLV.js';
2
+
3
+ // src/contrast.ts
4
+ function hex6(color, opts = {}) {
5
+ let c = String(color).trim().replace(/^#+/, "");
6
+ if (c.length === 3 || c.length === 4) c = [...c].map((ch) => ch + ch).join("");
7
+ if (c.length !== 6 && c.length !== 8 || !/^[0-9a-fA-F]+$/.test(c))
8
+ throw new InputError(`not a hex color: ${JSON.stringify(color)}`);
9
+ if (c.length === 8 && c.slice(6).toLowerCase() !== "ff" && !opts.dropAlpha)
10
+ throw new InputError(
11
+ `${JSON.stringify(color)} has transparency; give an opaque color such as '#${c.slice(0, 6).toLowerCase()}'`
12
+ );
13
+ return `#${c.slice(0, 6).toLowerCase()}`;
14
+ }
15
+ var channels = (c) => [
16
+ Number.parseInt(c.slice(1, 3), 16),
17
+ Number.parseInt(c.slice(3, 5), 16),
18
+ Number.parseInt(c.slice(5, 7), 16)
19
+ ];
20
+ function luminance(color) {
21
+ const [r, g, b] = channels(hex6(color)).map((v) => {
22
+ const s = v / 255;
23
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
24
+ });
25
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
26
+ }
27
+ function contrast(a, b) {
28
+ const la = luminance(a);
29
+ const lb = luminance(b);
30
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
31
+ }
32
+ function onColor(background) {
33
+ return contrast("#000000", background) >= contrast("#ffffff", background) ? "#000000" : "#ffffff";
34
+ }
35
+ function roundHalfEven(x) {
36
+ const f = Math.floor(x);
37
+ const d = x - f;
38
+ return d > 0.5 || d === 0.5 && f % 2 !== 0 ? f + 1 : f;
39
+ }
40
+ function mix(a, b, t) {
41
+ if (!(t >= 0 && t <= 1)) throw new InputError(`t must be in [0, 1], got ${t}`);
42
+ const ca = channels(hex6(a));
43
+ const cb = channels(hex6(b));
44
+ return `#${ca.map(
45
+ (v, i) => roundHalfEven(v * (1 - t) + cb[i] * t).toString(16).padStart(2, "0")
46
+ ).join("")}`;
47
+ }
48
+ function solid(color, background = "#ffffff") {
49
+ const opaque = hex6(color, { dropAlpha: true });
50
+ let c = String(color).trim().replace(/^#+/, "");
51
+ if (c.length === 4) c = [...c].map((ch) => ch + ch).join("");
52
+ const alpha = c.length === 8 ? Number.parseInt(c.slice(6), 16) / 255 : 1;
53
+ return mix(background, opaque, alpha);
54
+ }
55
+
56
+ export { contrast, hex6, luminance, mix, onColor, roundHalfEven, solid };
57
+ //# sourceMappingURL=chunk-J6R2LEJ7.js.map
58
+ //# sourceMappingURL=chunk-J6R2LEJ7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/contrast.ts"],"names":[],"mappings":"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","file":"chunk-J6R2LEJ7.js","sourcesContent":["import { InputError } from \"./errors.js\";\n\n/** A color as lowercase `#rrggbb`: accepts `#rgb`, `#rrggbb`, `#rgba`, `#rrggbbaa` (`#` optional). Transparency throws unless `dropAlpha`. */\nexport function hex6(color: string, opts: { dropAlpha?: boolean } = {}): string {\n let c = String(color).trim().replace(/^#+/, \"\");\n if (c.length === 3 || c.length === 4) c = [...c].map((ch) => ch + ch).join(\"\");\n if ((c.length !== 6 && c.length !== 8) || !/^[0-9a-fA-F]+$/.test(c))\n throw new InputError(`not a hex color: ${JSON.stringify(color)}`);\n if (c.length === 8 && c.slice(6).toLowerCase() !== \"ff\" && !opts.dropAlpha)\n throw new InputError(\n `${JSON.stringify(color)} has transparency; give an opaque color such as '#${c.slice(0, 6).toLowerCase()}'`,\n );\n return `#${c.slice(0, 6).toLowerCase()}`;\n}\n\nconst channels = (c: string): [number, number, number] => [\n Number.parseInt(c.slice(1, 3), 16),\n Number.parseInt(c.slice(3, 5), 16),\n Number.parseInt(c.slice(5, 7), 16),\n];\n\n/** WCAG relative luminance, 0 (black) to 1 (white). */\nexport function luminance(color: string): number {\n const [r, g, b] = channels(hex6(color)).map((v) => {\n const s = v / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n }) as [number, number, number];\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/** WCAG contrast ratio, 1 (same) to 21 (black on white). */\nexport function contrast(a: string, b: string): number {\n const la = luminance(a);\n const lb = luminance(b);\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\n/** Black or white, whichever reads better on `background`. */\nexport function onColor(background: string): string {\n return contrast(\"#000000\", background) >= contrast(\"#ffffff\", background) ? \"#000000\" : \"#ffffff\";\n}\n\n/** Python's builtin round(): half to even (inputs are non-negative). */\nexport function roundHalfEven(x: number): number {\n const f = Math.floor(x);\n const d = x - f;\n return d > 0.5 || (d === 0.5 && f % 2 !== 0) ? f + 1 : f;\n}\n\n/** The color `t` of the way from `a` to `b` in sRGB (`t` in [0, 1]). */\nexport function mix(a: string, b: string, t: number): string {\n if (!(t >= 0 && t <= 1)) throw new InputError(`t must be in [0, 1], got ${t}`);\n const ca = channels(hex6(a));\n const cb = channels(hex6(b));\n return `#${ca\n .map((v, i) =>\n roundHalfEven(v * (1 - t) + (cb[i] as number) * t)\n .toString(16)\n .padStart(2, \"0\"),\n )\n .join(\"\")}`;\n}\n\n/** The opaque `#rrggbb` a hex color shows as over `background`: a translucent color is alpha-composited onto it. */\nexport function solid(color: string, background = \"#ffffff\"): string {\n const opaque = hex6(color, { dropAlpha: true });\n let c = String(color).trim().replace(/^#+/, \"\");\n if (c.length === 4) c = [...c].map((ch) => ch + ch).join(\"\");\n const alpha = c.length === 8 ? Number.parseInt(c.slice(6), 16) / 255 : 1;\n return mix(background, opaque, alpha);\n}\n"]}
@@ -0,0 +1,132 @@
1
+ import { aspect, colorPalette, seasons, imageSource } from './chunk-UL5M6KDE.js';
2
+ import { placeSync, placedName, checkAlpha } from './chunk-7ULOCCFL.js';
3
+ import { warn, InputError } from './chunk-E7G7VSLV.js';
4
+ import { createElement } from 'react';
5
+
6
+ function checkSize(size) {
7
+ if (!(typeof size === "number" && Number.isFinite(size) && size > 0))
8
+ throw new InputError(`size is an image height in px > 0, got ${String(size)}`);
9
+ if (size < 1)
10
+ throw new InputError(
11
+ `size is a height in px, not a fraction of the plot (echarts' \`height\`): got ${size}, which draws a sub-pixel image`
12
+ );
13
+ return size;
14
+ }
15
+ var px = (v) => {
16
+ const n = typeof v === "string" ? Number(v) : v;
17
+ return typeof n === "number" && Number.isFinite(n) ? n : void 0;
18
+ };
19
+ function image(p, kind, label, at, h, alpha, embed) {
20
+ return createElement("image", {
21
+ href: imageSource(p, embed),
22
+ x: at.x,
23
+ y: at.y,
24
+ width: h * aspect(p),
25
+ height: h,
26
+ preserveAspectRatio: "xMidYMid meet",
27
+ ...alpha === 1 ? {} : { opacity: alpha },
28
+ role: "img",
29
+ "aria-label": `${label} ${kind}`,
30
+ "data-sdv-id": p.id,
31
+ "data-sdv-kind": kind,
32
+ "data-sdv-x": String(at.cx),
33
+ "data-sdv-y": String(at.cy),
34
+ "data-sdv-frame": "1"
35
+ });
36
+ }
37
+ function dot(kind, column, o) {
38
+ const h = checkSize(o.size ?? 24);
39
+ const alpha = checkAlpha(o.alpha ?? 1);
40
+ return (props) => {
41
+ const cx = px(props.cx);
42
+ const cy = px(props.cy);
43
+ if (cx === void 0 || cy === void 0) return null;
44
+ if (o.last && props.points === void 0)
45
+ warn(
46
+ "recharts:last:no-points",
47
+ "last: true needs the series' points, which a Scatter shape is not given: every point is drawn (use it on a Line or Area dot)"
48
+ );
49
+ else if (o.last && props.points !== void 0 && props.index !== props.points.length - 1) return null;
50
+ const row = props.payload ?? {};
51
+ const raw = row[column];
52
+ if (raw === void 0 || raw === null) return null;
53
+ let ps;
54
+ if (kind === "headshot") {
55
+ const ho = o;
56
+ ps = placeSync([cx], [cy], [raw], { league: ho.league, kind, idSystem: ho.idSystem ?? "espn" });
57
+ } else {
58
+ const mo = o;
59
+ const season = seasons([row], mo.season);
60
+ ps = placeSync([cx], [cy], [raw], {
61
+ league: mo.league,
62
+ kind,
63
+ ...season === void 0 ? {} : { season },
64
+ ...mo.variant === void 0 ? {} : { variant: mo.variant },
65
+ ...mo.idSystem === void 0 ? {} : { idSystem: mo.idSystem }
66
+ });
67
+ }
68
+ const p = ps[0];
69
+ if (p === void 0) return null;
70
+ const w = h * aspect(p);
71
+ return image(
72
+ p,
73
+ kind,
74
+ placedName(p, o.league, raw),
75
+ { x: cx - w / 2, y: cy - h / 2, cx, cy },
76
+ h,
77
+ alpha,
78
+ o.embed
79
+ );
80
+ };
81
+ }
82
+ function logoDot(o) {
83
+ return dot("logo", o.team, o);
84
+ }
85
+ function headshotDot(o) {
86
+ return dot("headshot", o.player, o);
87
+ }
88
+ function logoTick(o) {
89
+ const h = checkSize(o.size ?? 24);
90
+ const kind = o.markType ?? "logo";
91
+ return (props) => {
92
+ const x = px(props.x) ?? 0;
93
+ const y = px(props.y) ?? 0;
94
+ const value = props.payload?.value;
95
+ const side = props.orientation ?? "bottom";
96
+ const p = placeSync([x], [y], [value], {
97
+ league: o.league,
98
+ kind,
99
+ ...o.season === void 0 ? {} : { season: o.season },
100
+ ...o.variant === void 0 ? {} : { variant: o.variant },
101
+ ...o.idSystem === void 0 ? {} : { idSystem: o.idSystem }
102
+ })[0];
103
+ if (p === void 0) {
104
+ const left = side === "left";
105
+ const anchor = left ? "end" : side === "right" ? "start" : "middle";
106
+ const dy = side === "bottom" ? "0.71em" : side === "top" ? "0" : "0.355em";
107
+ return createElement(
108
+ "text",
109
+ // Recharts' own tick classes, so a stylesheet that styles its tick text styles this one too
110
+ {
111
+ className: "recharts-text recharts-cartesian-axis-tick-value",
112
+ x,
113
+ y,
114
+ textAnchor: anchor,
115
+ dy,
116
+ fill: props.fill ?? "#666"
117
+ },
118
+ String(value ?? "")
119
+ );
120
+ }
121
+ const w = h * aspect(p);
122
+ const at = side === "left" ? { x: x - w, y: y - h / 2 } : side === "right" ? { x, y: y - h / 2 } : side === "top" ? { x: x - w / 2, y: y - h } : { x: x - w / 2, y };
123
+ return image(p, kind, placedName(p, o.league, value), { ...at, cx: x, cy: y }, h, 1, o.embed);
124
+ };
125
+ }
126
+ function teamColorPalette(league, teams, o = {}) {
127
+ return colorPalette(league, teams, o);
128
+ }
129
+
130
+ export { headshotDot, logoDot, logoTick, teamColorPalette };
131
+ //# sourceMappingURL=chunk-M3XD2OSN.js.map
132
+ //# sourceMappingURL=chunk-M3XD2OSN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/recharts.ts"],"names":[],"mappings":"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","file":"chunk-M3XD2OSN.js","sourcesContent":["/**\n * The Recharts adapter: team logos and player headshots as Recharts render props (a series' `dot` or `shape`, an\n * axis' `tick`), and team colours for the series' `stroke` / `fill`. Pure: recharts is never imported (the prop types\n * here are structural, read from recharts 3.8 and later); React's `createElement` builds the SVG `<image>` each prop\n * returns. Call after `loadLeague(league)` / `preloadAll()`. The court / field / rink backdrop is a component,\n * `<SurfaceBackdrop>` in `sdvplot/react`.\n */\nimport { type ReactElement, createElement } from \"react\";\nimport { type Row, aspect, checkAlpha, colorPalette, imageSource, place, seasons } from \"./_web.js\";\nimport { InputError, warn } from \"./errors.js\";\nimport type { EspnHeadshotLeague } from \"./headshots.js\";\nimport { type Placement, placedName } from \"./placement.js\";\nimport type { Value } from \"./resolve.js\";\nimport type { HeadshotIdSystem, IdSystem, League, MarkType, SeasonInput, Variant, Which } from \"./types.js\";\nexport type { Row } from \"./_web.js\";\nexport { embedSources } from \"./_web.js\"; // public: build `embed` with it, as for the other adapters\n\n/** What Recharts hands a series' `dot` (Line, Area, Radar) or `shape` (Scatter) render prop: the subset read here. */\nexport interface RechartsDotProps {\n /** The point's centre in px. */\n cx?: number | string | undefined;\n cy?: number | string | undefined;\n /** The point's index in its series. */\n index?: number | undefined;\n /** The series' points (a Line's or Area's `dot`), so `last` can find the final one. */\n points?: readonly unknown[] | undefined;\n /** The data row the point was drawn from. */\n // biome-ignore lint/suspicious/noExplicitAny: Recharts types the row `any`; a narrower type would not accept its props\n payload?: any;\n}\n/** What Recharts hands an axis' `tick` render prop: the subset read here. */\nexport interface RechartsTickProps {\n /** The tick label's anchor in px. */\n x?: number | string | undefined;\n y?: number | string | undefined;\n /** The tick: `value` is the category the axis shows (a team). */\n // biome-ignore lint/suspicious/noExplicitAny: Recharts types the tick value `any`\n payload?: { value?: any } | undefined;\n /** Which side of the plot the axis is on. Default \"bottom\". */\n orientation?: string | undefined;\n /** The axis' tick text colour, kept for a category drawn as text. */\n fill?: string | undefined;\n}\n/** A render prop for a series' `dot` or `shape`: an `<image>`, or nothing where no image can be drawn. */\nexport type DotRenderer = (props: RechartsDotProps) => ReactElement | null;\n/** A render prop for an axis' `tick`: an `<image>`, or the category's own text where no image can be drawn. */\nexport type TickRenderer = (props: RechartsTickProps) => ReactElement;\n\ninterface Shared {\n /** Image height in px, 1 or more (Recharts hands a render prop no plot height to take a fraction of). Default 24. */\n size?: number;\n /** Opacity in [0, 1]. Default 1. */\n alpha?: number;\n /**\n * Draw only at the series' last point: an end-dot on a trend line. Default false. It needs the series' `points`,\n * which Recharts hands a Line's or Area's `dot` but not a Scatter's `shape`: there every point is drawn, with one\n * warning.\n */\n last?: boolean;\n /** url → data URI map from `embedSources`, to inline the images. */\n embed?: ReadonlyMap<string, string>;\n}\n/** `logoDot` options. */\nexport interface RechartsMarkOptions extends Shared {\n /** Name of the data row column holding the team (abbreviation, name or id; see `idSystem`). */\n team: string;\n /** The league the teams belong to, e.g. \"nba\". */\n league: League;\n /** A season (number or string) for every row, or the name of a row column holding each row's season. */\n season?: SeasonInput;\n /** Logo variant, e.g. \"dark\". Default \"default\". */\n variant?: Variant;\n /** How the `team` values are read. Default \"auto\". */\n idSystem?: IdSystem;\n}\n/** `headshotDot` options. */\nexport interface RechartsHeadshotOptions extends Shared {\n /** Name of the data row column holding the player id. */\n player: string;\n /** The league the players belong to, e.g. \"nfl\". */\n league: EspnHeadshotLeague;\n /** ESPN athlete ids, or nflverse gsis ids (needs `loadGsis()` first). Default \"espn\". */\n idSystem?: HeadshotIdSystem;\n}\n/** `logoTick` options: the axis' categories are the teams. */\nexport interface RechartsTickOptions {\n /** The league the teams belong to, e.g. \"nba\". */\n league: League;\n /** The season the axis' teams are resolved for. */\n season?: SeasonInput;\n /** Image height in px, 1 or more. Default 24. */\n size?: number;\n /** Logo variant, e.g. \"dark\". Default \"default\". */\n variant?: Variant;\n /** \"logo\" (default) or \"wordmark\". */\n markType?: MarkType;\n /** How the axis categories are read. Default \"auto\". */\n idSystem?: IdSystem;\n /** url → data URI map from `embedSources`, to inline the images. */\n embed?: ReadonlyMap<string, string>;\n}\n\nfunction checkSize(size: unknown): number {\n if (!(typeof size === \"number\" && Number.isFinite(size) && size > 0))\n throw new InputError(`size is an image height in px > 0, got ${String(size)}`);\n if (size < 1)\n throw new InputError(\n `size is a height in px, not a fraction of the plot (echarts' \\`height\\`): got ${size}, which draws a sub-pixel image`,\n );\n return size;\n}\nconst px = (v: unknown): number | undefined => {\n const n = typeof v === \"string\" ? Number(v) : v;\n return typeof n === \"number\" && Number.isFinite(n) ? n : undefined;\n};\n/** The `<image>` of a placed mark, `h` px tall at (x, y) top-left, stamped with what `sdvplot/testing`'s\n * `drawnMarks` reads back. ponytail: the frame is 1 px, so drawnMarks' `height` reads in px (no plot height here). */\nfunction image(\n p: Placement,\n kind: string,\n label: string,\n at: { x: number; y: number; cx: number; cy: number },\n h: number,\n alpha: number,\n embed: ReadonlyMap<string, string> | undefined,\n): ReactElement {\n return createElement(\"image\", {\n href: imageSource(p, embed),\n x: at.x,\n y: at.y,\n width: h * aspect(p),\n height: h,\n preserveAspectRatio: \"xMidYMid meet\",\n ...(alpha === 1 ? {} : { opacity: alpha }),\n role: \"img\",\n \"aria-label\": `${label} ${kind}`,\n \"data-sdv-id\": p.id,\n \"data-sdv-kind\": kind,\n \"data-sdv-x\": String(at.cx),\n \"data-sdv-y\": String(at.cy),\n \"data-sdv-frame\": \"1\",\n });\n}\n\nfunction dot(\n kind: \"logo\" | \"headshot\",\n column: string,\n o: RechartsMarkOptions | RechartsHeadshotOptions,\n): DotRenderer {\n const h = checkSize(o.size ?? 24);\n const alpha = checkAlpha(o.alpha ?? 1);\n return (props) => {\n const cx = px(props.cx);\n const cy = px(props.cy);\n if (cx === undefined || cy === undefined) return null;\n if (o.last && props.points === undefined)\n warn(\n \"recharts:last:no-points\",\n \"last: true needs the series' points, which a Scatter shape is not given: every point is drawn (use it on a Line or Area dot)\",\n );\n else if (o.last && props.points !== undefined && props.index !== props.points.length - 1) return null;\n const row: Row = props.payload ?? {};\n const raw = row[column] as Value;\n if (raw === undefined || raw === null) return null;\n let ps: Placement[];\n if (kind === \"headshot\") {\n const ho = o as RechartsHeadshotOptions;\n ps = place([cx], [cy], [raw], { league: ho.league, kind, idSystem: ho.idSystem ?? \"espn\" });\n } else {\n const mo = o as RechartsMarkOptions;\n const season = seasons([row], mo.season);\n ps = place([cx], [cy], [raw], {\n league: mo.league,\n kind,\n ...(season === undefined ? {} : { season }),\n ...(mo.variant === undefined ? {} : { variant: mo.variant }),\n ...(mo.idSystem === undefined ? {} : { idSystem: mo.idSystem }),\n });\n }\n const p = ps[0];\n if (p === undefined) return null; // no mark: nothing drawn, one warning (placeSync), as sdvplot/echarts\n const w = h * aspect(p);\n return image(\n p,\n kind,\n placedName(p, o.league, raw),\n { x: cx - w / 2, y: cy - h / 2, cx, cy },\n h,\n alpha,\n o.embed,\n );\n };\n}\n\n/**\n * Team logos as a series' points: the `dot` of a `<Line>` / `<Area>`, or the `shape` of a `<Scatter>`. Each point\n * draws the logo of its data row's `team` column, `size` px tall and centred on the point; `last: true` draws only\n * the series' final point (an end-dot). A team with no logo draws nothing and warns once, as `sdvplot/echarts` does.\n *\n * @example\n * ```tsx\n * import { loadLeague } from \"@sportsdataverse/sdvplot\";\n * import { logoDot } from \"@sportsdataverse/sdvplot/recharts\";\n * import { Scatter, ScatterChart, XAxis, YAxis } from \"recharts\";\n *\n * await loadLeague(\"nfl\");\n * const rows = [\n * { team: \"KC\", pf: 385, pa: 326 },\n * { team: \"LAC\", pf: 402, pa: 301 },\n * ];\n * <ScatterChart width={400} height={300}>\n * <XAxis dataKey=\"pf\" type=\"number\" domain={[350, 450]} />\n * <YAxis dataKey=\"pa\" type=\"number\" domain={[280, 350]} />\n * <Scatter data={rows} shape={logoDot({ team: \"team\", league: \"nfl\", size: 32 })} />\n * </ScatterChart>;\n * ```\n */\nexport function logoDot(o: RechartsMarkOptions): DotRenderer {\n return dot(\"logo\", o.team, o);\n}\n\n/** ESPN player headshots as a series' points (`dot` or `shape`), from the data row's `player` column; an id with no\n * headshot draws nothing and warns once. `idSystem: \"gsis\"` needs `loadGsis()` first. */\nexport function headshotDot(o: RechartsHeadshotOptions): DotRenderer {\n return dot(\"headshot\", o.player, o);\n}\n\n/**\n * Team logos as an axis' tick labels: the `tick` of a category `<XAxis>` / `<YAxis>` whose values are teams. The\n * logo sits where the label would (under a bottom axis, left of a left one). A category that resolves to no logo keeps\n * its text label, as `sdvplot/echarts`' `withAxisLogos` does.\n */\nexport function logoTick(o: RechartsTickOptions): TickRenderer {\n const h = checkSize(o.size ?? 24);\n const kind = o.markType ?? \"logo\";\n return (props) => {\n const x = px(props.x) ?? 0;\n const y = px(props.y) ?? 0;\n const value = props.payload?.value;\n const side = props.orientation ?? \"bottom\";\n const p = place([x], [y], [value as Value], {\n league: o.league,\n kind,\n ...(o.season === undefined ? {} : { season: o.season }),\n ...(o.variant === undefined ? {} : { variant: o.variant }),\n ...(o.idSystem === undefined ? {} : { idSystem: o.idSystem }),\n })[0];\n if (p === undefined) {\n const left = side === \"left\";\n const anchor = left ? \"end\" : side === \"right\" ? \"start\" : \"middle\";\n const dy = side === \"bottom\" ? \"0.71em\" : side === \"top\" ? \"0\" : \"0.355em\";\n return createElement(\n \"text\",\n // Recharts' own tick classes, so a stylesheet that styles its tick text styles this one too\n {\n className: \"recharts-text recharts-cartesian-axis-tick-value\",\n x,\n y,\n textAnchor: anchor,\n dy,\n fill: props.fill ?? \"#666\",\n },\n String(value ?? \"\"),\n );\n }\n const w = h * aspect(p);\n const at =\n side === \"left\"\n ? { x: x - w, y: y - h / 2 }\n : side === \"right\"\n ? { x, y: y - h / 2 }\n : side === \"top\"\n ? { x: x - w / 2, y: y - h }\n : { x: x - w / 2, y };\n return image(p, kind, placedName(p, o.league, value), { ...at, cx: x, cy: y }, h, 1, o.embed);\n };\n}\n\n/** `teamColorPalette` options. */\nexport interface RechartsColorOptions {\n which?: Which;\n season?: SeasonInput;\n idSystem?: IdSystem;\n /** The colour of an unresolved team. Default \"#808080\". */\n fallback?: string;\n /**\n * The chart's background. Given, a team colour under 3:1 contrast against it is swapped for the team's other\n * colour, else moved towards white (on a dark background) or black (a light one) until it reads: dark mode. A\n * colour that would then sit too close to an earlier team's (CIE76 ΔE under 20) takes the team's other colour, or\n * the nearest colour to its own (lightness, hue or chroma stepped) that is distinct and still reads; failing that it\n * is kept, with one warning.\n */\n background?: string;\n}\n/**\n * One colour per team, in order, for each series' `stroke` / `fill`. With `background`, every colour keeps 3:1\n * contrast against it (dark mode) and stays distinct from the others.\n *\n * @example\n * ```tsx\n * import { loadLeague } from \"@sportsdataverse/sdvplot\";\n * import { teamColorPalette } from \"@sportsdataverse/sdvplot/recharts\";\n *\n * await loadLeague(\"nba\");\n * teamColorPalette(\"nba\", [\"Clippers\", \"Suns\", \"Lakers\"], { background: \"#181a1b\" });\n * ```\n */\nexport function teamColorPalette(\n league: League,\n teams: readonly unknown[],\n o: RechartsColorOptions = {},\n): string[] {\n return colorPalette(league, teams, o);\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import { getLeagueSync, teamColorsSync } from './chunk-ZAEQXFJM.js';
2
+
3
+ // src/stamp.ts
4
+ function stampImage(img, p, kind, px, frame, cx, cy) {
5
+ const w = px * (p.aspect ?? 1);
6
+ img.setAttribute("width", String(w));
7
+ img.setAttribute("height", String(px));
8
+ img.setAttribute("x", String(cx - w / 2));
9
+ img.setAttribute("y", String(cy - px / 2));
10
+ img.setAttribute("data-sdv-id", p.id);
11
+ img.setAttribute("data-sdv-kind", kind);
12
+ img.setAttribute("data-sdv-frame", String(frame));
13
+ }
14
+
15
+ // src/team-color-domain.ts
16
+ var has = (v) => v !== null && v !== void 0 && !Number.isNaN(v);
17
+ function teamColorDomain(league, o = {}) {
18
+ const domain = o.values ? [...new Set(o.values.filter(has).map(String))] : [...new Set(getLeagueSync(league).teams.flatMap((t) => t.abbr ? [t.team_id, t.abbr] : [t.team_id]))];
19
+ const colors = teamColorsSync(league, domain, {
20
+ which: o.which ?? "primary",
21
+ idSystem: o.idSystem ?? "auto",
22
+ strict: o.strict ?? false,
23
+ ...o.season !== void 0 ? { season: o.season } : {}
24
+ });
25
+ return { domain, colors };
26
+ }
27
+
28
+ export { stampImage, teamColorDomain };
29
+ //# sourceMappingURL=chunk-OIILARXI.js.map
30
+ //# sourceMappingURL=chunk-OIILARXI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stamp.ts","../src/team-color-domain.ts"],"names":[],"mappings":";;;AAMO,SAAS,WACd,GAAA,EACA,CAAA,EACA,MACA,EAAA,EACA,KAAA,EACA,IACA,EAAA,EACM;AACN,EAAA,MAAM,CAAA,GAAI,EAAA,IAAM,CAAA,CAAE,MAAA,IAAU,CAAA,CAAA;AAC5B,EAAA,GAAA,CAAI,YAAA,CAAa,OAAA,EAAS,MAAA,CAAO,CAAC,CAAC,CAAA;AACnC,EAAA,GAAA,CAAI,YAAA,CAAa,QAAA,EAAU,MAAA,CAAO,EAAE,CAAC,CAAA;AACrC,EAAA,GAAA,CAAI,aAAa,GAAA,EAAK,MAAA,CAAO,EAAA,GAAK,CAAA,GAAI,CAAC,CAAC,CAAA;AACxC,EAAA,GAAA,CAAI,aAAa,GAAA,EAAK,MAAA,CAAO,EAAA,GAAK,EAAA,GAAK,CAAC,CAAC,CAAA;AACzC,EAAA,GAAA,CAAI,YAAA,CAAa,aAAA,EAAe,CAAA,CAAE,EAAE,CAAA;AACpC,EAAA,GAAA,CAAI,YAAA,CAAa,iBAAiB,IAAI,CAAA;AACtC,EAAA,GAAA,CAAI,YAAA,CAAa,gBAAA,EAAkB,MAAA,CAAO,KAAK,CAAC,CAAA;AAClD;;;ACVA,IAAM,GAAA,GAAM,CAAC,CAAA,KAAmC,CAAA,KAAM,IAAA,IAAQ,MAAM,MAAA,IAAa,CAAC,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA;AAGzF,SAAS,eAAA,CACd,MAAA,EACA,CAAA,GAA4B,EAAC,EACyB;AACtD,EAAA,MAAM,SAAS,CAAA,CAAE,MAAA,GACb,CAAC,GAAG,IAAI,IAAI,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,GAAG,EAAE,GAAA,CAAI,MAAM,CAAC,CAAC,CAAA,GAC7C,CAAC,GAAG,IAAI,GAAA,CAAI,aAAA,CAAc,MAAM,CAAA,CAAE,KAAA,CAAM,QAAQ,CAAC,CAAA,KAAO,EAAE,IAAA,GAAO,CAAC,EAAE,OAAA,EAAS,CAAA,CAAE,IAAI,CAAA,GAAI,CAAC,EAAE,OAAO,CAAE,CAAC,CAAC,CAAA;AACzG,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,MAAA,EAAQ,MAAA,EAAQ;AAAA,IAC5C,KAAA,EAAO,EAAE,KAAA,IAAS,SAAA;AAAA,IAClB,QAAA,EAAU,EAAE,QAAA,IAAY,MAAA;AAAA,IACxB,MAAA,EAAQ,EAAE,MAAA,IAAU,KAAA;AAAA,IACpB,GAAI,EAAE,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,GAAI;AAAC,GACtD,CAAA;AACD,EAAA,OAAO,EAAE,QAAQ,MAAA,EAAO;AAC1B","file":"chunk-OIILARXI.js","sourcesContent":["import type { Kind, Placement } from \"./placement.js\";\n\n/**\n * Size an `<image>` to `px` tall (width from the mark's aspect), centre it on (cx, cy) and stamp the\n * `data-sdv-id/kind/frame` attributes the testing hooks read. Plot-free: shared by the Plot and d3 adapters.\n */\nexport function stampImage(\n img: Element,\n p: Placement,\n kind: Kind,\n px: number,\n frame: number,\n cx: number,\n cy: number,\n): void {\n const w = px * (p.aspect ?? 1);\n img.setAttribute(\"width\", String(w));\n img.setAttribute(\"height\", String(px));\n img.setAttribute(\"x\", String(cx - w / 2));\n img.setAttribute(\"y\", String(cy - px / 2));\n img.setAttribute(\"data-sdv-id\", p.id);\n img.setAttribute(\"data-sdv-kind\", kind);\n img.setAttribute(\"data-sdv-frame\", String(frame));\n}\n","import { teamColorsSync } from \"./colors.js\";\nimport { getLeagueSync } from \"./index-data.js\";\nimport type { Value } from \"./resolve.js\";\nimport type { IdSystem, League, SeasonInput, Which } from \"./types.js\";\n\nexport interface TeamColorDomainOptions {\n which?: Which | undefined;\n season?: SeasonInput | undefined;\n idSystem?: IdSystem | undefined;\n strict?: boolean | undefined;\n /** Domain = these distinct values; default every team_id and abbr of the league. */\n values?: readonly Value[] | undefined;\n}\nconst has = (v: Value): v is string | number => v !== null && v !== undefined && !Number.isNaN(v);\n\n/** Plot-free: the ordinal domain and the matching team colours (undefined where a value resolves to no team). Shared by `teamColor` (Plot) and `teamColorScale` (d3). */\nexport function teamColorDomain(\n league: League,\n o: TeamColorDomainOptions = {},\n): { domain: string[]; colors: (string | undefined)[] } {\n const domain = o.values\n ? [...new Set(o.values.filter(has).map(String))]\n : [...new Set(getLeagueSync(league).teams.flatMap((t) => (t.abbr ? [t.team_id, t.abbr] : [t.team_id])))];\n const colors = teamColorsSync(league, domain, {\n which: o.which ?? \"primary\",\n idSystem: o.idSystem ?? \"auto\",\n strict: o.strict ?? false,\n ...(o.season !== undefined ? { season: o.season } : {}),\n });\n return { domain, colors };\n}\n"]}
@@ -0,0 +1,170 @@
1
+ import { aspect, colorPalette, seasons, imageSource } from './chunk-UL5M6KDE.js';
2
+ import { checkHeight, checkAlpha, placeSync, placedName } from './chunk-7ULOCCFL.js';
3
+ import { resolveSync } from './chunk-ZAEQXFJM.js';
4
+ import { InputError, UnsupportedTargetError, warn } from './chunk-E7G7VSLV.js';
5
+ import { createElement } from 'react';
6
+
7
+ var AT = ["last", "first", "all"];
8
+ var CHORD_GAP = 4;
9
+ var field = (id, data, team) => team === void 0 ? id : (data ?? {})[team];
10
+ function image(p, o, at, h, frame, alpha) {
11
+ const kind = o.markType ?? "logo";
12
+ const w = h * aspect(p);
13
+ return createElement("image", {
14
+ key: `${p.index}`,
15
+ href: imageSource(p, o.embed),
16
+ x: at.x - w / 2,
17
+ y: at.y - h / 2,
18
+ width: w,
19
+ height: h,
20
+ preserveAspectRatio: "xMidYMid meet",
21
+ ...alpha === 1 ? {} : { opacity: alpha },
22
+ role: "img",
23
+ "aria-label": `${placedName(p, o.league, at.raw)} ${kind}`,
24
+ "data-sdv-id": p.id,
25
+ "data-sdv-kind": kind,
26
+ "data-sdv-x": String(at.x),
27
+ "data-sdv-y": String(at.y),
28
+ "data-sdv-frame": String(frame)
29
+ });
30
+ }
31
+ function placed(ts, o) {
32
+ const season = seasons(
33
+ ts.map((t) => t.row),
34
+ o.season
35
+ );
36
+ return placeSync(
37
+ ts.map((t) => t.x),
38
+ ts.map((t) => t.y),
39
+ ts.map((t) => t.raw),
40
+ {
41
+ league: o.league,
42
+ kind: o.markType ?? "logo",
43
+ ...season === void 0 ? {} : { season },
44
+ ...o.variant === void 0 ? {} : { variant: o.variant },
45
+ ...o.idSystem === void 0 ? {} : { idSystem: o.idSystem }
46
+ }
47
+ );
48
+ }
49
+ function bumpPoints(points, at) {
50
+ if (at === "all") return [...points];
51
+ const pick = /* @__PURE__ */ new Map();
52
+ for (const p of points) if (at === "last" || !pick.has(p.serie.id)) pick.set(p.serie.id, p);
53
+ return [...pick.values()];
54
+ }
55
+ function logoLayer(o) {
56
+ const height = checkHeight(o.height ?? 0.08);
57
+ const alpha = checkAlpha(o.alpha ?? 1);
58
+ const at = o.at ?? "last";
59
+ if (!AT.includes(at))
60
+ throw new InputError(`at must be "last", "first" or "all", got ${JSON.stringify(at)}`);
61
+ return function SdvLogoLayer(props) {
62
+ let frame;
63
+ let ts;
64
+ let chord;
65
+ if (props.points !== void 0) {
66
+ frame = props.innerHeight ?? 0;
67
+ ts = bumpPoints(props.points, at).flatMap(
68
+ (p) => p.y === null ? [] : [
69
+ {
70
+ x: p.x,
71
+ y: p.y,
72
+ raw: field(p.serie.id, p.serie.data, o.team),
73
+ row: p.serie.data ?? {}
74
+ }
75
+ ]
76
+ );
77
+ } else if (props.nodes !== void 0) {
78
+ frame = props.innerHeight ?? 0;
79
+ ts = props.nodes.map((n) => ({
80
+ x: n.x,
81
+ y: n.y,
82
+ raw: field(n.id, n.data, o.team),
83
+ row: n.data ?? {}
84
+ }));
85
+ } else if (props.arcs !== void 0 && props.center !== void 0 && props.radius !== void 0) {
86
+ const [cx, cy] = props.center;
87
+ frame = 2 * cy;
88
+ chord = { cx, cy, radius: props.radius, mids: props.arcs.map((a) => (a.startAngle + a.endAngle) / 2) };
89
+ ts = props.arcs.map((a) => ({ x: cx, y: cy, raw: a.id, row: {} }));
90
+ } else
91
+ throw new UnsupportedTargetError(
92
+ `logoLayer draws on a nivo Bump (points), SwarmPlot (nodes) or Chord (arcs) layer; got props ${Object.keys(props).join(", ")}`
93
+ );
94
+ const ps = placed(ts, o);
95
+ if (chord !== void 0)
96
+ for (const p of ps) {
97
+ const m = chord.mids[p.index];
98
+ const h = height * frame;
99
+ const r = chord.radius + Math.abs(Math.sin(m)) * h * aspect(p) / 2 + Math.abs(Math.cos(m)) * h / 2;
100
+ const t = ts[p.index];
101
+ t.x = chord.cx + (r + CHORD_GAP) * Math.sin(m);
102
+ t.y = chord.cy - (r + CHORD_GAP) * Math.cos(m);
103
+ }
104
+ return createElement(
105
+ "g",
106
+ { "data-sdv-layer": "logos", pointerEvents: "none" },
107
+ // the lines and nodes under it keep their mouse events
108
+ ps.map((p) => image(p, o, ts[p.index], height * frame, frame, alpha))
109
+ );
110
+ };
111
+ }
112
+ function logoNode(o) {
113
+ if ("height" in o)
114
+ throw new InputError(
115
+ "logoNode takes no height: each logo is as tall as nivo sized the node (the chart's size or pointSize, in px)"
116
+ );
117
+ const alpha = checkAlpha(o.alpha ?? 1);
118
+ return function SdvLogoNode({ node, point }) {
119
+ const n = node ?? point;
120
+ const t = n === void 0 || n.y === null ? void 0 : node !== void 0 ? { x: node.x, y: node.y, raw: field(node.id, node.data, o.team), row: node.data ?? {} } : point !== void 0 && point.y !== null ? {
121
+ x: point.x,
122
+ y: point.y,
123
+ raw: field(point.serie.id, point.serie.data, o.team),
124
+ row: point.serie.data ?? {}
125
+ } : void 0;
126
+ const size = n?.size ?? 0;
127
+ const p = t === void 0 || !(size > 0) ? void 0 : placed([t], o)[0];
128
+ return p === void 0 ? createElement("g") : createElement("g", null, image(p, o, t, size, 1, alpha));
129
+ };
130
+ }
131
+ function teamColors(o) {
132
+ const fallback = o.fallback ?? "#808080";
133
+ const by = o.by ?? "id";
134
+ const co = {
135
+ ...o.season === void 0 ? {} : { season: o.season },
136
+ ...o.idSystem === void 0 ? {} : { idSystem: o.idSystem }
137
+ };
138
+ const read = (d) => {
139
+ const r = d;
140
+ return r[by] ?? (r.data !== null && typeof r.data === "object" ? r.data[by] : void 0);
141
+ };
142
+ const po = { ...co, ...o.which === void 0 ? {} : { which: o.which }, fallback };
143
+ if (o.background === void 0) return (d) => colorPalette(o.league, [read(d)], po)[0];
144
+ if (o.teams === void 0)
145
+ throw new InputError(
146
+ "teamColors: background needs teams, every team the chart draws (the palette keeps them apart)"
147
+ );
148
+ const teams = o.teams;
149
+ const palette = colorPalette(o.league, teams, { ...po, background: o.background });
150
+ const ids = resolveSync(teams, o.league, co);
151
+ const byId = /* @__PURE__ */ new Map();
152
+ ids.forEach((id, i) => {
153
+ if (id !== void 0 && !byId.has(id)) byId.set(id, palette[i]);
154
+ });
155
+ return (d) => {
156
+ const raw = read(d);
157
+ const id = resolveSync([raw], o.league, co)[0];
158
+ const c = id === void 0 ? void 0 : byId.get(id);
159
+ if (c === void 0 && id !== void 0)
160
+ warn(
161
+ `nivo:teamColors:${o.league}:${id}`,
162
+ `teamColors: ${String(raw)} is not in teams: drawn in the fallback`
163
+ );
164
+ return c ?? fallback;
165
+ };
166
+ }
167
+
168
+ export { logoLayer, logoNode, teamColors };
169
+ //# sourceMappingURL=chunk-RPVVJY74.js.map
170
+ //# sourceMappingURL=chunk-RPVVJY74.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nivo.ts"],"names":[],"mappings":";;;;;;AAmHA,IAAM,EAAA,GAAK,CAAC,MAAA,EAAQ,OAAA,EAAS,KAAK,CAAA;AAClC,IAAM,SAAA,GAAY,CAAA;AAQlB,IAAM,KAAA,GAAQ,CAAC,EAAA,EAAY,IAAA,EAAe,IAAA,KACvC,IAAA,KAAS,MAAA,GAAY,EAAA,GAAA,CAAO,IAAA,IAAQ,EAAC,EAAW,IAAI,CAAA;AAIvD,SAAS,MAAM,CAAA,EAAc,CAAA,EAAW,EAAA,EAAY,CAAA,EAAW,OAAe,KAAA,EAA6B;AACzG,EAAA,MAAM,IAAA,GAAO,EAAE,QAAA,IAAY,MAAA;AAC3B,EAAA,MAAM,CAAA,GAAI,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACtB,EAAA,OAAO,cAAc,OAAA,EAAS;AAAA,IAC5B,GAAA,EAAK,CAAA,EAAG,CAAA,CAAE,KAAK,CAAA,CAAA;AAAA,IACf,IAAA,EAAM,WAAA,CAAY,CAAA,EAAG,CAAA,CAAE,KAAK,CAAA;AAAA,IAC5B,CAAA,EAAG,EAAA,CAAG,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,IACd,CAAA,EAAG,EAAA,CAAG,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,IACd,KAAA,EAAO,CAAA;AAAA,IACP,MAAA,EAAQ,CAAA;AAAA,IACR,mBAAA,EAAqB,eAAA;AAAA,IACrB,GAAI,KAAA,KAAU,CAAA,GAAI,EAAC,GAAI,EAAE,SAAS,KAAA,EAAM;AAAA,IACxC,IAAA,EAAM,KAAA;AAAA,IACN,YAAA,EAAc,CAAA,EAAG,UAAA,CAAW,CAAA,EAAG,CAAA,CAAE,QAAQ,EAAA,CAAG,GAAG,CAAC,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,IACxD,eAAe,CAAA,CAAE,EAAA;AAAA,IACjB,eAAA,EAAiB,IAAA;AAAA,IACjB,YAAA,EAAc,MAAA,CAAO,EAAA,CAAG,CAAC,CAAA;AAAA,IACzB,YAAA,EAAc,MAAA,CAAO,EAAA,CAAG,CAAC,CAAA;AAAA,IACzB,gBAAA,EAAkB,OAAO,KAAK;AAAA,GAC/B,CAAA;AACH;AAGA,SAAS,MAAA,CAAO,IAAuB,CAAA,EAAwB;AAC7D,EAAA,MAAM,MAAA,GAAS,OAAA;AAAA,IACb,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,GAAG,CAAA;AAAA,IACnB,CAAA,CAAE;AAAA,GACJ;AACA,EAAA,OAAO,SAAA;AAAA,IACL,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,CAAC,CAAA;AAAA,IACjB,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,CAAC,CAAA;AAAA,IACjB,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,GAAG,CAAA;AAAA,IACnB;AAAA,MACE,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,IAAA,EAAM,EAAE,QAAA,IAAY,MAAA;AAAA,MACpB,GAAI,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,MAAA,EAAO;AAAA,MACzC,GAAI,EAAE,OAAA,KAAY,MAAA,GAAY,EAAC,GAAI,EAAE,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ;AAAA,MACxD,GAAI,EAAE,QAAA,KAAa,MAAA,GAAY,EAAC,GAAI,EAAE,QAAA,EAAU,CAAA,CAAE,QAAA;AAAS;AAC7D,GACF;AACF;AAGA,SAAS,UAAA,CAAW,QAAkC,EAAA,EAA0C;AAC9F,EAAA,IAAI,EAAA,KAAO,KAAA,EAAO,OAAO,CAAC,GAAG,MAAM,CAAA;AACnC,EAAA,MAAM,IAAA,uBAAW,GAAA,EAA2B;AAC5C,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ,IAAI,EAAA,KAAO,MAAA,IAAU,CAAC,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,CAAE,KAAA,CAAM,IAAI,CAAC,CAAA;AAC1F,EAAA,OAAO,CAAC,GAAG,IAAA,CAAK,MAAA,EAAQ,CAAA;AAC1B;AAsCO,SAAS,UAAU,CAAA,EAAgC;AACxD,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,CAAA,CAAE,MAAA,IAAU,IAAI,CAAA;AAC3C,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,CAAA,CAAE,KAAA,IAAS,CAAC,CAAA;AACrC,EAAA,MAAM,EAAA,GAAK,EAAE,EAAA,IAAM,MAAA;AACnB,EAAA,IAAI,CAAC,EAAA,CAAG,QAAA,CAAS,EAAE,CAAA;AACjB,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,yCAAA,EAA4C,KAAK,SAAA,CAAU,EAAE,CAAC,CAAA,CAAE,CAAA;AACvF,EAAA,OAAO,SAAS,aAAa,KAAA,EAAO;AAClC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI,EAAA;AACJ,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI,KAAA,CAAM,WAAW,MAAA,EAAW;AAC9B,MAAA,KAAA,GAAQ,MAAM,WAAA,IAAe,CAAA;AAC7B,MAAA,EAAA,GAAK,UAAA,CAAW,KAAA,CAAM,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA;AAAA,QAAQ,CAAC,CAAA,KACzC,CAAA,CAAE,CAAA,KAAM,IAAA,GACJ,EAAC,GACD;AAAA,UACE;AAAA,YACE,GAAG,CAAA,CAAE,CAAA;AAAA,YACL,GAAG,CAAA,CAAE,CAAA;AAAA,YACL,GAAA,EAAK,MAAM,CAAA,CAAE,KAAA,CAAM,IAAI,CAAA,CAAE,KAAA,CAAM,IAAA,EAAM,CAAA,CAAE,IAAI,CAAA;AAAA,YAC3C,GAAA,EAAM,CAAA,CAAE,KAAA,CAAM,IAAA,IAAQ;AAAC;AACzB;AACF,OACN;AAAA,IACF,CAAA,MAAA,IAAW,KAAA,CAAM,KAAA,KAAU,MAAA,EAAW;AACpC,MAAA,KAAA,GAAQ,MAAM,WAAA,IAAe,CAAA;AAC7B,MAAA,EAAA,GAAK,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QAC3B,GAAG,CAAA,CAAE,CAAA;AAAA,QACL,GAAG,CAAA,CAAE,CAAA;AAAA,QACL,KAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,EAAM,EAAE,IAAI,CAAA;AAAA,QAC/B,GAAA,EAAM,CAAA,CAAE,IAAA,IAAQ;AAAC,OACnB,CAAE,CAAA;AAAA,IACJ,CAAA,MAAA,IAAW,MAAM,IAAA,KAAS,MAAA,IAAa,MAAM,MAAA,KAAW,MAAA,IAAa,KAAA,CAAM,MAAA,KAAW,MAAA,EAAW;AAC/F,MAAA,MAAM,CAAC,EAAA,EAAI,EAAE,CAAA,GAAI,KAAA,CAAM,MAAA;AACvB,MAAA,KAAA,GAAQ,CAAA,GAAI,EAAA;AAEZ,MAAA,KAAA,GAAQ,EAAE,EAAA,EAAI,EAAA,EAAI,MAAA,EAAQ,KAAA,CAAM,QAAQ,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAA,CAAO,CAAA,CAAE,aAAa,CAAA,CAAE,QAAA,IAAY,CAAC,CAAA,EAAE;AACrG,MAAA,EAAA,GAAK,MAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,KAAK,CAAA,CAAE,EAAA,EAAa,GAAA,EAAK,IAAG,CAAE,CAAA;AAAA,IAC5E,CAAA;AACE,MAAA,MAAM,IAAI,sBAAA;AAAA,QACR,+FAA+F,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OAC9H;AACF,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,EAAA,EAAI,CAAC,CAAA;AACvB,IAAA,IAAI,KAAA,KAAU,MAAA;AACZ,MAAA,KAAA,MAAW,KAAK,EAAA,EAAI;AAElB,QAAA,MAAM,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA;AAC5B,QAAA,MAAM,IAAI,MAAA,GAAS,KAAA;AACnB,QAAA,MAAM,CAAA,GACJ,MAAM,MAAA,GAAU,IAAA,CAAK,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAC,CAAA,GAAI,CAAA,GAAI,OAAO,CAAC,CAAA,GAAK,IAAK,IAAA,CAAK,GAAA,CAAI,KAAK,GAAA,CAAI,CAAC,CAAC,CAAA,GAAI,CAAA,GAAK,CAAA;AAC7F,QAAA,MAAM,CAAA,GAAI,EAAA,CAAG,CAAA,CAAE,KAAK,CAAA;AACpB,QAAA,CAAA,CAAE,IAAI,KAAA,CAAM,EAAA,GAAA,CAAM,IAAI,SAAA,IAAa,IAAA,CAAK,IAAI,CAAC,CAAA;AAC7C,QAAA,CAAA,CAAE,IAAI,KAAA,CAAM,EAAA,GAAA,CAAM,IAAI,SAAA,IAAa,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,MAC/C;AACF,IAAA,OAAO,aAAA;AAAA,MACL,GAAA;AAAA,MACA,EAAE,gBAAA,EAAkB,OAAA,EAAS,aAAA,EAAe,MAAA,EAAO;AAAA;AAAA,MACnD,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA,KAAM,MAAM,CAAA,EAAG,CAAA,EAAG,EAAA,CAAG,CAAA,CAAE,KAAK,CAAA,EAAa,MAAA,GAAS,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC;AAAA,KAChF;AAAA,EACF,CAAA;AACF;AAQO,SAAS,SAAS,CAAA,EAAuC;AAC9D,EAAA,IAAI,QAAA,IAAY,CAAA;AACd,IAAA,MAAM,IAAI,UAAA;AAAA,MACR;AAAA,KACF;AACF,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,CAAA,CAAE,KAAA,IAAS,CAAC,CAAA;AACrC,EAAA,OAAO,SAAS,WAAA,CAAY,EAAE,IAAA,EAAM,OAAM,EAAG;AAC3C,IAAA,MAAM,IAAI,IAAA,IAAQ,KAAA;AAClB,IAAA,MAAM,CAAA,GACJ,CAAA,KAAM,MAAA,IAAa,CAAA,CAAE,MAAM,IAAA,GACvB,MAAA,GACA,IAAA,KAAS,MAAA,GACP,EAAE,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA,EAAG,GAAA,EAAK,KAAA,CAAM,IAAA,CAAK,IAAI,IAAA,CAAK,IAAA,EAAM,CAAA,CAAE,IAAI,GAAG,GAAA,EAAM,IAAA,CAAK,IAAA,IAAQ,IAAW,GAC9F,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,MAAM,IAAA,GACjC;AAAA,MACE,GAAG,KAAA,CAAM,CAAA;AAAA,MACT,GAAG,KAAA,CAAM,CAAA;AAAA,MACT,GAAA,EAAK,MAAM,KAAA,CAAM,KAAA,CAAM,IAAI,KAAA,CAAM,KAAA,CAAM,IAAA,EAAM,CAAA,CAAE,IAAI,CAAA;AAAA,MACnD,GAAA,EAAM,KAAA,CAAM,KAAA,CAAM,IAAA,IAAQ;AAAC,KAC7B,GACA,MAAA;AACV,IAAA,MAAM,IAAA,GAAO,GAAG,IAAA,IAAQ,CAAA;AACxB,IAAA,MAAM,CAAA,GAAI,CAAA,KAAM,MAAA,IAAa,EAAE,IAAA,GAAO,CAAA,CAAA,GAAK,MAAA,GAAY,MAAA,CAAO,CAAC,CAAC,CAAA,EAAG,CAAC,EAAE,CAAC,CAAA;AAEvE,IAAA,OAAO,CAAA,KAAM,MAAA,GACT,aAAA,CAAc,GAAG,IACjB,aAAA,CAAc,GAAA,EAAK,IAAA,EAAM,KAAA,CAAM,GAAG,CAAA,EAAG,CAAA,EAAa,IAAA,EAAM,CAAA,EAAG,KAAK,CAAC,CAAA;AAAA,EACvE,CAAA;AACF;AA6CO,SAAS,WAAW,CAAA,EAAgD;AACzE,EAAA,MAAM,QAAA,GAAW,EAAE,QAAA,IAAY,SAAA;AAC/B,EAAA,MAAM,EAAA,GAAK,EAAE,EAAA,IAAM,IAAA;AACnB,EAAA,MAAM,EAAA,GAAK;AAAA,IACT,GAAI,EAAE,MAAA,KAAW,MAAA,GAAY,EAAC,GAAI,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO;AAAA,IACrD,GAAI,EAAE,QAAA,KAAa,MAAA,GAAY,EAAC,GAAI,EAAE,QAAA,EAAU,CAAA,CAAE,QAAA;AAAS,GAC7D;AACA,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KAAuB;AACnC,IAAA,MAAM,CAAA,GAAI,CAAA;AACV,IAAA,OAAO,CAAA,CAAE,EAAE,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,IAAA,IAAQ,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,GAAY,CAAA,CAAE,IAAA,CAAa,EAAE,CAAA,GAAI,MAAA,CAAA;AAAA,EACzF,CAAA;AACA,EAAA,MAAM,EAAA,GAAK,EAAE,GAAG,EAAA,EAAI,GAAI,CAAA,CAAE,KAAA,KAAU,MAAA,GAAY,KAAK,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,IAAU,QAAA,EAAS;AACnF,EAAA,IAAI,EAAE,UAAA,KAAe,MAAA,EAAW,OAAO,CAAC,MAAM,YAAA,CAAa,CAAA,CAAE,MAAA,EAAQ,CAAC,KAAK,CAAC,CAAC,CAAA,EAAG,EAAE,EAAE,CAAC,CAAA;AACrF,EAAA,IAAI,EAAE,KAAA,KAAU,MAAA;AACd,IAAA,MAAM,IAAI,UAAA;AAAA,MACR;AAAA,KACF;AACF,EAAA,MAAM,QAAQ,CAAA,CAAE,KAAA;AAEhB,EAAA,MAAM,OAAA,GAAU,YAAA,CAAa,CAAA,CAAE,MAAA,EAAQ,KAAA,EAAO,EAAE,GAAG,EAAA,EAAI,UAAA,EAAY,CAAA,CAAE,UAAA,EAAY,CAAA;AACjF,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,KAAA,EAA2B,CAAA,CAAE,QAAQ,EAAE,CAAA;AAC/D,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAoB;AACrC,EAAA,GAAA,CAAI,OAAA,CAAQ,CAAC,EAAA,EAAI,CAAA,KAAM;AACrB,IAAA,IAAI,EAAA,KAAO,MAAA,IAAa,CAAC,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,OAAA,CAAQ,CAAC,CAAW,CAAA;AAAA,EAC1E,CAAC,CAAA;AACD,EAAA,OAAO,CAAC,CAAA,KAAM;AACZ,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,MAAM,EAAA,GAAK,YAAY,CAAC,GAAG,GAAG,CAAA,CAAE,MAAA,EAAQ,EAAE,CAAA,CAAE,CAAC,CAAA;AAC7C,IAAA,MAAM,IAAI,EAAA,KAAO,MAAA,GAAY,MAAA,GAAY,IAAA,CAAK,IAAI,EAAE,CAAA;AACpD,IAAA,IAAI,CAAA,KAAM,UAAa,EAAA,KAAO,MAAA;AAC5B,MAAA,IAAA;AAAA,QACE,CAAA,gBAAA,EAAmB,CAAA,CAAE,MAAM,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AAAA,QACjC,CAAA,YAAA,EAAe,MAAA,CAAO,GAAG,CAAC,CAAA,uCAAA;AAAA,OAC5B;AACF,IAAA,OAAO,CAAA,IAAK,QAAA;AAAA,EACd,CAAA;AACF","file":"chunk-RPVVJY74.js","sourcesContent":["/**\n * The nivo adapter: team colours as a chart's `colors`, team logos as a custom layer over a Bump, SwarmPlot or Chord\n * (`logoLayer`), and logos as the nodes themselves (`logoNode`, a SwarmPlot `circleComponent` or a Bump\n * `pointComponent`). Pure: nivo is never imported (the prop types here are structural, read from nivo 0.99); React's\n * `createElement` builds the SVG `<image>` each one returns. Call after `loadLeague(league)` / `preloadAll()`. The\n * ready-made chart is a component, `<LogoBump>` in `sdvplot/react`.\n */\nimport { type ReactElement, createElement } from \"react\";\nimport {\n type Row,\n aspect,\n checkAlpha,\n checkHeight,\n colorPalette,\n imageSource,\n place,\n seasons,\n} from \"./_web.js\";\nimport { InputError, UnsupportedTargetError, warn } from \"./errors.js\";\nimport { type Placement, placedName } from \"./placement.js\";\nimport { type Value, resolveSync } from \"./resolve.js\";\nimport type { IdSystem, League, MarkType, SeasonInput, Variant, Which } from \"./types.js\";\nexport type { Row } from \"./_web.js\";\nexport { embedSources } from \"./_web.js\"; // public: build `embed` with it, as for the other adapters\n\n/** A Bump point as nivo computes it: the subset read here. */\nexport interface NivoBumpPoint {\n /** The point's centre in px, inside the plot area. */\n x: number;\n y: number | null;\n /** Its diameter in px (the chart's `pointSize`). */\n size?: number;\n /** The series: `id`, and `data`, the series object the chart was given (with any extra fields). */\n serie: { id: string; data?: object };\n}\n/** A SwarmPlot node as nivo computes it: the subset read here. */\nexport interface NivoNode {\n /** The node's id (the chart's `id` accessor). */\n id: string;\n /** The node's centre in px, inside the plot area. */\n x: number;\n y: number;\n /** Its diameter in px (the chart's `size`). */\n size?: number;\n /** The datum the node was drawn from. */\n data?: unknown;\n}\n/** A Chord arc as nivo computes it: the subset read here. Angles in radians, clockwise from 12 o'clock. */\nexport interface NivoArc {\n /** The arc's key (the chart's `keys`). */\n id: string;\n startAngle: number;\n endAngle: number;\n}\n/** What nivo hands a custom layer of a Bump (`points`), a SwarmPlot (`nodes`) or a Chord (`arcs`): the subset read. */\nexport interface NivoLayerProps {\n /** The plot area's height in px (Bump, SwarmPlot). */\n innerHeight?: number;\n /** A Bump's points (only those with a rank: a `null` y has none). */\n points?: readonly NivoBumpPoint[];\n /** A SwarmPlot's nodes. */\n nodes?: readonly NivoNode[];\n /** A Chord's arcs. */\n arcs?: readonly NivoArc[];\n /** The Chord's centre in px: half the plot area's width and height. */\n center?: readonly [number, number];\n /** The Chord ring's outer radius in px. */\n radius?: number;\n}\n/** A nivo custom layer: an SVG group of logos. */\nexport type NivoLayer = (props: NivoLayerProps) => ReactElement | null;\n/** What nivo hands a SwarmPlot `circleComponent` (`node`) or a Bump `pointComponent` (`point`): the subset read. */\nexport interface NivoNodeProps {\n /** A SwarmPlot `circleComponent`'s node. */\n node?: NivoNode;\n /** A Bump `pointComponent`'s point. */\n point?: NivoBumpPoint;\n}\n/** A node component: the logo, or an empty group where none can be drawn (nivo's types want an element). */\nexport type NivoNodeComponent = (props: NivoNodeProps) => ReactElement;\n\ninterface Shared {\n /** The league the teams belong to, e.g. \"nfl\". */\n league: League;\n /**\n * The field holding the team (abbreviation, name or id; see `idSystem`): read from a Bump series' object or a\n * SwarmPlot node's datum. Default: the series' or node's `id`. A Chord arc is read by its id (the chart's `keys`).\n */\n team?: string;\n /** A season (number or string) for every team, or the name of the field holding each one's season. */\n season?: SeasonInput;\n /** Opacity in [0, 1]. Default 1. */\n alpha?: number;\n /** Logo variant, e.g. \"dark\". Default \"default\". */\n variant?: Variant;\n /** How the team values are read. Default \"auto\". */\n idSystem?: IdSystem;\n /** \"logo\" (default) or \"wordmark\". */\n markType?: MarkType;\n /** url → data URI map from `embedSources`, to inline the images. */\n embed?: ReadonlyMap<string, string>;\n}\n/** `logoLayer` options. */\nexport interface NivoLayerOptions extends Shared {\n /**\n * Image height as a fraction of the plot area's height, in (0, 1] (nivo hands a layer the plot's `innerHeight`, so\n * a px value is refused). Default 0.08.\n */\n height?: number;\n /** Which of a Bump series' points get a logo: \"last\" (default: the end of each line), \"first\" or \"all\". */\n at?: \"last\" | \"first\" | \"all\";\n}\n/** `logoNode` options: the logo is as tall as nivo sized the node (the chart's `size` / `pointSize`). */\nexport type NivoNodeOptions = Shared;\n\nconst AT = [\"last\", \"first\", \"all\"] as const;\nconst CHORD_GAP = 4; // px between a Chord's ring and its logos\n\ninterface Target {\n x: number;\n y: number;\n raw: Value;\n row: Row;\n}\nconst field = (id: string, data: unknown, team: string | undefined): Value =>\n (team === undefined ? id : ((data ?? {}) as Row)[team]) as Value;\n\n/** The `<image>` of a placed mark, `h` px tall, centred on (x, y), stamped with what `sdvplot/testing`'s\n * `drawnMarks` reads back (`frame`: the plot height a layer's fraction is of, 1 for a node's px). */\nfunction image(p: Placement, o: Shared, at: Target, h: number, frame: number, alpha: number): ReactElement {\n const kind = o.markType ?? \"logo\";\n const w = h * aspect(p);\n return createElement(\"image\", {\n key: `${p.index}`,\n href: imageSource(p, o.embed),\n x: at.x - w / 2,\n y: at.y - h / 2,\n width: w,\n height: h,\n preserveAspectRatio: \"xMidYMid meet\",\n ...(alpha === 1 ? {} : { opacity: alpha }),\n role: \"img\",\n \"aria-label\": `${placedName(p, o.league, at.raw)} ${kind}`,\n \"data-sdv-id\": p.id,\n \"data-sdv-kind\": kind,\n \"data-sdv-x\": String(at.x),\n \"data-sdv-y\": String(at.y),\n \"data-sdv-frame\": String(frame),\n });\n}\n\n/** placeSync over the targets; a target with no mark is dropped with one warning, as sdvplot/echarts does. */\nfunction placed(ts: readonly Target[], o: Shared): Placement[] {\n const season = seasons(\n ts.map((t) => t.row),\n o.season,\n );\n return place(\n ts.map((t) => t.x),\n ts.map((t) => t.y),\n ts.map((t) => t.raw),\n {\n league: o.league,\n kind: o.markType ?? \"logo\",\n ...(season === undefined ? {} : { season }),\n ...(o.variant === undefined ? {} : { variant: o.variant }),\n ...(o.idSystem === undefined ? {} : { idSystem: o.idSystem }),\n },\n );\n}\n\n/** Each Bump series' first or last point, or every point. Points with no rank (y null) are not in `points`. */\nfunction bumpPoints(points: readonly NivoBumpPoint[], at: (typeof AT)[number]): NivoBumpPoint[] {\n if (at === \"all\") return [...points];\n const pick = new Map<string, NivoBumpPoint>();\n for (const p of points) if (at === \"last\" || !pick.has(p.serie.id)) pick.set(p.serie.id, p);\n return [...pick.values()];\n}\n\n/**\n * Team logos as a nivo custom layer: add it to a chart's `layers`, after the built-in ones it should sit over.\n * - Bump: a logo at each series' last point (`at` picks the first, or every point), the team read from the series'\n * `id` (or its `team` field).\n * - SwarmPlot: a logo at every node, the team read from the node's `id` (or its datum's `team` field).\n * - Chord: a logo outside the ring at the middle of each arc, the team read from the arc's id (the chart's `keys`).\n *\n * Logos are `height` × the plot height tall. Given your own `layers`, put the logo layer before `\"mesh\"`; appended after\n * it, it is harmless (its group has `pointer-events: none`, so the mesh still gets the mouse). A team with no logo draws nothing and warns once, as `sdvplot/echarts`\n * does. The logos sit at nivo's final positions: they do not tween with `animate`.\n *\n * @example\n * ```tsx\n * import { SwarmPlot } from \"@nivo/swarmplot\";\n * import { loadLeague } from \"@sportsdataverse/sdvplot\";\n * import { logoLayer, teamColors } from \"@sportsdataverse/sdvplot/nivo\";\n *\n * await loadLeague(\"nfl\");\n * const rows = [\n * { team: \"KC\", pf: 385 },\n * { team: \"LAC\", pf: 402 },\n * { team: \"DEN\", pf: 425 },\n * ];\n * <SwarmPlot\n * width={500}\n * height={200}\n * data={rows.map((r) => ({ ...r, group: \"AFC West\" }))}\n * groups={[\"AFC West\"]}\n * id=\"team\"\n * value=\"pf\"\n * size={10}\n * colors={teamColors({ league: \"nfl\" })}\n * layers={[\"grid\", \"axes\", \"circles\", logoLayer({ league: \"nfl\", height: 0.2 })]}\n * />;\n * ```\n */\nexport function logoLayer(o: NivoLayerOptions): NivoLayer {\n const height = checkHeight(o.height ?? 0.08);\n const alpha = checkAlpha(o.alpha ?? 1);\n const at = o.at ?? \"last\";\n if (!AT.includes(at))\n throw new InputError(`at must be \"last\", \"first\" or \"all\", got ${JSON.stringify(at)}`);\n return function SdvLogoLayer(props) {\n let frame: number;\n let ts: Target[];\n let chord: { cx: number; cy: number; radius: number; mids: number[] } | undefined;\n if (props.points !== undefined) {\n frame = props.innerHeight ?? 0;\n ts = bumpPoints(props.points, at).flatMap((p) =>\n p.y === null\n ? []\n : [\n {\n x: p.x,\n y: p.y,\n raw: field(p.serie.id, p.serie.data, o.team),\n row: (p.serie.data ?? {}) as Row,\n },\n ],\n );\n } else if (props.nodes !== undefined) {\n frame = props.innerHeight ?? 0;\n ts = props.nodes.map((n) => ({\n x: n.x,\n y: n.y,\n raw: field(n.id, n.data, o.team),\n row: (n.data ?? {}) as Row,\n }));\n } else if (props.arcs !== undefined && props.center !== undefined && props.radius !== undefined) {\n const [cx, cy] = props.center;\n frame = 2 * cy; // nivo centres the chord in the plot area\n // placed below, once each mark's aspect is known\n chord = { cx, cy, radius: props.radius, mids: props.arcs.map((a) => (a.startAngle + a.endAngle) / 2) };\n ts = props.arcs.map((a) => ({ x: cx, y: cy, raw: a.id as Value, row: {} }));\n } else\n throw new UnsupportedTargetError(\n `logoLayer draws on a nivo Bump (points), SwarmPlot (nodes) or Chord (arcs) layer; got props ${Object.keys(props).join(\", \")}`,\n );\n const ps = placed(ts, o);\n if (chord !== undefined)\n for (const p of ps) {\n // clear the ring by the mark's half-extent along its radius: a w x h box reaches |sin m| w/2 + |cos m| h/2\n const m = chord.mids[p.index] as number;\n const h = height * frame;\n const r =\n chord.radius + (Math.abs(Math.sin(m)) * h * aspect(p)) / 2 + (Math.abs(Math.cos(m)) * h) / 2;\n const t = ts[p.index] as Target;\n t.x = chord.cx + (r + CHORD_GAP) * Math.sin(m);\n t.y = chord.cy - (r + CHORD_GAP) * Math.cos(m);\n }\n return createElement(\n \"g\",\n { \"data-sdv-layer\": \"logos\", pointerEvents: \"none\" }, // the lines and nodes under it keep their mouse events\n ps.map((p) => image(p, o, ts[p.index] as Target, height * frame, frame, alpha)),\n );\n };\n}\n\n/**\n * Team logos as the nodes themselves: a SwarmPlot's `circleComponent` or a Bump's `pointComponent`. Each logo is as\n * tall as nivo sized the node (the chart's `size` or `pointSize`, in px) and replaces its circle; the team is read as\n * `logoLayer` reads it. A team with no logo draws nothing and warns once. The logo sits at the node's final position:\n * it does not tween with `animate`.\n */\nexport function logoNode(o: NivoNodeOptions): NivoNodeComponent {\n if (\"height\" in o)\n throw new InputError(\n \"logoNode takes no height: each logo is as tall as nivo sized the node (the chart's size or pointSize, in px)\",\n );\n const alpha = checkAlpha(o.alpha ?? 1);\n return function SdvLogoNode({ node, point }) {\n const n = node ?? point;\n const t: Target | undefined =\n n === undefined || n.y === null\n ? undefined\n : node !== undefined\n ? { x: node.x, y: node.y, raw: field(node.id, node.data, o.team), row: (node.data ?? {}) as Row }\n : point !== undefined && point.y !== null\n ? {\n x: point.x,\n y: point.y,\n raw: field(point.serie.id, point.serie.data, o.team),\n row: (point.serie.data ?? {}) as Row,\n }\n : undefined;\n const size = n?.size ?? 0;\n const p = t === undefined || !(size > 0) ? undefined : placed([t], o)[0];\n // ponytail: the frame is 1, so drawnMarks' height reads in px (a node component gets no plot height)\n return p === undefined\n ? createElement(\"g\")\n : createElement(\"g\", null, image(p, o, t as Target, size, 1, alpha));\n };\n}\n\n/** `teamColors` options. */\nexport interface NivoColorOptions {\n /** The league the teams belong to, e.g. \"nfl\". */\n league: League;\n /**\n * The field holding the team: read from the datum nivo hands `colors` (a Bump series, a Chord arc), else from its\n * `data` (a SwarmPlot node's datum). Default \"id\".\n */\n by?: string;\n /** Every team the chart draws, in order. Needed with `background`: the palette keeps them apart from each other. */\n teams?: readonly unknown[];\n /** \"primary\" (default) or \"secondary\" colour. */\n which?: Which;\n /** The season the teams are resolved for (a number or string). */\n season?: SeasonInput;\n /** How the team values are read. Default \"auto\". */\n idSystem?: IdSystem;\n /** The colour of an unresolved team. Default \"#808080\". */\n fallback?: string;\n /**\n * The chart's background. Given, a team colour under 3:1 contrast against it is swapped for the team's other\n * colour, else moved towards white (on a dark background) or black (a light one) until it reads: dark mode. A\n * colour that would then sit too close to an earlier team's (CIE76 ΔE under 20) takes the team's other colour, or\n * the nearest colour to its own (lightness, hue or chroma stepped) that is distinct and still reads; failing that it\n * is kept, with one warning.\n */\n background?: string;\n}\n/**\n * A nivo `colors` accessor: each datum's team colour. A Bump series and a Chord arc are read by `id`; for a SwarmPlot\n * pass `by: \"<team field>\"`. With `background` (and `teams`), every colour keeps 3:1 contrast against it (dark mode)\n * and aims to stay distinct from the others (when it cannot, it keeps the readable colour and warns once).\n *\n * @example\n * ```ts\n * import { loadLeague } from \"@sportsdataverse/sdvplot\";\n * import { teamColors } from \"@sportsdataverse/sdvplot/nivo\";\n *\n * await loadLeague(\"nfl\");\n * const colors = teamColors({ league: \"nfl\", teams: [\"KC\", \"LAC\", \"DEN\", \"LV\"], background: \"#181a1b\" });\n * [\"KC\", \"LAC\", \"DEN\", \"LV\"].map((id) => colors({ id }));\n * ```\n */\nexport function teamColors(o: NivoColorOptions): (datum: object) => string {\n const fallback = o.fallback ?? \"#808080\";\n const by = o.by ?? \"id\";\n const co = {\n ...(o.season === undefined ? {} : { season: o.season }),\n ...(o.idSystem === undefined ? {} : { idSystem: o.idSystem }),\n };\n const read = (d: object): unknown => {\n const r = d as Row;\n return r[by] ?? (r.data !== null && typeof r.data === \"object\" ? (r.data as Row)[by] : undefined);\n };\n const po = { ...co, ...(o.which === undefined ? {} : { which: o.which }), fallback };\n if (o.background === undefined) return (d) => colorPalette(o.league, [read(d)], po)[0] as string;\n if (o.teams === undefined)\n throw new InputError(\n \"teamColors: background needs teams, every team the chart draws (the palette keeps them apart)\",\n );\n const teams = o.teams;\n // the shared palette, over the resolved teams: an alias or an unresolved value takes no slot of its own\n const palette = colorPalette(o.league, teams, { ...po, background: o.background });\n const ids = resolveSync(teams as readonly Value[], o.league, co);\n const byId = new Map<string, string>();\n ids.forEach((id, i) => {\n if (id !== undefined && !byId.has(id)) byId.set(id, palette[i] as string);\n });\n return (d) => {\n const raw = read(d) as Value;\n const id = resolveSync([raw], o.league, co)[0];\n const c = id === undefined ? undefined : byId.get(id);\n if (c === undefined && id !== undefined)\n warn(\n `nivo:teamColors:${o.league}:${id}`,\n `teamColors: ${String(raw)} is not in teams: drawn in the fallback`,\n );\n return c ?? fallback;\n };\n}\n"]}