@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.
package/dist/pages.js CHANGED
@@ -23497,64 +23497,15 @@ var SPORTS_LEGACY_PROP_CATEGORY_KEY_SET = /* @__PURE__ */ new Set([
23497
23497
  "assists",
23498
23498
  "shots"
23499
23499
  ]);
23500
- var SPORTS_CATEGORY_OVERRIDE_TAB_KEY_SET = /* @__PURE__ */ new Set([
23501
- "exact_score",
23502
- ...SPORTS_LEGACY_PROP_CATEGORY_KEY_SET
23503
- ]);
23504
- var SPORTS_MARKET_GROUP_TO_TAB = {
23505
- game_lines: "game_lines",
23506
- spreads: "game_lines",
23507
- totals: "game_lines",
23508
- period_lines: "halves",
23509
- exact_score: "exact_score",
23510
- team_props: "other",
23511
- player_props: "other",
23512
- specials: "other",
23513
- completion: "other",
23514
- other: "other"
23515
- };
23516
- var SPORTS_SECTION_TAB_DEFINITIONS = [
23517
- {
23518
- key: "game_lines",
23519
- // NO sportsMarketType filter: spread/total markets on some sports (e.g.
23520
- // esports "Map 1 Rounds Handicap"/"Total Rounds") are sportsMarketType="other"
23521
- // with marketGroup=spreads/totals; AND-ing the game-line types would drop them
23522
- // and leave only the moneyline. marketGroup already scopes the tab. (Safe now
23523
- // that classify_market no longer mis-groups prop/to-score-first/extra-innings
23524
- // markets into game_lines/totals — see agg-venue-core market_group.rs.)
23525
- marketGroup: ["game_lines", "spreads", "totals"]
23526
- // No server-side period filter: many regular-time game-line markets arrive
23527
- // with period=null (moneyline sides, team totals, BTTS), and a
23528
- // period=["full"] filter would drop them server-side. The Game Lines tab
23529
- // narrows to the regular-time group client-side instead (see SportsMarkets).
23530
- },
23531
- { key: "exact_score", marketGroup: ["exact_score"] },
23532
- {
23533
- key: "halves",
23534
- // NO sportsMarketType filter: half-result legs ("France leading at halftime?")
23535
- // are sportsMarketType="other"; AND-ing the game-line types would drop them.
23536
- // marketGroup=period_lines + period already scope the tab.
23537
- marketGroup: ["period_lines"],
23538
- period: ["1h", "2h"]
23539
- },
23540
- { key: "corners", marketCategory: "corners" },
23541
- { key: "goals", marketCategory: "goals" },
23542
- { key: "assists", marketCategory: "assists" },
23543
- { key: "shots", marketCategory: "shots" },
23544
- {
23545
- key: "other",
23546
- // `player_props` is deliberately NOT fetched here: goals/assists/shots/corners
23547
- // props already have dedicated tabs (resolveMarketSectionTabKey routes them
23548
- // there by category), so including the group would re-fetch hundreds of props
23549
- // already shown elsewhere. The handful with no stat category (e.g. "saves")
23550
- // are back-filled from the game-wide set in resolveSportsSectionMarkets.
23551
- marketGroup: ["other", "team_props", "specials", "completion"]
23552
- }
23500
+ var SPORTS_GAME_LINE_GROUPS = [
23501
+ "game_lines",
23502
+ "spreads",
23503
+ "totals",
23504
+ "team_props",
23505
+ "specials",
23506
+ "completion"
23553
23507
  ];
23554
- var SPORTS_NON_STANDARD_VISIBLE_TAB_KEYS = ["game_lines", "other"];
23555
- var SPORTS_NON_STANDARD_VISIBLE_TAB_KEY_SET = new Set(
23556
- SPORTS_NON_STANDARD_VISIBLE_TAB_KEYS
23557
- );
23508
+ var SPORTS_GENERIC_STAT = "player_props";
23558
23509
  var ESPORTS_CATEGORY_TOKENS = /* @__PURE__ */ new Set([
23559
23510
  "esports",
23560
23511
  "video games",
@@ -23565,9 +23516,6 @@ var ESPORTS_CATEGORY_TOKENS = /* @__PURE__ */ new Set([
23565
23516
  ]);
23566
23517
  var ESPORTS_TITLE_PATTERN = /\b(?:esports?|valorant|counter-strike|cs2|league of legends|lol|dota|rocket league|overwatch|rainbow six|starcraft|call of duty)\b/i;
23567
23518
  var SERIES_SCOPE_PATTERN = /\b(?:bo[1-9]|best of \d+|map \d+|game \d+)\b/i;
23568
- var SPORTS_SECTION_TAB_BY_KEY = new Map(
23569
- SPORTS_SECTION_TAB_DEFINITIONS.map((definition) => [definition.key, definition])
23570
- );
23571
23519
  var SPORTS_PERIOD_ORDER = [
23572
23520
  "full",
23573
23521
  "1h",
@@ -23632,12 +23580,13 @@ var getSportsMarketTypeOrderIndex = (sportsMarketType) => {
23632
23580
  const marketTypeIndex = SPORTS_MARKET_TYPE_ORDER.indexOf(sportsMarketType);
23633
23581
  return marketTypeIndex >= 0 ? marketTypeIndex : SPORTS_MARKET_TYPE_ORDER.length;
23634
23582
  };
23635
- var resolveSportsSectionDefinition = (key) => {
23636
- const resolvedDefinition = SPORTS_SECTION_TAB_BY_KEY.get(key);
23637
- if (!resolvedDefinition) {
23638
- return SPORTS_SECTION_TAB_DEFINITIONS[0];
23639
- }
23640
- return resolvedDefinition;
23583
+ var resolveSportsPeriodFamily = (period) => {
23584
+ if (period === "1h" || period === "2h") return "halves";
23585
+ if (period === "q1" || period === "q2" || period === "q3" || period === "q4") return "quarters";
23586
+ if (/^inning_\d{1,2}$/.test(period)) return "innings";
23587
+ if (/^set_\d{1,2}$/.test(period)) return "sets";
23588
+ if (/^(?:map|game)_\d{1,2}$/.test(period)) return "maps";
23589
+ return period;
23641
23590
  };
23642
23591
  var normalizeSportsPeriod = (value) => {
23643
23592
  const resolvedValue = toTrimmedString(value).toLowerCase();
@@ -23682,53 +23631,182 @@ var resolveFallbackSportsMarketCategory = (market) => {
23682
23631
  if (question.includes("goal")) return "goals";
23683
23632
  return null;
23684
23633
  };
23634
+ var resolveSportsStatToken = (market) => {
23635
+ const subtype = toTrimmedString(market.marketSubtype).toLowerCase();
23636
+ const playerMatch = /_player_(.+)$/.exec(subtype);
23637
+ if (playerMatch) return playerMatch[1];
23638
+ const category = normalizeSportsMarketCategory(market.marketCategory);
23639
+ if (category && SPORTS_LEGACY_PROP_CATEGORY_KEY_SET.has(category)) return category;
23640
+ return null;
23641
+ };
23685
23642
  var resolveMarketSectionTabKey = (market) => {
23643
+ var _a;
23686
23644
  if (normalizeSportsMarketType(market.sportsMarketType) === "to_advance") {
23687
23645
  return "game_lines";
23688
23646
  }
23689
23647
  const normalizedCategory = normalizeSportsMarketCategory(market.marketCategory);
23690
23648
  const fallbackCategory = !normalizedCategory || normalizedCategory === "other" ? resolveFallbackSportsMarketCategory(market) : null;
23691
23649
  const category = fallbackCategory != null ? fallbackCategory : normalizedCategory;
23692
- if (category && SPORTS_CATEGORY_OVERRIDE_TAB_KEY_SET.has(category)) {
23693
- return category;
23694
- }
23650
+ if (category && SPORTS_LEGACY_PROP_CATEGORY_KEY_SET.has(category)) return `stat:${category}`;
23651
+ if (category === "exact_score") return "exact_score";
23695
23652
  const group = normalizeSportsMarketGroup(market.marketGroup);
23696
- if (group) return SPORTS_MARKET_GROUP_TO_TAB[group];
23653
+ if (group === "exact_score") return "exact_score";
23654
+ if (group === "player_props") {
23655
+ return `stat:${(_a = resolveSportsStatToken(market)) != null ? _a : SPORTS_GENERIC_STAT}`;
23656
+ }
23657
+ if (group === "period_lines") {
23658
+ return `period:${resolveSportsPeriodFamily(normalizeSportsPeriod(market.period))}`;
23659
+ }
23660
+ if (group === "other") return "other";
23661
+ if (group) return "game_lines";
23697
23662
  if (category === "game_lines") return "game_lines";
23698
23663
  if (category === "other") return "other";
23699
23664
  return null;
23700
23665
  };
23701
- var resolveSportsSectionFilters = (key) => {
23702
- var _a;
23703
- const resolvedDefinition = resolveSportsSectionDefinition(key);
23704
- const useMarketGroup = !!((_a = resolvedDefinition.marketGroup) == null ? void 0 : _a.length);
23666
+ var resolveVisibleSportsSectionTabs = (event) => {
23667
+ var _a, _b, _c;
23668
+ const periodsByFamily = /* @__PURE__ */ new Map();
23669
+ const statVolume = /* @__PURE__ */ new Map();
23670
+ let hasGameLines = false;
23671
+ let hasExactScore = false;
23672
+ let hasOther = false;
23673
+ for (const market of event.venueMarkets) {
23674
+ const key = resolveMarketSectionTabKey(market);
23675
+ if (!key) continue;
23676
+ if (key === "game_lines") hasGameLines = true;
23677
+ else if (key === "exact_score") hasExactScore = true;
23678
+ else if (key === "other") hasOther = true;
23679
+ else if (key.startsWith("period:")) {
23680
+ const family = key.slice("period:".length);
23681
+ const periods = (_a = periodsByFamily.get(family)) != null ? _a : /* @__PURE__ */ new Set();
23682
+ periods.add(normalizeSportsPeriod(market.period));
23683
+ periodsByFamily.set(family, periods);
23684
+ } else if (key.startsWith("stat:")) {
23685
+ const stat = key.slice("stat:".length);
23686
+ statVolume.set(stat, ((_b = statVolume.get(stat)) != null ? _b : 0) + ((_c = market.volume) != null ? _c : 0));
23687
+ }
23688
+ }
23689
+ const tabs = [];
23690
+ if (hasGameLines) tabs.push({ key: "game_lines", kind: "game_lines" });
23691
+ const periodTabs = Array.from(periodsByFamily.entries()).map(([periodFamily, periods]) => ({
23692
+ key: `period:${periodFamily}`,
23693
+ kind: "period",
23694
+ periodFamily,
23695
+ periods: Array.from(periods).sort(
23696
+ (left, right) => getSportsPeriodOrderIndex(left) - getSportsPeriodOrderIndex(right)
23697
+ )
23698
+ })).sort(
23699
+ (left, right) => getSportsPeriodOrderIndex(left.periods[0]) - getSportsPeriodOrderIndex(right.periods[0])
23700
+ );
23701
+ tabs.push(...periodTabs);
23702
+ const statTabs = Array.from(statVolume.entries()).sort((left, right) => {
23703
+ if (left[0] === SPORTS_GENERIC_STAT !== (right[0] === SPORTS_GENERIC_STAT)) {
23704
+ return left[0] === SPORTS_GENERIC_STAT ? 1 : -1;
23705
+ }
23706
+ return right[1] - left[1];
23707
+ }).map(([stat]) => ({ key: `stat:${stat}`, kind: "stat", stat }));
23708
+ tabs.push(...statTabs);
23709
+ if (hasExactScore) tabs.push({ key: "exact_score", kind: "exact_score" });
23710
+ if (hasOther) tabs.push({ key: "other", kind: "other" });
23711
+ if (isNonStandardSportsLikeEvent(event)) {
23712
+ return tabs.filter((tab) => tab.kind === "game_lines" || tab.kind === "other");
23713
+ }
23714
+ return tabs;
23715
+ };
23716
+ var resolveSportsSectionFilters = (tab) => {
23717
+ if (tab.kind === "period") {
23718
+ return {
23719
+ marketGroup: ["period_lines"],
23720
+ marketCategory: void 0,
23721
+ sportsMarketType: void 0,
23722
+ period: tab.periods ? [...tab.periods] : void 0
23723
+ };
23724
+ }
23725
+ if (tab.kind === "stat") {
23726
+ const legacyCategory = SPORTS_LEGACY_PROP_CATEGORY_KEY_SET.has(
23727
+ tab.stat
23728
+ ) ? tab.stat : null;
23729
+ return legacyCategory ? {
23730
+ marketGroup: void 0,
23731
+ marketCategory: [legacyCategory],
23732
+ sportsMarketType: void 0,
23733
+ period: void 0
23734
+ } : {
23735
+ marketGroup: ["player_props"],
23736
+ marketCategory: void 0,
23737
+ sportsMarketType: void 0,
23738
+ period: void 0
23739
+ };
23740
+ }
23741
+ if (tab.kind === "exact_score") {
23742
+ return {
23743
+ marketGroup: ["exact_score"],
23744
+ marketCategory: void 0,
23745
+ sportsMarketType: void 0,
23746
+ period: void 0
23747
+ };
23748
+ }
23749
+ if (tab.kind === "other") {
23750
+ return {
23751
+ marketGroup: ["other"],
23752
+ marketCategory: void 0,
23753
+ sportsMarketType: void 0,
23754
+ period: void 0
23755
+ };
23756
+ }
23705
23757
  return {
23706
- marketGroup: useMarketGroup ? [...resolvedDefinition.marketGroup] : void 0,
23707
- // Only fall back to the deprecated marketCategory filter when the tab has no
23708
- // marketGroup mapping. Sending both would AND them server-side and drop
23709
- // markets that carry only one of the two.
23710
- marketCategory: !useMarketGroup && resolvedDefinition.marketCategory ? [resolvedDefinition.marketCategory] : void 0,
23711
- sportsMarketType: resolvedDefinition.sportsMarketType ? [...resolvedDefinition.sportsMarketType] : void 0,
23712
- period: resolvedDefinition.period ? [...resolvedDefinition.period] : void 0
23758
+ marketGroup: [...SPORTS_GAME_LINE_GROUPS],
23759
+ marketCategory: void 0,
23760
+ sportsMarketType: void 0,
23761
+ period: void 0
23713
23762
  };
23714
23763
  };
23764
+ var hasTeamTitledOutcomes = (market) => {
23765
+ var _a;
23766
+ const titles = ((_a = market.venueMarketOutcomes) != null ? _a : []).map(
23767
+ (outcome) => toTrimmedString(outcome.title)
23768
+ );
23769
+ return titles.length > 1 && titles.every((title2) => title2 && !YES_NO_LABELS.has(title2.toLowerCase())) && new Set(titles).size === titles.length;
23770
+ };
23771
+ var isClusterRelation = (left, right) => {
23772
+ var _a, _b;
23773
+ return ((_a = left.matchedVenueMarkets) != null ? _a : []).some((market) => market.id === right.id) || ((_b = right.matchedVenueMarkets) != null ? _b : []).some((market) => market.id === left.id);
23774
+ };
23775
+ var isDecomposedLeg = (market) => {
23776
+ var _a;
23777
+ const labels = ((_a = market.venueMarketOutcomes) != null ? _a : []).map(
23778
+ (outcome) => toTrimmedString(outcome.label).toLowerCase()
23779
+ );
23780
+ return labels.length === 2 && labels.every((label2) => YES_NO_LABELS.has(label2)) && !hasTeamTitledOutcomes(market);
23781
+ };
23782
+ var dropDecomposedLegsMergedIntoSingle = (markets) => {
23783
+ const legs = markets.filter((market) => isDecomposedLeg(market));
23784
+ if (legs.length === 0) return markets;
23785
+ const hasMergedSingle = markets.some(
23786
+ (market) => {
23787
+ var _a, _b;
23788
+ return hasTeamTitledOutcomes(market) && ((_b = (_a = market.venueMarketOutcomes) == null ? void 0 : _a.length) != null ? _b : 0) >= legs.length && markets.some((other) => other !== market && isClusterRelation(market, other));
23789
+ }
23790
+ );
23791
+ return hasMergedSingle ? markets.filter((market) => !isDecomposedLeg(market)) : markets;
23792
+ };
23715
23793
  var resolveSportsSectionMarkets = ({
23716
- tabKey,
23794
+ tab,
23717
23795
  eventMarkets,
23718
23796
  sectionMarkets
23719
23797
  }) => {
23720
- const effectiveSectionMarkets = sectionMarkets.length > 0 ? sectionMarkets : eventMarkets.filter((market) => resolveMarketSectionTabKey(market) === tabKey);
23798
+ const effectiveSectionMarkets = sectionMarkets.length > 0 ? sectionMarkets : eventMarkets.filter((market) => resolveMarketSectionTabKey(market) === tab.key);
23721
23799
  const filteredSectionMarkets = effectiveSectionMarkets.filter(
23722
- (market) => resolveMarketSectionTabKey(market) === tabKey
23800
+ (market) => resolveMarketSectionTabKey(market) === tab.key
23723
23801
  );
23724
- if (tabKey === "other") {
23802
+ if (tab.key === "other" || tab.key === `stat:${SPORTS_GENERIC_STAT}`) {
23725
23803
  const seenIds = new Set(filteredSectionMarkets.map((market) => market.id));
23726
- const strayOtherMarkets = eventMarkets.filter(
23727
- (market) => !seenIds.has(market.id) && resolveMarketSectionTabKey(market) === "other"
23804
+ const strayMarkets = eventMarkets.filter(
23805
+ (market) => !seenIds.has(market.id) && resolveMarketSectionTabKey(market) === tab.key
23728
23806
  );
23729
- return [...filteredSectionMarkets, ...strayOtherMarkets];
23807
+ return [...filteredSectionMarkets, ...strayMarkets];
23730
23808
  }
23731
- if (tabKey !== "game_lines") return filteredSectionMarkets;
23809
+ if (tab.kind !== "game_lines") return filteredSectionMarkets;
23732
23810
  const dedupeEventMarketsOfType = (type) => {
23733
23811
  const dedupedMarkets = [];
23734
23812
  const seenKeys = /* @__PURE__ */ new Set();
@@ -23741,7 +23819,7 @@ var resolveSportsSectionMarkets = ({
23741
23819
  seenKeys.add(key);
23742
23820
  dedupedMarkets.push(market);
23743
23821
  }
23744
- return dedupedMarkets;
23822
+ return dropDecomposedLegsMergedIntoSingle(dedupedMarkets);
23745
23823
  };
23746
23824
  const eventMoneylineMarkets = dedupeEventMarketsOfType("moneyline");
23747
23825
  const eventToAdvanceMarkets = dedupeEventMarketsOfType("to_advance");
@@ -23828,7 +23906,9 @@ var resolveSpreadOutcomeTeamNames = (activeMarket, groupMarkets) => {
23828
23906
  return toTrimmedString((_b = (_a = market.venueMarketOutcomes) == null ? void 0 : _a[index]) == null ? void 0 : _b.title);
23829
23907
  }).filter((title2) => isSpreadTeamTitle(title2));
23830
23908
  if (cleanTitles.length === 0) return null;
23831
- return cleanTitles.reduce((longest, title2) => title2.length > longest.length ? title2 : longest);
23909
+ return cleanTitles.reduce(
23910
+ (longest, title2) => title2.length > longest.length ? title2 : longest
23911
+ );
23832
23912
  };
23833
23913
  return { favored: pickName(0), dog: pickName(1) };
23834
23914
  };
@@ -23837,9 +23917,7 @@ var resolveCombinedMoneylineLegLabel = (market) => {
23837
23917
  return toTrimmedString(typedMarket.shortTitle) || toTrimmedString(market.question);
23838
23918
  };
23839
23919
  var areCombinedMoneylineLegsDistinct = (markets) => {
23840
- const labels = markets.map(
23841
- (market) => resolveCombinedMoneylineLegLabel(market).toLowerCase()
23842
- );
23920
+ const labels = markets.map((market) => resolveCombinedMoneylineLegLabel(market).toLowerCase());
23843
23921
  return labels.every((label2) => label2.length > 0) && new Set(labels).size === labels.length;
23844
23922
  };
23845
23923
  var resolveDisplayGroupFamilyKey = (market) => {
@@ -24124,6 +24202,15 @@ var buildSportsSlideFromGroup = (group) => {
24124
24202
  defaultStopIndex
24125
24203
  };
24126
24204
  };
24205
+ var formatSportsPeriodGrammarLabel = (period) => {
24206
+ const grammarMatch = SPORTS_PERIOD_GRAMMAR_PATTERN.exec(period);
24207
+ if (!grammarMatch) return null;
24208
+ if (grammarMatch[1]) {
24209
+ const family = grammarMatch[1].charAt(0).toUpperCase() + grammarMatch[1].slice(1);
24210
+ return `${family} ${Number(grammarMatch[2])}`;
24211
+ }
24212
+ return `First ${Number(grammarMatch[3])} Innings`;
24213
+ };
24127
24214
  var resolveSportsCategoryTokens = (event) => {
24128
24215
  return new Set(
24129
24216
  event.categories.flatMap((entry) => {
@@ -24146,39 +24233,20 @@ var isNonStandardSportsLikeEvent = (event) => {
24146
24233
  return ESPORTS_TITLE_PATTERN.test(question) || SERIES_SCOPE_PATTERN.test(question);
24147
24234
  });
24148
24235
  };
24149
- var resolveVisibleSportsSectionTabDefinitions = (event) => {
24150
- const presentTabKeys = /* @__PURE__ */ new Set();
24151
- for (const market of event.venueMarkets) {
24152
- const tabKey = resolveMarketSectionTabKey(market);
24153
- if (tabKey) presentTabKeys.add(tabKey);
24154
- }
24155
- let definitions = SPORTS_SECTION_TAB_DEFINITIONS.filter(
24156
- (definition) => presentTabKeys.has(definition.key)
24157
- );
24158
- if (isNonStandardSportsLikeEvent(event)) {
24159
- definitions = definitions.filter(
24160
- (definition) => SPORTS_NON_STANDARD_VISIBLE_TAB_KEY_SET.has(definition.key)
24161
- );
24162
- }
24163
- return definitions;
24164
- };
24165
24236
  var mergeSportsSectionMarketsIntoEvent = ({
24166
24237
  event,
24167
24238
  sectionMarketsByKey
24168
24239
  }) => {
24169
- var _a;
24170
24240
  const orderedVenueMarkets = [...event.venueMarkets];
24171
24241
  const seenMarketIds = new Set(orderedVenueMarkets.map((market) => market.id));
24172
- for (const sectionKey of SPORTS_SECTION_TAB_DEFINITIONS.map((definition) => definition.key)) {
24173
- for (const market of (_a = sectionMarketsByKey[sectionKey]) != null ? _a : []) {
24242
+ for (const markets of Object.values(sectionMarketsByKey)) {
24243
+ for (const market of markets != null ? markets : []) {
24174
24244
  if (seenMarketIds.has(market.id)) continue;
24175
24245
  seenMarketIds.add(market.id);
24176
24246
  orderedVenueMarkets.push(market);
24177
24247
  }
24178
24248
  }
24179
- return __spreadProps(__spreadValues({}, event), {
24180
- venueMarkets: orderedVenueMarkets
24181
- });
24249
+ return __spreadProps(__spreadValues({}, event), { venueMarkets: orderedVenueMarkets });
24182
24250
  };
24183
24251
 
24184
24252
  // src/pages/event-market/sports-market-card.tsx
@@ -24429,6 +24497,15 @@ function SportsLineRail({
24429
24497
 
24430
24498
  // src/pages/event-market/sports-market-card.tsx
24431
24499
  var import_jsx_runtime161 = require("react/jsx-runtime");
24500
+ var resolveSportsLineOutcomeSide = (outcome) => {
24501
+ var _a;
24502
+ for (const candidate of [outcome.label, outcome.title]) {
24503
+ if (typeof candidate !== "string") continue;
24504
+ const matchedSide = (_a = candidate.trim().toLowerCase().match(/(?:^|\s)(over|under)(?=\s|$)/)) == null ? void 0 : _a[1];
24505
+ if (matchedSide === "over" || matchedSide === "under") return matchedSide;
24506
+ }
24507
+ return null;
24508
+ };
24432
24509
  var SportsMarketCard = ({
24433
24510
  group,
24434
24511
  venueMarkets,
@@ -24591,16 +24668,22 @@ var SportsMarketCard = ({
24591
24668
  setSelectedLineIndex(index);
24592
24669
  const market = (_a2 = slide.stops[index]) == null ? void 0 : _a2.market;
24593
24670
  if (!market) return;
24594
- const isGroupBeingTraded = group.markets.some(
24595
- (groupMarket) => groupMarket.id === (tradingContext == null ? void 0 : tradingContext.selectedMarketId)
24596
- );
24597
- if (!isGroupBeingTraded) return;
24598
24671
  const previousOutcomeIndex = previousMarket ? previousMarket.venueMarketOutcomes.findIndex(
24599
24672
  (outcome) => outcome.id === (tradingContext == null ? void 0 : tradingContext.selectedOutcomeId)
24600
24673
  ) : -1;
24601
- const nextOutcome = (_b2 = previousOutcomeIndex >= 0 ? market.venueMarketOutcomes[previousOutcomeIndex] : void 0) != null ? _b2 : market.venueMarketOutcomes[0];
24674
+ const previousOutcome = previousOutcomeIndex >= 0 ? previousMarket == null ? void 0 : previousMarket.venueMarketOutcomes[previousOutcomeIndex] : void 0;
24675
+ const previousOutcomeSide = previousOutcome ? resolveSportsLineOutcomeSide(previousOutcome) : null;
24676
+ const matchingSideOutcomes = previousOutcomeSide ? market.venueMarketOutcomes.filter(
24677
+ (outcome) => resolveSportsLineOutcomeSide(outcome) === previousOutcomeSide
24678
+ ) : [];
24679
+ const matchingSideOutcome = matchingSideOutcomes.length === 1 ? matchingSideOutcomes[0] : void 0;
24680
+ const nextOutcome = (_b2 = matchingSideOutcome != null ? matchingSideOutcome : previousOutcomeIndex >= 0 ? market.venueMarketOutcomes[previousOutcomeIndex] : void 0) != null ? _b2 : market.venueMarketOutcomes[0];
24602
24681
  if (nextOutcome) {
24603
24682
  tradingContext == null ? void 0 : tradingContext.selectMarketAndOutcome(market.id, nextOutcome.id);
24683
+ onOutcomeSelect == null ? void 0 : onOutcomeSelect(group.id, {
24684
+ marketId: market.id,
24685
+ outcomeId: nextOutcome.id
24686
+ });
24604
24687
  } else {
24605
24688
  tradingContext == null ? void 0 : tradingContext.selectMarket(market.id, market);
24606
24689
  }
@@ -24646,24 +24729,48 @@ SportsMarketCard.displayName = "SportsMarketCard";
24646
24729
 
24647
24730
  // src/pages/event-market/sports-markets.tsx
24648
24731
  var import_jsx_runtime162 = require("react/jsx-runtime");
24649
- var resolveSportsSectionLabel = (labels, key) => {
24650
- switch (key) {
24732
+ var STAT_LABEL_OVERRIDES = {
24733
+ rbis: "RBIs",
24734
+ hits_runs_rbis: "Hits + Runs + RBIs",
24735
+ ot: "OT"
24736
+ };
24737
+ var formatStatLabel = (stat) => {
24738
+ var _a;
24739
+ return (_a = STAT_LABEL_OVERRIDES[stat]) != null ? _a : stat.split("_").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
24740
+ };
24741
+ var LEGACY_STAT_LABEL_KEYS = {
24742
+ corners: "cornersTab",
24743
+ goals: "goalsTab",
24744
+ assists: "assistsTab",
24745
+ shots: "shotsTab"
24746
+ };
24747
+ var resolveSportsSectionLabel = (labels, tab) => {
24748
+ var _a, _b, _c, _d, _e;
24749
+ const sports = labels.eventMarketPage.sports;
24750
+ switch (tab.kind) {
24651
24751
  case "game_lines":
24652
- return labels.eventMarketPage.sports.gameLinesTab;
24653
- case "halves":
24654
- return labels.eventMarketPage.sports.halvesTab;
24752
+ return sports.gameLinesTab;
24655
24753
  case "exact_score":
24656
- return labels.eventMarketPage.sports.exactScoreTab;
24657
- case "corners":
24658
- return labels.eventMarketPage.sports.cornersTab;
24659
- case "goals":
24660
- return labels.eventMarketPage.sports.goalsTab;
24661
- case "assists":
24662
- return labels.eventMarketPage.sports.assistsTab;
24663
- case "shots":
24664
- return labels.eventMarketPage.sports.shotsTab;
24754
+ return sports.exactScoreTab;
24665
24755
  case "other":
24666
- return labels.eventMarketPage.sports.otherTab;
24756
+ return sports.otherTab;
24757
+ case "stat": {
24758
+ if (tab.stat === "player_props") return sports.playerPropsTab;
24759
+ const legacyLabelKey = tab.stat ? LEGACY_STAT_LABEL_KEYS[tab.stat] : void 0;
24760
+ return legacyLabelKey ? sports[legacyLabelKey] : formatStatLabel((_a = tab.stat) != null ? _a : "");
24761
+ }
24762
+ case "period": {
24763
+ switch (tab.periodFamily) {
24764
+ case "halves":
24765
+ return sports.halvesTab;
24766
+ case "quarters":
24767
+ return sports.quartersTab;
24768
+ case "sets":
24769
+ return sports.setsTab;
24770
+ default:
24771
+ return (_e = (_c = formatSportsPeriodGrammarLabel((_b = tab.periodFamily) != null ? _b : "")) == null ? void 0 : _c.replace(/^First /, "")) != null ? _e : formatStatLabel((_d = tab.periodFamily) != null ? _d : "");
24772
+ }
24773
+ }
24667
24774
  }
24668
24775
  };
24669
24776
  var SportsTabButton = ({
@@ -24751,18 +24858,23 @@ var SportsMarkets = ({
24751
24858
  }
24752
24859
  return merged;
24753
24860
  }, [event.venueMarkets, gameMarkets]);
24754
- const visibleSectionDefinitions = (0, import_react41.useMemo)(
24755
- () => resolveVisibleSportsSectionTabDefinitions(__spreadProps(__spreadValues({}, event), { venueMarkets: tabSourceMarkets })),
24861
+ const visibleTabs = (0, import_react41.useMemo)(
24862
+ () => resolveVisibleSportsSectionTabs(__spreadProps(__spreadValues({}, event), { venueMarkets: tabSourceMarkets })),
24756
24863
  [event, tabSourceMarkets]
24757
24864
  );
24758
- const shouldRenderTabs = visibleSectionDefinitions.length > 1 && tabSourceMarkets.length > 1;
24759
- const [activeTabKey, setActiveTabKey] = (0, import_react41.useState)(
24760
- (_b = (_a = visibleSectionDefinitions[0]) == null ? void 0 : _a.key) != null ? _b : "game_lines"
24865
+ const shouldRenderTabs = visibleTabs.length > 1 && tabSourceMarkets.length > 1;
24866
+ const [activeTabKey, setActiveTabKey] = (0, import_react41.useState)((_b = (_a = visibleTabs[0]) == null ? void 0 : _a.key) != null ? _b : "game_lines");
24867
+ const activeTab = (0, import_react41.useMemo)(
24868
+ () => {
24869
+ var _a2, _b2;
24870
+ return (_b2 = (_a2 = visibleTabs.find((tab) => tab.key === activeTabKey)) != null ? _a2 : visibleTabs[0]) != null ? _b2 : { key: "game_lines", kind: "game_lines" };
24871
+ },
24872
+ [visibleTabs, activeTabKey]
24761
24873
  );
24762
24874
  const [expandedGroupId, setExpandedGroupId] = (0, import_react41.useState)(null);
24763
24875
  const [stableMarketsByTab, setStableMarketsByTab] = (0, import_react41.useState)({});
24764
- const activeTabLabel = resolveSportsSectionLabel(labels, activeTabKey);
24765
- const sectionFilters = resolveSportsSectionFilters(activeTabKey);
24876
+ const activeTabLabel = resolveSportsSectionLabel(labels, activeTab);
24877
+ const sectionFilters = resolveSportsSectionFilters(activeTab);
24766
24878
  const sectionMarketsQuery = (0, import_hooks65.useVenueMarkets)({
24767
24879
  aggKey: event.aggKey ? [event.aggKey] : void 0,
24768
24880
  sportsMarketType: sectionFilters.sportsMarketType,
@@ -24785,26 +24897,25 @@ var SportsMarkets = ({
24785
24897
  } = sectionMarketsQuery;
24786
24898
  const resolvedSectionMarkets = (0, import_react41.useMemo)(
24787
24899
  () => resolveSportsSectionMarkets({
24788
- tabKey: activeTabKey,
24900
+ tab: activeTab,
24789
24901
  eventMarkets: tabSourceMarkets,
24790
24902
  sectionMarkets
24791
24903
  }),
24792
- [activeTabKey, tabSourceMarkets, sectionMarkets]
24904
+ [activeTab, tabSourceMarkets, sectionMarkets]
24793
24905
  );
24794
24906
  const isSectionSettled = !isSectionLoading && !hasNextPage && !isFetchingNextPage;
24795
24907
  const stableSectionMarkets = stableMarketsByTab[activeTabKey];
24796
- const displayedSectionMarkets = stableSectionMarkets != null ? stableSectionMarkets : isSectionSettled ? resolvedSectionMarkets : [];
24908
+ const displayedSectionMarkets = (0, import_react41.useMemo)(
24909
+ () => stableSectionMarkets != null ? stableSectionMarkets : isSectionSettled ? resolvedSectionMarkets : [],
24910
+ [stableSectionMarkets, isSectionSettled, resolvedSectionMarkets]
24911
+ );
24797
24912
  const periodGroups = (0, import_react41.useMemo)(
24798
24913
  () => groupSportsMarketsByPeriod(displayedSectionMarkets),
24799
24914
  [displayedSectionMarkets]
24800
24915
  );
24801
- const displayedPeriodGroups = (0, import_react41.useMemo)(
24802
- () => activeTabKey === "game_lines" ? periodGroups.filter((periodGroup) => periodGroup.key === "full") : periodGroups,
24803
- [activeTabKey, periodGroups]
24804
- );
24805
24916
  const allGroups = (0, import_react41.useMemo)(
24806
- () => displayedPeriodGroups.flatMap((periodGroup) => periodGroup.groups),
24807
- [displayedPeriodGroups]
24917
+ () => periodGroups.flatMap((periodGroup) => periodGroup.groups),
24918
+ [periodGroups]
24808
24919
  );
24809
24920
  (0, import_react41.useEffect)(() => {
24810
24921
  if (hasNextPage && !isFetchingNextPage) {
@@ -24838,9 +24949,9 @@ var SportsMarkets = ({
24838
24949
  }, [activeTabKey, displayedSectionMarkets, hasAggKey, onSectionMarketsChange]);
24839
24950
  (0, import_react41.useEffect)(() => {
24840
24951
  var _a2, _b2;
24841
- if (visibleSectionDefinitions.some((definition) => definition.key === activeTabKey)) return;
24842
- setActiveTabKey((_b2 = (_a2 = visibleSectionDefinitions[0]) == null ? void 0 : _a2.key) != null ? _b2 : "game_lines");
24843
- }, [activeTabKey, visibleSectionDefinitions]);
24952
+ if (visibleTabs.some((tab) => tab.key === activeTabKey)) return;
24953
+ setActiveTabKey((_b2 = (_a2 = visibleTabs[0]) == null ? void 0 : _a2.key) != null ? _b2 : "game_lines");
24954
+ }, [activeTabKey, visibleTabs]);
24844
24955
  const lastActiveTabRef = (0, import_react41.useRef)(null);
24845
24956
  (0, import_react41.useEffect)(() => {
24846
24957
  if (allGroups.length === 0) return;
@@ -24887,14 +24998,14 @@ var SportsMarkets = ({
24887
24998
  role: "tablist",
24888
24999
  "aria-label": labels.eventMarketPage.sports.sectionTabsAria,
24889
25000
  className: "flex flex-nowrap items-center gap-2 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
24890
- children: visibleSectionDefinitions.map((definition) => /* @__PURE__ */ (0, import_jsx_runtime162.jsx)(
25001
+ children: visibleTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime162.jsx)(
24891
25002
  SportsTabButton,
24892
25003
  {
24893
- isActive: definition.key === activeTabKey,
24894
- label: resolveSportsSectionLabel(labels, definition.key),
24895
- onClick: () => setActiveTabKey(definition.key)
25004
+ isActive: tab.key === activeTabKey,
25005
+ label: resolveSportsSectionLabel(labels, tab),
25006
+ onClick: () => setActiveTabKey(tab.key)
24896
25007
  },
24897
- definition.key
25008
+ tab.key
24898
25009
  ))
24899
25010
  }
24900
25011
  ) : null,
@@ -24908,7 +25019,7 @@ var SportsMarkets = ({
24908
25019
  classNames: { root: "min-h-[220px]" }
24909
25020
  }
24910
25021
  ) : null,
24911
- displayedPeriodGroups.map((periodGroup) => {
25022
+ periodGroups.map((periodGroup) => {
24912
25023
  return /* @__PURE__ */ (0, import_jsx_runtime162.jsx)(
24913
25024
  "section",
24914
25025
  {
@@ -24965,7 +25076,7 @@ var SportsEventMarketPage = ({
24965
25076
  }, [event, sectionMarketsByKey]);
24966
25077
  const eventTradingState = (0, import_react42.useMemo)(() => (0, import_hooks66.resolveEventTradingState)(composedEvent), [composedEvent]);
24967
25078
  const hasSportsSections = (0, import_react42.useMemo)(
24968
- () => resolveVisibleSportsSectionTabDefinitions(event).length > 0,
25079
+ () => resolveVisibleSportsSectionTabs(event).length > 0,
24969
25080
  [event]
24970
25081
  );
24971
25082
  const stickyOrderPanelState = resolveEventMarketPageStickyState({
package/dist/pages.mjs CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  UserProfilePage,
9
9
  buildAggTxExplorerHref,
10
10
  useHomePageModals
11
- } from "./chunk-AJJ73RM4.mjs";
11
+ } from "./chunk-TQL5I4GX.mjs";
12
12
  import "./chunk-XAG432PJ.mjs";
13
13
  import {
14
14
  DEPOSIT_MODAL_OPEN_EVENT,
@@ -1,12 +1,12 @@
1
1
  import { type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
2
  export declare const sportsSectionMarketsByTab: {
3
3
  game_lines: VenueMarket[];
4
- halves: readonly [VenueMarket, VenueMarket, VenueMarket];
4
+ "period:halves": readonly [VenueMarket, VenueMarket, VenueMarket];
5
5
  exact_score: readonly [VenueMarket];
6
- corners: readonly [VenueMarket, VenueMarket];
7
- goals: VenueMarket[];
8
- assists: readonly [VenueMarket];
9
- shots: readonly [VenueMarket];
6
+ "stat:corners": readonly [VenueMarket, VenueMarket];
7
+ "stat:goals": VenueMarket[];
8
+ "stat:assists": readonly [VenueMarket];
9
+ "stat:shots": readonly [VenueMarket];
10
10
  other: readonly [VenueMarket];
11
11
  };
12
12
  export declare const sportsEventPageFixture: VenueEventWithMarkets;
@@ -1,12 +1,12 @@
1
1
  import { type VenueEventWithMarkets, type VenueMarket } from "@agg-build/hooks";
2
2
  export declare const sportsSectionMarketsByTab: {
3
3
  game_lines: VenueMarket[];
4
- halves: readonly [VenueMarket, VenueMarket, VenueMarket];
4
+ "period:halves": readonly [VenueMarket, VenueMarket, VenueMarket];
5
5
  exact_score: readonly [VenueMarket];
6
- corners: readonly [VenueMarket, VenueMarket];
7
- goals: VenueMarket[];
8
- assists: readonly [VenueMarket];
9
- shots: readonly [VenueMarket];
6
+ "stat:corners": readonly [VenueMarket, VenueMarket];
7
+ "stat:goals": VenueMarket[];
8
+ "stat:assists": readonly [VenueMarket];
9
+ "stat:shots": readonly [VenueMarket];
10
10
  other: readonly [VenueMarket];
11
11
  };
12
12
  export declare const sportsEventPageFixture: VenueEventWithMarkets;