@maestro_io/maestro-web-sdk 2.1.2 → 2.1.3

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 (68) hide show
  1. package/dist/components/atoms/Rive/index.d.ts +1 -0
  2. package/dist/components/atoms/Rive/index.js +3 -2
  3. package/dist/components/molecules/ActionButton/ActionButton.d.ts +1 -0
  4. package/dist/components/molecules/PanelNavButton/PanelNavButton.d.ts +1 -0
  5. package/dist/components/organisms/PanelNavigation/PanelNavigation.js +5 -6
  6. package/dist/components/organisms/SegmentController/SegmentController.d.ts +2 -2
  7. package/dist/components/organisms/SegmentController/SegmentController.js +5 -6
  8. package/dist/external/spatial-navigation/index.d.ts +2 -3
  9. package/dist/external/spatial-navigation/index.js +1 -2
  10. package/dist/external/spatial-navigation/spatialNavigation.d.ts +2 -4
  11. package/dist/external/spatial-navigation/spatialNavigation.js +25 -36
  12. package/dist/external/spatial-navigation/withFocusable.d.ts +1 -0
  13. package/dist/external/spatial-navigation/withFocusable.js +17 -10
  14. package/dist/maestro-web-sdk.umd.js +3 -3
  15. package/dist/maestro-web-sdk.umd.js.map +1 -1
  16. package/dist/modules/bets/view/HotProps/HotPropsView.d.ts +7 -6
  17. package/dist/modules/bets/view/HotProps/HotPropsView.js +11 -11
  18. package/dist/modules/bets/view/SixPack/SixPackView.d.ts +2 -2
  19. package/dist/modules/bets/view/SixPack/SixPackView.js +4 -4
  20. package/dist/modules/bets/view/TabLoadFailureView.d.ts +1 -0
  21. package/dist/modules/bets/view/UserBets/BetsCard/BetsCard.d.ts +7 -6
  22. package/dist/modules/bets/view/UserBets/BetsCard/BetsCard.js +10 -10
  23. package/dist/modules/bets/view/components/Bet/Bet.d.ts +1 -0
  24. package/dist/modules/bets/view/components/PromoCodeBanner/PromoCodeBanner.d.ts +2 -2
  25. package/dist/modules/bets/view/components/PromoCodeBanner/PromoCodeBanner.js +4 -4
  26. package/dist/modules/bets/view-model/BetsViewModel.js +2 -2
  27. package/dist/modules/key-plays/view/KeyPlayCardView.d.ts +0 -4
  28. package/dist/modules/key-plays/view/KeyPlayCardView.js +4 -26
  29. package/dist/modules/key-plays/view/KeyPlaysView.js +1 -2
  30. package/dist/modules/stats/interfaces/IStats.d.ts +6 -3
  31. package/dist/modules/stats/mocks.d.ts +80 -0
  32. package/dist/modules/stats/mocks.js +140 -0
  33. package/dist/modules/stats/utils/renderTeamStatistic.d.ts +21 -0
  34. package/dist/modules/stats/utils/renderTeamStatistic.js +16 -0
  35. package/dist/modules/stats/view/ActiveAthletes/ActiveAthletes.d.ts +34 -0
  36. package/dist/modules/stats/view/ActiveAthletes/ActiveAthletes.js +78 -0
  37. package/dist/modules/stats/view/ActiveAthletes/CollapsedAthletes/CollapsedAthletes.d.ts +5 -0
  38. package/dist/modules/stats/view/ActiveAthletes/CollapsedAthletes/CollapsedAthletes.js +27 -0
  39. package/dist/modules/stats/view/ActiveAthletes/ExpandedAthletes/ExpandedAthletes.d.ts +10 -0
  40. package/dist/modules/stats/view/ActiveAthletes/ExpandedAthletes/ExpandedAthletes.js +15 -0
  41. package/dist/modules/stats/view/ActiveAthletes/index.d.ts +2 -0
  42. package/dist/modules/stats/view/ActiveAthletes/index.js +2 -0
  43. package/dist/modules/stats/view/GameLeaders/GameLeaders.d.ts +2 -23
  44. package/dist/modules/stats/view/GameLeaders/GameLeaders.js +1 -1
  45. package/dist/modules/stats/view/MatchPredictor/MatchPredictorView.d.ts +1 -0
  46. package/dist/modules/stats/view/RecentGames/RecentGames.d.ts +1 -0
  47. package/dist/modules/stats/view/StatsQRCode/StatsQRCodeView.d.ts +1 -0
  48. package/dist/modules/stats/view/StatsView.d.ts +1 -1
  49. package/dist/modules/stats/view/StatsView.js +31 -11
  50. package/dist/modules/stats/view/TeamStats/TeamStatsView.d.ts +54 -0
  51. package/dist/modules/stats/view/TeamStats/TeamStatsView.js +69 -0
  52. package/dist/modules/stats/view/TeamStats/index.d.ts +2 -0
  53. package/dist/modules/stats/view/TeamStats/index.js +1 -0
  54. package/dist/modules/stats/view/Teams/StatsProgressBar.js +7 -3
  55. package/dist/modules/stats/view/Teams/Teams.d.ts +1 -0
  56. package/dist/modules/stats/view/Teams/Teams.js +15 -8
  57. package/dist/modules/stats/view/WinProbability/WinProbability.d.ts +1 -0
  58. package/dist/modules/stats/view/components/AthletesStatistics/AthletesStatistics.d.ts +19 -3
  59. package/dist/modules/stats/view/components/AthletesStatistics/AthletesStatistics.js +7 -6
  60. package/dist/modules/stats/view/components/AthletesStatistics/StatisticTable.d.ts +2 -8
  61. package/dist/modules/stats/view/components/AthletesStatistics/StatisticTable.js +4 -3
  62. package/dist/modules/stats/view/index.d.ts +1 -0
  63. package/dist/modules/stats/view/index.js +1 -0
  64. package/dist/services/StatsService.d.ts +36 -0
  65. package/dist/services/StatsService.js +68 -0
  66. package/dist/view-models/MaestroEventViewModel.d.ts +7 -0
  67. package/dist/view-models/MaestroEventViewModel.js +18 -6
  68. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export { default } from './TeamStatsView';
2
+ export type { TeamStatsViewProps } from './TeamStatsView';
@@ -0,0 +1 @@
1
+ export { default } from './TeamStatsView';
@@ -4,11 +4,15 @@ const StatsProgressBar = (props) => {
4
4
  const awayTeamPercentage = total === 0 ? 0 : Math.round((props.awayTeamValue / total) * 100);
5
5
  return (React.createElement("div", { className: "progress-bar" },
6
6
  React.createElement("div", { className: "progress-fill" },
7
- React.createElement("div", { className: "progress-divider", style: {
8
- right: `${awayTeamPercentage}%`,
7
+ React.createElement("div", { className: "progress-solid", style: {
8
+ width: `${awayTeamPercentage}%`,
9
9
  } }),
10
10
  React.createElement("div", { className: "progress-stripes", style: {
11
- width: `${awayTeamPercentage}%`,
11
+ left: `${awayTeamPercentage}%`,
12
+ width: `${100 - awayTeamPercentage}%`,
13
+ } }),
14
+ React.createElement("div", { className: "progress-divider", style: {
15
+ left: `${awayTeamPercentage}%`,
12
16
  } }))));
13
17
  };
14
18
  export default StatsProgressBar;
@@ -25,6 +25,7 @@ export type HeaderTeamStatItem = {
25
25
  declare const _default: {
26
26
  new (props?: (HeaderTeamStatItem & WithFocusableProps) | undefined, context?: any): {
27
27
  state: import("../../../../external/spatial-navigation/withFocusable").WithFocusableState;
28
+ navigation: import("../../../../external/spatial-navigation/spatialNavigation").default;
28
29
  getChildContext(): {
29
30
  parentFocusKey: string;
30
31
  };
@@ -3,7 +3,7 @@ import './TeamsView.styles.css';
3
3
  import Image from '@/components/atoms/Image';
4
4
  import { withFocusable, } from '@/external/spatial-navigation';
5
5
  import { CarouselSlider, StatsCarousel } from './StatsCarousel';
6
- import StatsProgressBar from './StatsProgressBar';
6
+ import { renderTeamStatistic } from '../../utils/renderTeamStatistic';
7
7
  const Teams = (props) => {
8
8
  const teams = [props.homeTeam, props.awayTeam];
9
9
  return (React.createElement("section", { className: "stats-teams-view focus-ring", "data-focused": props.focused, style: {
@@ -24,12 +24,19 @@ const Teams = (props) => {
24
24
  React.createElement("tbody", null, teams.map((team) => (React.createElement("tr", { key: team.id },
25
25
  React.createElement("td", { className: "T30" }, team.name),
26
26
  team.linescores.map((lineScore, index) => (React.createElement("td", { key: `${lineScore}-${index}`, className: "T10" }, lineScore)))))))),
27
- props.statistics && props.statistics.length > 0 && (React.createElement(StatsCarousel, { itemsLength: props.statistics.length }, props.statistics.map((statistic) => (React.createElement(CarouselSlider, { itemsLength: props.statistics.length, key: statistic.displayName },
28
- React.createElement("div", { className: "score-statistics" },
29
- React.createElement("div", { className: "score-statistics-header" },
30
- React.createElement("span", { className: "T30" }, statistic.homeTeamValue),
31
- React.createElement("span", { className: "statistic-name T02" }, statistic.displayName),
32
- React.createElement("span", { className: "T30" }, statistic.awayTeamValue)),
33
- React.createElement(StatsProgressBar, { awayTeamValue: statistic.awayTeamValue, homeTeamValue: statistic.homeTeamValue })))))))))));
27
+ props.statistics && props.statistics.length > 0 && (React.createElement(StatsCarousel, { itemsLength: props.statistics.length }, props.statistics.map((statistic) => (React.createElement(CarouselSlider, { itemsLength: props.statistics.length, key: statistic.displayName }, renderTeamStatistic({
28
+ statisticName: statistic.displayName,
29
+ firstDisplayValue: statistic.homeTeamValue,
30
+ secondDisplayValue: statistic.awayTeamValue,
31
+ awayProgressValue: statistic.awayTeamValue,
32
+ homeProgressValue: statistic.homeTeamValue,
33
+ classNames: {
34
+ container: 'score-statistics',
35
+ header: 'score-statistics-header',
36
+ firstValue: 'T30',
37
+ secondValue: 'T30',
38
+ statisticName: 'statistic-name T02',
39
+ },
40
+ }))))))))));
34
41
  };
35
42
  export default withFocusable()(Teams);
@@ -20,6 +20,7 @@ export type WinProbabilityStatsItem = {
20
20
  declare const _default: {
21
21
  new (props?: (WinProbabilityStatsItem & WithFocusableProps) | undefined, context?: any): {
22
22
  state: import("../../../../external/spatial-navigation/withFocusable").WithFocusableState;
23
+ navigation: import("../../../../external/spatial-navigation/spatialNavigation").default;
23
24
  getChildContext(): {
24
25
  parentFocusKey: string;
25
26
  };
@@ -1,14 +1,30 @@
1
1
  /// <reference types="prop-types" />
2
2
  import React from 'react';
3
3
  import { WithFocusableProps } from '@/external/spatial-navigation';
4
- import { LeaderStatsItem } from '../../GameLeaders/GameLeaders';
5
4
  import './AthleteStatistics.styles.css';
6
- type AthletesStatisticsProps = {
7
- item: LeaderStatsItem;
5
+ import { LeaderStatistic } from '@/modules/stats/interfaces/IStats';
6
+ type Athlete = {
7
+ id: string;
8
+ displayName: string;
9
+ headshot: string;
10
+ position: string;
11
+ shortName: string;
12
+ jersey: string;
13
+ statistics: LeaderStatistic[];
14
+ minifiedStatistics?: string;
15
+ };
16
+ export type AthletesStatisticsItem = {
17
+ displayName?: string;
18
+ awayAthlete: Athlete;
19
+ homeAthlete: Athlete;
20
+ };
21
+ export type AthletesStatisticsProps = {
22
+ item: AthletesStatisticsItem;
8
23
  };
9
24
  declare const _default: {
10
25
  new (props?: (AthletesStatisticsProps & WithFocusableProps) | undefined, context?: any): {
11
26
  state: import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState;
27
+ navigation: import("../../../../../external/spatial-navigation/spatialNavigation").default;
12
28
  getChildContext(): {
13
29
  parentFocusKey: string;
14
30
  };
@@ -5,8 +5,8 @@ import { withFocusable, } from '@/external/spatial-navigation';
5
5
  import './AthleteStatistics.styles.css';
6
6
  const AthletesStatistics = (props) => {
7
7
  const item = props.item;
8
- return (React.createElement("div", { className: "athletes-statistics focus-ring", key: item.displayName, "data-focused": props.focused },
9
- React.createElement("span", { className: "T05_ALT" }, item.displayName),
8
+ return (React.createElement("div", { className: "athletes-statistics focus-ring", "data-focused": props.focused },
9
+ !!item.displayName && (React.createElement("span", { className: "T05_ALT" }, item.displayName)),
10
10
  React.createElement("div", { className: "leaders-wrapper" }, [item.awayAthlete, item.homeAthlete].map((athlete) => {
11
11
  return (React.createElement("div", { className: "leader", key: athlete.id + item.displayName },
12
12
  React.createElement("div", { className: "image-wrapper T02", "data-position": athlete.position },
@@ -18,11 +18,12 @@ const AthletesStatistics = (props) => {
18
18
  React.createElement("span", { className: "athlete-number T02" },
19
19
  "#",
20
20
  athlete.jersey)),
21
- athlete.mainStatistic && (React.createElement("div", { className: "main-statistic T30" },
22
- athlete.mainStatistic.displayValue,
21
+ Array.isArray(athlete.statistics) &&
22
+ !!athlete.statistics.length && (React.createElement("div", { className: "main-statistic T30" },
23
+ athlete.statistics[0].displayValue,
23
24
  ' ',
24
- React.createElement("span", { className: "athlete-points T02" }, athlete.mainStatistic.abbreviation))))));
25
+ React.createElement("span", { className: "athlete-points T02" }, athlete.statistics[0].abbreviation))))));
25
26
  })),
26
- React.createElement(StatisticsTable, { statistics: item.statistics || [] })));
27
+ React.createElement(StatisticsTable, { item: item })));
27
28
  };
28
29
  export default withFocusable()(AthletesStatistics);
@@ -1,10 +1,4 @@
1
1
  import React from 'react';
2
- type LeadersStatisticTableProps = {
3
- statistics: {
4
- awayAthleteValue: string;
5
- abbreviation: string;
6
- homeAthleteValue: string;
7
- }[];
8
- };
9
- declare const StatisticsTable: (props: LeadersStatisticTableProps) => React.JSX.Element;
2
+ import { AthletesStatisticsProps } from './AthletesStatistics';
3
+ declare const StatisticsTable: (props: AthletesStatisticsProps) => React.JSX.Element;
10
4
  export default StatisticsTable;
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
2
  const StatisticsTable = (props) => {
3
3
  return (React.createElement("table", { className: "athletes-statistics-table T10" },
4
- React.createElement("tbody", null, props.statistics.map((statistic) => {
4
+ React.createElement("tbody", null, props.item.awayAthlete.statistics.slice(1).map((statistic, index) => {
5
5
  return (React.createElement("tr", { key: statistic.abbreviation },
6
- React.createElement("td", null, statistic.awayAthleteValue),
6
+ React.createElement("td", null, statistic.displayValue),
7
7
  React.createElement("td", null, statistic.abbreviation),
8
- React.createElement("td", null, statistic.homeAthleteValue)));
8
+ React.createElement("td", null, props.item.homeAthlete.statistics[index + 1].displayValue ||
9
+ '0')));
9
10
  }))));
10
11
  };
11
12
  export default StatisticsTable;
@@ -1 +1,2 @@
1
1
  export { default } from './StatsView';
2
+ export { default as TeamStatsView } from './TeamStats';
@@ -1 +1,2 @@
1
1
  export { default } from './StatsView';
2
+ export { default as TeamStatsView } from './TeamStats';
@@ -0,0 +1,36 @@
1
+ import NetworkManager from './NetworkManager/NetworkManager';
2
+ import { StatsApiResponse } from '../modules/stats/interfaces/IStats';
3
+ import IMaestroEventDelegate from '@/interfaces/IMaestroEventDelegate';
4
+ /**
5
+ * Service for handling stats-related API calls
6
+ */
7
+ declare class StatsService {
8
+ networkManager: NetworkManager;
9
+ constructor(delegate: IMaestroEventDelegate);
10
+ /**
11
+ * Get stats for an event
12
+ *
13
+ * @param eventID - The ID of the event
14
+ * @param gameState - Optional game state filter (e.g., 'pre', 'in', 'post')
15
+ * @returns Promise with the stats data
16
+ */
17
+ getStats(eventID: string, gameState?: string): Promise<StatsApiResponse>;
18
+ /**
19
+ * Start polling for stats
20
+ *
21
+ * @param eventID - The ID of the event
22
+ * @param gameState - Optional game state filter (e.g., 'pre', 'in', 'post')
23
+ * @param interval - The polling interval in milliseconds
24
+ * @param onData - Callback for successful data fetch
25
+ * @param onError - Callback for errors
26
+ * @returns Object with a stop function to stop polling
27
+ */
28
+ pollStats(eventID: string, gameState: string | undefined, interval: number, onData: (data: StatsApiResponse) => void, onError?: (error: Error) => void): {
29
+ stop: () => void;
30
+ };
31
+ /**
32
+ * Get the endpoint for stats
33
+ */
34
+ statsEndpoint(eventID: string): string;
35
+ }
36
+ export default StatsService;
@@ -0,0 +1,68 @@
1
+ import NetworkManager, { HttpMethod } from './NetworkManager/NetworkManager';
2
+ /**
3
+ * Service for handling stats-related API calls
4
+ */
5
+ class StatsService {
6
+ constructor(delegate) {
7
+ Object.defineProperty(this, "networkManager", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: void 0
12
+ });
13
+ this.networkManager = NetworkManager.getInstance({
14
+ externalBaseURL: delegate.getBettingAPIBaseURL(),
15
+ });
16
+ }
17
+ /**
18
+ * Get stats for an event
19
+ *
20
+ * @param eventID - The ID of the event
21
+ * @param gameState - Optional game state filter (e.g., 'pre', 'in', 'post')
22
+ * @returns Promise with the stats data
23
+ */
24
+ async getStats(eventID, gameState) {
25
+ const params = {};
26
+ if (gameState) {
27
+ params.gameState = gameState;
28
+ }
29
+ return this.networkManager.externalApiRequest({
30
+ endpoint: this.statsEndpoint(eventID),
31
+ method: HttpMethod.GET,
32
+ params,
33
+ headers: {},
34
+ });
35
+ }
36
+ /**
37
+ * Start polling for stats
38
+ *
39
+ * @param eventID - The ID of the event
40
+ * @param gameState - Optional game state filter (e.g., 'pre', 'in', 'post')
41
+ * @param interval - The polling interval in milliseconds
42
+ * @param onData - Callback for successful data fetch
43
+ * @param onError - Callback for errors
44
+ * @returns Object with a stop function to stop polling
45
+ */
46
+ pollStats(eventID, gameState, interval, onData, onError) {
47
+ const params = {};
48
+ if (gameState) {
49
+ params.gameState = gameState;
50
+ }
51
+ return this.networkManager.pollExternalApiRequest({
52
+ endpoint: this.statsEndpoint(eventID),
53
+ interval,
54
+ method: HttpMethod.GET,
55
+ params,
56
+ headers: {},
57
+ onData,
58
+ onError,
59
+ });
60
+ }
61
+ /**
62
+ * Get the endpoint for stats
63
+ */
64
+ statsEndpoint(eventID) {
65
+ return `/v4/events/${eventID}/stats`;
66
+ }
67
+ }
68
+ export default StatsService;
@@ -4,6 +4,7 @@ import { Observable } from '../helpers/Observable';
4
4
  import { ViewModel } from './ViewModel';
5
5
  import KeyPlaysViewModel from '../modules/key-plays/view-model/KeyPlaysViewModel';
6
6
  import BetsViewModel from '../modules/bets/view-model/BetsViewModel';
7
+ import SpatialNavigation from '@/external/spatial-navigation/spatialNavigation';
7
8
  import StatsViewModel from '../modules/stats/view-model/StatsViewModel';
8
9
  import IMaestroKeyPlaysResponse from '../modules/key-plays/interfaces/IKeyPlaysResponse';
9
10
  import { MaestroPanelType } from '@/models/IPanel';
@@ -16,6 +17,7 @@ export declare class MaestroEventViewModel extends ViewModel implements IMaestro
16
17
  keyPlaysViewModel: KeyPlaysViewModel;
17
18
  betsViewModel: BetsViewModel;
18
19
  statsViewModel: StatsViewModel;
20
+ navigation: SpatialNavigation;
19
21
  constructor(eventId: string | undefined, delegate: IMaestroEventDelegate);
20
22
  deinit(): void;
21
23
  updateKeyPlaysData(data: IMaestroKeyPlaysResponse | null): Promise<void>;
@@ -40,4 +42,9 @@ export declare class MaestroEventViewModel extends ViewModel implements IMaestro
40
42
  get isShowingPanel(): boolean;
41
43
  set isShowingPanel(value: boolean);
42
44
  simulateUseCase<T = any>(useCase: TestUseCase, panelType: MaestroPanelType, testData?: T): void;
45
+ /**
46
+ * This method is called when the user navigates to the MaestroEventViewModel.
47
+ * It will pause navigation and start focus management.
48
+ */
49
+ deliverFocus(): void;
43
50
  }
@@ -55,25 +55,30 @@ export class MaestroEventViewModel extends ViewModel {
55
55
  writable: true,
56
56
  value: void 0
57
57
  });
58
+ Object.defineProperty(this, "navigation", {
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true,
62
+ value: void 0
63
+ });
58
64
  this._eventId.value = eventId;
59
65
  this.delegate = delegate;
60
66
  this.betsViewModel = new BetsViewModel(eventId, delegate);
61
67
  this.statsViewModel = new StatsViewModel(eventId, { useMockData: true });
62
- SpatialNavigation.init();
68
+ this.navigation = new SpatialNavigation();
63
69
  }
64
70
  deinit() {
65
71
  this.betsViewModel.cleanup();
66
72
  this.statsViewModel.cleanup();
67
- SpatialNavigation.destroy();
73
+ this.navigation.destroy();
68
74
  }
69
75
  updateKeyPlaysData(data) {
70
76
  return this.keyPlaysViewModel.setKeyPlays(data);
71
77
  }
72
78
  startFocusManagement() {
73
- SpatialNavigation.setFocus('');
74
- SpatialNavigation.resume();
79
+ this.navigation.setCurrentFocusedKey('PANEL_NAV_BUTTON_0', {});
75
80
  setTimeout(() => {
76
- SpatialNavigation.setFocus('PANEL_NAV_BUTTON_0');
81
+ this.navigation.resume();
77
82
  }, 0);
78
83
  return Promise.resolve();
79
84
  }
@@ -102,7 +107,6 @@ export class MaestroEventViewModel extends ViewModel {
102
107
  }
103
108
  async didHidePanel() {
104
109
  this.isShowingPanel = false;
105
- SpatialNavigation.pause();
106
110
  // Analytics call?
107
111
  }
108
112
  didShowOverlay() {
@@ -153,4 +157,12 @@ export class MaestroEventViewModel extends ViewModel {
153
157
  throw new Error(`Unsupported panel type: ${panelType}`);
154
158
  }
155
159
  }
160
+ /**
161
+ * This method is called when the user navigates to the MaestroEventViewModel.
162
+ * It will pause navigation and start focus management.
163
+ */
164
+ deliverFocus() {
165
+ this.navigation.pause();
166
+ this.delegate.startFocusManagement();
167
+ }
156
168
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maestro_io/maestro-web-sdk",
3
3
  "private": false,
4
- "version": "2.1.2",
4
+ "version": "2.1.3",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "main": "dist/maestro-web-sdk.umd.js",