@sportsdataverse/sdvplot 0.0.0-stage → 0.1.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 (166) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +94 -0
  3. package/README.md +908 -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 +132 -0
  22. package/dist/chartjs.js +339 -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-C2CDY5OG.js +137 -0
  27. package/dist/chunk-C2CDY5OG.js.map +1 -0
  28. package/dist/chunk-E7G7VSLV.js +43 -0
  29. package/dist/chunk-E7G7VSLV.js.map +1 -0
  30. package/dist/chunk-J6R2LEJ7.js +58 -0
  31. package/dist/chunk-J6R2LEJ7.js.map +1 -0
  32. package/dist/chunk-JJFTD4VB.js +175 -0
  33. package/dist/chunk-JJFTD4VB.js.map +1 -0
  34. package/dist/chunk-KKH6ABMA.js +223 -0
  35. package/dist/chunk-KKH6ABMA.js.map +1 -0
  36. package/dist/chunk-NLPH2VZT.js +127 -0
  37. package/dist/chunk-NLPH2VZT.js.map +1 -0
  38. package/dist/chunk-OKEE4AH6.js +30 -0
  39. package/dist/chunk-OKEE4AH6.js.map +1 -0
  40. package/dist/chunk-QY65DUEF.js +306 -0
  41. package/dist/chunk-QY65DUEF.js.map +1 -0
  42. package/dist/chunk-RMT2GMFH.js +97 -0
  43. package/dist/chunk-RMT2GMFH.js.map +1 -0
  44. package/dist/chunk-SEBO35DV.js +76 -0
  45. package/dist/chunk-SEBO35DV.js.map +1 -0
  46. package/dist/chunk-TAXO3VXH.js +556 -0
  47. package/dist/chunk-TAXO3VXH.js.map +1 -0
  48. package/dist/chunk-TDNBAEQB.js +105 -0
  49. package/dist/chunk-TDNBAEQB.js.map +1 -0
  50. package/dist/cricket-KPCYG2HL.js +493 -0
  51. package/dist/cricket-NDXLE25B.js +116 -0
  52. package/dist/cricket-YUUF7P6M.js +160 -0
  53. package/dist/d3.d.ts +234 -0
  54. package/dist/d3.js +198 -0
  55. package/dist/d3.js.map +1 -0
  56. package/dist/echarts.d.ts +121 -0
  57. package/dist/echarts.js +228 -0
  58. package/dist/echarts.js.map +1 -0
  59. package/dist/echl-3CR4RGFC.js +241 -0
  60. package/dist/echl-NPC32C23.js +107 -0
  61. package/dist/echl-PI33DGJC.js +64 -0
  62. package/dist/export.d.ts +130 -0
  63. package/dist/export.js +258 -0
  64. package/dist/export.js.map +1 -0
  65. package/dist/headshots-B2J_LOO8.d.ts +40 -0
  66. package/dist/index.d.ts +182 -0
  67. package/dist/index.js +10 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/interact.d.ts +567 -0
  70. package/dist/interact.js +809 -0
  71. package/dist/interact.js.map +1 -0
  72. package/dist/marks-DH-tQIP-.d.ts +75 -0
  73. package/dist/mbb-3TRLVW3H.js +3619 -0
  74. package/dist/mbb-DQUHCHZP.js +5111 -0
  75. package/dist/mbb-PRAIO2P5.js +371 -0
  76. package/dist/milb-6IQ6NCEW.js +291 -0
  77. package/dist/milb-EYY5MD4T.js +1752 -0
  78. package/dist/milb-EYZ4SZLI.js +797 -0
  79. package/dist/mlb-4PBUJSVQ.js +35 -0
  80. package/dist/mlb-FHPY3GQJ.js +701 -0
  81. package/dist/mlb-REVGL3N2.js +665 -0
  82. package/dist/nba-ATT775GS.js +485 -0
  83. package/dist/nba-LKM4UHVU.js +482 -0
  84. package/dist/nba-YX7PXM3R.js +35 -0
  85. package/dist/nbagl-3WGZCZ4S.js +37 -0
  86. package/dist/nbagl-LP4XJRAL.js +229 -0
  87. package/dist/nbagl-VTTOU7LN.js +499 -0
  88. package/dist/ncaa_baseball-UV75LNVR.js +2670 -0
  89. package/dist/ncaa_baseball-VD5J5C72.js +419 -0
  90. package/dist/ncaa_baseball-YRBS32D6.js +4592 -0
  91. package/dist/ncaa_mhockey-IMYHS7QS.js +1033 -0
  92. package/dist/ncaa_mhockey-TXTKWHE3.js +115 -0
  93. package/dist/ncaa_mhockey-U3MFW5VT.js +663 -0
  94. package/dist/ncaa_softball-6WR6KS64.js +420 -0
  95. package/dist/ncaa_softball-RZCTIE56.js +2654 -0
  96. package/dist/ncaa_softball-VOD4PVGY.js +4599 -0
  97. package/dist/ncaa_whockey-6XXGUTBK.js +607 -0
  98. package/dist/ncaa_whockey-AKKYKY67.js +53 -0
  99. package/dist/ncaa_whockey-KBEKXFBB.js +293 -0
  100. package/dist/nfl-BDB2HYAR.js +625 -0
  101. package/dist/nfl-EHYHDLJD.js +37 -0
  102. package/dist/nfl-VF4NJCHY.js +514 -0
  103. package/dist/nfl_gsis-UY64JO37.js +4 -0
  104. package/dist/nhl-6WPHME7H.js +511 -0
  105. package/dist/nhl-EMIJFZHY.js +884 -0
  106. package/dist/nhl-ISFUKRFU.js +37 -0
  107. package/dist/ohl-2FEM554G.js +113 -0
  108. package/dist/ohl-C5Q4W6JB.js +32 -0
  109. package/dist/ohl-TQ4J46VC.js +66 -0
  110. package/dist/phf-H7POU2KW.js +32 -0
  111. package/dist/phf-K5IFMZUM.js +13 -0
  112. package/dist/phf-TWJI3BOW.js +20 -0
  113. package/dist/plot.d.ts +449 -0
  114. package/dist/plot.js +711 -0
  115. package/dist/plot.js.map +1 -0
  116. package/dist/plotly.d.ts +129 -0
  117. package/dist/plotly.js +360 -0
  118. package/dist/plotly.js.map +1 -0
  119. package/dist/pwhl-OX3BO4JI.js +53 -0
  120. package/dist/pwhl-W44OC3C6.js +17 -0
  121. package/dist/pwhl-ZJGG3H7W.js +23 -0
  122. package/dist/qmjhl-5HISEHLL.js +35 -0
  123. package/dist/qmjhl-DA3UHKE5.js +125 -0
  124. package/dist/qmjhl-YG4BOQPF.js +614 -0
  125. package/dist/react.d.ts +101 -0
  126. package/dist/react.js +164 -0
  127. package/dist/react.js.map +1 -0
  128. package/dist/resolve-CQW-jzvr.d.ts +28 -0
  129. package/dist/selection-D4T3PkRt.d.ts +140 -0
  130. package/dist/shots.d.ts +364 -0
  131. package/dist/shots.js +85 -0
  132. package/dist/shots.js.map +1 -0
  133. package/dist/soccer-7BH3ZLVL.js +7898 -0
  134. package/dist/soccer-MRU25OGE.js +2636 -0
  135. package/dist/soccer-PF4IPPVA.js +12342 -0
  136. package/dist/surfaces-ChaD9nei.d.ts +38 -0
  137. package/dist/testing.d.ts +75 -0
  138. package/dist/testing.js +240 -0
  139. package/dist/testing.js.map +1 -0
  140. package/dist/tiers-B6pUBPcE.d.ts +93 -0
  141. package/dist/types-C7n6gJF3.d.ts +62 -0
  142. package/dist/ufl-7VLZTLTT.js +143 -0
  143. package/dist/ufl-CCMBLPSW.js +100 -0
  144. package/dist/ufl-F2BJRXME.js +16 -0
  145. package/dist/usfl-4CR5RMZJ.js +32 -0
  146. package/dist/usfl-LD7HP2YK.js +14 -0
  147. package/dist/usfl-VU4YSJQD.js +19 -0
  148. package/dist/ushl-CPG2LB4L.js +73 -0
  149. package/dist/ushl-PQL6HJAD.js +88 -0
  150. package/dist/ushl-ZT2ATPHK.js +22 -0
  151. package/dist/vega.d.ts +85 -0
  152. package/dist/vega.js +362 -0
  153. package/dist/vega.js.map +1 -0
  154. package/dist/wbb-3KHCDYTK.js +5087 -0
  155. package/dist/wbb-BMX53Q3Q.js +369 -0
  156. package/dist/wbb-QNRN2CJJ.js +3620 -0
  157. package/dist/whl-4ATYZWUB.js +97 -0
  158. package/dist/whl-RVFPL6MH.js +79 -0
  159. package/dist/whl-Y7ASKYMM.js +28 -0
  160. package/dist/wnba-FWX5SFVI.js +232 -0
  161. package/dist/wnba-GX6HZR4B.js +220 -0
  162. package/dist/wnba-NTMWIPP6.js +20 -0
  163. package/dist/xfl-43R2JMJK.js +30 -0
  164. package/dist/xfl-H3BXQPZZ.js +16 -0
  165. package/dist/xfl-XON7A7FI.js +69 -0
  166. package/package.json +154 -3
@@ -0,0 +1,76 @@
1
+ import { placeSync } from './chunk-RMT2GMFH.js';
2
+ import { HEADSHOT_ASPECT, teamColorsSync } from './chunk-TAXO3VXH.js';
3
+ import { InputError, DownloadError } from './chunk-E7G7VSLV.js';
4
+
5
+ // src/_web.ts
6
+ function aspect(p) {
7
+ return p.aspect ?? HEADSHOT_ASPECT;
8
+ }
9
+ function axisLetter(axis) {
10
+ if (axis !== "x" && axis !== "y")
11
+ throw new InputError(`axis must be "x" or "y", got ${JSON.stringify(axis)}`);
12
+ return axis;
13
+ }
14
+ function imageSource(p, embed) {
15
+ return embed?.get(p.url) ?? encodeURI(p.url).replace(/%25([0-9A-Fa-f]{2})/g, "%$1");
16
+ }
17
+ function imageSources(ps, embed) {
18
+ return ps.map((p) => imageSource(p, embed));
19
+ }
20
+ async function embedSources(urls, fetchFn = fetch) {
21
+ const out = /* @__PURE__ */ new Map();
22
+ for (const url of new Set(urls)) {
23
+ const res = await fetchFn(url);
24
+ if (!res.ok) throw new DownloadError(`embed: ${url} answered ${res.status}`, url, res.status);
25
+ const mime = res.headers.get("content-type")?.split(";")[0]?.trim() || (url.toLowerCase().endsWith(".svg") ? "image/svg+xml" : "application/octet-stream");
26
+ const bytes = new Uint8Array(await res.arrayBuffer());
27
+ let bin = "";
28
+ for (const b of bytes) bin += String.fromCharCode(b);
29
+ out.set(url, `data:${mime};base64,${btoa(bin)}`);
30
+ }
31
+ return out;
32
+ }
33
+ function column(rows, name, what) {
34
+ if (rows.length > 0 && !rows.some((r) => name in r))
35
+ throw new InputError(`${what} column ${JSON.stringify(name)} is not in rows`);
36
+ return rows.map((r) => r[name]);
37
+ }
38
+ function seasons(rows, season) {
39
+ if (typeof season === "string" && rows.some((r) => season in r))
40
+ return rows.map((r) => r[season]);
41
+ return season;
42
+ }
43
+ function markPlacements(rows, kind, o) {
44
+ const xs = column(rows, o.x, "x");
45
+ const ys = column(rows, o.y, "y");
46
+ if (kind === "headshot") {
47
+ const h = o;
48
+ return placeSync(xs, ys, column(rows, h.player, "player"), {
49
+ league: h.league,
50
+ kind,
51
+ idSystem: h.idSystem ?? "espn"
52
+ });
53
+ }
54
+ const m = o;
55
+ const po = { league: m.league, kind };
56
+ if (m.season !== void 0) po.season = seasons(rows, m.season);
57
+ if (m.variant !== void 0) po.variant = m.variant;
58
+ if (m.idSystem !== void 0) po.idSystem = m.idSystem;
59
+ return placeSync(xs, ys, column(rows, m.team, "team"), po);
60
+ }
61
+ function axisPlacements(labels, letter, o) {
62
+ const index = labels.map((_, i) => i);
63
+ const across = labels.map(() => 0);
64
+ const po = { league: o.league, kind: o.markType ?? "logo" };
65
+ if (o.season !== void 0) po.season = o.season;
66
+ if (o.variant !== void 0) po.variant = o.variant;
67
+ if (o.idSystem !== void 0) po.idSystem = o.idSystem;
68
+ return placeSync(letter === "x" ? index : across, letter === "x" ? across : index, labels, po);
69
+ }
70
+ function colorList(league, teams, o = {}) {
71
+ return teamColorsSync(league, teams, o).map((c) => c ?? null);
72
+ }
73
+
74
+ export { aspect, axisLetter, axisPlacements, colorList, embedSources, imageSources, markPlacements };
75
+ //# sourceMappingURL=chunk-SEBO35DV.js.map
76
+ //# sourceMappingURL=chunk-SEBO35DV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/_web.ts"],"names":[],"mappings":"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","file":"chunk-SEBO35DV.js","sourcesContent":["/** What the spec adapters (Plotly, Vega-Lite, ECharts) share: image sources, aspect ratios, row access, team colours. */\nimport { teamColorsSync } from \"./colors.js\";\nimport { DownloadError, InputError } from \"./errors.js\";\nimport { HEADSHOT_ASPECT } from \"./headshots.js\";\nimport { type Kind, type PlaceOptions, type Placement, placeSync as place } from \"./placement.js\";\nimport type { Value } from \"./resolve.js\";\nimport type { IdSystem, League, MarkType, SeasonInput, Variant } from \"./types.js\";\n\nexport type { Placement } from \"./placement.js\";\nexport { checkAlpha, checkHeight, placeSync as place } from \"./placement.js\";\n\n/** What the module-level test hooks return. Positional on purpose (cheap to assert); the contract shim in test/adapters.contract.test.ts converts. */\nexport type DrawnMark = readonly [id: string, x: unknown, y: unknown, height: number, url: string];\nexport type DrawnAxisMark = readonly [id: string, index: number, height: number];\n\nexport type Row = Record<string, unknown>;\n/** Options of `withLogos` / `withWordmarks` (each adapter adds its own subplot options). */\nexport interface MarkOptions {\n /** Name of the row column holding each mark's x position. */\n x: string;\n /** Name of the row column holding each mark's y position. */\n y: string;\n /** Name of the row column holding the team (abbreviation, name or id; see `idSystem`). */\n team: string;\n /** The league the teams (or players) belong to, e.g. \"nfl\". */\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 /** Mark height as a fraction of the plot area's height, in (0, 1]. Default 0.1. */\n height?: number;\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 /** url → data URI map from `embedSources`, to inline the images. */\n embed?: ReadonlyMap<string, string>;\n}\n/** Options of `withHeadshots`. */\nexport interface HeadshotOptions {\n /** Name of the row column holding each headshot's x position. */\n x: string;\n /** Name of the row column holding each headshot's y position. */\n y: string;\n /** Name of the row column holding the player id. */\n player: string;\n /** The league the teams (or players) belong to, e.g. \"nfl\". */\n league: League;\n /** Headshot height as a fraction of the plot area's height, in (0, 1]. Default 0.1. */\n height?: number;\n /** Opacity in [0, 1]. Default 1. */\n alpha?: number;\n /** What the `player` ids are: ESPN athlete ids, or nflverse gsis ids (needs `loadGsis()` first). Default \"espn\". */\n idSystem?: \"espn\" | \"gsis\";\n /** url → data URI map from `embedSources`, to inline the images. */\n embed?: ReadonlyMap<string, string>;\n}\n/** Options of `withAxisLogos`: the categories of the axis are the teams. */\nexport interface AxisOptions {\n /** The league the teams (or players) belong to, e.g. \"nfl\". */\n league: League;\n /** The season the axis' teams are resolved for. */\n season?: SeasonInput;\n /** Image height as a fraction of the plot area's height, in (0, 1]. Default 0.1. */\n height?: 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\nexport function aspect(p: Placement): number {\n return p.aspect ?? HEADSHOT_ASPECT;\n}\n\nexport function axisLetter(axis: string): \"x\" | \"y\" {\n if (axis !== \"x\" && axis !== \"y\")\n throw new InputError(`axis must be \"x\" or \"y\", got ${JSON.stringify(axis)}`);\n return axis;\n}\n\n// encodeURI keeps the URL punctuation Python's SAFE_URL keeps (-._~:/?#[]@!$&()*+,;=%) and escapes the rest, so an\n// unvalidated URL still cannot close an attribute the adapter writes it into. `%` is re-escaped only when it does not\n// already start a %XX escape.\nexport function imageSource(p: Placement, embed?: ReadonlyMap<string, string>): string {\n return embed?.get(p.url) ?? encodeURI(p.url).replace(/%25([0-9A-Fa-f]{2})/g, \"%$1\");\n}\nexport function imageSources(ps: readonly Placement[], embed?: ReadonlyMap<string, string>): string[] {\n return ps.map((p) => imageSource(p, embed));\n}\n\n/** Data URIs for each distinct url, fetched once each. The one async helper of the adapters: call it, then pass the map as `embed`. */\nexport async function embedSources(\n urls: Iterable<string>,\n fetchFn: typeof fetch = fetch,\n): Promise<Map<string, string>> {\n const out = new Map<string, string>();\n for (const url of new Set(urls)) {\n const res = await fetchFn(url);\n if (!res.ok) throw new DownloadError(`embed: ${url} answered ${res.status}`, url, res.status);\n // `||`: an empty content-type header falls back to the inferred type too\n const mime =\n res.headers.get(\"content-type\")?.split(\";\")[0]?.trim() ||\n (url.toLowerCase().endsWith(\".svg\") ? \"image/svg+xml\" : \"application/octet-stream\");\n const bytes = new Uint8Array(await res.arrayBuffer());\n let bin = \"\";\n for (const b of bytes) bin += String.fromCharCode(b);\n out.set(url, `data:${mime};base64,${btoa(bin)}`);\n }\n return out;\n}\n\n// Cells are typed Value for placeSync; a Date (temporal x) or any other cell passes through it untouched.\nexport function column(rows: readonly Row[], name: string, what: string): Value[] {\n if (rows.length > 0 && !rows.some((r) => name in r))\n throw new InputError(`${what} column ${JSON.stringify(name)} is not in rows`);\n return rows.map((r) => r[name] as Value);\n}\n\nexport function seasons(\n rows: readonly Row[],\n season: MarkOptions[\"season\"],\n): readonly SeasonInput[] | SeasonInput {\n if (typeof season === \"string\" && rows.some((r) => season in r))\n return rows.map((r) => r[season] as SeasonInput);\n return season as SeasonInput;\n}\n\n/** placeSync over row columns (x, y, team or player, season value or column), leaving out options the caller left out. */\nexport function markPlacements(\n rows: readonly Row[],\n kind: Kind,\n o: MarkOptions | HeadshotOptions,\n): Placement[] {\n const xs = column(rows, o.x, \"x\");\n const ys = column(rows, o.y, \"y\");\n if (kind === \"headshot\") {\n const h = o as HeadshotOptions;\n return place(xs, ys, column(rows, h.player, \"player\"), {\n league: h.league,\n kind,\n idSystem: h.idSystem ?? \"espn\",\n });\n }\n const m = o as MarkOptions;\n const po: PlaceOptions = { league: m.league, kind };\n if (m.season !== undefined) po.season = seasons(rows, m.season);\n if (m.variant !== undefined) po.variant = m.variant;\n if (m.idSystem !== undefined) po.idSystem = m.idSystem;\n return place(xs, ys, column(rows, m.team, \"team\"), po);\n}\n/** placeSync over a category axis: label i sits at index i along `letter` and 0 across, so `p.x`/`p.y` is its tick index. */\nexport function axisPlacements(labels: readonly string[], letter: \"x\" | \"y\", o: AxisOptions): Placement[] {\n const index = labels.map((_, i) => i);\n const across = labels.map(() => 0);\n const po: PlaceOptions = { league: o.league, kind: o.markType ?? \"logo\" };\n if (o.season !== undefined) po.season = o.season;\n if (o.variant !== undefined) po.variant = o.variant;\n if (o.idSystem !== undefined) po.idSystem = o.idSystem;\n return place(letter === \"x\" ? index : across, letter === \"x\" ? across : index, labels, po);\n}\n\nexport function colorList(\n league: League,\n teams: readonly unknown[],\n o: { which?: \"primary\" | \"secondary\"; season?: SeasonInput; idSystem?: IdSystem } = {},\n): (string | null)[] {\n return teamColorsSync(league, teams as readonly Value[], o).map((c) => c ?? null);\n}\n"]}
@@ -0,0 +1,556 @@
1
+ import { InputError, warn, UnresolvedTeamError } from './chunk-E7G7VSLV.js';
2
+
3
+ // src/types.ts
4
+ var asTeamId = (s) => s;
5
+ var PRIORITY = [
6
+ "team_id",
7
+ "espn",
8
+ "espn_abbr",
9
+ "nhl",
10
+ "nflverse",
11
+ "mlbstats",
12
+ "nba_api",
13
+ "hockeytech",
14
+ "ncaa",
15
+ "pff",
16
+ "cricinfo",
17
+ "cfbd",
18
+ "bref",
19
+ "sportsipy",
20
+ "fangraphs",
21
+ "sdvplotr",
22
+ "name"
23
+ ];
24
+ var EXPLICIT_ONLY = ["nhl_id"];
25
+
26
+ // src/data/index.ts
27
+ var LEAGUES = ["aaf", "ahl", "cfb", "cricket", "echl", "mbb", "milb", "mlb", "nba", "nbagl", "ncaa_baseball", "ncaa_mhockey", "ncaa_softball", "ncaa_whockey", "nfl", "nhl", "ohl", "phf", "pwhl", "qmjhl", "soccer", "ufl", "usfl", "ushl", "wbb", "whl", "wnba", "xfl"];
28
+ var INDEX_VERSION = "1c025b69f8cf";
29
+ var MANIFEST_LAST_MODIFIED = "2026-10-06";
30
+ var VARIANTS = ["alternate", "cap_on_dark", "cap_on_light", "cricinfo", "crop_64px", "dark", "default", "grayscale", "large", "logo2", "medium", "on_dark", "on_light", "primary_logo_black", "primary_logo_on_black_color", "primary_logo_on_primary_color", "primary_logo_on_secondary_color", "primary_logo_on_white_color", "primary_logo_white", "primary_on_dark", "primary_on_light", "scoreboard", "scoreboard_dark", "secondary_logo_black", "secondary_logo_on_black_color", "secondary_logo_on_primary_color", "secondary_logo_on_secondary_color", "secondary_logo_on_white_color", "secondary_logo_white", "sport_pictogram", "squared", "team_strip"];
31
+ var INDEX_FIRST_SEASON = 1871;
32
+ var INDEX_LAST_ALIAS_SEASON = 2027;
33
+ var LEAGUE_META = { "aaf": { "latestSeason": null, "firstSeason": null }, "ahl": { "latestSeason": null, "firstSeason": null }, "cfb": { "latestSeason": null, "firstSeason": null }, "cricket": { "latestSeason": null, "firstSeason": null }, "echl": { "latestSeason": null, "firstSeason": null }, "mbb": { "latestSeason": null, "firstSeason": null }, "milb": { "latestSeason": null, "firstSeason": null }, "mlb": { "latestSeason": 2026, "firstSeason": 1871 }, "nba": { "latestSeason": 2027, "firstSeason": 1947 }, "nbagl": { "latestSeason": null, "firstSeason": null }, "ncaa_baseball": { "latestSeason": null, "firstSeason": null }, "ncaa_mhockey": { "latestSeason": null, "firstSeason": null }, "ncaa_softball": { "latestSeason": null, "firstSeason": null }, "ncaa_whockey": { "latestSeason": null, "firstSeason": null }, "nfl": { "latestSeason": 2026, "firstSeason": 1920 }, "nhl": { "latestSeason": 1997, "firstSeason": null }, "ohl": { "latestSeason": null, "firstSeason": null }, "phf": { "latestSeason": null, "firstSeason": null }, "pwhl": { "latestSeason": null, "firstSeason": null }, "qmjhl": { "latestSeason": null, "firstSeason": null }, "soccer": { "latestSeason": null, "firstSeason": null }, "ufl": { "latestSeason": 2026, "firstSeason": 2024 }, "usfl": { "latestSeason": null, "firstSeason": null }, "ushl": { "latestSeason": null, "firstSeason": null }, "wbb": { "latestSeason": null, "firstSeason": null }, "whl": { "latestSeason": null, "firstSeason": null }, "wnba": { "latestSeason": 2026, "firstSeason": 1997 }, "xfl": { "latestSeason": 2023, "firstSeason": 2020 } };
34
+ var ARCHIVE_BASE = "https://sdv.nyc3.cdn.digitaloceanspaces.com/assets/public/sha256";
35
+ function archiveUrl(sha256, ext) {
36
+ return `${ARCHIVE_BASE}/${sha256.slice(0, 2)}/${sha256}.${ext}`;
37
+ }
38
+ var loaders = {
39
+ "aaf": async () => {
40
+ const [t, a, m] = await Promise.all([import('./aaf-GJ3SH34T.js'), import('./aaf-HCYN5T6Y.js'), import('./aaf-ZAE5KS2Y.js')]);
41
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
42
+ },
43
+ "ahl": async () => {
44
+ const [t, a, m] = await Promise.all([import('./ahl-E66MDVCU.js'), import('./ahl-NPQQWZEV.js'), import('./ahl-QRDU73XX.js')]);
45
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
46
+ },
47
+ "cfb": async () => {
48
+ const [t, a, m] = await Promise.all([import('./cfb-P3SHEYRZ.js'), import('./cfb-WXRZANLP.js'), import('./cfb-F42SVS4X.js')]);
49
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
50
+ },
51
+ "cricket": async () => {
52
+ const [t, a, m] = await Promise.all([import('./cricket-NDXLE25B.js'), import('./cricket-KPCYG2HL.js'), import('./cricket-YUUF7P6M.js')]);
53
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
54
+ },
55
+ "echl": async () => {
56
+ const [t, a, m] = await Promise.all([import('./echl-PI33DGJC.js'), import('./echl-3CR4RGFC.js'), import('./echl-NPC32C23.js')]);
57
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
58
+ },
59
+ "mbb": async () => {
60
+ const [t, a, m] = await Promise.all([import('./mbb-PRAIO2P5.js'), import('./mbb-3TRLVW3H.js'), import('./mbb-DQUHCHZP.js')]);
61
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
62
+ },
63
+ "milb": async () => {
64
+ const [t, a, m] = await Promise.all([import('./milb-6IQ6NCEW.js'), import('./milb-EYY5MD4T.js'), import('./milb-EYZ4SZLI.js')]);
65
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
66
+ },
67
+ "mlb": async () => {
68
+ const [t, a, m] = await Promise.all([import('./mlb-4PBUJSVQ.js'), import('./mlb-FHPY3GQJ.js'), import('./mlb-REVGL3N2.js')]);
69
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
70
+ },
71
+ "nba": async () => {
72
+ const [t, a, m] = await Promise.all([import('./nba-YX7PXM3R.js'), import('./nba-LKM4UHVU.js'), import('./nba-ATT775GS.js')]);
73
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
74
+ },
75
+ "nbagl": async () => {
76
+ const [t, a, m] = await Promise.all([import('./nbagl-3WGZCZ4S.js'), import('./nbagl-LP4XJRAL.js'), import('./nbagl-VTTOU7LN.js')]);
77
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
78
+ },
79
+ "ncaa_baseball": async () => {
80
+ const [t, a, m] = await Promise.all([import('./ncaa_baseball-VD5J5C72.js'), import('./ncaa_baseball-UV75LNVR.js'), import('./ncaa_baseball-YRBS32D6.js')]);
81
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
82
+ },
83
+ "ncaa_mhockey": async () => {
84
+ const [t, a, m] = await Promise.all([import('./ncaa_mhockey-TXTKWHE3.js'), import('./ncaa_mhockey-U3MFW5VT.js'), import('./ncaa_mhockey-IMYHS7QS.js')]);
85
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
86
+ },
87
+ "ncaa_softball": async () => {
88
+ const [t, a, m] = await Promise.all([import('./ncaa_softball-6WR6KS64.js'), import('./ncaa_softball-RZCTIE56.js'), import('./ncaa_softball-VOD4PVGY.js')]);
89
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
90
+ },
91
+ "ncaa_whockey": async () => {
92
+ const [t, a, m] = await Promise.all([import('./ncaa_whockey-AKKYKY67.js'), import('./ncaa_whockey-KBEKXFBB.js'), import('./ncaa_whockey-6XXGUTBK.js')]);
93
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
94
+ },
95
+ "nfl": async () => {
96
+ const [t, a, m] = await Promise.all([import('./nfl-EHYHDLJD.js'), import('./nfl-VF4NJCHY.js'), import('./nfl-BDB2HYAR.js')]);
97
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
98
+ },
99
+ "nhl": async () => {
100
+ const [t, a, m] = await Promise.all([import('./nhl-ISFUKRFU.js'), import('./nhl-6WPHME7H.js'), import('./nhl-EMIJFZHY.js')]);
101
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
102
+ },
103
+ "ohl": async () => {
104
+ const [t, a, m] = await Promise.all([import('./ohl-C5Q4W6JB.js'), import('./ohl-2FEM554G.js'), import('./ohl-TQ4J46VC.js')]);
105
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
106
+ },
107
+ "phf": async () => {
108
+ const [t, a, m] = await Promise.all([import('./phf-K5IFMZUM.js'), import('./phf-H7POU2KW.js'), import('./phf-TWJI3BOW.js')]);
109
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
110
+ },
111
+ "pwhl": async () => {
112
+ const [t, a, m] = await Promise.all([import('./pwhl-W44OC3C6.js'), import('./pwhl-OX3BO4JI.js'), import('./pwhl-ZJGG3H7W.js')]);
113
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
114
+ },
115
+ "qmjhl": async () => {
116
+ const [t, a, m] = await Promise.all([import('./qmjhl-5HISEHLL.js'), import('./qmjhl-DA3UHKE5.js'), import('./qmjhl-YG4BOQPF.js')]);
117
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
118
+ },
119
+ "soccer": async () => {
120
+ const [t, a, m] = await Promise.all([import('./soccer-MRU25OGE.js'), import('./soccer-7BH3ZLVL.js'), import('./soccer-PF4IPPVA.js')]);
121
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
122
+ },
123
+ "ufl": async () => {
124
+ const [t, a, m] = await Promise.all([import('./ufl-F2BJRXME.js'), import('./ufl-CCMBLPSW.js'), import('./ufl-7VLZTLTT.js')]);
125
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
126
+ },
127
+ "usfl": async () => {
128
+ const [t, a, m] = await Promise.all([import('./usfl-LD7HP2YK.js'), import('./usfl-4CR5RMZJ.js'), import('./usfl-VU4YSJQD.js')]);
129
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
130
+ },
131
+ "ushl": async () => {
132
+ const [t, a, m] = await Promise.all([import('./ushl-ZT2ATPHK.js'), import('./ushl-CPG2LB4L.js'), import('./ushl-PQL6HJAD.js')]);
133
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
134
+ },
135
+ "wbb": async () => {
136
+ const [t, a, m] = await Promise.all([import('./wbb-BMX53Q3Q.js'), import('./wbb-QNRN2CJJ.js'), import('./wbb-3KHCDYTK.js')]);
137
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
138
+ },
139
+ "whl": async () => {
140
+ const [t, a, m] = await Promise.all([import('./whl-Y7ASKYMM.js'), import('./whl-4ATYZWUB.js'), import('./whl-RVFPL6MH.js')]);
141
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
142
+ },
143
+ "wnba": async () => {
144
+ const [t, a, m] = await Promise.all([import('./wnba-NTMWIPP6.js'), import('./wnba-GX6HZR4B.js'), import('./wnba-FWX5SFVI.js')]);
145
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
146
+ },
147
+ "xfl": async () => {
148
+ const [t, a, m] = await Promise.all([import('./xfl-H3BXQPZZ.js'), import('./xfl-XON7A7FI.js'), import('./xfl-43R2JMJK.js')]);
149
+ return { teams: t.teams, aliases: a.aliases, marks: m.marks.map((r) => ({ ...r, archive_url: archiveUrl(r.sha256, r.ext) })) };
150
+ }
151
+ };
152
+
153
+ // src/index-data.ts
154
+ var loaded = /* @__PURE__ */ new Map();
155
+ var pending = /* @__PURE__ */ new Map();
156
+ function checkLeague(league) {
157
+ if (!LEAGUES.includes(league))
158
+ throw new InputError(`unknown league ${JSON.stringify(league)}; known leagues: ${LEAGUES.join(", ")}`);
159
+ }
160
+ async function loadLeague(league) {
161
+ checkLeague(league);
162
+ const hit = loaded.get(league);
163
+ if (hit) return hit;
164
+ let p = pending.get(league);
165
+ if (!p) {
166
+ p = loaders[league]().then(
167
+ (d) => {
168
+ loaded.set(league, d);
169
+ pending.delete(league);
170
+ return d;
171
+ },
172
+ (e) => {
173
+ pending.delete(league);
174
+ throw e;
175
+ }
176
+ );
177
+ pending.set(league, p);
178
+ }
179
+ return p;
180
+ }
181
+ async function preloadAll() {
182
+ await Promise.all([...LEAGUES.map(loadLeague), loadGsis()]);
183
+ }
184
+ function getLeagueSync(league) {
185
+ checkLeague(league);
186
+ const d = loaded.get(league);
187
+ if (!d)
188
+ throw new InputError(
189
+ `league ${league} is not loaded; await loadLeague("${league}") or preloadAll() before calling the *Sync variant`
190
+ );
191
+ return d;
192
+ }
193
+ function seasonBounds(league) {
194
+ const last = Math.max(INDEX_LAST_ALIAS_SEASON, (/* @__PURE__ */ new Date()).getFullYear() + 1);
195
+ const first = league ? LEAGUE_META[league].firstSeason ?? INDEX_FIRST_SEASON : INDEX_FIRST_SEASON;
196
+ return [first, last];
197
+ }
198
+ var latestSeason = (league) => LEAGUE_META[league].latestSeason;
199
+
200
+ // src/normalize.ts
201
+ var FLOAT_ID = /^-?\d+\.0+$/;
202
+ var PUNCT = { "\u2018": "'", "\u2019": "'", "\u2013": "-", "\u2014": "-" };
203
+ function normValue(value) {
204
+ if (value === null || value === void 0) return null;
205
+ if (typeof value === "boolean") return String(value);
206
+ if (typeof value === "bigint") return value.toString();
207
+ if (typeof value === "number") return Number.isNaN(value) ? null : String(value);
208
+ let s = String(value).trim();
209
+ if (!/^[\x00-\x7F]*$/.test(s))
210
+ s = s.replace(/[‘’–—]/g, (c) => PUNCT[c] ?? c).normalize("NFKD").replace(/\p{M}/gu, "");
211
+ s = s.toLowerCase().replace(/ß/g, "ss").replace(/ς/g, "\u03C3");
212
+ if (FLOAT_ID.test(s)) s = s.split(".")[0];
213
+ return s || null;
214
+ }
215
+ function checkSeason(year, league) {
216
+ const b = seasonBounds(league);
217
+ if (b && !(b[0] <= year && year <= b[1]))
218
+ throw new InputError(
219
+ `season ${year} is outside the seasons sdvplot knows${league ? ` for ${league}` : ""} (${b[0]} to ${b[1]}); pass a year such as 2020`
220
+ );
221
+ }
222
+ var SPLIT = /^\s*(\d{4})\s*[-/]\s*(\d{2}|\d{4})\s*$/;
223
+ function normSeason(value, league) {
224
+ if (value === null || value === void 0) return null;
225
+ let year = null;
226
+ if (typeof value === "number") {
227
+ if (Number.isNaN(value)) return null;
228
+ if (Number.isInteger(value)) year = value;
229
+ } else if (/^\d+$/.test(value.trim())) year = Number.parseInt(value.trim(), 10);
230
+ if (year === null) {
231
+ const m = typeof value === "string" ? SPLIT.exec(value) : null;
232
+ const hint = m ? `; for a split season pass its ending year (${Number(m[1]) + 1} for '${String(value).trim()}')` : "";
233
+ throw new InputError(`season must be a year such as 2020, got ${JSON.stringify(value)}${hint}`);
234
+ }
235
+ checkSeason(year, league);
236
+ return year;
237
+ }
238
+
239
+ // src/headshots.ts
240
+ var ESPN_HEADSHOT_LEAGUES = {
241
+ nfl: "nfl",
242
+ nba: "nba",
243
+ wnba: "wnba",
244
+ mlb: "mlb",
245
+ nhl: "nhl",
246
+ cfb: "college-football",
247
+ mbb: "mens-college-basketball",
248
+ wbb: "womens-college-basketball"
249
+ };
250
+ var HEADSHOT_ASPECT = 600 / 436;
251
+ function nbaHeadshotUrl(id) {
252
+ return `https://cdn.nba.com/headshots/nba/latest/260x190/${id}.png`;
253
+ }
254
+ function wnbaHeadshotUrl(id) {
255
+ return `https://cdn.wnba.com/headshots/wnba/latest/260x190/${id}.png`;
256
+ }
257
+ function mlbHeadshotUrl(id) {
258
+ return `https://img.mlbstatic.com/mlb-photos/image/upload/d_people:generic:headshot:67:current.png/w_213,q_auto:best/v1/people/${id}/headshot/67/current.png`;
259
+ }
260
+ function nhlHeadshotUrl(id) {
261
+ return `https://assets.nhle.com/mugs/nhl/latest/${id}.png`;
262
+ }
263
+ function espn(id, league) {
264
+ if (!/^\d+$/.test(id)) return void 0;
265
+ return `https://a.espncdn.com/combiner/i?img=/i/headshots/${ESPN_HEADSHOT_LEAGUES[league]}/players/full/${id}.png`;
266
+ }
267
+ var gsis;
268
+ var gsisPending;
269
+ async function loadGsis() {
270
+ if (gsis) return;
271
+ gsisPending ??= import('./nfl_gsis-UY64JO37.js').then(
272
+ (m) => {
273
+ gsis = m.NFL_GSIS;
274
+ },
275
+ (e) => {
276
+ gsisPending = void 0;
277
+ throw e;
278
+ }
279
+ );
280
+ return gsisPending;
281
+ }
282
+ function headshotUrl(playerId, league, { idSystem = "espn" } = {}) {
283
+ if (idSystem === "espn" && !Object.hasOwn(ESPN_HEADSHOT_LEAGUES, league))
284
+ throw new InputError(
285
+ `no ESPN headshots for league ${JSON.stringify(league)}; supported: ${Object.keys(ESPN_HEADSHOT_LEAGUES).sort().join(", ")}`
286
+ );
287
+ if (idSystem !== "espn" && !(idSystem === "gsis" && league === "nfl"))
288
+ throw new InputError(
289
+ `idSystem must be 'espn' (any league) or 'gsis' (nfl), got ${JSON.stringify(idSystem)} for ${JSON.stringify(league)}`
290
+ );
291
+ if (idSystem === "gsis" && !gsis)
292
+ throw new InputError(
293
+ 'the gsis map is not loaded; await loadGsis() (or preloadAll()) before headshotUrl(\u2026, { idSystem: "gsis" })'
294
+ );
295
+ const pid = normValue(playerId);
296
+ if (pid === null) return void 0;
297
+ if (idSystem === "espn") return espn(pid, league);
298
+ const key = String(playerId).trim();
299
+ const row = gsis && Object.hasOwn(gsis, key) ? gsis[key] : void 0;
300
+ if (!row) return void 0;
301
+ if (row.headshot) {
302
+ const t = row.headshot.replace("/f_auto,q_auto/", "/t_headshot_desktop/f_auto/");
303
+ return t.endsWith(".png") ? t : `${t}.png`;
304
+ }
305
+ return row.espn_id ? espn(row.espn_id, "nfl") : void 0;
306
+ }
307
+
308
+ // src/resolve.ts
309
+ var lookups = /* @__PURE__ */ new WeakMap();
310
+ function lookup(d) {
311
+ let l = lookups.get(d);
312
+ if (!l) {
313
+ l = /* @__PURE__ */ new Map();
314
+ for (const a of d.aliases) {
315
+ const k = normValue(a.value);
316
+ if (k === null) continue;
317
+ let sys = l.get(a.id_system);
318
+ if (!sys) {
319
+ sys = /* @__PURE__ */ new Map();
320
+ l.set(a.id_system, sys);
321
+ }
322
+ let c = sys.get(k);
323
+ if (!c) {
324
+ c = [];
325
+ sys.set(k, c);
326
+ }
327
+ c.push([a.team_id, a.valid_from, a.valid_to]);
328
+ }
329
+ lookups.set(d, l);
330
+ }
331
+ return l;
332
+ }
333
+ var covers = (lo, hi, s) => (lo === null || s >= lo) && (hi === null || s <= hi);
334
+ function systems(idSystem) {
335
+ if (idSystem !== "auto" && !PRIORITY.includes(idSystem) && !EXPLICIT_ONLY.includes(idSystem))
336
+ throw new InputError(
337
+ `unknown idSystem ${JSON.stringify(idSystem)}; use "auto" or one of ${[...PRIORITY, ...EXPLICIT_ONLY].join(", ")}`
338
+ );
339
+ return idSystem === "auto" ? PRIORITY : [idSystem];
340
+ }
341
+ function match(key, season, sys, table, latest) {
342
+ const whens = [];
343
+ for (const w of [season, latest]) if (w !== null && !whens.includes(w)) whens.push(w);
344
+ whens.push(null);
345
+ for (const when of whens)
346
+ for (const s of sys) {
347
+ let cands = table.get(s)?.get(key);
348
+ if (!cands?.length) continue;
349
+ if (when !== null) {
350
+ cands = cands.filter((c) => covers(c[1], c[2], when));
351
+ if (!cands.length) continue;
352
+ }
353
+ const ids = [...new Set(cands.map((c) => c[0]))];
354
+ return ids.length === 1 ? ids[0] : ids.sort();
355
+ }
356
+ return null;
357
+ }
358
+ function seasons(season, n, league) {
359
+ if (!Array.isArray(season)) return Array(n).fill(normSeason(season, league));
360
+ if (season.length !== n)
361
+ throw new InputError(`season has ${season.length} values but there are ${n} teams`);
362
+ return season.map((s) => normSeason(s, league));
363
+ }
364
+ function resolveIds(items, league, ss, idSystem, d) {
365
+ const sys = systems(idSystem);
366
+ for (const y of new Set(ss)) if (y !== null) checkSeason(y, league);
367
+ const table = lookup(d);
368
+ const latest = latestSeason(league);
369
+ let names;
370
+ const nameOf = (t) => {
371
+ names ??= new Map(d.teams.map((x) => [x.team_id, x.name ?? ""]));
372
+ return names.get(t) ?? "";
373
+ };
374
+ const out = [];
375
+ const unresolved = /* @__PURE__ */ new Map();
376
+ const memo = /* @__PURE__ */ new Map();
377
+ items.forEach((v, i) => {
378
+ const key = normValue(v);
379
+ if (key === null) {
380
+ out.push(void 0);
381
+ return;
382
+ }
383
+ const mk = `${key}\0${ss[i]}`;
384
+ if (!memo.has(mk)) memo.set(mk, match(key, ss[i] ?? null, sys, table, latest));
385
+ const hit = memo.get(mk);
386
+ if (hit === null || Array.isArray(hit)) {
387
+ unresolved.set(
388
+ String(v),
389
+ hit === null ? "unknown" : `ambiguous: ${hit.map((t) => `${t} ${nameOf(t)}`.trim()).join(" or ")}`
390
+ );
391
+ out.push(void 0);
392
+ } else out.push(asTeamId(hit));
393
+ });
394
+ return { out, unresolved };
395
+ }
396
+ function report(unresolved, league, strict) {
397
+ const shown = [...unresolved].map(([v, why]) => `'${v}' (${why})`).join(", ");
398
+ let msg = `${unresolved.size} value(s) did not resolve to a ${league} team: ${shown}`;
399
+ if ([...unresolved.values()].some((w) => w.startsWith("ambiguous")))
400
+ msg += "; pass season for a code reused across eras, or idSystem for the id system of the values";
401
+ if (strict) throw new UnresolvedTeamError(msg);
402
+ warn(
403
+ `${league}:${[...unresolved.keys()].join(",")}`,
404
+ `${msg}. Use suggest() for candidates, or strict: true to throw.`
405
+ );
406
+ }
407
+ function resolveSync(values, league, opts = {}) {
408
+ const d = getLeagueSync(league);
409
+ const arr = Array.isArray(values);
410
+ const items = arr ? values : [values];
411
+ const { out, unresolved } = resolveIds(
412
+ items,
413
+ league,
414
+ seasons(opts.season, items.length, league),
415
+ opts.idSystem ?? "auto",
416
+ d
417
+ );
418
+ if (unresolved.size) report(unresolved, league, opts.strict ?? false);
419
+ return arr ? out : out[0];
420
+ }
421
+ async function resolve(values, league, opts = {}) {
422
+ await loadLeague(league);
423
+ return resolveSync(values, league, opts);
424
+ }
425
+ async function suggest(value, league, opts = {}) {
426
+ const n = opts.n ?? 5;
427
+ if (!Number.isInteger(n) || n < 1)
428
+ throw new InputError(
429
+ `n is the most candidates to return, an int of at least 1, got ${JSON.stringify(n)}`
430
+ );
431
+ const d = await loadLeague(league);
432
+ const key = normValue(value);
433
+ if (key === null) return [];
434
+ const merged = /* @__PURE__ */ new Map();
435
+ for (const sys of lookup(d).values())
436
+ for (const [k, cands] of sys) merged.set(k, [...merged.get(k) ?? [], ...cands.map((c) => c[0])]);
437
+ const names = new Map(d.teams.map((t) => [t.team_id, t.name ?? t.team_id]));
438
+ const scored = [...merged.keys()].map((k) => [k, ratio(k, key)]).filter(([, r]) => r >= 0.6).sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? 1 : a[0] > b[0] ? -1 : 0)).slice(0, n * 3);
439
+ const out = [];
440
+ for (const [k] of scored)
441
+ for (const tid of merged.get(k) ?? [])
442
+ if (!out.some(([t]) => t === tid)) out.push([asTeamId(tid), names.get(tid) ?? tid]);
443
+ return out.slice(0, n);
444
+ }
445
+ function ratio(a, b) {
446
+ const matches = (x, y) => {
447
+ if (!x || !y) return 0;
448
+ let bi = 0;
449
+ let bj = 0;
450
+ let best = 0;
451
+ let prev = Array(y.length + 1).fill(0);
452
+ for (let i = 1; i <= x.length; i++) {
453
+ const cur = Array(y.length + 1).fill(0);
454
+ for (let j = 1; j <= y.length; j++)
455
+ if (x[i - 1] === y[j - 1]) {
456
+ const v = (prev[j - 1] ?? 0) + 1;
457
+ cur[j] = v;
458
+ if (v > best) {
459
+ best = v;
460
+ bi = i;
461
+ bj = j;
462
+ }
463
+ }
464
+ prev = cur;
465
+ }
466
+ if (!best) return 0;
467
+ return best + matches(x.slice(0, bi - best), y.slice(0, bj - best)) + matches(x.slice(bi), y.slice(bj));
468
+ };
469
+ return a.length + b.length === 0 ? 1 : 2 * matches(a, b) / (a.length + b.length);
470
+ }
471
+
472
+ // src/colors.ts
473
+ var COLUMNS = { primary: "color_primary", secondary: "color_secondary" };
474
+ function column(which) {
475
+ if (which !== "primary" && which !== "secondary")
476
+ throw new InputError(`which must be one of primary, secondary, got ${JSON.stringify(which)}`);
477
+ return COLUMNS[which];
478
+ }
479
+ function colorMap(league, col) {
480
+ const m = /* @__PURE__ */ new Map();
481
+ for (const t of getLeagueSync(league).teams) if (t[col]) m.set(t.team_id, t[col]);
482
+ return m;
483
+ }
484
+ async function palette(league, teams, opts = {}) {
485
+ const col = column(opts.which ?? "primary");
486
+ checkLeague(league);
487
+ await loadLeague(league);
488
+ const colors = colorMap(league, col);
489
+ const out = /* @__PURE__ */ Object.create(null);
490
+ if (teams == null) {
491
+ const rows = getLeagueSync(league).teams;
492
+ const counts = /* @__PURE__ */ new Map();
493
+ for (const t of rows) if (t.abbr) counts.set(t.abbr, (counts.get(t.abbr) ?? 0) + 1);
494
+ const shared = [...counts].filter(([, n]) => n > 1).map(([a]) => a);
495
+ if (shared.length)
496
+ warn(
497
+ `palette:shared:${league}`,
498
+ `abbreviations shared by several ${league} teams are keyed by team_id: ${shared.sort().join(", ")}`
499
+ );
500
+ for (const t of rows) {
501
+ const c = colors.get(t.team_id);
502
+ if (c === void 0) continue;
503
+ out[!t.abbr || shared.includes(t.abbr) ? t.team_id : t.abbr] = c;
504
+ }
505
+ return out;
506
+ }
507
+ const values = Array.isArray(teams) ? teams : [teams];
508
+ const slot = values.find((v) => v === "primary" || v === "secondary");
509
+ if (slot !== void 0)
510
+ throw new InputError(
511
+ `${JSON.stringify(slot)} is a color slot, not a team; pass it as an option: palette(league, teams, { which: "${slot}" })`
512
+ );
513
+ const ss = Array.isArray(opts.season) ? opts.season : Array(values.length).fill(opts.season);
514
+ if (ss.length !== values.length)
515
+ throw new InputError(`season has ${ss.length} values but there are ${values.length} teams`);
516
+ const seen = /* @__PURE__ */ new Set();
517
+ const vs = [];
518
+ const ys = [];
519
+ values.forEach((v, i) => {
520
+ if (v === null || v === void 0) return;
521
+ const k = `${typeof v}:${String(v)}\0${String(ss[i])}`;
522
+ if (seen.has(k)) return;
523
+ seen.add(k);
524
+ vs.push(v);
525
+ ys.push(ss[i]);
526
+ });
527
+ const ids = resolveSync(vs, league, { ...opts, season: ys });
528
+ vs.forEach((v, i) => {
529
+ const id = ids[i];
530
+ const c = id === void 0 ? void 0 : colors.get(id);
531
+ if (c !== void 0) out[String(v)] ??= c;
532
+ });
533
+ return out;
534
+ }
535
+ function teamColorsSync(league, teams, opts = {}) {
536
+ const col = column(opts.which ?? "primary");
537
+ checkLeague(league);
538
+ const colors = colorMap(league, col);
539
+ const ids = resolveSync(teams, league, opts);
540
+ const pick = (id) => id === void 0 ? void 0 : colors.get(id);
541
+ return Array.isArray(ids) ? ids.map(pick) : pick(ids);
542
+ }
543
+ function teamColorPairSync(league, team, opts = {}) {
544
+ checkLeague(league);
545
+ const id = resolveSync(team, league, opts);
546
+ const pick = (col) => id === void 0 ? void 0 : colorMap(league, col).get(id);
547
+ return { primary: pick("color_primary"), secondary: pick("color_secondary") };
548
+ }
549
+ async function teamColors(league, teams, opts = {}) {
550
+ await loadLeague(league);
551
+ return teamColorsSync(league, teams, opts);
552
+ }
553
+
554
+ export { ESPN_HEADSHOT_LEAGUES, EXPLICIT_ONLY, HEADSHOT_ASPECT, INDEX_VERSION, LEAGUES, MANIFEST_LAST_MODIFIED, PRIORITY, VARIANTS, archiveUrl, getLeagueSync, headshotUrl, latestSeason, loadGsis, loadLeague, mlbHeadshotUrl, nbaHeadshotUrl, nhlHeadshotUrl, normSeason, normValue, palette, preloadAll, resolve, resolveSync, seasonBounds, suggest, teamColorPairSync, teamColors, teamColorsSync, wnbaHeadshotUrl };
555
+ //# sourceMappingURL=chunk-TAXO3VXH.js.map
556
+ //# sourceMappingURL=chunk-TAXO3VXH.js.map