@agg-build/ui 2.5.2 → 2.6.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.
@@ -1,6 +1,4 @@
1
1
  import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
2
- export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
3
- export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
4
2
  export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
5
3
  export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
6
4
  export declare const SPORTS_PERIOD_KEYS: readonly ["full", "1h", "2h", "q1", "q2", "q3", "q4", "ot", "first_inning", "second_inning", "third_inning", "first_5_innings", "other"];
@@ -17,41 +15,18 @@ export declare const SPORTS_MARKET_CATEGORY_KEYS: readonly ["game_lines", "exact
17
15
  export type SportsMarketCategoryKey = (typeof SPORTS_MARKET_CATEGORY_KEYS)[number];
18
16
  export declare const SPORTS_MARKET_GROUP_KEYS: readonly ["game_lines", "spreads", "totals", "period_lines", "exact_score", "team_props", "player_props", "specials", "completion", "other"];
19
17
  export type SportsMarketGroupKey = (typeof SPORTS_MARKET_GROUP_KEYS)[number];
20
- export type SportsSectionTabDefinition = {
21
- key: SportsSectionTabKey;
22
- /** Preferred section filter — supersedes `marketCategory`. */
23
- marketGroup?: readonly SportsMarketGroupKey[];
24
- /** Legacy compatibility filter (soccer prop tabs without a marketGroup). */
25
- marketCategory?: SportsMarketCategoryKey;
26
- sportsMarketType?: readonly SportsMarketTypeKey[];
27
- period?: readonly SportsPeriodKey[];
18
+ export type SportsSectionTabKind = "game_lines" | "period" | "stat" | "exact_score" | "other";
19
+ export type SportsSectionTab = {
20
+ /** Stable key: "game_lines" | "exact_score" | "other" | `period:<family>` | `stat:<token>` */
21
+ key: string;
22
+ kind: SportsSectionTabKind;
23
+ /** kind="period": the family this tab covers (e.g. "halves", "first_5_innings"). */
24
+ periodFamily?: string;
25
+ /** kind="period": every period in the family that this game actually has. */
26
+ periods?: readonly SportsPeriodKey[];
27
+ /** kind="stat": the stat token, e.g. "home_runs". "player_props" = the catch-all. */
28
+ stat?: string;
28
29
  };
29
- export declare const SPORTS_SECTION_TAB_DEFINITIONS: readonly [{
30
- readonly key: "game_lines";
31
- readonly marketGroup: readonly ["game_lines", "spreads", "totals"];
32
- }, {
33
- readonly key: "exact_score";
34
- readonly marketGroup: readonly ["exact_score"];
35
- }, {
36
- readonly key: "halves";
37
- readonly marketGroup: readonly ["period_lines"];
38
- readonly period: readonly ["1h", "2h"];
39
- }, {
40
- readonly key: "corners";
41
- readonly marketCategory: "corners";
42
- }, {
43
- readonly key: "goals";
44
- readonly marketCategory: "goals";
45
- }, {
46
- readonly key: "assists";
47
- readonly marketCategory: "assists";
48
- }, {
49
- readonly key: "shots";
50
- readonly marketCategory: "shots";
51
- }, {
52
- readonly key: "other";
53
- readonly marketGroup: readonly ["other", "team_props", "specials", "completion"];
54
- }];
55
30
  export type SportsMarketCardVariant = "outcome" | "line" | "yes_no";
56
31
  export type SportsMarketDisplayGroup = {
57
32
  id: string;
@@ -69,11 +44,27 @@ export type SportsPeriodGroup = {
69
44
  markets: VenueMarket[];
70
45
  groups: SportsMarketDisplayGroup[];
71
46
  };
72
- export declare const resolveSportsSectionDefinition: (key: SportsSectionTabKey) => SportsSectionTabDefinition;
47
+ /**
48
+ * Collapse a period into its display FAMILY, so one tab covers the periods a
49
+ * viewer thinks of together: soccer's 1h+2h are a single "Halves" tab (as
50
+ * today), basketball's q1–q4 a single "Quarters" tab, while baseball's
51
+ * `first_5_innings` stands alone and reads "5 Innings" like Polymarket.
52
+ */
53
+ export declare const resolveSportsPeriodFamily: (period: SportsPeriodKey) => string;
73
54
  export declare const normalizeSportsPeriod: (value: string | null | undefined) => SportsPeriodKey;
74
55
  export declare const normalizeSportsMarketType: (value: string | null | undefined) => SportsMarketTypeKey | null;
75
56
  export declare const normalizeSportsMarketCategory: (value: string | null | undefined) => SportsMarketCategoryKey | null;
76
57
  export declare const normalizeSportsMarketGroup: (value: string | null | undefined) => SportsMarketGroupKey | null;
58
+ /**
59
+ * The stat a player prop measures, as a bare token ("home_runs").
60
+ *
61
+ * Primary source is `marketSubtype`, which both Polymarket and (since the
62
+ * kalshi series-suffix mapping) Kalshi spell identically —
63
+ * `baseball_player_home_runs` on both — so one tab holds both venues' markets.
64
+ * Falls back to `marketCategory` for soccer's legacy corners/goals/assists/
65
+ * shots, which have no player subtype. Null when neither resolves.
66
+ */
67
+ export declare const resolveSportsStatToken: (market: Pick<VenueMarket, "marketSubtype" | "marketCategory" | "question">) => string | null;
77
68
  /**
78
69
  * Map a market to the sports section tab it belongs to — marketGroup-first, with
79
70
  * marketCategory as the documented compatibility fallback (see the
@@ -81,34 +72,16 @@ export declare const normalizeSportsMarketGroup: (value: string | null | undefin
81
72
  * recognizable grouping metadata, so the page can fall back to the default,
82
73
  * ungrouped market list instead of inventing an empty tab.
83
74
  */
84
- export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
85
- export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
75
+ export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType" | "period">) => string | null;
76
+ export declare const resolveVisibleSportsSectionTabs: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTab[];
77
+ export declare const resolveSportsSectionFilters: (tab: SportsSectionTab) => {
86
78
  marketGroup?: SportsMarketGroupKey[];
87
79
  marketCategory?: SportsMarketCategoryKey[];
88
80
  sportsMarketType?: SportsMarketTypeKey[];
89
81
  period?: SportsPeriodKey[];
90
82
  };
91
- /**
92
- * Resolve the markets a sports section tab should display and group.
93
- *
94
- * Section markets are fetched by `aggKey`, which intentionally spans every
95
- * sibling venue-event for the same real-world game (so cross-venue line ladders
96
- * and prop categories aggregate together). For the Game Lines MONEYLINE
97
- * (match-result) group, that aggregation is wrong: it can surface duplicate
98
- * draws sourced from sibling events, props mis-classified as `moneyline`, and —
99
- * because a sibling's market often wins the cross-venue collapse — it can omit
100
- * THIS event's own outcome markets entirely (e.g. show two "Draw"s and drop the
101
- * "Australia" win).
102
- *
103
- * The event's own curated `venueMarkets` are the authoritative N-way result for
104
- * this event (the same source the non-sports event page renders correctly). So
105
- * on the Game Lines tab we take the moneyline markets from the event and keep
106
- * only the line markets (spread/total) from the aggKey fetch. Every other tab —
107
- * and the spread/total ladders within Game Lines — use the fetched markets
108
- * unchanged.
109
- */
110
- export declare const resolveSportsSectionMarkets: ({ tabKey, eventMarkets, sectionMarkets, }: {
111
- tabKey: SportsSectionTabKey;
83
+ export declare const resolveSportsSectionMarkets: ({ tab, eventMarkets, sectionMarkets, }: {
84
+ tab: SportsSectionTab;
112
85
  eventMarkets: VenueMarket[];
113
86
  sectionMarkets: VenueMarket[];
114
87
  }) => VenueMarket[];
@@ -192,8 +165,7 @@ export declare const resolveSportsLeagueLabel: (event: Pick<VenueEventWithMarket
192
165
  */
193
166
  export declare const formatSportsPeriodGrammarLabel: (period: string) => string | null;
194
167
  export declare const isNonStandardSportsLikeEvent: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => boolean;
195
- export declare const resolveVisibleSportsSectionTabDefinitions: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTabDefinition[];
196
168
  export declare const mergeSportsSectionMarketsIntoEvent: ({ event, sectionMarketsByKey, }: {
197
169
  event: import("@agg-build/hooks").VenueEventWithMarkets;
198
- sectionMarketsByKey: Partial<Record<SportsSectionTabKey, VenueMarket[]>>;
170
+ sectionMarketsByKey: Partial<Record<string, VenueMarket[]>>;
199
171
  }) => import("@agg-build/hooks").VenueEventWithMarkets;
@@ -1,6 +1,4 @@
1
1
  import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
2
- export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
3
- export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
4
2
  export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
5
3
  export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
6
4
  export declare const SPORTS_PERIOD_KEYS: readonly ["full", "1h", "2h", "q1", "q2", "q3", "q4", "ot", "first_inning", "second_inning", "third_inning", "first_5_innings", "other"];
@@ -17,41 +15,18 @@ export declare const SPORTS_MARKET_CATEGORY_KEYS: readonly ["game_lines", "exact
17
15
  export type SportsMarketCategoryKey = (typeof SPORTS_MARKET_CATEGORY_KEYS)[number];
18
16
  export declare const SPORTS_MARKET_GROUP_KEYS: readonly ["game_lines", "spreads", "totals", "period_lines", "exact_score", "team_props", "player_props", "specials", "completion", "other"];
19
17
  export type SportsMarketGroupKey = (typeof SPORTS_MARKET_GROUP_KEYS)[number];
20
- export type SportsSectionTabDefinition = {
21
- key: SportsSectionTabKey;
22
- /** Preferred section filter — supersedes `marketCategory`. */
23
- marketGroup?: readonly SportsMarketGroupKey[];
24
- /** Legacy compatibility filter (soccer prop tabs without a marketGroup). */
25
- marketCategory?: SportsMarketCategoryKey;
26
- sportsMarketType?: readonly SportsMarketTypeKey[];
27
- period?: readonly SportsPeriodKey[];
18
+ export type SportsSectionTabKind = "game_lines" | "period" | "stat" | "exact_score" | "other";
19
+ export type SportsSectionTab = {
20
+ /** Stable key: "game_lines" | "exact_score" | "other" | `period:<family>` | `stat:<token>` */
21
+ key: string;
22
+ kind: SportsSectionTabKind;
23
+ /** kind="period": the family this tab covers (e.g. "halves", "first_5_innings"). */
24
+ periodFamily?: string;
25
+ /** kind="period": every period in the family that this game actually has. */
26
+ periods?: readonly SportsPeriodKey[];
27
+ /** kind="stat": the stat token, e.g. "home_runs". "player_props" = the catch-all. */
28
+ stat?: string;
28
29
  };
29
- export declare const SPORTS_SECTION_TAB_DEFINITIONS: readonly [{
30
- readonly key: "game_lines";
31
- readonly marketGroup: readonly ["game_lines", "spreads", "totals"];
32
- }, {
33
- readonly key: "exact_score";
34
- readonly marketGroup: readonly ["exact_score"];
35
- }, {
36
- readonly key: "halves";
37
- readonly marketGroup: readonly ["period_lines"];
38
- readonly period: readonly ["1h", "2h"];
39
- }, {
40
- readonly key: "corners";
41
- readonly marketCategory: "corners";
42
- }, {
43
- readonly key: "goals";
44
- readonly marketCategory: "goals";
45
- }, {
46
- readonly key: "assists";
47
- readonly marketCategory: "assists";
48
- }, {
49
- readonly key: "shots";
50
- readonly marketCategory: "shots";
51
- }, {
52
- readonly key: "other";
53
- readonly marketGroup: readonly ["other", "team_props", "specials", "completion"];
54
- }];
55
30
  export type SportsMarketCardVariant = "outcome" | "line" | "yes_no";
56
31
  export type SportsMarketDisplayGroup = {
57
32
  id: string;
@@ -69,11 +44,27 @@ export type SportsPeriodGroup = {
69
44
  markets: VenueMarket[];
70
45
  groups: SportsMarketDisplayGroup[];
71
46
  };
72
- export declare const resolveSportsSectionDefinition: (key: SportsSectionTabKey) => SportsSectionTabDefinition;
47
+ /**
48
+ * Collapse a period into its display FAMILY, so one tab covers the periods a
49
+ * viewer thinks of together: soccer's 1h+2h are a single "Halves" tab (as
50
+ * today), basketball's q1–q4 a single "Quarters" tab, while baseball's
51
+ * `first_5_innings` stands alone and reads "5 Innings" like Polymarket.
52
+ */
53
+ export declare const resolveSportsPeriodFamily: (period: SportsPeriodKey) => string;
73
54
  export declare const normalizeSportsPeriod: (value: string | null | undefined) => SportsPeriodKey;
74
55
  export declare const normalizeSportsMarketType: (value: string | null | undefined) => SportsMarketTypeKey | null;
75
56
  export declare const normalizeSportsMarketCategory: (value: string | null | undefined) => SportsMarketCategoryKey | null;
76
57
  export declare const normalizeSportsMarketGroup: (value: string | null | undefined) => SportsMarketGroupKey | null;
58
+ /**
59
+ * The stat a player prop measures, as a bare token ("home_runs").
60
+ *
61
+ * Primary source is `marketSubtype`, which both Polymarket and (since the
62
+ * kalshi series-suffix mapping) Kalshi spell identically —
63
+ * `baseball_player_home_runs` on both — so one tab holds both venues' markets.
64
+ * Falls back to `marketCategory` for soccer's legacy corners/goals/assists/
65
+ * shots, which have no player subtype. Null when neither resolves.
66
+ */
67
+ export declare const resolveSportsStatToken: (market: Pick<VenueMarket, "marketSubtype" | "marketCategory" | "question">) => string | null;
77
68
  /**
78
69
  * Map a market to the sports section tab it belongs to — marketGroup-first, with
79
70
  * marketCategory as the documented compatibility fallback (see the
@@ -81,34 +72,16 @@ export declare const normalizeSportsMarketGroup: (value: string | null | undefin
81
72
  * recognizable grouping metadata, so the page can fall back to the default,
82
73
  * ungrouped market list instead of inventing an empty tab.
83
74
  */
84
- export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
85
- export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
75
+ export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType" | "period">) => string | null;
76
+ export declare const resolveVisibleSportsSectionTabs: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTab[];
77
+ export declare const resolveSportsSectionFilters: (tab: SportsSectionTab) => {
86
78
  marketGroup?: SportsMarketGroupKey[];
87
79
  marketCategory?: SportsMarketCategoryKey[];
88
80
  sportsMarketType?: SportsMarketTypeKey[];
89
81
  period?: SportsPeriodKey[];
90
82
  };
91
- /**
92
- * Resolve the markets a sports section tab should display and group.
93
- *
94
- * Section markets are fetched by `aggKey`, which intentionally spans every
95
- * sibling venue-event for the same real-world game (so cross-venue line ladders
96
- * and prop categories aggregate together). For the Game Lines MONEYLINE
97
- * (match-result) group, that aggregation is wrong: it can surface duplicate
98
- * draws sourced from sibling events, props mis-classified as `moneyline`, and —
99
- * because a sibling's market often wins the cross-venue collapse — it can omit
100
- * THIS event's own outcome markets entirely (e.g. show two "Draw"s and drop the
101
- * "Australia" win).
102
- *
103
- * The event's own curated `venueMarkets` are the authoritative N-way result for
104
- * this event (the same source the non-sports event page renders correctly). So
105
- * on the Game Lines tab we take the moneyline markets from the event and keep
106
- * only the line markets (spread/total) from the aggKey fetch. Every other tab —
107
- * and the spread/total ladders within Game Lines — use the fetched markets
108
- * unchanged.
109
- */
110
- export declare const resolveSportsSectionMarkets: ({ tabKey, eventMarkets, sectionMarkets, }: {
111
- tabKey: SportsSectionTabKey;
83
+ export declare const resolveSportsSectionMarkets: ({ tab, eventMarkets, sectionMarkets, }: {
84
+ tab: SportsSectionTab;
112
85
  eventMarkets: VenueMarket[];
113
86
  sectionMarkets: VenueMarket[];
114
87
  }) => VenueMarket[];
@@ -192,8 +165,7 @@ export declare const resolveSportsLeagueLabel: (event: Pick<VenueEventWithMarket
192
165
  */
193
166
  export declare const formatSportsPeriodGrammarLabel: (period: string) => string | null;
194
167
  export declare const isNonStandardSportsLikeEvent: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => boolean;
195
- export declare const resolveVisibleSportsSectionTabDefinitions: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTabDefinition[];
196
168
  export declare const mergeSportsSectionMarketsIntoEvent: ({ event, sectionMarketsByKey, }: {
197
169
  event: import("@agg-build/hooks").VenueEventWithMarkets;
198
- sectionMarketsByKey: Partial<Record<SportsSectionTabKey, VenueMarket[]>>;
170
+ sectionMarketsByKey: Partial<Record<string, VenueMarket[]>>;
199
171
  }) => import("@agg-build/hooks").VenueEventWithMarkets;
@@ -1,8 +1,7 @@
1
1
  import { type UseMidpointsResult, type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
- import { type SportsSectionTabKey } from "./sports-event-market.utils";
3
2
  export type SportsMarketsProps = {
4
3
  event: VenueEventWithMarkets;
5
- onSectionMarketsChange: (tabKey: SportsSectionTabKey, markets: VenueMarket[]) => void;
4
+ onSectionMarketsChange: (tabKey: string, markets: VenueMarket[]) => void;
6
5
  onOutcomeSelect?: () => void;
7
6
  live?: boolean;
8
7
  midpointsResult?: UseMidpointsResult;
@@ -1,8 +1,7 @@
1
1
  import { type UseMidpointsResult, type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
- import { type SportsSectionTabKey } from "./sports-event-market.utils";
3
2
  export type SportsMarketsProps = {
4
3
  event: VenueEventWithMarkets;
5
- onSectionMarketsChange: (tabKey: SportsSectionTabKey, markets: VenueMarket[]) => void;
4
+ onSectionMarketsChange: (tabKey: string, markets: VenueMarket[]) => void;
6
5
  onOutcomeSelect?: () => void;
7
6
  live?: boolean;
8
7
  midpointsResult?: UseMidpointsResult;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agg-build/ui",
3
- "version": "2.5.2",
3
+ "version": "2.6.0",
4
4
  "description": "Pre-built React component library for the AGG prediction market aggregator. Tailwind-based, themeable, with primitives, event surfaces, trading flows, full pages, and modals.",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -100,7 +100,7 @@
100
100
  "liveline": "^0.0.7",
101
101
  "react": "^18.0.0 || ^19.0.0",
102
102
  "react-dom": "^18.0.0 || ^19.0.0",
103
- "@agg-build/hooks": "^2.5.1",
103
+ "@agg-build/hooks": "^2.6.0",
104
104
  "@agg-build/sdk": "^2.5.1"
105
105
  },
106
106
  "dependencies": {