@maestro_io/maestro-web-sdk 3.1.3 → 3.3.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/dist/maestro-web-sdk.esm.js +5 -5
- package/dist/maestro-web-sdk.esm.js.map +1 -1
- package/dist/maestro-web-sdk.umd.js +5 -5
- package/dist/maestro-web-sdk.umd.js.map +1 -1
- package/dist/src/components/atoms/SvgIcon/FantasyIcon.d.ts +7 -0
- package/dist/src/components/atoms/SvgIcon/Icon.d.ts +4 -0
- package/dist/src/components/atoms/SvgIcon/ShopIcon.d.ts +5 -0
- package/dist/src/components/molecules/HeadshotImage/HeadshotImage.d.ts +16 -0
- package/dist/src/components/molecules/HeadshotImage/index.d.ts +2 -0
- package/dist/src/development/MaestroEventDelegate.d.ts +2 -1
- package/dist/src/helpers/strings.d.ts +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/interfaces/IMaestroEvent.d.ts +4 -0
- package/dist/src/interfaces/IMaestroEventDelegate.d.ts +15 -0
- package/dist/src/interfaces/IUserSettings.d.ts +8 -0
- package/dist/src/models/IPanel.d.ts +2 -6
- package/dist/src/modules/bets/view-model/BetsViewModel.d.ts +0 -5
- package/dist/src/modules/fantasy/components/ExpandedAthleteList/ExpandedAthletesList.d.ts +28 -0
- package/dist/src/modules/fantasy/components/ExpandedAthleteList/index.d.ts +1 -0
- package/dist/src/modules/fantasy/components/LeagueCard/LeagueCard.d.ts +56 -0
- package/dist/src/modules/fantasy/components/LeagueCard/index.d.ts +2 -0
- package/dist/src/modules/fantasy/components/TopPlayerCard/TopPlayerCard.d.ts +53 -0
- package/dist/src/modules/fantasy/components/TopPlayerCard/index.d.ts +2 -0
- package/dist/src/modules/fantasy/mocks.d.ts +7620 -0
- package/dist/src/modules/fantasy/types.d.ts +176 -0
- package/dist/src/modules/fantasy/view/ActiveAthletesMarquee/ActiveAthletesMarquee.d.ts +21 -0
- package/dist/src/modules/fantasy/view/ActiveAthletesMarquee/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/FantasyItemView.d.ts +21 -0
- package/dist/src/modules/fantasy/view/FantasyView.d.ts +27 -0
- package/dist/src/modules/fantasy/view/InactiveLeague/DraftDateCountdown.d.ts +23 -0
- package/dist/src/modules/fantasy/view/InactiveLeague/InactiveLeague.d.ts +52 -0
- package/dist/src/modules/fantasy/view/InactiveLeague/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/LoginView/LoginView.d.ts +48 -0
- package/dist/src/modules/fantasy/view/LoginView/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/MatchupPair/DoubleAthleteCard/DoubleAthleteCard.d.ts +49 -0
- package/dist/src/modules/fantasy/view/MatchupPair/DoubleAthleteCard/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/MatchupPair/ExpandedDoubleAthleteCards.d.ts +14 -0
- package/dist/src/modules/fantasy/view/MatchupPair/MatchupPair.d.ts +54 -0
- package/dist/src/modules/fantasy/view/MatchupPair/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/MatchupSingle/ExpandedSingleAthleteCards.d.ts +14 -0
- package/dist/src/modules/fantasy/view/MatchupSingle/MatchupSingle.d.ts +54 -0
- package/dist/src/modules/fantasy/view/MatchupSingle/SingleAthleteCard/SingleAthleteCard.d.ts +49 -0
- package/dist/src/modules/fantasy/view/MatchupSingle/SingleAthleteCard/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/MatchupSingle/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/PromoView/PromoView.d.ts +52 -0
- package/dist/src/modules/fantasy/view/PromoView/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view/index.d.ts +2 -0
- package/dist/src/modules/fantasy/view-model/FantasyViewModel.FantasyPolling.d.ts +32 -0
- package/dist/src/modules/fantasy/view-model/FantasyViewModel.LeagueManagerPolling.d.ts +32 -0
- package/dist/src/modules/fantasy/view-model/FantasyViewModel.d.ts +148 -0
- package/dist/src/modules/shop/mocks.d.ts +22 -0
- package/dist/src/modules/shop/types.d.ts +161 -0
- package/dist/src/modules/shop/view/ProductDetailView/ProductDetailView.d.ts +10 -0
- package/dist/src/modules/shop/view/ProductDetailView/index.d.ts +2 -0
- package/dist/src/modules/shop/view/ShopView.d.ts +35 -0
- package/dist/src/modules/shop/view/components/BrowseCard/BrowseCard.d.ts +55 -0
- package/dist/src/modules/shop/view/components/BrowseCard/index.d.ts +2 -0
- package/dist/src/modules/shop/view/components/ProductSummaryCard/ProductSummaryCard.d.ts +56 -0
- package/dist/src/modules/shop/view/components/ProductSummaryCard/index.d.ts +2 -0
- package/dist/src/modules/shop/view/components/ShopPromoView/ShopPromoView.d.ts +9 -0
- package/dist/src/modules/shop/view/components/ShopPromoView/index.d.ts +1 -0
- package/dist/src/modules/shop/view/components/ShopSection/ShopSection.d.ts +21 -0
- package/dist/src/modules/shop/view/components/ShopSection/index.d.ts +1 -0
- package/dist/src/modules/shop/view/index.d.ts +2 -0
- package/dist/src/modules/shop/view-model/ShopViewModel.ShopPolling.d.ts +31 -0
- package/dist/src/modules/shop/view-model/ShopViewModel.d.ts +77 -0
- package/dist/src/modules/stats/view-model/StatsViewModel.d.ts +0 -5
- package/dist/src/services/AnalyticsService/AnalyticsService.d.ts +23 -3
- package/dist/src/services/FantasyService.d.ts +53 -0
- package/dist/src/services/NetworkManager/types.d.ts +2 -0
- package/dist/src/services/ShopService.d.ts +23 -0
- package/dist/src/view-models/MaestroEventViewModel.d.ts +4 -0
- package/package.json +1 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/// <reference types="prop-types" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { WithFocusableProps } from '@/external/spatial-navigation';
|
|
4
|
+
import './PromoView.styles.css';
|
|
5
|
+
import { PromoFantasyItem } from '../../view-model/FantasyViewModel';
|
|
6
|
+
type Props = {
|
|
7
|
+
item: PromoFantasyItem;
|
|
8
|
+
};
|
|
9
|
+
declare const _default: {
|
|
10
|
+
new (props?: (Props & WithFocusableProps) | undefined, context?: any): {
|
|
11
|
+
state: import("../../../../external/spatial-navigation/withFocusable").WithFocusableState;
|
|
12
|
+
navigation: import("../../../../external/spatial-navigation/spatialNavigation").default;
|
|
13
|
+
getChildContext(): {
|
|
14
|
+
parentFocusKey: string;
|
|
15
|
+
};
|
|
16
|
+
setFocus: (focusKey: string) => void;
|
|
17
|
+
navigateByDirection: (direction: import("../../../../external/spatial-navigation/utils").Direction, details?: Record<string, any>) => void;
|
|
18
|
+
stealFocus: () => void;
|
|
19
|
+
onUpdateFocus: (focused: boolean) => void;
|
|
20
|
+
onUpdateHasFocusedChild: (hasFocusedChild: boolean) => void;
|
|
21
|
+
onEnterPressHandler: (details: import("../../../../external/spatial-navigation/utils").Details) => void;
|
|
22
|
+
onEnterReleaseHandler: () => void;
|
|
23
|
+
onBackPressHandler: (details: import("../../../../external/spatial-navigation/utils").Details) => void;
|
|
24
|
+
onArrowPressHandler: (direction: import("../../../../external/spatial-navigation/utils").Direction, details: import("../../../../external/spatial-navigation/utils").Details) => boolean | void;
|
|
25
|
+
onBecameFocusedHandler: (layout: import("../../../../external/spatial-navigation/utils").Layout, details: import("../../../../external/spatial-navigation/utils").Details) => void;
|
|
26
|
+
onBecameBlurredHandler: (layout: import("../../../../external/spatial-navigation/utils").Layout, details: import("../../../../external/spatial-navigation/utils").Details) => void;
|
|
27
|
+
componentDidMount(): void;
|
|
28
|
+
componentDidUpdate(): void;
|
|
29
|
+
componentWillUnmount(): void;
|
|
30
|
+
render(): React.ReactElement<Props & WithFocusableProps>;
|
|
31
|
+
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: Props & WithFocusableProps) => import("../../../../external/spatial-navigation/withFocusable").WithFocusableState | Pick<import("../../../../external/spatial-navigation/withFocusable").WithFocusableState, K>) | Pick<import("../../../../external/spatial-navigation/withFocusable").WithFocusableState, K>, callback?: (() => any) | undefined): void;
|
|
32
|
+
forceUpdate(callBack?: (() => any) | undefined): void;
|
|
33
|
+
props: Readonly<{
|
|
34
|
+
children?: React.ReactNode;
|
|
35
|
+
}> & Readonly<Props & WithFocusableProps>;
|
|
36
|
+
context: any;
|
|
37
|
+
refs: {
|
|
38
|
+
[key: string]: React.ReactInstance;
|
|
39
|
+
};
|
|
40
|
+
componentWillMount?(): void;
|
|
41
|
+
componentWillReceiveProps?(nextProps: Readonly<Props & WithFocusableProps>, nextContext: any): void;
|
|
42
|
+
shouldComponentUpdate?(nextProps: Readonly<Props & WithFocusableProps>, nextState: Readonly<import("../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): boolean;
|
|
43
|
+
componentWillUpdate?(nextProps: Readonly<Props & WithFocusableProps>, nextState: Readonly<import("../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
|
|
44
|
+
};
|
|
45
|
+
contextTypes: {
|
|
46
|
+
parentFocusKey: import("prop-types").Requireable<string>;
|
|
47
|
+
};
|
|
48
|
+
childContextTypes: {
|
|
49
|
+
parentFocusKey: import("prop-types").Requireable<string>;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export default _default;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import FantasyService, { FantasyPollingParams } from '@/services/FantasyService';
|
|
2
|
+
import { IFantasyResponse } from '../types';
|
|
3
|
+
export default class FantasyPolling {
|
|
4
|
+
private polling;
|
|
5
|
+
private fantasyService;
|
|
6
|
+
constructor(service: FantasyService);
|
|
7
|
+
/**
|
|
8
|
+
* Refresh polling for fantasy data
|
|
9
|
+
*/
|
|
10
|
+
refresh(params: FantasyPollingParams, callback: (data: IFantasyResponse) => void): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Stop polling for fantasy data
|
|
13
|
+
*/
|
|
14
|
+
stop(): void;
|
|
15
|
+
removeLastResponseHash(): void;
|
|
16
|
+
private start;
|
|
17
|
+
/**
|
|
18
|
+
* @description Update polling interval checking either response header or panel config.
|
|
19
|
+
* Refresh polling if necessary.
|
|
20
|
+
*/
|
|
21
|
+
private updateInterval;
|
|
22
|
+
private getResponseHeaderPollingIntervalValue;
|
|
23
|
+
private getPanelConfigInterval;
|
|
24
|
+
/**
|
|
25
|
+
* Process data received from polling
|
|
26
|
+
*/
|
|
27
|
+
private processPolledData;
|
|
28
|
+
/**
|
|
29
|
+
* Handle errors that occur during fantasy polling
|
|
30
|
+
*/
|
|
31
|
+
private handlePollingError;
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import FantasyService, { LeagueManagerPollingParams } from '@/services/FantasyService';
|
|
2
|
+
import { ILeagueManagerResponse, ILeagueManagerRotoResponse } from '../types';
|
|
3
|
+
export default class LeagueManagerPolling {
|
|
4
|
+
private polling;
|
|
5
|
+
private fantasyService;
|
|
6
|
+
constructor(service: FantasyService);
|
|
7
|
+
/**
|
|
8
|
+
* Refresh polling for league manager data
|
|
9
|
+
*/
|
|
10
|
+
refresh(key: string, params: LeagueManagerPollingParams, callback: (data: ILeagueManagerResponse | ILeagueManagerRotoResponse) => void): void;
|
|
11
|
+
/**
|
|
12
|
+
* Stop polling for fantasy data
|
|
13
|
+
*/
|
|
14
|
+
stop(key: string): void;
|
|
15
|
+
private start;
|
|
16
|
+
/**
|
|
17
|
+
* Process data received from polling
|
|
18
|
+
*/
|
|
19
|
+
private processPolledData;
|
|
20
|
+
/**
|
|
21
|
+
* @description Update polling interval checking either response header or panel config.
|
|
22
|
+
* Refresh polling if necessary.
|
|
23
|
+
*/
|
|
24
|
+
private updateInterval;
|
|
25
|
+
private getResponseHeaderPollingIntervalValue;
|
|
26
|
+
private getPanelConfigInterval;
|
|
27
|
+
stopAll(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Handle errors that occur during league manager polling
|
|
30
|
+
*/
|
|
31
|
+
private handlePollingError;
|
|
32
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Observable } from '@/helpers/Observable';
|
|
2
|
+
import IMaestroEventDelegate from '@/interfaces/IMaestroEventDelegate';
|
|
3
|
+
type NotLoggedInFantasyItem = {
|
|
4
|
+
id: string;
|
|
5
|
+
type: 'notLoggedIn';
|
|
6
|
+
};
|
|
7
|
+
export type PromoFantasyItem = {
|
|
8
|
+
id: string;
|
|
9
|
+
type: 'promo';
|
|
10
|
+
background: string;
|
|
11
|
+
logo: string;
|
|
12
|
+
title: string;
|
|
13
|
+
qrCode: string;
|
|
14
|
+
description: string;
|
|
15
|
+
};
|
|
16
|
+
export type InactiveLeague = {
|
|
17
|
+
id: string;
|
|
18
|
+
type: 'inactiveLeague';
|
|
19
|
+
leagueName: string;
|
|
20
|
+
draftDate?: number;
|
|
21
|
+
leagueLogo: string;
|
|
22
|
+
leagueColor: string;
|
|
23
|
+
};
|
|
24
|
+
type MatchupSingleTeam = {
|
|
25
|
+
points: number;
|
|
26
|
+
logo: string;
|
|
27
|
+
scoringType: string;
|
|
28
|
+
};
|
|
29
|
+
export type MatchupSingleRoster = {
|
|
30
|
+
athleteHeadshot: string;
|
|
31
|
+
athleteAbbrevName: string;
|
|
32
|
+
athletesSlot: string;
|
|
33
|
+
teamTriCode: string;
|
|
34
|
+
proGameStatusLines: string[];
|
|
35
|
+
};
|
|
36
|
+
export type MatchupActiveAthlete = {
|
|
37
|
+
abbrevName: string;
|
|
38
|
+
points: string;
|
|
39
|
+
};
|
|
40
|
+
export type MatchupSingleItem = {
|
|
41
|
+
id: string;
|
|
42
|
+
type: 'matchup-single';
|
|
43
|
+
league: {
|
|
44
|
+
title: string;
|
|
45
|
+
subtitle: string | undefined;
|
|
46
|
+
color: string;
|
|
47
|
+
logo: string;
|
|
48
|
+
};
|
|
49
|
+
team: MatchupSingleTeam;
|
|
50
|
+
roster: MatchupSingleRoster[];
|
|
51
|
+
activeAthletes: MatchupActiveAthlete[];
|
|
52
|
+
topPlayers: TopPlayer[];
|
|
53
|
+
};
|
|
54
|
+
export type TopPlayer = {
|
|
55
|
+
abbrevName: string;
|
|
56
|
+
headshot: string;
|
|
57
|
+
position: string;
|
|
58
|
+
teamTriCode: string;
|
|
59
|
+
points: number;
|
|
60
|
+
rosteredBy: string;
|
|
61
|
+
};
|
|
62
|
+
type MatchupPairTeam = {
|
|
63
|
+
name: string | undefined;
|
|
64
|
+
record: string | undefined;
|
|
65
|
+
points: string | undefined;
|
|
66
|
+
projectedPoints: string | undefined;
|
|
67
|
+
logo: string | undefined;
|
|
68
|
+
winProbability: number | undefined;
|
|
69
|
+
};
|
|
70
|
+
type MatchupPairRosterData = {
|
|
71
|
+
headshot: string;
|
|
72
|
+
abbrevName: string;
|
|
73
|
+
slot: string;
|
|
74
|
+
triCode: string;
|
|
75
|
+
points?: number;
|
|
76
|
+
projectedPoints?: number;
|
|
77
|
+
stats: string[];
|
|
78
|
+
};
|
|
79
|
+
export type MatchupPairRoster = {
|
|
80
|
+
away: MatchupPairRosterData;
|
|
81
|
+
home: MatchupPairRosterData;
|
|
82
|
+
};
|
|
83
|
+
export type MatchupPairItem = {
|
|
84
|
+
id: string;
|
|
85
|
+
type: 'matchup-pair';
|
|
86
|
+
league: {
|
|
87
|
+
title: string | undefined;
|
|
88
|
+
subtitle: string | undefined;
|
|
89
|
+
color: string;
|
|
90
|
+
logo: string;
|
|
91
|
+
};
|
|
92
|
+
awayTeam: MatchupPairTeam;
|
|
93
|
+
homeTeam: MatchupPairTeam;
|
|
94
|
+
roster: MatchupPairRoster[];
|
|
95
|
+
activeAthletes: MatchupActiveAthlete[];
|
|
96
|
+
topPlayers: TopPlayer[];
|
|
97
|
+
};
|
|
98
|
+
export type FantasyItem = NotLoggedInFantasyItem | MatchupPairItem | MatchupSingleItem | InactiveLeague | PromoFantasyItem;
|
|
99
|
+
declare const FANTASY_ERROR_STATE: {
|
|
100
|
+
readonly NONE: "none";
|
|
101
|
+
readonly TAB_LOAD_FAILURE: "tabLoadFailure";
|
|
102
|
+
};
|
|
103
|
+
export type FantasyErrorState = typeof FANTASY_ERROR_STATE[keyof typeof FANTASY_ERROR_STATE];
|
|
104
|
+
export declare class FantasyViewModel {
|
|
105
|
+
fantasyItems: Observable<FantasyItem[]>;
|
|
106
|
+
isDataLoading: Observable<boolean>;
|
|
107
|
+
hasEverSuccessfullyLoaded: Observable<boolean>;
|
|
108
|
+
private eventId;
|
|
109
|
+
private delegate;
|
|
110
|
+
private analyticsService;
|
|
111
|
+
private fantasyService;
|
|
112
|
+
private fantasyPolling;
|
|
113
|
+
private leagueManagerPolling;
|
|
114
|
+
errorState: Observable<FantasyErrorState>;
|
|
115
|
+
private leagueSortOrder;
|
|
116
|
+
private itemToLeagueKey;
|
|
117
|
+
private useMockData;
|
|
118
|
+
constructor(eventId: string, delegate: IMaestroEventDelegate, options?: {
|
|
119
|
+
useMockData?: boolean;
|
|
120
|
+
});
|
|
121
|
+
/**
|
|
122
|
+
* Initialize the ViewModel and start data fetching
|
|
123
|
+
*/
|
|
124
|
+
init(): Promise<void>;
|
|
125
|
+
private fetchData;
|
|
126
|
+
onEngage(type: FantasyItem['type']): void;
|
|
127
|
+
onAskLogin(): void;
|
|
128
|
+
/**
|
|
129
|
+
* Clean up resources when the ViewModel is no longer needed
|
|
130
|
+
*/
|
|
131
|
+
cleanup(): void;
|
|
132
|
+
/**
|
|
133
|
+
* Track panel view event
|
|
134
|
+
*/
|
|
135
|
+
private trackPanelView;
|
|
136
|
+
private processFantasy;
|
|
137
|
+
private parseRoto;
|
|
138
|
+
append(item: FantasyItem | null, leagueKey?: string): void;
|
|
139
|
+
private parseHeadToHead;
|
|
140
|
+
private parseTopPlayers;
|
|
141
|
+
private parseInactiveLeague;
|
|
142
|
+
/**
|
|
143
|
+
* Fetch mock data for testing
|
|
144
|
+
*/
|
|
145
|
+
private fetchMockData;
|
|
146
|
+
clearTabLoadFailure(): void;
|
|
147
|
+
}
|
|
148
|
+
export default FantasyViewModel;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IShopResponse } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Mock shop data for NFL game with multiple sections
|
|
4
|
+
* Covers: regular products, sale products, and browse card
|
|
5
|
+
*/
|
|
6
|
+
export declare const MOCK_SHOP_NFL_RESPONSE: IShopResponse;
|
|
7
|
+
/**
|
|
8
|
+
* Mock shop data for NBA game
|
|
9
|
+
*/
|
|
10
|
+
export declare const MOCK_SHOP_NBA_RESPONSE: IShopResponse;
|
|
11
|
+
/**
|
|
12
|
+
* Mock shop data for NCAA Football
|
|
13
|
+
*/
|
|
14
|
+
export declare const MOCK_SHOP_NCF_RESPONSE: IShopResponse;
|
|
15
|
+
/**
|
|
16
|
+
* Mock shop data with empty sections
|
|
17
|
+
*/
|
|
18
|
+
export declare const MOCK_SHOP_EMPTY_RESPONSE: IShopResponse;
|
|
19
|
+
/**
|
|
20
|
+
* Mock shop data with single section
|
|
21
|
+
*/
|
|
22
|
+
export declare const MOCK_SHOP_SINGLE_SECTION_RESPONSE: IShopResponse;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shop module type definitions
|
|
3
|
+
* Based on ESPN Shop API structure
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Image reference
|
|
7
|
+
*/
|
|
8
|
+
export interface IShopImage {
|
|
9
|
+
/** Image URL */
|
|
10
|
+
href?: string;
|
|
11
|
+
/** Image width */
|
|
12
|
+
width?: number;
|
|
13
|
+
/** Image height */
|
|
14
|
+
height?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Logo reference (same structure as image)
|
|
18
|
+
*/
|
|
19
|
+
export interface IShopLogo {
|
|
20
|
+
/** Logo URL */
|
|
21
|
+
href?: string;
|
|
22
|
+
/** Logo width */
|
|
23
|
+
width?: number;
|
|
24
|
+
/** Logo height */
|
|
25
|
+
height?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Link reference
|
|
29
|
+
*/
|
|
30
|
+
export interface IShopLink {
|
|
31
|
+
/** Link URL */
|
|
32
|
+
href?: string;
|
|
33
|
+
/** Link text */
|
|
34
|
+
text?: string;
|
|
35
|
+
/** Link relations (e.g., ["ictv", "fanatics", "index", "team"]) */
|
|
36
|
+
rel?: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Price information for a product
|
|
40
|
+
*/
|
|
41
|
+
export interface IShopPrice {
|
|
42
|
+
/** Retail price display string (e.g., "$29.99") */
|
|
43
|
+
displayRetail?: string;
|
|
44
|
+
/** Sale price display string (e.g., "$19.99") - optional */
|
|
45
|
+
displaySale?: string;
|
|
46
|
+
/** Clearance price display string (e.g., "$14.99") - optional */
|
|
47
|
+
displayClearance?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Product detail information shown in detail view
|
|
51
|
+
*/
|
|
52
|
+
export interface IShopDetail {
|
|
53
|
+
/** Title for the detail view */
|
|
54
|
+
title?: string;
|
|
55
|
+
/** Description (optional, used for browse cards) */
|
|
56
|
+
description?: string;
|
|
57
|
+
/** Link information */
|
|
58
|
+
link?: IShopLink;
|
|
59
|
+
/** Background image URL */
|
|
60
|
+
backgroundImage?: string;
|
|
61
|
+
/** QR code image URL */
|
|
62
|
+
qrCode?: string;
|
|
63
|
+
/** Disclaimer text */
|
|
64
|
+
disclaimer?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Product item in a shop section
|
|
68
|
+
*/
|
|
69
|
+
export interface IShopProduct {
|
|
70
|
+
/** Item type discriminator */
|
|
71
|
+
type?: 'product';
|
|
72
|
+
/** Product name */
|
|
73
|
+
name?: string;
|
|
74
|
+
/** Product image */
|
|
75
|
+
image?: IShopImage;
|
|
76
|
+
/** Price information */
|
|
77
|
+
price?: IShopPrice;
|
|
78
|
+
/** Detail view information */
|
|
79
|
+
detail?: IShopDetail;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Browse card item (Want More?) in a shop section
|
|
83
|
+
*/
|
|
84
|
+
export interface IShopBrowseCard {
|
|
85
|
+
/** Item type discriminator */
|
|
86
|
+
type?: 'browse';
|
|
87
|
+
/** Browse card name */
|
|
88
|
+
name?: string;
|
|
89
|
+
/** Caption text (e.g., "Browse all Canadiens merch") */
|
|
90
|
+
caption?: string;
|
|
91
|
+
/** Team/League/Event logo */
|
|
92
|
+
image?: IShopImage;
|
|
93
|
+
/** Detail view information */
|
|
94
|
+
detail?: IShopDetail;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Union type for all shop items
|
|
98
|
+
*/
|
|
99
|
+
export type IShopItem = IShopProduct | IShopBrowseCard;
|
|
100
|
+
/**
|
|
101
|
+
* Section product information (team/league info)
|
|
102
|
+
*/
|
|
103
|
+
export interface IShopSectionProduct {
|
|
104
|
+
/** Product/Team ID */
|
|
105
|
+
id?: string;
|
|
106
|
+
/** Short display name (e.g., "Canadiens") */
|
|
107
|
+
shortDisplayName?: string;
|
|
108
|
+
/** Logo reference */
|
|
109
|
+
logo?: IShopLogo;
|
|
110
|
+
/** Type (e.g., "team") */
|
|
111
|
+
type?: string;
|
|
112
|
+
/** Link information */
|
|
113
|
+
link?: IShopLink;
|
|
114
|
+
/** Background image URL */
|
|
115
|
+
backgroundImage?: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Shop section containing a title and list of items
|
|
119
|
+
*/
|
|
120
|
+
export interface IShopSection {
|
|
121
|
+
/** Section title (e.g., "Shop Canadiens Merch") */
|
|
122
|
+
title?: string;
|
|
123
|
+
/** Section product/team information */
|
|
124
|
+
product?: IShopSectionProduct;
|
|
125
|
+
/** Array of products or browse cards */
|
|
126
|
+
items?: IShopItem[];
|
|
127
|
+
}
|
|
128
|
+
export type IShopDefaultItem = {
|
|
129
|
+
image?: {
|
|
130
|
+
href?: string;
|
|
131
|
+
width?: number;
|
|
132
|
+
height?: number;
|
|
133
|
+
};
|
|
134
|
+
type?: string;
|
|
135
|
+
detail?: {
|
|
136
|
+
title?: string;
|
|
137
|
+
link?: {
|
|
138
|
+
href?: string;
|
|
139
|
+
text?: string;
|
|
140
|
+
};
|
|
141
|
+
backgroundImage?: string;
|
|
142
|
+
qrCode?: string;
|
|
143
|
+
disclaimer?: string;
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Shop container with sections
|
|
148
|
+
*/
|
|
149
|
+
export interface IShopContainer {
|
|
150
|
+
/** Array of shop sections */
|
|
151
|
+
sections?: IShopSection[];
|
|
152
|
+
defaultItem?: IShopDefaultItem;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Main shop API response
|
|
156
|
+
*/
|
|
157
|
+
export interface IShopResponse {
|
|
158
|
+
/** Array of shop containers (typically one) */
|
|
159
|
+
shop?: IShopContainer[];
|
|
160
|
+
}
|
|
161
|
+
export declare const isShopProduct: (item: IShopItem) => item is IShopProduct;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './ProductDetailView.styles.css';
|
|
3
|
+
import { IShopBrowseCard, IShopProduct } from '../../types';
|
|
4
|
+
import { WithFocusableProps } from '@/external/spatial-navigation';
|
|
5
|
+
export type ProductDetailViewProps = {
|
|
6
|
+
product: IShopProduct | IShopBrowseCard;
|
|
7
|
+
focusKey: string;
|
|
8
|
+
};
|
|
9
|
+
declare const ProductDetailView: (props: ProductDetailViewProps & WithFocusableProps) => React.JSX.Element;
|
|
10
|
+
export default ProductDetailView;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import './ShopView.styles.css';
|
|
3
|
+
import { Direction } from '@/external/spatial-navigation/utils';
|
|
4
|
+
import ShopViewModel, { ShopErrorState } from '../view-model/ShopViewModel';
|
|
5
|
+
import { IShopProduct, IShopSection, IShopBrowseCard, IShopDefaultItem } from '../types';
|
|
6
|
+
interface State {
|
|
7
|
+
container: HTMLDivElement | null;
|
|
8
|
+
sections: IShopSection[];
|
|
9
|
+
isDataLoading: boolean;
|
|
10
|
+
errorState: ShopErrorState;
|
|
11
|
+
selectedItem: IShopProduct | IShopBrowseCard | null;
|
|
12
|
+
selectedShopSection: IShopSection | null;
|
|
13
|
+
selectedItemFocusKey: string;
|
|
14
|
+
promoData: IShopDefaultItem | null;
|
|
15
|
+
}
|
|
16
|
+
declare class ShopView extends Component<{}, State> {
|
|
17
|
+
private container;
|
|
18
|
+
private sectionsListener;
|
|
19
|
+
private isDataLoadingListener;
|
|
20
|
+
private errorStateListener;
|
|
21
|
+
private promoDataListener;
|
|
22
|
+
private vm;
|
|
23
|
+
constructor(props: {});
|
|
24
|
+
get viewModel(): ShopViewModel;
|
|
25
|
+
componentDidMount(): void;
|
|
26
|
+
componentWillUnmount(): void;
|
|
27
|
+
clearTabLoadFailure: () => void;
|
|
28
|
+
onArrowPress: (d: Direction) => void;
|
|
29
|
+
openItemDetail: (selectedItem: IShopProduct | IShopBrowseCard, selectedShopSection: IShopSection, selectedItemFocusKey: string) => void;
|
|
30
|
+
closeProductDetail: () => void;
|
|
31
|
+
trackPromoEnterPress: () => void;
|
|
32
|
+
renderContent: () => React.JSX.Element | React.JSX.Element[];
|
|
33
|
+
render(): React.JSX.Element;
|
|
34
|
+
}
|
|
35
|
+
export default ShopView;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/// <reference types="prop-types" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import './BrowseCard.styles.css';
|
|
4
|
+
import { WithFocusableProps } from '@/external/spatial-navigation';
|
|
5
|
+
import { IShopBrowseCard } from '../../../types';
|
|
6
|
+
export type BrowseCardProps = {
|
|
7
|
+
browseCard: IShopBrowseCard;
|
|
8
|
+
};
|
|
9
|
+
export declare class BrowseCardView extends React.Component<BrowseCardProps & WithFocusableProps> {
|
|
10
|
+
render(): React.JSX.Element;
|
|
11
|
+
}
|
|
12
|
+
declare const _default: {
|
|
13
|
+
new (props?: (BrowseCardProps & WithFocusableProps) | undefined, context?: any): {
|
|
14
|
+
state: import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState;
|
|
15
|
+
navigation: import("../../../../../external/spatial-navigation/spatialNavigation").default;
|
|
16
|
+
getChildContext(): {
|
|
17
|
+
parentFocusKey: string;
|
|
18
|
+
};
|
|
19
|
+
setFocus: (focusKey: string) => void;
|
|
20
|
+
navigateByDirection: (direction: import("../../../../../external/spatial-navigation/utils").Direction, details?: Record<string, any>) => void;
|
|
21
|
+
stealFocus: () => void;
|
|
22
|
+
onUpdateFocus: (focused: boolean) => void;
|
|
23
|
+
onUpdateHasFocusedChild: (hasFocusedChild: boolean) => void;
|
|
24
|
+
onEnterPressHandler: (details: import("../../../../../external/spatial-navigation/utils").Details) => void;
|
|
25
|
+
onEnterReleaseHandler: () => void;
|
|
26
|
+
onBackPressHandler: (details: import("../../../../../external/spatial-navigation/utils").Details) => void;
|
|
27
|
+
onArrowPressHandler: (direction: import("../../../../../external/spatial-navigation/utils").Direction, details: import("../../../../../external/spatial-navigation/utils").Details) => boolean | void;
|
|
28
|
+
onBecameFocusedHandler: (layout: import("../../../../../external/spatial-navigation/utils").Layout, details: import("../../../../../external/spatial-navigation/utils").Details) => void;
|
|
29
|
+
onBecameBlurredHandler: (layout: import("../../../../../external/spatial-navigation/utils").Layout, details: import("../../../../../external/spatial-navigation/utils").Details) => void;
|
|
30
|
+
componentDidMount(): void;
|
|
31
|
+
componentDidUpdate(): void;
|
|
32
|
+
componentWillUnmount(): void;
|
|
33
|
+
render(): React.ReactElement<BrowseCardProps & WithFocusableProps>;
|
|
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: BrowseCardProps & WithFocusableProps) => import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState | Pick<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K>) | Pick<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K>, callback?: (() => any) | undefined): void;
|
|
35
|
+
forceUpdate(callBack?: (() => any) | undefined): void;
|
|
36
|
+
props: Readonly<{
|
|
37
|
+
children?: React.ReactNode;
|
|
38
|
+
}> & Readonly<BrowseCardProps & WithFocusableProps>;
|
|
39
|
+
context: any;
|
|
40
|
+
refs: {
|
|
41
|
+
[key: string]: React.ReactInstance;
|
|
42
|
+
};
|
|
43
|
+
componentWillMount?(): void;
|
|
44
|
+
componentWillReceiveProps?(nextProps: Readonly<BrowseCardProps & WithFocusableProps>, nextContext: any): void;
|
|
45
|
+
shouldComponentUpdate?(nextProps: Readonly<BrowseCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): boolean;
|
|
46
|
+
componentWillUpdate?(nextProps: Readonly<BrowseCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
|
|
47
|
+
};
|
|
48
|
+
contextTypes: {
|
|
49
|
+
parentFocusKey: import("prop-types").Requireable<string>;
|
|
50
|
+
};
|
|
51
|
+
childContextTypes: {
|
|
52
|
+
parentFocusKey: import("prop-types").Requireable<string>;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
export default _default;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/// <reference types="prop-types" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import './ProductSummaryCard.styles.css';
|
|
4
|
+
import { WithFocusableProps } from '@/external/spatial-navigation';
|
|
5
|
+
import { Direction, Layout } from '@/external/spatial-navigation/utils';
|
|
6
|
+
import { IShopProduct } from '../../../types';
|
|
7
|
+
export type ProductSummaryCardProps = {
|
|
8
|
+
product: IShopProduct;
|
|
9
|
+
onEnterPress?: () => void;
|
|
10
|
+
onArrowPress?: (direction: Direction) => void;
|
|
11
|
+
onBecameFocused?: (layout: Layout) => void;
|
|
12
|
+
};
|
|
13
|
+
declare const _default: {
|
|
14
|
+
new (props?: (ProductSummaryCardProps & WithFocusableProps) | undefined, context?: any): {
|
|
15
|
+
state: import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState;
|
|
16
|
+
navigation: import("../../../../../external/spatial-navigation/spatialNavigation").default;
|
|
17
|
+
getChildContext(): {
|
|
18
|
+
parentFocusKey: string;
|
|
19
|
+
};
|
|
20
|
+
setFocus: (focusKey: string) => void;
|
|
21
|
+
navigateByDirection: (direction: Direction, details?: Record<string, any>) => void;
|
|
22
|
+
stealFocus: () => void;
|
|
23
|
+
onUpdateFocus: (focused: boolean) => void;
|
|
24
|
+
onUpdateHasFocusedChild: (hasFocusedChild: boolean) => void;
|
|
25
|
+
onEnterPressHandler: (details: import("@/external/spatial-navigation/utils").Details) => void;
|
|
26
|
+
onEnterReleaseHandler: () => void;
|
|
27
|
+
onBackPressHandler: (details: import("@/external/spatial-navigation/utils").Details) => void;
|
|
28
|
+
onArrowPressHandler: (direction: Direction, details: import("@/external/spatial-navigation/utils").Details) => boolean | void;
|
|
29
|
+
onBecameFocusedHandler: (layout: Layout, details: import("@/external/spatial-navigation/utils").Details) => void;
|
|
30
|
+
onBecameBlurredHandler: (layout: Layout, details: import("@/external/spatial-navigation/utils").Details) => void;
|
|
31
|
+
componentDidMount(): void;
|
|
32
|
+
componentDidUpdate(): void;
|
|
33
|
+
componentWillUnmount(): void;
|
|
34
|
+
render(): React.ReactElement<ProductSummaryCardProps & WithFocusableProps>;
|
|
35
|
+
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: ProductSummaryCardProps & WithFocusableProps) => import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState | Pick<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K>) | Pick<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState, K>, callback?: (() => any) | undefined): void;
|
|
36
|
+
forceUpdate(callBack?: (() => any) | undefined): void;
|
|
37
|
+
props: Readonly<{
|
|
38
|
+
children?: React.ReactNode;
|
|
39
|
+
}> & Readonly<ProductSummaryCardProps & WithFocusableProps>;
|
|
40
|
+
context: any;
|
|
41
|
+
refs: {
|
|
42
|
+
[key: string]: React.ReactInstance;
|
|
43
|
+
};
|
|
44
|
+
componentWillMount?(): void;
|
|
45
|
+
componentWillReceiveProps?(nextProps: Readonly<ProductSummaryCardProps & WithFocusableProps>, nextContext: any): void;
|
|
46
|
+
shouldComponentUpdate?(nextProps: Readonly<ProductSummaryCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): boolean;
|
|
47
|
+
componentWillUpdate?(nextProps: Readonly<ProductSummaryCardProps & WithFocusableProps>, nextState: Readonly<import("../../../../../external/spatial-navigation/withFocusable").WithFocusableState>, nextContext: any): void;
|
|
48
|
+
};
|
|
49
|
+
contextTypes: {
|
|
50
|
+
parentFocusKey: import("prop-types").Requireable<string>;
|
|
51
|
+
};
|
|
52
|
+
childContextTypes: {
|
|
53
|
+
parentFocusKey: import("prop-types").Requireable<string>;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WithFocusableProps } from '@/external/spatial-navigation';
|
|
3
|
+
import './ShopPromoView.styles.css';
|
|
4
|
+
import { IShopDefaultItem } from '../../../types';
|
|
5
|
+
type Props = {
|
|
6
|
+
promoData: IShopDefaultItem;
|
|
7
|
+
};
|
|
8
|
+
declare const ShopPromoViewWrapper: (props: Props & WithFocusableProps) => React.JSX.Element;
|
|
9
|
+
export default ShopPromoViewWrapper;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './ShopPromoView';
|