@maestro_io/maestro-web-sdk 5.1.2 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/1.maestro-web-sdk.esm.js +1 -1
  2. package/dist/1.maestro-web-sdk.esm.js.map +1 -1
  3. package/dist/10.maestro-web-sdk.esm.js +1 -1
  4. package/dist/10.maestro-web-sdk.esm.js.map +1 -1
  5. package/dist/11.maestro-web-sdk.esm.js +1 -1
  6. package/dist/11.maestro-web-sdk.esm.js.map +1 -1
  7. package/dist/12.maestro-web-sdk.esm.js +1 -1
  8. package/dist/12.maestro-web-sdk.esm.js.map +1 -1
  9. package/dist/13.maestro-web-sdk.esm.js +1 -1
  10. package/dist/13.maestro-web-sdk.esm.js.map +1 -1
  11. package/dist/14.maestro-web-sdk.esm.js +1 -1
  12. package/dist/14.maestro-web-sdk.esm.js.map +1 -1
  13. package/dist/15.maestro-web-sdk.esm.js +1 -1
  14. package/dist/15.maestro-web-sdk.esm.js.map +1 -1
  15. package/dist/16.maestro-web-sdk.esm.js +1 -1
  16. package/dist/16.maestro-web-sdk.esm.js.map +1 -1
  17. package/dist/17.maestro-web-sdk.esm.js +1 -1
  18. package/dist/17.maestro-web-sdk.esm.js.map +1 -1
  19. package/dist/18.maestro-web-sdk.esm.js +1 -1
  20. package/dist/18.maestro-web-sdk.esm.js.map +1 -1
  21. package/dist/19.maestro-web-sdk.esm.js +1 -1
  22. package/dist/19.maestro-web-sdk.esm.js.map +1 -1
  23. package/dist/2.maestro-web-sdk.esm.js +1 -1
  24. package/dist/20.maestro-web-sdk.esm.js +1 -1
  25. package/dist/20.maestro-web-sdk.esm.js.map +1 -1
  26. package/dist/21.maestro-web-sdk.esm.js +1 -1
  27. package/dist/21.maestro-web-sdk.esm.js.map +1 -1
  28. package/dist/22.maestro-web-sdk.esm.js +1 -1
  29. package/dist/22.maestro-web-sdk.esm.js.map +1 -1
  30. package/dist/23.maestro-web-sdk.esm.js +1 -1
  31. package/dist/23.maestro-web-sdk.esm.js.map +1 -1
  32. package/dist/24.maestro-web-sdk.esm.js +1 -1
  33. package/dist/24.maestro-web-sdk.esm.js.map +1 -1
  34. package/dist/25.maestro-web-sdk.esm.js +1 -1
  35. package/dist/25.maestro-web-sdk.esm.js.map +1 -1
  36. package/dist/26.maestro-web-sdk.esm.js +1 -1
  37. package/dist/26.maestro-web-sdk.esm.js.map +1 -1
  38. package/dist/27.maestro-web-sdk.esm.js +1 -1
  39. package/dist/27.maestro-web-sdk.esm.js.map +1 -1
  40. package/dist/28.maestro-web-sdk.esm.js +1 -1
  41. package/dist/28.maestro-web-sdk.esm.js.map +1 -1
  42. package/dist/29.maestro-web-sdk.esm.js +1 -1
  43. package/dist/29.maestro-web-sdk.esm.js.map +1 -1
  44. package/dist/3.maestro-web-sdk.esm.js +1 -1
  45. package/dist/3.maestro-web-sdk.esm.js.map +1 -1
  46. package/dist/30.maestro-web-sdk.esm.js +1 -1
  47. package/dist/30.maestro-web-sdk.esm.js.map +1 -1
  48. package/dist/31.maestro-web-sdk.esm.js +1 -1
  49. package/dist/31.maestro-web-sdk.esm.js.map +1 -1
  50. package/dist/32.maestro-web-sdk.esm.js +1 -1
  51. package/dist/32.maestro-web-sdk.esm.js.map +1 -1
  52. package/dist/33.maestro-web-sdk.esm.js +1 -1
  53. package/dist/33.maestro-web-sdk.esm.js.map +1 -1
  54. package/dist/34.maestro-web-sdk.esm.js +1 -1
  55. package/dist/34.maestro-web-sdk.esm.js.map +1 -1
  56. package/dist/35.maestro-web-sdk.esm.js +1 -1
  57. package/dist/35.maestro-web-sdk.esm.js.map +1 -1
  58. package/dist/36.maestro-web-sdk.esm.js +1 -1
  59. package/dist/36.maestro-web-sdk.esm.js.map +1 -1
  60. package/dist/37.maestro-web-sdk.esm.js +1 -1
  61. package/dist/37.maestro-web-sdk.esm.js.map +1 -1
  62. package/dist/38.maestro-web-sdk.esm.js +1 -1
  63. package/dist/38.maestro-web-sdk.esm.js.map +1 -1
  64. package/dist/39.maestro-web-sdk.esm.js +2 -0
  65. package/dist/39.maestro-web-sdk.esm.js.map +1 -0
  66. package/dist/4.maestro-web-sdk.esm.js +1 -1
  67. package/dist/4.maestro-web-sdk.esm.js.map +1 -1
  68. package/dist/40.maestro-web-sdk.esm.js +2 -0
  69. package/dist/40.maestro-web-sdk.esm.js.map +1 -0
  70. package/dist/5.maestro-web-sdk.esm.js +1 -1
  71. package/dist/5.maestro-web-sdk.esm.js.map +1 -1
  72. package/dist/6.maestro-web-sdk.esm.js +1 -1
  73. package/dist/6.maestro-web-sdk.esm.js.map +1 -1
  74. package/dist/7.maestro-web-sdk.esm.js +1 -1
  75. package/dist/7.maestro-web-sdk.esm.js.map +1 -1
  76. package/dist/8.maestro-web-sdk.esm.js +1 -1
  77. package/dist/8.maestro-web-sdk.esm.js.map +1 -1
  78. package/dist/9.maestro-web-sdk.esm.js +1 -1
  79. package/dist/9.maestro-web-sdk.esm.js.map +1 -1
  80. package/dist/index.d.ts +4 -1
  81. package/dist/maestro-web-sdk.esm.js +3 -3
  82. package/dist/maestro-web-sdk.esm.js.map +1 -1
  83. package/dist/maestro-web-sdk.umd.js +3 -3
  84. package/dist/maestro-web-sdk.umd.js.map +1 -1
  85. package/dist/package.json +1 -1
  86. package/dist/src/components/atoms/SvgIcon/AddIcon.d.ts +3 -0
  87. package/dist/src/components/atoms/SvgIcon/AddIcon.js +6 -0
  88. package/dist/src/components/atoms/SvgIcon/Icon.js +2 -0
  89. package/dist/src/components/core/PanelManager/PanelManager.js +5 -3
  90. package/dist/src/components/molecules/NetworkDialog/NetworkDialog.d.ts +11 -0
  91. package/dist/src/components/molecules/NetworkDialog/NetworkDialog.js +34 -0
  92. package/dist/src/components/molecules/NetworkDialog/index.d.ts +2 -0
  93. package/dist/src/components/molecules/NetworkDialog/index.js +2 -0
  94. package/dist/src/components/molecules/NetworkError/NetworkError.d.ts +104 -0
  95. package/dist/src/components/molecules/NetworkError/NetworkError.js +26 -0
  96. package/dist/src/components/molecules/NetworkError/index.d.ts +2 -0
  97. package/dist/src/components/molecules/NetworkError/index.js +2 -0
  98. package/dist/src/components/molecules/PanelNavButton/PanelNavButton.d.ts +1 -0
  99. package/dist/src/components/molecules/PanelNavButton/PanelNavButton.js +16 -7
  100. package/dist/src/components/organisms/PanelNavigation/PanelNavigation.d.ts +1 -0
  101. package/dist/src/components/organisms/PanelNavigation/PanelNavigation.js +11 -7
  102. package/dist/src/development/MaestroEventDelegate.js +1 -0
  103. package/dist/src/helpers/site.d.ts +1 -0
  104. package/dist/src/helpers/site.js +6 -0
  105. package/dist/src/helpers/siteConfig.d.ts +1 -0
  106. package/dist/src/helpers/siteConfig.js +5 -0
  107. package/dist/src/models/IPanel.d.ts +1 -1
  108. package/dist/src/models/IPanel.js +1 -1
  109. package/dist/src/modules/espn/bets/view/BetsView.js +1 -1
  110. package/dist/src/modules/espn/components/TabLoadError/TabLoadError.d.ts +96 -0
  111. package/dist/src/modules/espn/components/TabLoadError/TabLoadError.js +14 -0
  112. package/dist/src/modules/espn/components/TabLoadError/index.d.ts +2 -0
  113. package/dist/src/modules/espn/components/TabLoadError/index.js +2 -0
  114. package/dist/src/modules/espn/fantasy/components/TournamentOverflowQR/TournamentOverflowQR.d.ts +5 -5
  115. package/dist/src/modules/espn/fantasy/components/TournamentOverflowQR/TournamentOverflowQR.js +7 -73
  116. package/dist/src/modules/espn/fantasy/services/FantasyService.js +1 -1
  117. package/dist/src/modules/espn/fantasy/view/FantasyItemView.js +1 -1
  118. package/dist/src/modules/espn/fantasy/view/FantasyView.js +1 -1
  119. package/dist/src/modules/espn/key-plays/view/KeyPlayErrorStateView.js +1 -1
  120. package/dist/src/modules/espn/shop/view/ShopView.js +1 -1
  121. package/dist/src/modules/espn/stats/view/StatsView.js +1 -1
  122. package/dist/src/modules/fox/components/TabLoadError/TabLoadError.d.ts +96 -0
  123. package/dist/src/modules/fox/components/TabLoadError/TabLoadError.js +19 -0
  124. package/dist/src/modules/fox/components/TabLoadError/index.d.ts +2 -0
  125. package/dist/src/modules/fox/components/TabLoadError/index.js +2 -0
  126. package/dist/src/modules/fox/multi-view/interfaces/IMultiViewViewModel.d.ts +3 -0
  127. package/dist/src/modules/fox/multi-view/interfaces/IMultiViewViewModel.js +1 -0
  128. package/dist/src/modules/fox/multi-view/services/MultiViewService.d.ts +99 -0
  129. package/dist/src/modules/fox/multi-view/services/MultiViewService.js +94 -0
  130. package/dist/src/modules/fox/multi-view/types.d.ts +29 -43
  131. package/dist/src/modules/fox/multi-view/types.js +79 -82
  132. package/dist/src/modules/fox/multi-view/view/CuratedMultiview/CuratedMultiviews.d.ts +8 -0
  133. package/dist/src/modules/fox/multi-view/view/CuratedMultiview/CuratedMultiviews.js +91 -0
  134. package/dist/src/modules/fox/multi-view/view/CuratedMultiview/index.d.ts +2 -0
  135. package/dist/src/modules/fox/multi-view/view/CuratedMultiview/index.js +2 -0
  136. package/dist/src/modules/fox/multi-view/view/FoxMultiView.d.ts +1 -0
  137. package/dist/src/modules/fox/multi-view/view/FoxMultiView.js +62 -2
  138. package/dist/src/modules/fox/multi-view/view/components/CustomMultiviewStreamsCard/CustomMultiviewStreamsCard.d.ts +122 -0
  139. package/dist/src/modules/fox/multi-view/view/components/CustomMultiviewStreamsCard/CustomMultiviewStreamsCard.js +51 -0
  140. package/dist/src/modules/fox/multi-view/view/components/CustomMultiviewStreamsCard/index.d.ts +2 -0
  141. package/dist/src/modules/fox/multi-view/view/components/CustomMultiviewStreamsCard/index.js +2 -0
  142. package/dist/src/modules/fox/multi-view/view/components/LayoutSelector/LayoutSelector.d.ts +1 -1
  143. package/dist/src/modules/fox/multi-view/view/components/LayoutSelector/LayoutSelector.js +11 -14
  144. package/dist/src/modules/fox/multi-view/view/components/curated-multiview-card/CuratedMultiviewCard.d.ts +101 -0
  145. package/dist/src/modules/fox/multi-view/view/components/curated-multiview-card/CuratedMultiviewCard.js +21 -0
  146. package/dist/src/modules/fox/multi-view/view/components/curated-multiview-card/index.d.ts +2 -0
  147. package/dist/src/modules/fox/multi-view/view/components/curated-multiview-card/index.js +2 -0
  148. package/dist/src/modules/fox/multi-view/view-model/MultiViewViewModel.d.ts +63 -0
  149. package/dist/src/modules/fox/multi-view/view-model/MultiViewViewModel.js +328 -0
  150. package/dist/src/modules/fox/multi-view/view-model/index.d.ts +1 -0
  151. package/dist/src/modules/fox/multi-view/view-model/index.js +1 -0
  152. package/dist/src/services/NetworkManager/NetworkManager.js +1 -1
  153. package/dist/src/services/NetworkManager/errors.d.ts +3 -1
  154. package/dist/src/services/NetworkManager/errors.js +15 -1
  155. package/dist/src/services/StaticService/StaticService.js +1 -0
  156. package/dist/src/view-models/MaestroEventViewModel.d.ts +2 -0
  157. package/dist/src/view-models/MaestroEventViewModel.js +17 -1
  158. package/package.json +1 -1
@@ -0,0 +1,101 @@
1
+ /// <reference types="prop-types" />
2
+ import React from 'react';
3
+ import './CuratedMultiviewCard.style.css';
4
+ import { WithFocusableProps } from '@/external/spatial-navigation';
5
+ import { CuratedMultiviewListing } from '../../../types';
6
+ export type CuratedMultiviewCardProps = {
7
+ listings: CuratedMultiviewListing[];
8
+ selected: boolean;
9
+ };
10
+ declare const _default: {
11
+ new (props: (CuratedMultiviewCardProps & WithFocusableProps) | Readonly<CuratedMultiviewCardProps & WithFocusableProps>): {
12
+ state: import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState;
13
+ navigation: import("../../../../../../external/spatial-navigation/spatialNavigation").default;
14
+ getChildContext(): {
15
+ parentFocusKey: string;
16
+ };
17
+ setFocus: (focusKey: string) => void;
18
+ navigateByDirection: (direction: import("../../../../../../external/spatial-navigation/utils").Direction, details?: import("../../../../../../external/spatial-navigation/utils").Details) => void;
19
+ stealFocus: () => void;
20
+ onUpdateFocus: (focused: boolean) => void;
21
+ onUpdateHasFocusedChild: (hasFocusedChild: boolean) => void;
22
+ onEnterPressHandler: (details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
23
+ onClickPressHandler: (details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
24
+ onEnterReleaseHandler: () => void;
25
+ onBackPressHandler: (details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
26
+ onArrowPressHandler: (direction: import("../../../../../../external/spatial-navigation/utils").Direction, details: import("../../../../../../external/spatial-navigation/utils").Details) => boolean | void;
27
+ onBecameFocusedHandler: (layout: import("../../../../../../external/spatial-navigation/utils").Layout, details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
28
+ onBecameBlurredHandler: (layout: import("../../../../../../external/spatial-navigation/utils").Layout, details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
29
+ componentDidMount(): void;
30
+ componentDidUpdate(): void;
31
+ componentWillUnmount(): void;
32
+ render(): React.ReactElement<CuratedMultiviewCardProps & WithFocusableProps, string | React.JSXElementConstructor<any>>;
33
+ context: any;
34
+ setState<K extends keyof import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>(state: import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState | ((prevState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, props: Readonly<CuratedMultiviewCardProps & WithFocusableProps>) => import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState | Pick<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K> | null) | Pick<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K> | null, callback?: (() => void) | undefined): void;
35
+ forceUpdate(callback?: (() => void) | undefined): void;
36
+ readonly props: Readonly<CuratedMultiviewCardProps & WithFocusableProps> & Readonly<{
37
+ children?: React.ReactNode;
38
+ }>;
39
+ refs: {
40
+ [key: string]: React.ReactInstance;
41
+ };
42
+ shouldComponentUpdate?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): boolean;
43
+ componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
44
+ getSnapshotBeforeUpdate?(prevProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, prevState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>): any;
45
+ componentWillMount?(): void;
46
+ UNSAFE_componentWillMount?(): void;
47
+ componentWillReceiveProps?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextContext: any): void;
48
+ UNSAFE_componentWillReceiveProps?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextContext: any): void;
49
+ componentWillUpdate?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
50
+ UNSAFE_componentWillUpdate?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
51
+ };
52
+ new (props: CuratedMultiviewCardProps & WithFocusableProps, context: any): {
53
+ state: import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState;
54
+ navigation: import("../../../../../../external/spatial-navigation/spatialNavigation").default;
55
+ getChildContext(): {
56
+ parentFocusKey: string;
57
+ };
58
+ setFocus: (focusKey: string) => void;
59
+ navigateByDirection: (direction: import("../../../../../../external/spatial-navigation/utils").Direction, details?: import("../../../../../../external/spatial-navigation/utils").Details) => void;
60
+ stealFocus: () => void;
61
+ onUpdateFocus: (focused: boolean) => void;
62
+ onUpdateHasFocusedChild: (hasFocusedChild: boolean) => void;
63
+ onEnterPressHandler: (details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
64
+ onClickPressHandler: (details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
65
+ onEnterReleaseHandler: () => void;
66
+ onBackPressHandler: (details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
67
+ onArrowPressHandler: (direction: import("../../../../../../external/spatial-navigation/utils").Direction, details: import("../../../../../../external/spatial-navigation/utils").Details) => boolean | void;
68
+ onBecameFocusedHandler: (layout: import("../../../../../../external/spatial-navigation/utils").Layout, details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
69
+ onBecameBlurredHandler: (layout: import("../../../../../../external/spatial-navigation/utils").Layout, details: import("../../../../../../external/spatial-navigation/utils").Details) => void;
70
+ componentDidMount(): void;
71
+ componentDidUpdate(): void;
72
+ componentWillUnmount(): void;
73
+ render(): React.ReactElement<CuratedMultiviewCardProps & WithFocusableProps, string | React.JSXElementConstructor<any>>;
74
+ context: any;
75
+ setState<K extends keyof import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>(state: import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState | ((prevState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, props: Readonly<CuratedMultiviewCardProps & WithFocusableProps>) => import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState | Pick<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K> | null) | Pick<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K> | null, callback?: (() => void) | undefined): void;
76
+ forceUpdate(callback?: (() => void) | undefined): void;
77
+ readonly props: Readonly<CuratedMultiviewCardProps & WithFocusableProps> & Readonly<{
78
+ children?: React.ReactNode;
79
+ }>;
80
+ refs: {
81
+ [key: string]: React.ReactInstance;
82
+ };
83
+ shouldComponentUpdate?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): boolean;
84
+ componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
85
+ getSnapshotBeforeUpdate?(prevProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, prevState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>): any;
86
+ componentWillMount?(): void;
87
+ UNSAFE_componentWillMount?(): void;
88
+ componentWillReceiveProps?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextContext: any): void;
89
+ UNSAFE_componentWillReceiveProps?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextContext: any): void;
90
+ componentWillUpdate?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
91
+ UNSAFE_componentWillUpdate?(nextProps: Readonly<CuratedMultiviewCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
92
+ };
93
+ contextTypes: {
94
+ parentFocusKey: import("prop-types").Requireable<string>;
95
+ };
96
+ childContextTypes: {
97
+ parentFocusKey: import("prop-types").Requireable<string>;
98
+ };
99
+ contextType?: React.Context<any> | undefined;
100
+ };
101
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import './CuratedMultiviewCard.style.css';
3
+ import { withFocusable, } from '@/external/spatial-navigation';
4
+ import Icon from '@/components/atoms/SvgIcon';
5
+ const StreamScreen = ({ listing }) => {
6
+ const { backgroundImage, description } = listing;
7
+ return (React.createElement("div", { className: "curated-multiview-screen", style: {
8
+ backgroundImage: `url(${backgroundImage})`,
9
+ } },
10
+ React.createElement("span", { className: "curated-multiview-screen-title FONT_BOLD" }, description)));
11
+ };
12
+ const CuratedMultiviewCard = (props) => {
13
+ const { listings, selected, focused } = props;
14
+ return (React.createElement("div", { className: "curated-multiview-card focus-ring", "data-focused": focused },
15
+ React.createElement("div", { className: "curated-multiview-card-row" },
16
+ React.createElement("div", { className: "curated-multiview-card-cell curated-multiview-card-cell-screens" },
17
+ React.createElement("div", { className: "curated-multiview-screens-container" }, listings.slice(0, 2).map((listing) => (React.createElement(StreamScreen, { key: listing.id, listing: listing }))))),
18
+ React.createElement("div", { className: "curated-multiview-card-cell curated-multiview-card-cell-radio" },
19
+ React.createElement("div", { className: "curated-multiview-radio", "data-selected": selected }, selected && React.createElement(Icon, { iconName: "checkmark", width: 22.5, height: 22 }))))));
20
+ };
21
+ export default withFocusable()(CuratedMultiviewCard);
@@ -0,0 +1,2 @@
1
+ import CuratedMultiviewCard from './CuratedMultiviewCard';
2
+ export default CuratedMultiviewCard;
@@ -0,0 +1,2 @@
1
+ import CuratedMultiviewCard from './CuratedMultiviewCard';
2
+ export default CuratedMultiviewCard;
@@ -0,0 +1,63 @@
1
+ import { ViewModel } from '@/view-models/ViewModel';
2
+ import { Observable } from '@/helpers/Observable';
3
+ import { CuratedMultiviewListing, MultiViewLayout } from '../types';
4
+ import IMaestroEventDelegate from '@/interfaces/IMaestroEventDelegate';
5
+ import { CuratedMultiviewResponse, MultiViewListingRequest } from '../services/MultiViewService';
6
+ import AnalyticsService from '@/services/AnalyticsService/AnalyticsService';
7
+ export type CuratedMultiviewItem = {
8
+ id: string;
9
+ isSelected: boolean;
10
+ listings: CuratedMultiviewListing[];
11
+ };
12
+ export type CuratedMultiviewsItem = {
13
+ type: 'curated-multiviews';
14
+ items: CuratedMultiviewItem[];
15
+ };
16
+ export type MultiviewItem = CuratedMultiviewsItem;
17
+ export declare class MultiViewViewModel extends ViewModel {
18
+ private _layouts;
19
+ private _isPolling;
20
+ private service;
21
+ private delegate;
22
+ private eventId;
23
+ private analyticsService;
24
+ isDataLoading: Observable<boolean>;
25
+ private pollingTask;
26
+ items: Observable<CuratedMultiviewsItem[]>;
27
+ private hasEverSuccessfullyLoaded;
28
+ private onAuthError?;
29
+ constructor(eventId: string, delegate: IMaestroEventDelegate, analyticsService: AnalyticsService);
30
+ getLayouts(): MultiViewLayout[];
31
+ getIsPolling(): Observable<boolean>;
32
+ getIsDataLoading(): Observable<boolean>;
33
+ getEventId(): string;
34
+ /**
35
+ * Notify client app about a Product API auth error.
36
+ * Uses configured callback first, and falls back to onPanelEvent.
37
+ */
38
+ private notifyProductAPIUnauthorized;
39
+ private trackPanelView;
40
+ init(): Promise<void>;
41
+ fetchLayouts(): Promise<void>;
42
+ setDataToPanel(data: Record<string, any>): Promise<void>;
43
+ onSelectCustomMultiview(params: MultiViewListingRequest): Promise<void>;
44
+ /**
45
+ * Clean up resources when the ViewModel is no longer needed
46
+ */
47
+ cleanup(): void;
48
+ /**
49
+ * Called when a curated multiview is selected. Notifies the client via onPanelEvent
50
+ * so the app can switch the video player to the selected multiview.
51
+ */
52
+ onSelectCuratedMultiview(item: CuratedMultiviewItem): void;
53
+ /**
54
+ * Stop polling for bet data
55
+ */
56
+ stopPolling(): void;
57
+ /**
58
+ * Refresh polling for curated multiviews
59
+ */
60
+ refreshPolling(): void;
61
+ processCuratedMultiviewData(data: CuratedMultiviewResponse): void;
62
+ clearTabLoadFailure(): Promise<void>;
63
+ }
@@ -0,0 +1,328 @@
1
+ import { ViewModel } from '@/view-models/ViewModel';
2
+ import { Observable } from '@/helpers/Observable';
3
+ import { DEFAULT_LAYOUTS_BY_LISTINGS_QUANTITY, } from '../types';
4
+ import MultiViewService, { isProductAPIValid, } from '../services/MultiViewService';
5
+ import { AuthError } from '@/services/NetworkManager/errors';
6
+ import { captureException } from '@/sentry';
7
+ export class MultiViewViewModel extends ViewModel {
8
+ constructor(eventId, delegate, analyticsService) {
9
+ super();
10
+ Object.defineProperty(this, "_layouts", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: new Observable([])
15
+ });
16
+ Object.defineProperty(this, "_isPolling", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: new Observable(false)
21
+ });
22
+ Object.defineProperty(this, "service", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: void 0
27
+ });
28
+ Object.defineProperty(this, "delegate", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: void 0
33
+ });
34
+ Object.defineProperty(this, "eventId", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: void 0
39
+ });
40
+ Object.defineProperty(this, "analyticsService", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: void 0
45
+ });
46
+ Object.defineProperty(this, "isDataLoading", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: new Observable(false)
51
+ });
52
+ Object.defineProperty(this, "pollingTask", {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: null
57
+ });
58
+ Object.defineProperty(this, "items", {
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true,
62
+ value: new Observable([])
63
+ });
64
+ Object.defineProperty(this, "hasEverSuccessfullyLoaded", {
65
+ enumerable: true,
66
+ configurable: true,
67
+ writable: true,
68
+ value: new Observable(false)
69
+ });
70
+ Object.defineProperty(this, "onAuthError", {
71
+ enumerable: true,
72
+ configurable: true,
73
+ writable: true,
74
+ value: void 0
75
+ });
76
+ this.eventId = eventId;
77
+ this.delegate = delegate;
78
+ this.analyticsService = analyticsService;
79
+ this.service = new MultiViewService();
80
+ }
81
+ getLayouts() {
82
+ return this._layouts.value;
83
+ }
84
+ getIsPolling() {
85
+ return this._isPolling;
86
+ }
87
+ getIsDataLoading() {
88
+ return this.isDataLoading;
89
+ }
90
+ getEventId() {
91
+ return this.eventId;
92
+ }
93
+ /**
94
+ * Notify client app about a Product API auth error.
95
+ * Uses configured callback first, and falls back to onPanelEvent.
96
+ */
97
+ notifyProductAPIUnauthorized(error) {
98
+ if (error.statusCode !== 401) {
99
+ return;
100
+ }
101
+ const payload = {
102
+ code: error.statusCode,
103
+ message: error.message || 'Not authorized',
104
+ success: false,
105
+ data: error.data,
106
+ };
107
+ if (this.onAuthError) {
108
+ this.onAuthError(payload);
109
+ }
110
+ }
111
+ async trackPanelView() {
112
+ try {
113
+ await this.analyticsService.panelView('foxMultiView');
114
+ }
115
+ catch (error) {
116
+ captureException(error, {
117
+ context: 'MultiViewViewModel.trackPanelView',
118
+ });
119
+ console.error('[MULTIVIEW] Error tracking panel view:', error);
120
+ }
121
+ }
122
+ async init() {
123
+ try {
124
+ await this.trackPanelView();
125
+ await this.fetchLayouts();
126
+ this.refreshPolling();
127
+ }
128
+ catch (error) {
129
+ const errorMessage = error instanceof Error
130
+ ? error.message
131
+ : 'Failed to initialize MultiView';
132
+ this.setError(errorMessage);
133
+ console.error('[MultiViewViewModel] Initialization error:', error);
134
+ }
135
+ }
136
+ async fetchLayouts() {
137
+ if (this.getLayouts().length) {
138
+ return;
139
+ }
140
+ try {
141
+ this.isDataLoading.value = true;
142
+ const layouts = await this.service.getLayouts();
143
+ if (layouts) {
144
+ this._layouts.value = layouts;
145
+ }
146
+ }
147
+ catch (error) {
148
+ console.log('[MultiViewViewModel] Error fetching layouts:', error);
149
+ if (error instanceof AuthError) {
150
+ this.notifyProductAPIUnauthorized(error);
151
+ return;
152
+ }
153
+ const errorMessage = error instanceof Error ? error.message : 'Failed to fetch layouts';
154
+ if (!this.hasEverSuccessfullyLoaded.value) {
155
+ this.setError(errorMessage);
156
+ }
157
+ }
158
+ finally {
159
+ this.isDataLoading.value = false;
160
+ }
161
+ }
162
+ async setDataToPanel(data) {
163
+ try {
164
+ const callback = typeof data.callback === 'function' ? data.callback : undefined;
165
+ if (isProductAPIValid(data)) {
166
+ this.onAuthError = callback;
167
+ this.service.setProductAPIData(data);
168
+ await this.fetchLayouts();
169
+ this.refreshPolling();
170
+ }
171
+ }
172
+ catch (error) {
173
+ const errorMessage = error instanceof Error ? error.message : 'Failed to set panel data';
174
+ console.error('[MultiViewViewModel] Error setting panel data:', error);
175
+ if (!this.hasEverSuccessfullyLoaded.value) {
176
+ this.setError(errorMessage);
177
+ }
178
+ }
179
+ }
180
+ async onSelectCustomMultiview(params) {
181
+ try {
182
+ this.setLoading(true);
183
+ this.setError(null);
184
+ const response = await this.service.getOrCreateCustomMultiview(params);
185
+ if (this.delegate) {
186
+ this.delegate.onPanelEvent({
187
+ type: 'fox-multiview:custom-multiview',
188
+ payload: response.multiviewId,
189
+ });
190
+ }
191
+ }
192
+ catch (error) {
193
+ const errorMessage = error instanceof Error
194
+ ? error.message
195
+ : 'Failed to select custom multiview';
196
+ this.setError(errorMessage);
197
+ console.error('[MultiViewViewModel] Error selecting multiview:', error);
198
+ throw error;
199
+ }
200
+ finally {
201
+ this.setLoading(false);
202
+ }
203
+ }
204
+ /**
205
+ * Clean up resources when the ViewModel is no longer needed
206
+ */
207
+ cleanup() {
208
+ this.stopPolling();
209
+ this.hasEverSuccessfullyLoaded.value = false;
210
+ }
211
+ /**
212
+ * Called when a curated multiview is selected. Notifies the client via onPanelEvent
213
+ * so the app can switch the video player to the selected multiview.
214
+ */
215
+ onSelectCuratedMultiview(item) {
216
+ if (item.isSelected) {
217
+ return;
218
+ }
219
+ const layout = DEFAULT_LAYOUTS_BY_LISTINGS_QUANTITY[item.listings.length];
220
+ if (!layout) {
221
+ return;
222
+ }
223
+ const payload = {
224
+ childListings: item.listings.map((l, listingIndex) => ({
225
+ callsign: l.type,
226
+ listingId: l.id,
227
+ position: layout.positions[layout.positionsOrder[listingIndex]],
228
+ })),
229
+ multiviewID: item.id,
230
+ };
231
+ this.delegate.onPanelEvent({
232
+ type: 'fox-multiview:new-multiview',
233
+ payload,
234
+ });
235
+ }
236
+ /**
237
+ * Stop polling for bet data
238
+ */
239
+ stopPolling() {
240
+ if (this.pollingTask) {
241
+ this.pollingTask.stop();
242
+ this.pollingTask = null;
243
+ }
244
+ if (this.isDataLoading.value) {
245
+ this.isDataLoading.value = false;
246
+ }
247
+ }
248
+ /**
249
+ * Refresh polling for curated multiviews
250
+ */
251
+ refreshPolling() {
252
+ // First stop any existing polling
253
+ this.stopPolling();
254
+ // Start the poll loop
255
+ this.pollingTask = this.service.pollCuratedMultiviews(30000, this.processCuratedMultiviewData.bind(this), (error) => {
256
+ console.error('[MultiViewViewModel] Error polling data:', error);
257
+ if (error instanceof AuthError) {
258
+ this.notifyProductAPIUnauthorized(error);
259
+ }
260
+ });
261
+ }
262
+ processCuratedMultiviewData(data) {
263
+ if (!data || !data.status || !data.data) {
264
+ return;
265
+ }
266
+ if (!Array.isArray(data.data.items)) {
267
+ return;
268
+ }
269
+ const curatedMultiviewItem = [];
270
+ for (const item of data.data.items) {
271
+ const listings = [];
272
+ if (!item.is_multiview) {
273
+ continue;
274
+ }
275
+ if (item.multiview_metadata && Array.isArray(item.multiview_metadata)) {
276
+ for (const mv of item.multiview_metadata) {
277
+ listings.push({
278
+ id: mv.entity_id || '',
279
+ description: mv.is_sportingevent && mv.left_team && mv.right_team
280
+ ? `${mv.left_team.abbreviation} vs ${mv.right_team.abbreviation}`
281
+ : item.title || '',
282
+ backgroundImage: 'https://placedog.net/640/480',
283
+ type: mv.type || 'unknown',
284
+ });
285
+ }
286
+ }
287
+ else {
288
+ listings.push({
289
+ id: item.entity_id || '',
290
+ description: item.title || '',
291
+ backgroundImage: item.images?.still || '',
292
+ type: item.type || 'unknown',
293
+ });
294
+ }
295
+ curatedMultiviewItem.push({
296
+ id: item.entity_id || '',
297
+ isSelected: this.eventId === item.entity_id,
298
+ listings,
299
+ });
300
+ }
301
+ const newItems = [...this.items.value];
302
+ const existingCuratedMultiviewIndex = newItems.findIndex((i) => i.type === 'curated-multiviews');
303
+ if (existingCuratedMultiviewIndex !== -1) {
304
+ newItems[existingCuratedMultiviewIndex] = {
305
+ type: 'curated-multiviews',
306
+ items: curatedMultiviewItem,
307
+ };
308
+ }
309
+ else {
310
+ newItems.unshift({
311
+ type: 'curated-multiviews',
312
+ items: curatedMultiviewItem,
313
+ });
314
+ }
315
+ this.items.value = newItems;
316
+ if (!this.hasEverSuccessfullyLoaded.value) {
317
+ this.hasEverSuccessfullyLoaded.value = true;
318
+ if (this.error.value) {
319
+ this.setError(null);
320
+ }
321
+ }
322
+ }
323
+ async clearTabLoadFailure() {
324
+ this.setError(null);
325
+ await this.fetchLayouts();
326
+ this.refreshPolling();
327
+ }
328
+ }
@@ -0,0 +1 @@
1
+ export { MultiViewViewModel } from './MultiViewViewModel';
@@ -0,0 +1 @@
1
+ export { MultiViewViewModel } from './MultiViewViewModel';
@@ -120,7 +120,7 @@ class NetworkManager {
120
120
  const status = error.response.status;
121
121
  const message = error.response.data?.message || error.message;
122
122
  if (status === 401 || status === 403) {
123
- throw new AuthError(message);
123
+ throw new AuthError(status, message, error.response.data);
124
124
  }
125
125
  else if (status === 404) {
126
126
  throw new NotFoundError(message);
@@ -2,7 +2,9 @@ export declare class NetworkError extends Error {
2
2
  constructor(message: string);
3
3
  }
4
4
  export declare class AuthError extends Error {
5
- constructor(message: string);
5
+ statusCode: number;
6
+ data?: unknown;
7
+ constructor(statusCode: number, message: string, data?: unknown);
6
8
  }
7
9
  export declare class NotFoundError extends Error {
8
10
  constructor(message: string);
@@ -6,9 +6,23 @@ export class NetworkError extends Error {
6
6
  }
7
7
  }
8
8
  export class AuthError extends Error {
9
- constructor(message) {
9
+ constructor(statusCode, message, data) {
10
10
  super(message);
11
+ Object.defineProperty(this, "statusCode", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: void 0
16
+ });
17
+ Object.defineProperty(this, "data", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: void 0
22
+ });
11
23
  this.name = 'AuthError';
24
+ this.statusCode = statusCode;
25
+ this.data = data;
12
26
  }
13
27
  }
14
28
  export class NotFoundError extends Error {
@@ -5,6 +5,7 @@ import NetworkManager from '../NetworkManager/NetworkManager';
5
5
  const SITE_ID_STATIC_BASE_URL_MAP = {
6
6
  '664b9c57d59a7a431542d814': 'https://static-prod.us-central1-espn-prod.gcp.maestro.io',
7
7
  '6930c214fcb9633b5484de81': 'https://static-prod.us-central1-espn-prod.gcp.maestro.io',
8
+ '695c05610f99e7584a1b7407': 'https://static-prod.us-central1-fox-prod.gcp.maestro.io', // fox
8
9
  };
9
10
  export default class StaticService {
10
11
  constructor(siteId) {
@@ -14,6 +14,7 @@ import { IStatsViewModel } from '../modules/espn/stats/interfaces/IStatsViewMode
14
14
  import { IFantasyViewModel } from '@/modules/espn/fantasy/types';
15
15
  import { IShopViewModel } from '@/modules/espn/shop/types';
16
16
  import { BuilderPanelViewModel } from '@/modules/maestro/builder/view-model/BuilderPanelViewModel';
17
+ import { IMultiViewViewModel } from '@/modules/fox/multi-view/interfaces/IMultiViewViewModel';
17
18
  export declare class MaestroEventViewModel extends ViewModel implements IMaestroEvent {
18
19
  private _eventId;
19
20
  private _pageId;
@@ -29,6 +30,7 @@ export declare class MaestroEventViewModel extends ViewModel implements IMaestro
29
30
  statsViewModel: IStatsViewModel | null;
30
31
  shopViewModel: IShopViewModel | null;
31
32
  builderPanelViewModel: BuilderPanelViewModel | null;
33
+ multiViewViewModel: IMultiViewViewModel | null;
32
34
  panelManagerViewModel: PanelManagerViewModel;
33
35
  navigation: SpatialNavigation;
34
36
  constructor(eventId: string | undefined, pageId: string | undefined, delegate: IMaestroEventDelegate, analyticsService: AnalyticsService);
@@ -92,6 +92,12 @@ export class MaestroEventViewModel extends ViewModel {
92
92
  writable: true,
93
93
  value: null
94
94
  });
95
+ Object.defineProperty(this, "multiViewViewModel", {
96
+ enumerable: true,
97
+ configurable: true,
98
+ writable: true,
99
+ value: null
100
+ });
95
101
  Object.defineProperty(this, "panelManagerViewModel", {
96
102
  enumerable: true,
97
103
  configurable: true,
@@ -187,6 +193,15 @@ export class MaestroEventViewModel extends ViewModel {
187
193
  console.warn('Failed to load ShopViewModel:', err);
188
194
  }));
189
195
  }
196
+ if (StaticService.isPanelAvailable(pageConfig, 'foxMultiView')) {
197
+ loadPromises.push(import('@/modules/fox/multi-view/view-model/MultiViewViewModel')
198
+ .then(({ MultiViewViewModel }) => {
199
+ this.multiViewViewModel = new MultiViewViewModel(this._eventId.value, this.delegate, this.analyticsService);
200
+ })
201
+ .catch((err) => {
202
+ console.warn('Failed to load MultiViewViewModel:', err);
203
+ }));
204
+ }
190
205
  if (StaticService.isPanelAvailable(pageConfig, 'builderBlockPanel')) {
191
206
  const builderPanel = pageConfig?.panels?.find((p) => p.panel_type === 'builderBlockPanel');
192
207
  if (builderPanel) {
@@ -239,7 +254,7 @@ export class MaestroEventViewModel extends ViewModel {
239
254
  espnShop: this.shopViewModel,
240
255
  builderBlockPanel: this.builderPanelViewModel,
241
256
  foxKeyPlays: null,
242
- foxMultiview: null,
257
+ foxMultiView: this.multiViewViewModel,
243
258
  foxStats: null,
244
259
  helloWorld: null,
245
260
  };
@@ -266,6 +281,7 @@ export class MaestroEventViewModel extends ViewModel {
266
281
  this.fantasyViewModel?.cleanup();
267
282
  this.shopViewModel?.cleanup();
268
283
  this.builderPanelViewModel?.cleanup();
284
+ this.multiViewViewModel?.cleanup();
269
285
  this.navigation.destroy();
270
286
  try {
271
287
  await this.didHidePanel();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maestro_io/maestro-web-sdk",
3
3
  "private": false,
4
- "version": "5.1.2",
4
+ "version": "5.2.0",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "main": "dist/maestro-web-sdk.umd.js",