@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.
- package/LICENSE +21 -0
- package/NOTICE.md +109 -0
- package/README.md +984 -2
- package/dist/_web-D7Aa5Rd8.d.ts +69 -0
- package/dist/aaf-GJ3SH34T.js +13 -0
- package/dist/aaf-HCYN5T6Y.js +37 -0
- package/dist/aaf-ZAE5KS2Y.js +13 -0
- package/dist/ahl-E66MDVCU.js +66 -0
- package/dist/ahl-NPQQWZEV.js +249 -0
- package/dist/ahl-QRDU73XX.js +309 -0
- package/dist/axis-CraWQRUJ.d.ts +49 -0
- package/dist/bins.d.ts +174 -0
- package/dist/bins.js +4 -0
- package/dist/bins.js.map +1 -0
- package/dist/cfb-F42SVS4X.js +5000 -0
- package/dist/cfb-P3SHEYRZ.js +692 -0
- package/dist/cfb-WXRZANLP.js +10226 -0
- package/dist/chartjs-surface.d.ts +42 -0
- package/dist/chartjs-surface.js +65 -0
- package/dist/chartjs-surface.js.map +1 -0
- package/dist/chartjs.d.ts +162 -0
- package/dist/chartjs.js +342 -0
- package/dist/chartjs.js.map +1 -0
- package/dist/chunk-4C3GX6QO.js +92 -0
- package/dist/chunk-4C3GX6QO.js.map +1 -0
- package/dist/chunk-57WFSI4Q.js +128 -0
- package/dist/chunk-57WFSI4Q.js.map +1 -0
- package/dist/chunk-7ULOCCFL.js +313 -0
- package/dist/chunk-7ULOCCFL.js.map +1 -0
- package/dist/chunk-AMXASQHT.js +120 -0
- package/dist/chunk-AMXASQHT.js.map +1 -0
- package/dist/chunk-B2MP37SR.js +175 -0
- package/dist/chunk-B2MP37SR.js.map +1 -0
- package/dist/chunk-C2CDY5OG.js +137 -0
- package/dist/chunk-C2CDY5OG.js.map +1 -0
- package/dist/chunk-DYMUVE6K.js +127 -0
- package/dist/chunk-DYMUVE6K.js.map +1 -0
- package/dist/chunk-E7G7VSLV.js +43 -0
- package/dist/chunk-E7G7VSLV.js.map +1 -0
- package/dist/chunk-H2C3FMMA.js +300 -0
- package/dist/chunk-H2C3FMMA.js.map +1 -0
- package/dist/chunk-J4P4HDBF.js +175 -0
- package/dist/chunk-J4P4HDBF.js.map +1 -0
- package/dist/chunk-J6R2LEJ7.js +58 -0
- package/dist/chunk-J6R2LEJ7.js.map +1 -0
- package/dist/chunk-M3XD2OSN.js +132 -0
- package/dist/chunk-M3XD2OSN.js.map +1 -0
- package/dist/chunk-OIILARXI.js +30 -0
- package/dist/chunk-OIILARXI.js.map +1 -0
- package/dist/chunk-RPVVJY74.js +170 -0
- package/dist/chunk-RPVVJY74.js.map +1 -0
- package/dist/chunk-UL5M6KDE.js +205 -0
- package/dist/chunk-UL5M6KDE.js.map +1 -0
- package/dist/chunk-WQT4IVLX.js +10 -0
- package/dist/chunk-WQT4IVLX.js.map +1 -0
- package/dist/chunk-ZAEQXFJM.js +556 -0
- package/dist/chunk-ZAEQXFJM.js.map +1 -0
- package/dist/cricket-KPCYG2HL.js +493 -0
- package/dist/cricket-NDXLE25B.js +116 -0
- package/dist/cricket-YUUF7P6M.js +160 -0
- package/dist/cytoscape.d.ts +188 -0
- package/dist/cytoscape.js +219 -0
- package/dist/cytoscape.js.map +1 -0
- package/dist/d3.d.ts +234 -0
- package/dist/d3.js +198 -0
- package/dist/d3.js.map +1 -0
- package/dist/deckgl.d.ts +232 -0
- package/dist/deckgl.js +197 -0
- package/dist/deckgl.js.map +1 -0
- package/dist/echarts.d.ts +121 -0
- package/dist/echarts.js +228 -0
- package/dist/echarts.js.map +1 -0
- package/dist/echl-3CR4RGFC.js +241 -0
- package/dist/echl-NPC32C23.js +107 -0
- package/dist/echl-PI33DGJC.js +64 -0
- package/dist/export.d.ts +130 -0
- package/dist/export.js +258 -0
- package/dist/export.js.map +1 -0
- package/dist/g2.d.ts +251 -0
- package/dist/g2.js +102 -0
- package/dist/g2.js.map +1 -0
- package/dist/headshots-B2J_LOO8.d.ts +40 -0
- package/dist/index.d.ts +183 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/interact.d.ts +567 -0
- package/dist/interact.js +809 -0
- package/dist/interact.js.map +1 -0
- package/dist/lightweight-charts.d.ts +217 -0
- package/dist/lightweight-charts.js +155 -0
- package/dist/lightweight-charts.js.map +1 -0
- package/dist/maplibre.d.ts +271 -0
- package/dist/maplibre.js +175 -0
- package/dist/maplibre.js.map +1 -0
- package/dist/marks-DH-tQIP-.d.ts +75 -0
- package/dist/mbb-3TRLVW3H.js +3619 -0
- package/dist/mbb-DQUHCHZP.js +5111 -0
- package/dist/mbb-PRAIO2P5.js +371 -0
- package/dist/milb-6IQ6NCEW.js +291 -0
- package/dist/milb-EYY5MD4T.js +1752 -0
- package/dist/milb-EYZ4SZLI.js +797 -0
- package/dist/mlb-4PBUJSVQ.js +35 -0
- package/dist/mlb-FHPY3GQJ.js +701 -0
- package/dist/mlb-REVGL3N2.js +665 -0
- package/dist/mui.d.ts +338 -0
- package/dist/mui.js +184 -0
- package/dist/mui.js.map +1 -0
- package/dist/nba-ATT775GS.js +485 -0
- package/dist/nba-LKM4UHVU.js +482 -0
- package/dist/nba-YX7PXM3R.js +35 -0
- package/dist/nbagl-3WGZCZ4S.js +37 -0
- package/dist/nbagl-LP4XJRAL.js +229 -0
- package/dist/nbagl-VTTOU7LN.js +499 -0
- package/dist/ncaa_baseball-UV75LNVR.js +2670 -0
- package/dist/ncaa_baseball-VD5J5C72.js +419 -0
- package/dist/ncaa_baseball-YRBS32D6.js +4592 -0
- package/dist/ncaa_mhockey-IMYHS7QS.js +1033 -0
- package/dist/ncaa_mhockey-TXTKWHE3.js +115 -0
- package/dist/ncaa_mhockey-U3MFW5VT.js +663 -0
- package/dist/ncaa_softball-6WR6KS64.js +420 -0
- package/dist/ncaa_softball-RZCTIE56.js +2654 -0
- package/dist/ncaa_softball-VOD4PVGY.js +4599 -0
- package/dist/ncaa_whockey-6XXGUTBK.js +607 -0
- package/dist/ncaa_whockey-AKKYKY67.js +53 -0
- package/dist/ncaa_whockey-KBEKXFBB.js +293 -0
- package/dist/nfl-BDB2HYAR.js +625 -0
- package/dist/nfl-EHYHDLJD.js +37 -0
- package/dist/nfl-VF4NJCHY.js +514 -0
- package/dist/nfl_gsis-UY64JO37.js +4 -0
- package/dist/nhl-6WPHME7H.js +511 -0
- package/dist/nhl-EMIJFZHY.js +884 -0
- package/dist/nhl-ISFUKRFU.js +37 -0
- package/dist/nivo.d.ts +193 -0
- package/dist/nivo.js +8 -0
- package/dist/nivo.js.map +1 -0
- package/dist/ohl-2FEM554G.js +113 -0
- package/dist/ohl-C5Q4W6JB.js +32 -0
- package/dist/ohl-TQ4J46VC.js +66 -0
- package/dist/perspective.d.ts +198 -0
- package/dist/perspective.js +171 -0
- package/dist/perspective.js.map +1 -0
- package/dist/phf-H7POU2KW.js +32 -0
- package/dist/phf-K5IFMZUM.js +13 -0
- package/dist/phf-TWJI3BOW.js +20 -0
- package/dist/placement-UWkqUzpa.d.ts +32 -0
- package/dist/plot.d.ts +451 -0
- package/dist/plot.js +712 -0
- package/dist/plot.js.map +1 -0
- package/dist/plotly.d.ts +129 -0
- package/dist/plotly.js +360 -0
- package/dist/plotly.js.map +1 -0
- package/dist/pwhl-OX3BO4JI.js +53 -0
- package/dist/pwhl-W44OC3C6.js +17 -0
- package/dist/pwhl-ZJGG3H7W.js +23 -0
- package/dist/qmjhl-5HISEHLL.js +35 -0
- package/dist/qmjhl-DA3UHKE5.js +125 -0
- package/dist/qmjhl-YG4BOQPF.js +614 -0
- package/dist/react.d.ts +377 -0
- package/dist/react.js +522 -0
- package/dist/react.js.map +1 -0
- package/dist/recharts.d.ts +162 -0
- package/dist/recharts.js +8 -0
- package/dist/recharts.js.map +1 -0
- package/dist/resolve-CQW-jzvr.d.ts +28 -0
- package/dist/selection-D4T3PkRt.d.ts +140 -0
- package/dist/shadcn.d.ts +83 -0
- package/dist/shadcn.js +88 -0
- package/dist/shadcn.js.map +1 -0
- package/dist/shots.d.ts +364 -0
- package/dist/shots.js +86 -0
- package/dist/shots.js.map +1 -0
- package/dist/soccer-7BH3ZLVL.js +7898 -0
- package/dist/soccer-MRU25OGE.js +2636 -0
- package/dist/soccer-PF4IPPVA.js +12342 -0
- package/dist/surface-TR7YFJW3.js +4 -0
- package/dist/surface-TR7YFJW3.js.map +1 -0
- package/dist/surfaces-MIG7HOFU.js +6 -0
- package/dist/surfaces-MIG7HOFU.js.map +1 -0
- package/dist/surfaces-W-odWLpT.d.ts +47 -0
- package/dist/svelte/HeadshotMark.svelte +25 -0
- package/dist/svelte/HeadshotMark.svelte.d.ts +10 -0
- package/dist/svelte/HeadshotMark.svelte.d.ts.map +1 -0
- package/dist/svelte/LogoMark.svelte +25 -0
- package/dist/svelte/LogoMark.svelte.d.ts +10 -0
- package/dist/svelte/LogoMark.svelte.d.ts.map +1 -0
- package/dist/svelte/Marks.svelte +25 -0
- package/dist/svelte/Marks.svelte.d.ts +10 -0
- package/dist/svelte/Marks.svelte.d.ts.map +1 -0
- package/dist/svelte/Surface.svelte +29 -0
- package/dist/svelte/Surface.svelte.d.ts +9 -0
- package/dist/svelte/Surface.svelte.d.ts.map +1 -0
- package/dist/svelte/SurfaceBackdrop.svelte +26 -0
- package/dist/svelte/SurfaceBackdrop.svelte.d.ts +11 -0
- package/dist/svelte/SurfaceBackdrop.svelte.d.ts.map +1 -0
- package/dist/svelte/index.d.ts +13 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +11 -0
- package/dist/svelte-core.d.ts +139 -0
- package/dist/svelte-core.js +123 -0
- package/dist/svelte-core.js.map +1 -0
- package/dist/tanstack.d.ts +240 -0
- package/dist/tanstack.js +110 -0
- package/dist/tanstack.js.map +1 -0
- package/dist/testing.d.ts +75 -0
- package/dist/testing.js +239 -0
- package/dist/testing.js.map +1 -0
- package/dist/three.d.ts +223 -0
- package/dist/three.js +50 -0
- package/dist/three.js.map +1 -0
- package/dist/tiers-BN4md-GB.d.ts +65 -0
- package/dist/types-C7n6gJF3.d.ts +62 -0
- package/dist/ufl-7VLZTLTT.js +143 -0
- package/dist/ufl-CCMBLPSW.js +100 -0
- package/dist/ufl-F2BJRXME.js +16 -0
- package/dist/unovis.d.ts +127 -0
- package/dist/unovis.js +108 -0
- package/dist/unovis.js.map +1 -0
- package/dist/uplot.d.ts +120 -0
- package/dist/uplot.js +110 -0
- package/dist/uplot.js.map +1 -0
- package/dist/usfl-4CR5RMZJ.js +32 -0
- package/dist/usfl-LD7HP2YK.js +14 -0
- package/dist/usfl-VU4YSJQD.js +19 -0
- package/dist/ushl-CPG2LB4L.js +73 -0
- package/dist/ushl-PQL6HJAD.js +88 -0
- package/dist/ushl-ZT2ATPHK.js +22 -0
- package/dist/vega.d.ts +85 -0
- package/dist/vega.js +362 -0
- package/dist/vega.js.map +1 -0
- package/dist/victory.d.ts +107 -0
- package/dist/victory.js +38 -0
- package/dist/victory.js.map +1 -0
- package/dist/wbb-3KHCDYTK.js +5087 -0
- package/dist/wbb-BMX53Q3Q.js +369 -0
- package/dist/wbb-QNRN2CJJ.js +3620 -0
- package/dist/whl-4ATYZWUB.js +97 -0
- package/dist/whl-RVFPL6MH.js +79 -0
- package/dist/whl-Y7ASKYMM.js +28 -0
- package/dist/wnba-FWX5SFVI.js +232 -0
- package/dist/wnba-GX6HZR4B.js +220 -0
- package/dist/wnba-NTMWIPP6.js +20 -0
- package/dist/xfl-43R2JMJK.js +30 -0
- package/dist/xfl-H3BXQPZZ.js +16 -0
- package/dist/xfl-XON7A7FI.js +69 -0
- package/package.json +366 -3
package/dist/deckgl.d.ts
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { Sport, OptionsOf, LeagueOf } from '@sportsdataverse/sporty';
|
|
2
|
+
import { R as Row } from './_web-D7Aa5Rd8.js';
|
|
3
|
+
import { L as League, S as SeasonInput, V as Variant, I as IdSystem, W as Which } from './types-C7n6gJF3.js';
|
|
4
|
+
|
|
5
|
+
/** A deck.gl colour: `[r, g, b, a]`, each 0-255. */
|
|
6
|
+
type Rgba = [r: number, g: number, b: number, a: number];
|
|
7
|
+
/** An icon deck.gl fetches and packs into its atlas itself (an "auto-packed" icon), keyed by its URL. */
|
|
8
|
+
interface LogoIcon {
|
|
9
|
+
url: string;
|
|
10
|
+
/** The icon's size in the atlas, px: 128 tall, as wide as the logo's aspect makes it. */
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
/** Half the height: the logo is centred on its point. */
|
|
14
|
+
anchorY: number;
|
|
15
|
+
mask: false;
|
|
16
|
+
}
|
|
17
|
+
/** One `logoIconLayer` data row. `index` is the row's position in the input (left-out rows leave gaps). */
|
|
18
|
+
interface IconRow {
|
|
19
|
+
position: [x: number, y: number];
|
|
20
|
+
icon: LogoIcon;
|
|
21
|
+
/** The resolved team id. */
|
|
22
|
+
team: string;
|
|
23
|
+
index: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* One `passArcLayer` data row. `team` is the resolved team id, or the row's own value as text when it does not
|
|
27
|
+
* resolve (a number without ".0", a missing value empty).
|
|
28
|
+
*/
|
|
29
|
+
interface ArcRow {
|
|
30
|
+
source: [x: number, y: number];
|
|
31
|
+
target: [x: number, y: number];
|
|
32
|
+
sourceColor: Rgba;
|
|
33
|
+
targetColor: Rgba;
|
|
34
|
+
team: string;
|
|
35
|
+
index: number;
|
|
36
|
+
}
|
|
37
|
+
/** One `surfaceLayer` data row: a closed loop of a sporty polygon feature. */
|
|
38
|
+
interface SurfaceRow {
|
|
39
|
+
name: string;
|
|
40
|
+
/** One closed loop of the feature's path (deck.gl closes it). */
|
|
41
|
+
polygon: (readonly [x: number, y: number])[];
|
|
42
|
+
fillColor: Rgba;
|
|
43
|
+
}
|
|
44
|
+
/** `logoIconLayer`'s props, for deck.gl's `IconLayer`. */
|
|
45
|
+
interface LogoIconLayerProps {
|
|
46
|
+
id: string;
|
|
47
|
+
data: IconRow[];
|
|
48
|
+
getPosition: (d: IconRow) => [number, number];
|
|
49
|
+
getIcon: (d: IconRow) => LogoIcon;
|
|
50
|
+
getSize: number;
|
|
51
|
+
sizeUnits: "pixels";
|
|
52
|
+
opacity: number;
|
|
53
|
+
}
|
|
54
|
+
/** `passArcLayer`'s props, for deck.gl's `ArcLayer`. */
|
|
55
|
+
interface PassArcLayerProps {
|
|
56
|
+
id: string;
|
|
57
|
+
data: ArcRow[];
|
|
58
|
+
getSourcePosition: (d: ArcRow) => [number, number];
|
|
59
|
+
getTargetPosition: (d: ArcRow) => [number, number];
|
|
60
|
+
getSourceColor: (d: ArcRow) => Rgba;
|
|
61
|
+
getTargetColor: (d: ArcRow) => Rgba;
|
|
62
|
+
getWidth: number;
|
|
63
|
+
widthUnits: "pixels";
|
|
64
|
+
opacity: number;
|
|
65
|
+
getHeight?: number;
|
|
66
|
+
getTilt?: number;
|
|
67
|
+
}
|
|
68
|
+
/** `surfaceLayer`'s props, for deck.gl's `PolygonLayer`. */
|
|
69
|
+
interface SurfaceLayerProps {
|
|
70
|
+
id: string;
|
|
71
|
+
data: SurfaceRow[];
|
|
72
|
+
getPolygon: (d: SurfaceRow) => SurfaceRow["polygon"];
|
|
73
|
+
getFillColor: (d: SurfaceRow) => Rgba;
|
|
74
|
+
coordinateSystem: "cartesian";
|
|
75
|
+
filled: true;
|
|
76
|
+
stroked: false;
|
|
77
|
+
}
|
|
78
|
+
/** `logoIconLayer` options. */
|
|
79
|
+
interface LogoIconOptions {
|
|
80
|
+
/** Name of the row column holding each logo's x position (a longitude on a map, or a surface's own x). */
|
|
81
|
+
x: string;
|
|
82
|
+
/** Name of the row column holding each logo's y position. */
|
|
83
|
+
y: string;
|
|
84
|
+
/** Name of the row column holding the team (abbreviation, name or id; see `idSystem`). */
|
|
85
|
+
team: string;
|
|
86
|
+
/** The league the teams belong to, e.g. "nhl". */
|
|
87
|
+
league: League;
|
|
88
|
+
/** A season (number or string) for every row, or the name of a row column holding each row's season. */
|
|
89
|
+
season?: SeasonInput;
|
|
90
|
+
/** Logo variant, e.g. "dark". Default "default". */
|
|
91
|
+
variant?: Variant;
|
|
92
|
+
/** How the `team` values are read. Default "auto". */
|
|
93
|
+
idSystem?: IdSystem;
|
|
94
|
+
/** The logo's height on screen in px, 1 or more (deck.gl's `getSize` in "pixels" units). Default 32. */
|
|
95
|
+
size?: number;
|
|
96
|
+
/** The layer's opacity in [0, 1]. Default 1. */
|
|
97
|
+
alpha?: number;
|
|
98
|
+
/** The layer id. Default "sdvplot-logos". */
|
|
99
|
+
id?: string;
|
|
100
|
+
}
|
|
101
|
+
/** `passArcLayer` options. */
|
|
102
|
+
interface PassArcOptions {
|
|
103
|
+
/** Name of the row column holding each arc's source x. */
|
|
104
|
+
x: string;
|
|
105
|
+
/** Name of the row column holding each arc's source y. */
|
|
106
|
+
y: string;
|
|
107
|
+
/** Name of the row column holding each arc's target x. */
|
|
108
|
+
xend: string;
|
|
109
|
+
/** Name of the row column holding each arc's target y. */
|
|
110
|
+
yend: string;
|
|
111
|
+
/** Name of the row column holding the team the arc is coloured by. */
|
|
112
|
+
team: string;
|
|
113
|
+
/** The league the teams belong to, e.g. "soccer". */
|
|
114
|
+
league: League;
|
|
115
|
+
/** The season the teams are resolved for. */
|
|
116
|
+
season?: SeasonInput;
|
|
117
|
+
/** How the `team` values are read. Default "auto". */
|
|
118
|
+
idSystem?: IdSystem;
|
|
119
|
+
/** The colour at the source end, "primary" (default) or "secondary"; the target end takes the other. */
|
|
120
|
+
which?: Which;
|
|
121
|
+
/**
|
|
122
|
+
* The background the arcs are drawn on. Given, each end's colour keeps 3:1 contrast against it (dark mode) and
|
|
123
|
+
* aims to stay distinct (CIE76 ΔE of 20 or more) from every other team's colour at that end, through the shared team
|
|
124
|
+
* palette, as `teamColorPalette` does in the other adapters. Caveat: a colour that does not read gives way to the
|
|
125
|
+
* team's other colour, so when only one of a team's two colours reads on the background, both ends take it and the
|
|
126
|
+
* arcs no longer show their direction (France's navy and mint on a dark pitch are both mint). Pick a background on
|
|
127
|
+
* which both colours read (France's both read on a mid-tone green such as `#4a7f3a`), or check that
|
|
128
|
+
* `sourceColor` and `targetColor` differ.
|
|
129
|
+
*/
|
|
130
|
+
background?: string;
|
|
131
|
+
/** The colour of a team that does not resolve, or has no colour. Default "#808080". */
|
|
132
|
+
fallback?: string;
|
|
133
|
+
/** The arc's width in px, 1 or more. Default 2. */
|
|
134
|
+
width?: number;
|
|
135
|
+
/** The layer's opacity in [0, 1]. Default 1. */
|
|
136
|
+
alpha?: number;
|
|
137
|
+
/**
|
|
138
|
+
* deck.gl's `getHeight`, how high each arc rises for its length, 0 or more (0 draws a straight line). Default none:
|
|
139
|
+
* deck.gl's 1. Lower, such as 0.3, keeps arcs laid flat (`tilt: 90`) close to their chord, inside the surface.
|
|
140
|
+
*/
|
|
141
|
+
height?: number;
|
|
142
|
+
/**
|
|
143
|
+
* deck.gl's `getTilt`, degrees in [-90, 90]: 90 lays each arc flat on the surface, so a top-down 2D view (an
|
|
144
|
+
* OrthographicView) shows the curve. Default none: deck.gl's upright arcs, for a pitched 3D view.
|
|
145
|
+
*/
|
|
146
|
+
tilt?: number;
|
|
147
|
+
/** The layer id. Default "sdvplot-arcs". */
|
|
148
|
+
id?: string;
|
|
149
|
+
}
|
|
150
|
+
/** `surfaceLayer` options: sporty's own `surface()` options for the sport, plus the layer id. */
|
|
151
|
+
type SurfaceLayerOptions<S extends Sport> = OptionsOf<S> & {
|
|
152
|
+
/** The layer id. Default "sdvplot-surface". */
|
|
153
|
+
id?: string;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* deck.gl `IconLayer` props drawing each row's team logo at its (x, y). The logos are auto-packed icons: deck.gl
|
|
157
|
+
* fetches each URL once and packs it into its own atlas, at 128 px tall and the logo's aspect, centred on the point.
|
|
158
|
+
* A team with no logo (or one that does not resolve) is left out with one warning, as the other adapters do; so is a
|
|
159
|
+
* row with a missing x or y. `x` and `y` are in the layer's coordinates: longitude and latitude on a map, or a
|
|
160
|
+
* surface's own units on `surfaceLayer` (set `coordinateSystem: "cartesian"` on both, or use a non-geographic view).
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* import { loadLeague } from "@sportsdataverse/sdvplot";
|
|
165
|
+
* import { logoIconLayer } from "@sportsdataverse/sdvplot/deckgl";
|
|
166
|
+
*
|
|
167
|
+
* await loadLeague("nhl");
|
|
168
|
+
* // Edmonton's first shot of game 7 of the 2024 Stanley Cup Final (NHL api-web), in feet from centre ice
|
|
169
|
+
* const shot = { team: "EDM", x: 82, y: -3 };
|
|
170
|
+
* const props = logoIconLayer([shot], { x: "x", y: "y", team: "team", league: "nhl", size: 28 });
|
|
171
|
+
* // in the browser: new IconLayer({ ...props, coordinateSystem: "cartesian" })
|
|
172
|
+
* props.data[0]?.icon.url;
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
declare function logoIconLayer(rows: readonly Row[], o: LogoIconOptions): LogoIconLayerProps;
|
|
176
|
+
/**
|
|
177
|
+
* deck.gl `ArcLayer` props: one arc per row from (x, y) to (xend, yend), in the team's colours: its primary colour at
|
|
178
|
+
* the source and its secondary at the target (`which: "secondary"` swaps them), so the two ends tell the direction
|
|
179
|
+
* apart where the two colours differ (see `background`). Each team keeps one colour per end, the teams taken in the
|
|
180
|
+
* order they first appear. With `background`, every colour keeps 3:1 contrast against it and aims to stay distinct from
|
|
181
|
+
* the other teams' (the shared team palette; when it cannot, it keeps the readable colour and warns once). A team that
|
|
182
|
+
* does not resolve takes `fallback`, as given (its contrast is not checked); a row with a missing
|
|
183
|
+
* coordinate is left out with one warning.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* import { loadLeague } from "@sportsdataverse/sdvplot";
|
|
188
|
+
* import { passArcLayer } from "@sportsdataverse/sdvplot/deckgl";
|
|
189
|
+
*
|
|
190
|
+
* await loadLeague("soccer");
|
|
191
|
+
* // France's first completed pass of the 2018 World Cup final (StatsBomb open data through SPADL, metres from the
|
|
192
|
+
* // corner); France is ESPN soccer team 478
|
|
193
|
+
* const pass = { team: "478", start_x: 54.68750000000001, start_y: 6.375, end_x: 56.4375, end_y: 1.2750000000000057 };
|
|
194
|
+
* const props = passArcLayer([pass], {
|
|
195
|
+
* x: "start_x",
|
|
196
|
+
* y: "start_y",
|
|
197
|
+
* xend: "end_x",
|
|
198
|
+
* yend: "end_y",
|
|
199
|
+
* team: "team",
|
|
200
|
+
* league: "soccer",
|
|
201
|
+
* idSystem: "team_id",
|
|
202
|
+
* tilt: 90,
|
|
203
|
+
* });
|
|
204
|
+
* // in the browser: new ArcLayer({ ...props, coordinateSystem: "cartesian" })
|
|
205
|
+
* props.data[0]?.sourceColor;
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
declare function passArcLayer(rows: readonly Row[], o: PassArcOptions): PassArcLayerProps;
|
|
209
|
+
/**
|
|
210
|
+
* deck.gl `PolygonLayer` props drawing sporty's playing surface for `sport` and `league` (sporty's own league keys,
|
|
211
|
+
* e.g. `surfaceLayer("hockey", "nhl")`, `surfaceLayer("soccer", "fifa")`), in the surface's own coordinates: deck.gl's
|
|
212
|
+
* `"cartesian"` coordinate system, in the surface's units (feet for a rink, metres for a pitch) with the origin at its
|
|
213
|
+
* centre, the frame sporty draws in and NHL api-web's shot coordinates are in. Each closed loop of a polygon feature
|
|
214
|
+
* is one data row (a faceoff circle is two: its half rings; a loop that crosses itself is split at the crossing into
|
|
215
|
+
* rings that do not, and a loop with no area is left out), in sporty's drawing order, filled with its colour (alpha
|
|
216
|
+
* included). sporty's default strokes equal their fills, so
|
|
217
|
+
* the layer is fill-only; a hidden feature (a `#rrggbb00` fill) and text features (a football field's yard numbers)
|
|
218
|
+
* are left out. `o` is passed to sporty's `surface()` (`updates`, `colorUpdates`, `units`, `rotation`, ...); sporty's
|
|
219
|
+
* own errors escape unwrapped. Draw it with deck.gl's OrthographicView.
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* import { surfaceLayer } from "@sportsdataverse/sdvplot/deckgl";
|
|
224
|
+
*
|
|
225
|
+
* const rink = surfaceLayer("hockey", "nhl");
|
|
226
|
+
* // in the browser: new PolygonLayer(rink), in a Deck with views: new OrthographicView({ flipY: false })
|
|
227
|
+
* rink.data.length;
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
declare function surfaceLayer<S extends Sport>(sport: S, league: LeagueOf<S>, o?: SurfaceLayerOptions<S>): SurfaceLayerProps;
|
|
231
|
+
|
|
232
|
+
export { type ArcRow, type IconRow, type LogoIcon, type LogoIconLayerProps, type LogoIconOptions, type PassArcLayerProps, type PassArcOptions, type Rgba, Row, type SurfaceLayerOptions, type SurfaceLayerProps, type SurfaceRow, logoIconLayer, passArcLayer, surfaceLayer };
|
package/dist/deckgl.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { markPlacements, aspect, column, colorList, teamPalette } from './chunk-UL5M6KDE.js';
|
|
2
|
+
import { checkAlpha } from './chunk-7ULOCCFL.js';
|
|
3
|
+
import { resolveSync, normValue } from './chunk-ZAEQXFJM.js';
|
|
4
|
+
import { hex6 } from './chunk-J6R2LEJ7.js';
|
|
5
|
+
import { InputError, warn } from './chunk-E7G7VSLV.js';
|
|
6
|
+
import { surface } from '@sportsdataverse/sporty';
|
|
7
|
+
|
|
8
|
+
var ICON_PX = 128;
|
|
9
|
+
var real = (v) => typeof v === "number" && Number.isFinite(v);
|
|
10
|
+
function checkPx(name, v) {
|
|
11
|
+
if (!real(v) || v < 1) throw new InputError(`${name} is in px, 1 or more, got ${String(v)}`);
|
|
12
|
+
return v;
|
|
13
|
+
}
|
|
14
|
+
function alphaOf(color) {
|
|
15
|
+
let c = String(color).trim().replace(/^#+/, "");
|
|
16
|
+
if (c.length === 4) c = [...c].map((ch) => ch + ch).join("");
|
|
17
|
+
return c.length === 8 ? Number.parseInt(c.slice(6), 16) : 255;
|
|
18
|
+
}
|
|
19
|
+
function rgba(color) {
|
|
20
|
+
const a = alphaOf(color);
|
|
21
|
+
const [r, g, b] = [1, 3, 5].map(
|
|
22
|
+
(i) => Number.parseInt(hex6(color, { dropAlpha: true }).slice(i, i + 2), 16)
|
|
23
|
+
);
|
|
24
|
+
return [r, g, b, a];
|
|
25
|
+
}
|
|
26
|
+
function logoIconLayer(rows, o) {
|
|
27
|
+
const size = checkPx("size", o.size ?? 32);
|
|
28
|
+
const opacity = checkAlpha(o.alpha ?? 1);
|
|
29
|
+
const data = markPlacements(rows, "logo", o).map((p) => {
|
|
30
|
+
const height = ICON_PX;
|
|
31
|
+
return {
|
|
32
|
+
position: [Number(p.x), Number(p.y)],
|
|
33
|
+
icon: { url: p.url, width: Math.round(ICON_PX * aspect(p)), height, anchorY: height / 2, mask: false },
|
|
34
|
+
team: p.id,
|
|
35
|
+
index: p.index
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
id: o.id ?? "sdvplot-logos",
|
|
40
|
+
data,
|
|
41
|
+
getPosition: (d) => d.position,
|
|
42
|
+
getIcon: (d) => d.icon,
|
|
43
|
+
getSize: size,
|
|
44
|
+
sizeUnits: "pixels",
|
|
45
|
+
opacity
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
var label = (t) => t === null || t === void 0 ? "" : typeof t === "number" ? normValue(t) ?? "" : String(t);
|
|
49
|
+
function endColors(ids, o, which) {
|
|
50
|
+
const fallback = hex6(o.fallback ?? "#808080");
|
|
51
|
+
const co = { idSystem: "team_id", ...o.season === void 0 ? {} : { season: o.season } };
|
|
52
|
+
const known = ids.filter((id) => id !== null);
|
|
53
|
+
const main = colorList(o.league, known, { ...co, which });
|
|
54
|
+
const other = colorList(o.league, known, { ...co, which: which === "primary" ? "secondary" : "primary" });
|
|
55
|
+
let colors = main.map((c, i) => hex6(c ?? other[i] ?? fallback, { dropAlpha: true }));
|
|
56
|
+
if (o.background !== void 0) colors = teamPalette(colors, other, hex6(o.background), known);
|
|
57
|
+
let k = 0;
|
|
58
|
+
return ids.map((id) => id === null ? fallback : colors[k++]);
|
|
59
|
+
}
|
|
60
|
+
function passArcLayer(rows, o) {
|
|
61
|
+
const width = checkPx("width", o.width ?? 2);
|
|
62
|
+
const opacity = checkAlpha(o.alpha ?? 1);
|
|
63
|
+
if (o.tilt !== void 0 && !(real(o.tilt) && o.tilt >= -90 && o.tilt <= 90))
|
|
64
|
+
throw new InputError(`tilt is in degrees, in [-90, 90], got ${String(o.tilt)}`);
|
|
65
|
+
if (o.height !== void 0 && !(real(o.height) && o.height >= 0))
|
|
66
|
+
throw new InputError(`height is an arc's height multiplier, 0 or more, got ${String(o.height)}`);
|
|
67
|
+
const cols = [o.x, o.y, o.xend, o.yend].map(
|
|
68
|
+
(c, k) => column(rows, c, ["x", "y", "xend", "yend"][k])
|
|
69
|
+
);
|
|
70
|
+
const teams = column(rows, o.team, "team");
|
|
71
|
+
const keep = [];
|
|
72
|
+
const missing = [];
|
|
73
|
+
rows.forEach((_, i) => {
|
|
74
|
+
if (cols.every((c) => real(c[i]))) keep.push(i);
|
|
75
|
+
else missing.push(teams[i]);
|
|
76
|
+
});
|
|
77
|
+
if (missing.length > 0) {
|
|
78
|
+
const shown = missing.slice(0, 10).map(String).join(", ") + (missing.length > 10 ? ` and ${missing.length - 10} more` : "");
|
|
79
|
+
warn(
|
|
80
|
+
`deckgl:arcs:${o.league}:missing:${shown}`,
|
|
81
|
+
`skipped ${missing.length} arc(s) with a missing coordinate: ${shown}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
const ro = {
|
|
85
|
+
...o.season === void 0 ? {} : { season: o.season },
|
|
86
|
+
...o.idSystem === void 0 ? {} : { idSystem: o.idSystem }
|
|
87
|
+
};
|
|
88
|
+
const kept = keep.map((i) => teams[i]);
|
|
89
|
+
const resolved = resolveSync(kept, o.league, ro);
|
|
90
|
+
const keys = kept.map((t, j) => resolved[j] ?? `?${label(t)}`);
|
|
91
|
+
const distinct = [...new Set(keys)];
|
|
92
|
+
const ids = distinct.map((k) => k.startsWith("?") ? null : k);
|
|
93
|
+
const which = o.which ?? "primary";
|
|
94
|
+
const src = endColors(ids, o, which);
|
|
95
|
+
const tgt = endColors(ids, o, which === "primary" ? "secondary" : "primary");
|
|
96
|
+
const at = new Map(distinct.map((k, j) => [k, j]));
|
|
97
|
+
const data = keep.map((i, j) => {
|
|
98
|
+
const k = at.get(keys[j]);
|
|
99
|
+
return {
|
|
100
|
+
source: [cols[0]?.[i], cols[1]?.[i]],
|
|
101
|
+
target: [cols[2]?.[i], cols[3]?.[i]],
|
|
102
|
+
sourceColor: rgba(src[k]),
|
|
103
|
+
targetColor: rgba(tgt[k]),
|
|
104
|
+
team: resolved[j] ?? label(kept[j]),
|
|
105
|
+
index: i
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
id: o.id ?? "sdvplot-arcs",
|
|
110
|
+
data,
|
|
111
|
+
getSourcePosition: (d) => d.source,
|
|
112
|
+
getTargetPosition: (d) => d.target,
|
|
113
|
+
getSourceColor: (d) => d.sourceColor,
|
|
114
|
+
getTargetColor: (d) => d.targetColor,
|
|
115
|
+
getWidth: width,
|
|
116
|
+
widthUnits: "pixels",
|
|
117
|
+
opacity,
|
|
118
|
+
...o.height === void 0 ? {} : { getHeight: o.height },
|
|
119
|
+
...o.tilt === void 0 ? {} : { getTilt: o.tilt }
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function loops(points) {
|
|
123
|
+
const out = [];
|
|
124
|
+
let loop = [];
|
|
125
|
+
let away = 0;
|
|
126
|
+
for (const p of points) {
|
|
127
|
+
const first = loop[0];
|
|
128
|
+
loop.push(p);
|
|
129
|
+
if (first === void 0) continue;
|
|
130
|
+
if (p[0] !== first[0] || p[1] !== first[1]) away++;
|
|
131
|
+
else if (away >= 2) {
|
|
132
|
+
out.push(loop);
|
|
133
|
+
loop = [];
|
|
134
|
+
away = 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (away >= 2) out.push(loop);
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
var turn = (a, b, c) => (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
|
|
141
|
+
function signedArea(r) {
|
|
142
|
+
let s = 0;
|
|
143
|
+
for (let i = 0; i < r.length; i++) {
|
|
144
|
+
const [a, b] = [r[i], r[(i + 1) % r.length]];
|
|
145
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
146
|
+
}
|
|
147
|
+
return s / 2;
|
|
148
|
+
}
|
|
149
|
+
function empty(r) {
|
|
150
|
+
let [x0, y0, x1, y1] = [
|
|
151
|
+
Number.POSITIVE_INFINITY,
|
|
152
|
+
Number.POSITIVE_INFINITY,
|
|
153
|
+
Number.NEGATIVE_INFINITY,
|
|
154
|
+
Number.NEGATIVE_INFINITY
|
|
155
|
+
];
|
|
156
|
+
for (const [x, y] of r)
|
|
157
|
+
[x0, y0, x1, y1] = [Math.min(x0, x), Math.min(y0, y), Math.max(x1, x), Math.max(y1, y)];
|
|
158
|
+
return r.length < 3 || Math.abs(signedArea(r)) <= 1e-9 * ((x1 - x0) ** 2 + (y1 - y0) ** 2);
|
|
159
|
+
}
|
|
160
|
+
function simple(r) {
|
|
161
|
+
const n = r.length;
|
|
162
|
+
const side = (a, b, c) => Math.sign(turn(a, b, c));
|
|
163
|
+
for (let i = 0; i < n; i++)
|
|
164
|
+
for (let j = i + 2; j < n; j++) {
|
|
165
|
+
if (i === 0 && j === n - 1) continue;
|
|
166
|
+
const [a, b, c, d] = [r[i], r[(i + 1) % n], r[j], r[(j + 1) % n]];
|
|
167
|
+
if (side(a, b, c) * side(a, b, d) >= 0 || side(c, d, a) * side(c, d, b) >= 0) continue;
|
|
168
|
+
const s = turn(c, d, a) / (turn(c, d, a) - turn(c, d, b));
|
|
169
|
+
const x = [a[0] + s * (b[0] - a[0]), a[1] + s * (b[1] - a[1])];
|
|
170
|
+
return [
|
|
171
|
+
...simple([...r.slice(0, i + 1), x, ...r.slice(j + 1)]),
|
|
172
|
+
...simple([x, ...r.slice(i + 1, j + 1)])
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
return [[...r]];
|
|
176
|
+
}
|
|
177
|
+
var drawn = (f) => f.points.length > 0 && f.points.every(([x, y]) => Number.isFinite(x) && Number.isFinite(y)) && alphaOf(f.fill) !== 0;
|
|
178
|
+
function surfaceLayer(sport, league, o = {}) {
|
|
179
|
+
const { id = "sdvplot-surface", ...opts } = o;
|
|
180
|
+
const scene = surface(sport, league, opts);
|
|
181
|
+
const data = scene.features.filter((f) => f.kind === "polygon" && drawn(f)).flatMap(
|
|
182
|
+
(f) => loops(f.points).flatMap(simple).filter((r) => !empty(r)).map((polygon) => ({ name: f.name, polygon, fillColor: rgba(f.fill) }))
|
|
183
|
+
);
|
|
184
|
+
return {
|
|
185
|
+
id,
|
|
186
|
+
data,
|
|
187
|
+
getPolygon: (d) => d.polygon,
|
|
188
|
+
getFillColor: (d) => d.fillColor,
|
|
189
|
+
coordinateSystem: "cartesian",
|
|
190
|
+
filled: true,
|
|
191
|
+
stroked: false
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export { logoIconLayer, passArcLayer, surfaceLayer };
|
|
196
|
+
//# sourceMappingURL=deckgl.js.map
|
|
197
|
+
//# sourceMappingURL=deckgl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/deckgl.ts"],"names":["sportySurface"],"mappings":"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","file":"deckgl.js","sourcesContent":["/**\n * The deck.gl adapter: team logos, team-coloured arcs and sporty playing surfaces as deck.gl layer props. Pure: it\n * never imports deck.gl (`@deck.gl/core` and `@deck.gl/layers` 9.4 or later are optional peers), so the props can be\n * built anywhere, a server included; pass them to the layer, as in `new IconLayer(logoIconLayer(rows, o))`. The props\n * are plain objects: the data rows, accessor functions that read them, and the layer's own settings. `surfaceLayer`\n * draws through `@sportsdataverse/sporty`, which this entry imports when it loads. Synchronous: call after\n * `loadLeague(league)` / `preloadAll()`. The Python package's `sdvplot.pydeck` builds the same props for pydeck; the\n * two are held to one shared fixture.\n */\nimport { type PolygonFeature, surface as sportySurface } from \"@sportsdataverse/sporty\";\nimport type { LeagueOf, OptionsOf, Sport } from \"@sportsdataverse/sporty\";\nimport { type Row, aspect, colorList, column, markPlacements } from \"./_web.js\";\nimport { hex6 } from \"./contrast.js\";\nimport { InputError, warn } from \"./errors.js\";\nimport { normValue } from \"./normalize.js\";\nimport { checkAlpha } from \"./placement.js\";\nimport { type Value, resolveSync } from \"./resolve.js\";\nimport { teamPalette } from \"./team-palette.js\";\nimport type { IdSystem, League, SeasonInput, Variant, Which } from \"./types.js\";\n\nexport type { Row } from \"./_web.js\";\n/** A deck.gl colour: `[r, g, b, a]`, each 0-255. */\nexport type Rgba = [r: number, g: number, b: number, a: number];\n/** An icon deck.gl fetches and packs into its atlas itself (an \"auto-packed\" icon), keyed by its URL. */\nexport interface LogoIcon {\n url: string;\n /** The icon's size in the atlas, px: 128 tall, as wide as the logo's aspect makes it. */\n width: number;\n height: number;\n /** Half the height: the logo is centred on its point. */\n anchorY: number;\n mask: false;\n}\n/** One `logoIconLayer` data row. `index` is the row's position in the input (left-out rows leave gaps). */\nexport interface IconRow {\n position: [x: number, y: number];\n icon: LogoIcon;\n /** The resolved team id. */\n team: string;\n index: number;\n}\n/**\n * One `passArcLayer` data row. `team` is the resolved team id, or the row's own value as text when it does not\n * resolve (a number without \".0\", a missing value empty).\n */\nexport interface ArcRow {\n source: [x: number, y: number];\n target: [x: number, y: number];\n sourceColor: Rgba;\n targetColor: Rgba;\n team: string;\n index: number;\n}\n/** One `surfaceLayer` data row: a closed loop of a sporty polygon feature. */\nexport interface SurfaceRow {\n name: string;\n /** One closed loop of the feature's path (deck.gl closes it). */\n polygon: (readonly [x: number, y: number])[];\n fillColor: Rgba;\n}\n/** `logoIconLayer`'s props, for deck.gl's `IconLayer`. */\nexport interface LogoIconLayerProps {\n id: string;\n data: IconRow[];\n getPosition: (d: IconRow) => [number, number];\n getIcon: (d: IconRow) => LogoIcon;\n getSize: number;\n sizeUnits: \"pixels\";\n opacity: number;\n}\n/** `passArcLayer`'s props, for deck.gl's `ArcLayer`. */\nexport interface PassArcLayerProps {\n id: string;\n data: ArcRow[];\n getSourcePosition: (d: ArcRow) => [number, number];\n getTargetPosition: (d: ArcRow) => [number, number];\n getSourceColor: (d: ArcRow) => Rgba;\n getTargetColor: (d: ArcRow) => Rgba;\n getWidth: number;\n widthUnits: \"pixels\";\n opacity: number;\n getHeight?: number;\n getTilt?: number;\n}\n/** `surfaceLayer`'s props, for deck.gl's `PolygonLayer`. */\nexport interface SurfaceLayerProps {\n id: string;\n data: SurfaceRow[];\n getPolygon: (d: SurfaceRow) => SurfaceRow[\"polygon\"];\n getFillColor: (d: SurfaceRow) => Rgba;\n coordinateSystem: \"cartesian\";\n filled: true;\n stroked: false;\n}\n\n/** `logoIconLayer` options. */\nexport interface LogoIconOptions {\n /** Name of the row column holding each logo's x position (a longitude on a map, or a surface's own x). */\n x: string;\n /** Name of the row column holding each logo'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 belong to, e.g. \"nhl\". */\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 /** The logo's height on screen in px, 1 or more (deck.gl's `getSize` in \"pixels\" units). Default 32. */\n size?: number;\n /** The layer's opacity in [0, 1]. Default 1. */\n alpha?: number;\n /** The layer id. Default \"sdvplot-logos\". */\n id?: string;\n}\n/** `passArcLayer` options. */\nexport interface PassArcOptions {\n /** Name of the row column holding each arc's source x. */\n x: string;\n /** Name of the row column holding each arc's source y. */\n y: string;\n /** Name of the row column holding each arc's target x. */\n xend: string;\n /** Name of the row column holding each arc's target y. */\n yend: string;\n /** Name of the row column holding the team the arc is coloured by. */\n team: string;\n /** The league the teams belong to, e.g. \"soccer\". */\n league: League;\n /** The season the teams are resolved for. */\n season?: SeasonInput;\n /** How the `team` values are read. Default \"auto\". */\n idSystem?: IdSystem;\n /** The colour at the source end, \"primary\" (default) or \"secondary\"; the target end takes the other. */\n which?: Which;\n /**\n * The background the arcs are drawn on. Given, each end's colour keeps 3:1 contrast against it (dark mode) and\n * aims to stay distinct (CIE76 ΔE of 20 or more) from every other team's colour at that end, through the shared team\n * palette, as `teamColorPalette` does in the other adapters. Caveat: a colour that does not read gives way to the\n * team's other colour, so when only one of a team's two colours reads on the background, both ends take it and the\n * arcs no longer show their direction (France's navy and mint on a dark pitch are both mint). Pick a background on\n * which both colours read (France's both read on a mid-tone green such as `#4a7f3a`), or check that\n * `sourceColor` and `targetColor` differ.\n */\n background?: string;\n /** The colour of a team that does not resolve, or has no colour. Default \"#808080\". */\n fallback?: string;\n /** The arc's width in px, 1 or more. Default 2. */\n width?: number;\n /** The layer's opacity in [0, 1]. Default 1. */\n alpha?: number;\n /**\n * deck.gl's `getHeight`, how high each arc rises for its length, 0 or more (0 draws a straight line). Default none:\n * deck.gl's 1. Lower, such as 0.3, keeps arcs laid flat (`tilt: 90`) close to their chord, inside the surface.\n */\n height?: number;\n /**\n * deck.gl's `getTilt`, degrees in [-90, 90]: 90 lays each arc flat on the surface, so a top-down 2D view (an\n * OrthographicView) shows the curve. Default none: deck.gl's upright arcs, for a pitched 3D view.\n */\n tilt?: number;\n /** The layer id. Default \"sdvplot-arcs\". */\n id?: string;\n}\n/** `surfaceLayer` options: sporty's own `surface()` options for the sport, plus the layer id. */\nexport type SurfaceLayerOptions<S extends Sport> = OptionsOf<S> & {\n /** The layer id. Default \"sdvplot-surface\". */\n id?: string;\n};\n\n/** The px height an icon is packed into deck.gl's atlas at (the logo is drawn at `size`, so this is its sharpness). */\nconst ICON_PX = 128;\nconst real = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v);\nfunction checkPx(name: string, v: unknown): number {\n if (!real(v) || v < 1) throw new InputError(`${name} is in px, 1 or more, got ${String(v)}`);\n return v;\n}\n/** The alpha byte of `#rgb`, `#rgba`, `#rrggbb` or `#rrggbbaa` (255 when it gives none). */\nfunction alphaOf(color: string): number {\n let c = String(color).trim().replace(/^#+/, \"\");\n if (c.length === 4) c = [...c].map((ch) => ch + ch).join(\"\");\n return c.length === 8 ? Number.parseInt(c.slice(6), 16) : 255;\n}\n/** `#rgb`, `#rgba`, `#rrggbb` or `#rrggbbaa` as deck.gl's `[r, g, b, a]`. */\nfunction rgba(color: string): Rgba {\n const a = alphaOf(color);\n const [r, g, b] = [1, 3, 5].map((i) =>\n Number.parseInt(hex6(color, { dropAlpha: true }).slice(i, i + 2), 16),\n );\n return [r as number, g as number, b as number, a];\n}\n\n/**\n * deck.gl `IconLayer` props drawing each row's team logo at its (x, y). The logos are auto-packed icons: deck.gl\n * fetches each URL once and packs it into its own atlas, at 128 px tall and the logo's aspect, centred on the point.\n * A team with no logo (or one that does not resolve) is left out with one warning, as the other adapters do; so is a\n * row with a missing x or y. `x` and `y` are in the layer's coordinates: longitude and latitude on a map, or a\n * surface's own units on `surfaceLayer` (set `coordinateSystem: \"cartesian\"` on both, or use a non-geographic view).\n *\n * @example\n * ```ts\n * import { loadLeague } from \"@sportsdataverse/sdvplot\";\n * import { logoIconLayer } from \"@sportsdataverse/sdvplot/deckgl\";\n *\n * await loadLeague(\"nhl\");\n * // Edmonton's first shot of game 7 of the 2024 Stanley Cup Final (NHL api-web), in feet from centre ice\n * const shot = { team: \"EDM\", x: 82, y: -3 };\n * const props = logoIconLayer([shot], { x: \"x\", y: \"y\", team: \"team\", league: \"nhl\", size: 28 });\n * // in the browser: new IconLayer({ ...props, coordinateSystem: \"cartesian\" })\n * props.data[0]?.icon.url;\n * ```\n */\nexport function logoIconLayer(rows: readonly Row[], o: LogoIconOptions): LogoIconLayerProps {\n const size = checkPx(\"size\", o.size ?? 32);\n const opacity = checkAlpha(o.alpha ?? 1);\n const data = markPlacements(rows, \"logo\", o).map((p): IconRow => {\n const height = ICON_PX;\n return {\n position: [Number(p.x), Number(p.y)],\n icon: { url: p.url, width: Math.round(ICON_PX * aspect(p)), height, anchorY: height / 2, mask: false },\n team: p.id,\n index: p.index,\n };\n });\n return {\n id: o.id ?? \"sdvplot-logos\",\n data,\n getPosition: (d) => d.position,\n getIcon: (d) => d.icon,\n getSize: size,\n sizeUnits: \"pixels\",\n opacity,\n };\n}\n\n/** An unresolved team value as text, the same in Python: a number without \".0\", a missing one empty. */\nconst label = (t: unknown): string =>\n t === null || t === undefined ? \"\" : typeof t === \"number\" ? (normValue(t) ?? \"\") : String(t);\n\n/**\n * One colour per distinct team at one end of the arcs (`ids[j]` null for a team that did not resolve): the teams'\n * `which` colours, or the shared palette of them on `background`. A team that did not resolve takes the fallback and\n * stays out of the palette, so it never moves a real team's colour (and no warning names it).\n */\nfunction endColors(ids: readonly (string | null)[], o: PassArcOptions, which: Which): string[] {\n const fallback = hex6(o.fallback ?? \"#808080\");\n const co = { idSystem: \"team_id\" as const, ...(o.season === undefined ? {} : { season: o.season }) };\n const known = ids.filter((id): id is string => id !== null);\n const main = colorList(o.league, known, { ...co, which });\n const other = colorList(o.league, known, { ...co, which: which === \"primary\" ? \"secondary\" : \"primary\" });\n // a team with no `which` colour (often no secondary) takes its other colour, then the fallback\n let colors = main.map((c, i) => hex6(c ?? other[i] ?? fallback, { dropAlpha: true }));\n if (o.background !== undefined) colors = teamPalette(colors, other, hex6(o.background), known);\n let k = 0;\n return ids.map((id) => (id === null ? fallback : (colors[k++] as string)));\n}\n\n/**\n * deck.gl `ArcLayer` props: one arc per row from (x, y) to (xend, yend), in the team's colours: its primary colour at\n * the source and its secondary at the target (`which: \"secondary\"` swaps them), so the two ends tell the direction\n * apart where the two colours differ (see `background`). Each team keeps one colour per end, the teams taken in the\n * order they first appear. With `background`, every colour keeps 3:1 contrast against it and aims to stay distinct from\n * the other teams' (the shared team palette; when it cannot, it keeps the readable colour and warns once). A team that\n * does not resolve takes `fallback`, as given (its contrast is not checked); a row with a missing\n * coordinate is left out with one warning.\n *\n * @example\n * ```ts\n * import { loadLeague } from \"@sportsdataverse/sdvplot\";\n * import { passArcLayer } from \"@sportsdataverse/sdvplot/deckgl\";\n *\n * await loadLeague(\"soccer\");\n * // France's first completed pass of the 2018 World Cup final (StatsBomb open data through SPADL, metres from the\n * // corner); France is ESPN soccer team 478\n * const pass = { team: \"478\", start_x: 54.68750000000001, start_y: 6.375, end_x: 56.4375, end_y: 1.2750000000000057 };\n * const props = passArcLayer([pass], {\n * x: \"start_x\",\n * y: \"start_y\",\n * xend: \"end_x\",\n * yend: \"end_y\",\n * team: \"team\",\n * league: \"soccer\",\n * idSystem: \"team_id\",\n * tilt: 90,\n * });\n * // in the browser: new ArcLayer({ ...props, coordinateSystem: \"cartesian\" })\n * props.data[0]?.sourceColor;\n * ```\n */\nexport function passArcLayer(rows: readonly Row[], o: PassArcOptions): PassArcLayerProps {\n const width = checkPx(\"width\", o.width ?? 2);\n const opacity = checkAlpha(o.alpha ?? 1);\n if (o.tilt !== undefined && !(real(o.tilt) && o.tilt >= -90 && o.tilt <= 90))\n throw new InputError(`tilt is in degrees, in [-90, 90], got ${String(o.tilt)}`);\n if (o.height !== undefined && !(real(o.height) && o.height >= 0))\n throw new InputError(`height is an arc's height multiplier, 0 or more, got ${String(o.height)}`);\n const cols = [o.x, o.y, o.xend, o.yend].map((c, k) =>\n column(rows, c, [\"x\", \"y\", \"xend\", \"yend\"][k] as string),\n );\n const teams = column(rows, o.team, \"team\");\n const keep: number[] = [];\n const missing: Value[] = [];\n rows.forEach((_, i) => {\n if (cols.every((c) => real(c[i]))) keep.push(i);\n else missing.push(teams[i] as Value);\n });\n if (missing.length > 0) {\n const shown =\n missing.slice(0, 10).map(String).join(\", \") +\n (missing.length > 10 ? ` and ${missing.length - 10} more` : \"\");\n warn(\n `deckgl:arcs:${o.league}:missing:${shown}`,\n `skipped ${missing.length} arc(s) with a missing coordinate: ${shown}`,\n );\n }\n const ro = {\n ...(o.season === undefined ? {} : { season: o.season }),\n ...(o.idSystem === undefined ? {} : { idSystem: o.idSystem }),\n };\n const kept = keep.map((i) => teams[i] as Value);\n const resolved = resolveSync(kept, o.league, ro);\n // one colour per distinct team, in order of first appearance; an unresolved team is keyed by its own value\n const keys = kept.map((t, j) => resolved[j] ?? `?${label(t)}`);\n const distinct = [...new Set(keys)];\n const ids = distinct.map((k) => (k.startsWith(\"?\") ? null : k));\n const which = o.which ?? \"primary\";\n const src = endColors(ids, o, which);\n const tgt = endColors(ids, o, which === \"primary\" ? \"secondary\" : \"primary\");\n const at = new Map(distinct.map((k, j) => [k, j]));\n const data = keep.map((i, j): ArcRow => {\n const k = at.get(keys[j] as string) as number;\n return {\n source: [cols[0]?.[i] as number, cols[1]?.[i] as number],\n target: [cols[2]?.[i] as number, cols[3]?.[i] as number],\n sourceColor: rgba(src[k] as string),\n targetColor: rgba(tgt[k] as string),\n team: resolved[j] ?? label(kept[j]),\n index: i,\n };\n });\n return {\n id: o.id ?? \"sdvplot-arcs\",\n data,\n getSourcePosition: (d) => d.source,\n getTargetPosition: (d) => d.target,\n getSourceColor: (d) => d.sourceColor,\n getTargetColor: (d) => d.targetColor,\n getWidth: width,\n widthUnits: \"pixels\",\n opacity,\n ...(o.height === undefined ? {} : { getHeight: o.height }),\n ...(o.tilt === undefined ? {} : { getTilt: o.tilt }),\n };\n}\n\ntype Pt = readonly [x: number, y: number];\n/**\n * A feature's path as closed loops. sporty (after sportyR) draws some features as two loops in one path, such as a\n * faceoff circle's two half rings each closing back on its first point: an SVG or canvas fill draws that as it is, but\n * deck.gl triangulates a polygon as one simple ring and fills the wrong side of it. A loop ends where the path comes\n * back to that loop's first point, after at least two other points (a repeated first point does not end it). The\n * same rule is in sdvplot.pydeck. ponytail: a loop inside another would be filled, not cut out as a hole; sporty\n * builds every ring from two half rings, so none is.\n */\nfunction loops(points: readonly Pt[]): Pt[][] {\n const out: Pt[][] = [];\n let loop: Pt[] = [];\n let away = 0; // points of this loop that are not its first\n for (const p of points) {\n const first = loop[0];\n loop.push(p);\n if (first === undefined) continue;\n if (p[0] !== first[0] || p[1] !== first[1]) away++;\n else if (away >= 2) {\n out.push(loop);\n loop = [];\n away = 0;\n }\n }\n if (away >= 2) out.push(loop); // an open path, closed by deck.gl\n return out;\n}\n\n// Copied from ./three/surface.ts (PR #79), where the three.js surface needs the same split: kept here so this PR stands\n// alone. ponytail: one shared internal module (src/rings.ts) for both once both have merged.\nconst turn = (a: Pt, b: Pt, c: Pt): number => (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);\nfunction signedArea(r: readonly Pt[]): number {\n let s = 0;\n for (let i = 0; i < r.length; i++) {\n const [a, b] = [r[i] as Pt, r[(i + 1) % r.length] as Pt];\n s += a[0] * b[1] - b[0] * a[1];\n }\n return s / 2;\n}\n/**\n * No area to fill: a path that goes out along a line and back along it (the NLL goal fan), which a fill leaves\n * invisible, as sporty's own SVG does, or the sliver left where a ring touched itself.\n */\nfunction empty(r: readonly Pt[]): boolean {\n let [x0, y0, x1, y1] = [\n Number.POSITIVE_INFINITY,\n Number.POSITIVE_INFINITY,\n Number.NEGATIVE_INFINITY,\n Number.NEGATIVE_INFINITY,\n ];\n for (const [x, y] of r)\n [x0, y0, x1, y1] = [Math.min(x0, x), Math.min(y0, y), Math.max(x1, x), Math.max(y1, y)];\n return r.length < 3 || Math.abs(signedArea(r)) <= 1e-9 * ((x1 - x0) ** 2 + (y1 - y0) ** 2);\n}\n/**\n * A ring that crosses itself split at each crossing into rings that do not, each to be filled: what an SVG (nonzero)\n * fill shows of a figure-of-eight, and what deck.gl's earcut cannot triangulate. sporty has a few: the NHL goaltender's\n * trapezoids and some faceoff hash marks twist at their corners by an inch.\n */\nfunction simple(r: readonly Pt[]): Pt[][] {\n const n = r.length;\n const side = (a: Pt, b: Pt, c: Pt): number => Math.sign(turn(a, b, c));\n for (let i = 0; i < n; i++)\n for (let j = i + 2; j < n; j++) {\n if (i === 0 && j === n - 1) continue; // neighbours across the closing edge\n const [a, b, c, d] = [r[i] as Pt, r[(i + 1) % n] as Pt, r[j] as Pt, r[(j + 1) % n] as Pt];\n if (side(a, b, c) * side(a, b, d) >= 0 || side(c, d, a) * side(c, d, b) >= 0) continue;\n const s = turn(c, d, a) / (turn(c, d, a) - turn(c, d, b)); // where the crossing is along a -> b\n const x: Pt = [a[0] + s * (b[0] - a[0]), a[1] + s * (b[1] - a[1])];\n return [\n ...simple([...r.slice(0, i + 1), x, ...r.slice(j + 1)]),\n ...simple([x, ...r.slice(i + 1, j + 1)]),\n ];\n }\n return [[...r]];\n}\n\nconst drawn = (f: PolygonFeature): boolean =>\n f.points.length > 0 &&\n f.points.every(([x, y]) => Number.isFinite(x) && Number.isFinite(y)) &&\n alphaOf(f.fill) !== 0;\n\n/**\n * deck.gl `PolygonLayer` props drawing sporty's playing surface for `sport` and `league` (sporty's own league keys,\n * e.g. `surfaceLayer(\"hockey\", \"nhl\")`, `surfaceLayer(\"soccer\", \"fifa\")`), in the surface's own coordinates: deck.gl's\n * `\"cartesian\"` coordinate system, in the surface's units (feet for a rink, metres for a pitch) with the origin at its\n * centre, the frame sporty draws in and NHL api-web's shot coordinates are in. Each closed loop of a polygon feature\n * is one data row (a faceoff circle is two: its half rings; a loop that crosses itself is split at the crossing into\n * rings that do not, and a loop with no area is left out), in sporty's drawing order, filled with its colour (alpha\n * included). sporty's default strokes equal their fills, so\n * the layer is fill-only; a hidden feature (a `#rrggbb00` fill) and text features (a football field's yard numbers)\n * are left out. `o` is passed to sporty's `surface()` (`updates`, `colorUpdates`, `units`, `rotation`, ...); sporty's\n * own errors escape unwrapped. Draw it with deck.gl's OrthographicView.\n *\n * @example\n * ```ts\n * import { surfaceLayer } from \"@sportsdataverse/sdvplot/deckgl\";\n *\n * const rink = surfaceLayer(\"hockey\", \"nhl\");\n * // in the browser: new PolygonLayer(rink), in a Deck with views: new OrthographicView({ flipY: false })\n * rink.data.length;\n * ```\n */\nexport function surfaceLayer<S extends Sport>(\n sport: S,\n league: LeagueOf<S>,\n o: SurfaceLayerOptions<S> = {} as SurfaceLayerOptions<S>,\n): SurfaceLayerProps {\n const { id = \"sdvplot-surface\", ...opts } = o;\n const scene = sportySurface(sport, league, opts as OptionsOf<S>);\n // ponytail: features draw in array order (sporty's zIndex is its position); sort here if that ever changes\n const data = scene.features\n .filter((f): f is PolygonFeature => f.kind === \"polygon\" && drawn(f))\n .flatMap((f) =>\n loops(f.points)\n .flatMap(simple)\n .filter((r) => !empty(r))\n .map((polygon): SurfaceRow => ({ name: f.name, polygon, fillColor: rgba(f.fill) })),\n );\n return {\n id,\n data,\n getPolygon: (d) => d.polygon,\n getFillColor: (d) => d.fillColor,\n coordinateSystem: \"cartesian\",\n filled: true,\n stroked: false,\n };\n}\n"]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { A as AxisOptions, H as HeadshotOptions, M as MarkOptions, D as DrawnAxisMark, a as DrawnMark, R as Row } from './_web-D7Aa5Rd8.js';
|
|
2
|
+
export { e as embedSources } from './_web-D7Aa5Rd8.js';
|
|
3
|
+
import { L as League, S as SeasonInput, I as IdSystem } from './types-C7n6gJF3.js';
|
|
4
|
+
|
|
5
|
+
/** The ECharts adapter: logos, wordmarks and headshots as a `custom` series whose renderItem draws image elements in
|
|
6
|
+
* data coordinates; axis logos as rich-text axis labels. Pure: echarts is never imported at runtime. */
|
|
7
|
+
|
|
8
|
+
/** Structural types for an ECharts option: the subset `sdvplot/echarts` reads and writes. No runtime import of echarts. */
|
|
9
|
+
interface EChartsAxis {
|
|
10
|
+
type?: "value" | "category" | "time" | "log";
|
|
11
|
+
data?: readonly unknown[];
|
|
12
|
+
axisLabel?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
interface EChartsOption {
|
|
15
|
+
xAxis?: EChartsAxis | readonly EChartsAxis[];
|
|
16
|
+
yAxis?: EChartsAxis | readonly EChartsAxis[];
|
|
17
|
+
series?: readonly (Record<string, unknown> | LogoSeries)[];
|
|
18
|
+
color?: readonly string[];
|
|
19
|
+
grid?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/** No `name`: ECharts leaves an unnamed series out of the default legend (measured, echarts 6.1.0), so `legend: {}`
|
|
22
|
+
* lists only the caller's series; the `id` carries the bookkeeping. `tooltip: { show: false }` keeps the series out
|
|
23
|
+
* of a `trigger: "axis"` tooltip, where it would add a stray row; `silent` alone does not (echarts 6.1.0
|
|
24
|
+
* axisPointer/modelHelper collectSeriesInfo reads the series' own tooltip.show, never silent). */
|
|
25
|
+
interface LogoSeries {
|
|
26
|
+
id: string;
|
|
27
|
+
type: "custom";
|
|
28
|
+
coordinateSystem: "cartesian2d";
|
|
29
|
+
xAxisIndex?: number;
|
|
30
|
+
yAxisIndex?: number;
|
|
31
|
+
data: (string | number)[][];
|
|
32
|
+
encode: {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
};
|
|
36
|
+
z: number;
|
|
37
|
+
silent: true;
|
|
38
|
+
tooltip: {
|
|
39
|
+
show: false;
|
|
40
|
+
};
|
|
41
|
+
renderItem: (params: RenderParams, api: RenderApi) => RenderedImage;
|
|
42
|
+
}
|
|
43
|
+
/** echarts types `coordSys` as `{ type: string }`; a cartesian2d series gets x, y, width and height at run time. */
|
|
44
|
+
interface RenderParams {
|
|
45
|
+
coordSys: {
|
|
46
|
+
type?: string;
|
|
47
|
+
x?: number;
|
|
48
|
+
y?: number;
|
|
49
|
+
width?: number;
|
|
50
|
+
height?: number;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
interface RenderApi {
|
|
54
|
+
value: (dim: number) => number | string;
|
|
55
|
+
coord: (data: (number | string)[]) => number[];
|
|
56
|
+
}
|
|
57
|
+
interface RenderedImage {
|
|
58
|
+
type: "image";
|
|
59
|
+
style: {
|
|
60
|
+
image: string;
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
opacity?: number;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** `withLogos` / `withWordmarks` options: the shared ones plus the axes (grid) the series draws on. */
|
|
69
|
+
interface EChartsMarkOptions extends MarkOptions {
|
|
70
|
+
/** The x axis (and so the grid) the logos draw on. Default 0. */
|
|
71
|
+
xAxisIndex?: number;
|
|
72
|
+
/** The y axis the logos draw on. Default 0. */
|
|
73
|
+
yAxisIndex?: number;
|
|
74
|
+
/** The series' z. Default 100 (above the caller's series). */
|
|
75
|
+
z?: number;
|
|
76
|
+
}
|
|
77
|
+
/** `withHeadshots` options: the shared ones plus the axes (grid) the series draws on. */
|
|
78
|
+
interface EChartsHeadshotOptions extends HeadshotOptions {
|
|
79
|
+
/** The x axis (and so the grid) the headshots draw on. Default 0. */
|
|
80
|
+
xAxisIndex?: number;
|
|
81
|
+
/** The y axis the headshots draw on. Default 0. */
|
|
82
|
+
yAxisIndex?: number;
|
|
83
|
+
/** The series' z. Default 100 (above the caller's series). */
|
|
84
|
+
z?: number;
|
|
85
|
+
}
|
|
86
|
+
/** The renderItem every sdvplot custom series uses: one image per datum, centred on api.coord([x, y]), `height` of the grid tall. */
|
|
87
|
+
declare function renderLogo(params: RenderParams, api: RenderApi): RenderedImage;
|
|
88
|
+
declare function withLogos(option: EChartsOption, rows: readonly Row[], o: EChartsMarkOptions): EChartsOption;
|
|
89
|
+
declare function withLogos<F extends object>(option: F, rows: readonly Row[], o: EChartsMarkOptions): F;
|
|
90
|
+
declare function withWordmarks(option: EChartsOption, rows: readonly Row[], o: EChartsMarkOptions): EChartsOption;
|
|
91
|
+
declare function withWordmarks<F extends object>(option: F, rows: readonly Row[], o: EChartsMarkOptions): F;
|
|
92
|
+
declare function withHeadshots(option: EChartsOption, rows: readonly Row[], o: EChartsHeadshotOptions): EChartsOption;
|
|
93
|
+
declare function withHeadshots<F extends object>(option: F, rows: readonly Row[], o: EChartsHeadshotOptions): F;
|
|
94
|
+
/** Test hook: [teamId, x, y, height, url] per datum of the sdvplot mark series, read from what the series' own
|
|
95
|
+
* renderItem draws (the point it asks api.coord for, the image and its height over the grid's). */
|
|
96
|
+
declare function drawnMarks(option: EChartsOption): DrawnMark[];
|
|
97
|
+
/** `withAxisLogos` options: the shared ones plus which axis and the canvas height. */
|
|
98
|
+
interface EChartsAxisOptions extends AxisOptions {
|
|
99
|
+
/** Which x (or y) axis, for an option with several. Default 0. */
|
|
100
|
+
axisIndex?: number;
|
|
101
|
+
/** The canvas height in px (an option has none). With the axis' grid it gives the plot-area height that `height`
|
|
102
|
+
* is a fraction of. Default 400. */
|
|
103
|
+
chartHeight?: number;
|
|
104
|
+
}
|
|
105
|
+
declare function withAxisLogos(option: EChartsOption, axis: "x" | "y", o: EChartsAxisOptions): EChartsOption;
|
|
106
|
+
declare function withAxisLogos<F extends object>(option: F, axis: "x" | "y", o: EChartsAxisOptions): F;
|
|
107
|
+
/** One colour per team, in order, for `option.color`. */
|
|
108
|
+
declare function teamColorPalette(league: League, teams: readonly unknown[], o?: {
|
|
109
|
+
which?: "primary" | "secondary";
|
|
110
|
+
season?: SeasonInput;
|
|
111
|
+
idSystem?: IdSystem;
|
|
112
|
+
fallback?: string;
|
|
113
|
+
}): string[];
|
|
114
|
+
/** Test hook: [teamId, category index, height] per axis image, in tick order; height is the axis label's rich
|
|
115
|
+
* image height over the grid height it was sized against. */
|
|
116
|
+
declare function drawnAxisMarks(option: EChartsOption, axis: "x" | "y"): DrawnAxisMark[];
|
|
117
|
+
/** Test hook: the text each category label shows (the axis' own formatter run on it), less the empty rich image
|
|
118
|
+
* labels, on the axis `withAxisLogos` drew on (`axisIndex`). */
|
|
119
|
+
declare function visibleAxisLabels(option: EChartsOption, axis: "x" | "y"): string[];
|
|
120
|
+
|
|
121
|
+
export { AxisOptions, DrawnAxisMark, DrawnMark, type EChartsAxis, type EChartsAxisOptions, type EChartsHeadshotOptions, type EChartsMarkOptions, type EChartsOption, HeadshotOptions, type LogoSeries, MarkOptions, type RenderApi, type RenderParams, type RenderedImage, Row, drawnAxisMarks, drawnMarks, renderLogo, teamColorPalette, visibleAxisLabels, withAxisLogos, withHeadshots, withLogos, withWordmarks };
|