@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/index.js CHANGED
@@ -25718,64 +25718,15 @@ var SPORTS_LEGACY_PROP_CATEGORY_KEY_SET = /* @__PURE__ */ new Set([
25718
25718
  "assists",
25719
25719
  "shots"
25720
25720
  ]);
25721
- var SPORTS_CATEGORY_OVERRIDE_TAB_KEY_SET = /* @__PURE__ */ new Set([
25722
- "exact_score",
25723
- ...SPORTS_LEGACY_PROP_CATEGORY_KEY_SET
25724
- ]);
25725
- var SPORTS_MARKET_GROUP_TO_TAB = {
25726
- game_lines: "game_lines",
25727
- spreads: "game_lines",
25728
- totals: "game_lines",
25729
- period_lines: "halves",
25730
- exact_score: "exact_score",
25731
- team_props: "other",
25732
- player_props: "other",
25733
- specials: "other",
25734
- completion: "other",
25735
- other: "other"
25736
- };
25737
- var SPORTS_SECTION_TAB_DEFINITIONS = [
25738
- {
25739
- key: "game_lines",
25740
- // NO sportsMarketType filter: spread/total markets on some sports (e.g.
25741
- // esports "Map 1 Rounds Handicap"/"Total Rounds") are sportsMarketType="other"
25742
- // with marketGroup=spreads/totals; AND-ing the game-line types would drop them
25743
- // and leave only the moneyline. marketGroup already scopes the tab. (Safe now
25744
- // that classify_market no longer mis-groups prop/to-score-first/extra-innings
25745
- // markets into game_lines/totals — see agg-venue-core market_group.rs.)
25746
- marketGroup: ["game_lines", "spreads", "totals"]
25747
- // No server-side period filter: many regular-time game-line markets arrive
25748
- // with period=null (moneyline sides, team totals, BTTS), and a
25749
- // period=["full"] filter would drop them server-side. The Game Lines tab
25750
- // narrows to the regular-time group client-side instead (see SportsMarkets).
25751
- },
25752
- { key: "exact_score", marketGroup: ["exact_score"] },
25753
- {
25754
- key: "halves",
25755
- // NO sportsMarketType filter: half-result legs ("France leading at halftime?")
25756
- // are sportsMarketType="other"; AND-ing the game-line types would drop them.
25757
- // marketGroup=period_lines + period already scope the tab.
25758
- marketGroup: ["period_lines"],
25759
- period: ["1h", "2h"]
25760
- },
25761
- { key: "corners", marketCategory: "corners" },
25762
- { key: "goals", marketCategory: "goals" },
25763
- { key: "assists", marketCategory: "assists" },
25764
- { key: "shots", marketCategory: "shots" },
25765
- {
25766
- key: "other",
25767
- // `player_props` is deliberately NOT fetched here: goals/assists/shots/corners
25768
- // props already have dedicated tabs (resolveMarketSectionTabKey routes them
25769
- // there by category), so including the group would re-fetch hundreds of props
25770
- // already shown elsewhere. The handful with no stat category (e.g. "saves")
25771
- // are back-filled from the game-wide set in resolveSportsSectionMarkets.
25772
- marketGroup: ["other", "team_props", "specials", "completion"]
25773
- }
25721
+ var SPORTS_GAME_LINE_GROUPS = [
25722
+ "game_lines",
25723
+ "spreads",
25724
+ "totals",
25725
+ "team_props",
25726
+ "specials",
25727
+ "completion"
25774
25728
  ];
25775
- var SPORTS_NON_STANDARD_VISIBLE_TAB_KEYS = ["game_lines", "other"];
25776
- var SPORTS_NON_STANDARD_VISIBLE_TAB_KEY_SET = new Set(
25777
- SPORTS_NON_STANDARD_VISIBLE_TAB_KEYS
25778
- );
25729
+ var SPORTS_GENERIC_STAT = "player_props";
25779
25730
  var ESPORTS_CATEGORY_TOKENS = /* @__PURE__ */ new Set([
25780
25731
  "esports",
25781
25732
  "video games",
@@ -25786,9 +25737,6 @@ var ESPORTS_CATEGORY_TOKENS = /* @__PURE__ */ new Set([
25786
25737
  ]);
25787
25738
  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;
25788
25739
  var SERIES_SCOPE_PATTERN = /\b(?:bo[1-9]|best of \d+|map \d+|game \d+)\b/i;
25789
- var SPORTS_SECTION_TAB_BY_KEY = new Map(
25790
- SPORTS_SECTION_TAB_DEFINITIONS.map((definition) => [definition.key, definition])
25791
- );
25792
25740
  var SPORTS_PERIOD_ORDER = [
25793
25741
  "full",
25794
25742
  "1h",
@@ -25853,12 +25801,13 @@ var getSportsMarketTypeOrderIndex = (sportsMarketType) => {
25853
25801
  const marketTypeIndex = SPORTS_MARKET_TYPE_ORDER.indexOf(sportsMarketType);
25854
25802
  return marketTypeIndex >= 0 ? marketTypeIndex : SPORTS_MARKET_TYPE_ORDER.length;
25855
25803
  };
25856
- var resolveSportsSectionDefinition = (key) => {
25857
- const resolvedDefinition = SPORTS_SECTION_TAB_BY_KEY.get(key);
25858
- if (!resolvedDefinition) {
25859
- return SPORTS_SECTION_TAB_DEFINITIONS[0];
25860
- }
25861
- return resolvedDefinition;
25804
+ var resolveSportsPeriodFamily = (period) => {
25805
+ if (period === "1h" || period === "2h") return "halves";
25806
+ if (period === "q1" || period === "q2" || period === "q3" || period === "q4") return "quarters";
25807
+ if (/^inning_\d{1,2}$/.test(period)) return "innings";
25808
+ if (/^set_\d{1,2}$/.test(period)) return "sets";
25809
+ if (/^(?:map|game)_\d{1,2}$/.test(period)) return "maps";
25810
+ return period;
25862
25811
  };
25863
25812
  var normalizeSportsPeriod = (value) => {
25864
25813
  const resolvedValue = toTrimmedString(value).toLowerCase();
@@ -25903,53 +25852,182 @@ var resolveFallbackSportsMarketCategory = (market) => {
25903
25852
  if (question.includes("goal")) return "goals";
25904
25853
  return null;
25905
25854
  };
25855
+ var resolveSportsStatToken = (market) => {
25856
+ const subtype = toTrimmedString(market.marketSubtype).toLowerCase();
25857
+ const playerMatch = /_player_(.+)$/.exec(subtype);
25858
+ if (playerMatch) return playerMatch[1];
25859
+ const category = normalizeSportsMarketCategory(market.marketCategory);
25860
+ if (category && SPORTS_LEGACY_PROP_CATEGORY_KEY_SET.has(category)) return category;
25861
+ return null;
25862
+ };
25906
25863
  var resolveMarketSectionTabKey = (market) => {
25864
+ var _a;
25907
25865
  if (normalizeSportsMarketType(market.sportsMarketType) === "to_advance") {
25908
25866
  return "game_lines";
25909
25867
  }
25910
25868
  const normalizedCategory = normalizeSportsMarketCategory(market.marketCategory);
25911
25869
  const fallbackCategory = !normalizedCategory || normalizedCategory === "other" ? resolveFallbackSportsMarketCategory(market) : null;
25912
25870
  const category = fallbackCategory != null ? fallbackCategory : normalizedCategory;
25913
- if (category && SPORTS_CATEGORY_OVERRIDE_TAB_KEY_SET.has(category)) {
25914
- return category;
25915
- }
25871
+ if (category && SPORTS_LEGACY_PROP_CATEGORY_KEY_SET.has(category)) return `stat:${category}`;
25872
+ if (category === "exact_score") return "exact_score";
25916
25873
  const group = normalizeSportsMarketGroup(market.marketGroup);
25917
- if (group) return SPORTS_MARKET_GROUP_TO_TAB[group];
25874
+ if (group === "exact_score") return "exact_score";
25875
+ if (group === "player_props") {
25876
+ return `stat:${(_a = resolveSportsStatToken(market)) != null ? _a : SPORTS_GENERIC_STAT}`;
25877
+ }
25878
+ if (group === "period_lines") {
25879
+ return `period:${resolveSportsPeriodFamily(normalizeSportsPeriod(market.period))}`;
25880
+ }
25881
+ if (group === "other") return "other";
25882
+ if (group) return "game_lines";
25918
25883
  if (category === "game_lines") return "game_lines";
25919
25884
  if (category === "other") return "other";
25920
25885
  return null;
25921
25886
  };
25922
- var resolveSportsSectionFilters = (key) => {
25923
- var _a;
25924
- const resolvedDefinition = resolveSportsSectionDefinition(key);
25925
- const useMarketGroup = !!((_a = resolvedDefinition.marketGroup) == null ? void 0 : _a.length);
25887
+ var resolveVisibleSportsSectionTabs = (event) => {
25888
+ var _a, _b, _c;
25889
+ const periodsByFamily = /* @__PURE__ */ new Map();
25890
+ const statVolume = /* @__PURE__ */ new Map();
25891
+ let hasGameLines = false;
25892
+ let hasExactScore = false;
25893
+ let hasOther = false;
25894
+ for (const market of event.venueMarkets) {
25895
+ const key = resolveMarketSectionTabKey(market);
25896
+ if (!key) continue;
25897
+ if (key === "game_lines") hasGameLines = true;
25898
+ else if (key === "exact_score") hasExactScore = true;
25899
+ else if (key === "other") hasOther = true;
25900
+ else if (key.startsWith("period:")) {
25901
+ const family = key.slice("period:".length);
25902
+ const periods = (_a = periodsByFamily.get(family)) != null ? _a : /* @__PURE__ */ new Set();
25903
+ periods.add(normalizeSportsPeriod(market.period));
25904
+ periodsByFamily.set(family, periods);
25905
+ } else if (key.startsWith("stat:")) {
25906
+ const stat = key.slice("stat:".length);
25907
+ statVolume.set(stat, ((_b = statVolume.get(stat)) != null ? _b : 0) + ((_c = market.volume) != null ? _c : 0));
25908
+ }
25909
+ }
25910
+ const tabs = [];
25911
+ if (hasGameLines) tabs.push({ key: "game_lines", kind: "game_lines" });
25912
+ const periodTabs = Array.from(periodsByFamily.entries()).map(([periodFamily, periods]) => ({
25913
+ key: `period:${periodFamily}`,
25914
+ kind: "period",
25915
+ periodFamily,
25916
+ periods: Array.from(periods).sort(
25917
+ (left, right) => getSportsPeriodOrderIndex(left) - getSportsPeriodOrderIndex(right)
25918
+ )
25919
+ })).sort(
25920
+ (left, right) => getSportsPeriodOrderIndex(left.periods[0]) - getSportsPeriodOrderIndex(right.periods[0])
25921
+ );
25922
+ tabs.push(...periodTabs);
25923
+ const statTabs = Array.from(statVolume.entries()).sort((left, right) => {
25924
+ if (left[0] === SPORTS_GENERIC_STAT !== (right[0] === SPORTS_GENERIC_STAT)) {
25925
+ return left[0] === SPORTS_GENERIC_STAT ? 1 : -1;
25926
+ }
25927
+ return right[1] - left[1];
25928
+ }).map(([stat]) => ({ key: `stat:${stat}`, kind: "stat", stat }));
25929
+ tabs.push(...statTabs);
25930
+ if (hasExactScore) tabs.push({ key: "exact_score", kind: "exact_score" });
25931
+ if (hasOther) tabs.push({ key: "other", kind: "other" });
25932
+ if (isNonStandardSportsLikeEvent(event)) {
25933
+ return tabs.filter((tab) => tab.kind === "game_lines" || tab.kind === "other");
25934
+ }
25935
+ return tabs;
25936
+ };
25937
+ var resolveSportsSectionFilters = (tab) => {
25938
+ if (tab.kind === "period") {
25939
+ return {
25940
+ marketGroup: ["period_lines"],
25941
+ marketCategory: void 0,
25942
+ sportsMarketType: void 0,
25943
+ period: tab.periods ? [...tab.periods] : void 0
25944
+ };
25945
+ }
25946
+ if (tab.kind === "stat") {
25947
+ const legacyCategory = SPORTS_LEGACY_PROP_CATEGORY_KEY_SET.has(
25948
+ tab.stat
25949
+ ) ? tab.stat : null;
25950
+ return legacyCategory ? {
25951
+ marketGroup: void 0,
25952
+ marketCategory: [legacyCategory],
25953
+ sportsMarketType: void 0,
25954
+ period: void 0
25955
+ } : {
25956
+ marketGroup: ["player_props"],
25957
+ marketCategory: void 0,
25958
+ sportsMarketType: void 0,
25959
+ period: void 0
25960
+ };
25961
+ }
25962
+ if (tab.kind === "exact_score") {
25963
+ return {
25964
+ marketGroup: ["exact_score"],
25965
+ marketCategory: void 0,
25966
+ sportsMarketType: void 0,
25967
+ period: void 0
25968
+ };
25969
+ }
25970
+ if (tab.kind === "other") {
25971
+ return {
25972
+ marketGroup: ["other"],
25973
+ marketCategory: void 0,
25974
+ sportsMarketType: void 0,
25975
+ period: void 0
25976
+ };
25977
+ }
25926
25978
  return {
25927
- marketGroup: useMarketGroup ? [...resolvedDefinition.marketGroup] : void 0,
25928
- // Only fall back to the deprecated marketCategory filter when the tab has no
25929
- // marketGroup mapping. Sending both would AND them server-side and drop
25930
- // markets that carry only one of the two.
25931
- marketCategory: !useMarketGroup && resolvedDefinition.marketCategory ? [resolvedDefinition.marketCategory] : void 0,
25932
- sportsMarketType: resolvedDefinition.sportsMarketType ? [...resolvedDefinition.sportsMarketType] : void 0,
25933
- period: resolvedDefinition.period ? [...resolvedDefinition.period] : void 0
25979
+ marketGroup: [...SPORTS_GAME_LINE_GROUPS],
25980
+ marketCategory: void 0,
25981
+ sportsMarketType: void 0,
25982
+ period: void 0
25934
25983
  };
25935
25984
  };
25985
+ var hasTeamTitledOutcomes = (market) => {
25986
+ var _a;
25987
+ const titles = ((_a = market.venueMarketOutcomes) != null ? _a : []).map(
25988
+ (outcome) => toTrimmedString(outcome.title)
25989
+ );
25990
+ return titles.length > 1 && titles.every((title2) => title2 && !YES_NO_LABELS.has(title2.toLowerCase())) && new Set(titles).size === titles.length;
25991
+ };
25992
+ var isClusterRelation = (left, right) => {
25993
+ var _a, _b;
25994
+ return ((_a = left.matchedVenueMarkets) != null ? _a : []).some((market) => market.id === right.id) || ((_b = right.matchedVenueMarkets) != null ? _b : []).some((market) => market.id === left.id);
25995
+ };
25996
+ var isDecomposedLeg = (market) => {
25997
+ var _a;
25998
+ const labels = ((_a = market.venueMarketOutcomes) != null ? _a : []).map(
25999
+ (outcome) => toTrimmedString(outcome.label).toLowerCase()
26000
+ );
26001
+ return labels.length === 2 && labels.every((label2) => YES_NO_LABELS.has(label2)) && !hasTeamTitledOutcomes(market);
26002
+ };
26003
+ var dropDecomposedLegsMergedIntoSingle = (markets) => {
26004
+ const legs = markets.filter((market) => isDecomposedLeg(market));
26005
+ if (legs.length === 0) return markets;
26006
+ const hasMergedSingle = markets.some(
26007
+ (market) => {
26008
+ var _a, _b;
26009
+ 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));
26010
+ }
26011
+ );
26012
+ return hasMergedSingle ? markets.filter((market) => !isDecomposedLeg(market)) : markets;
26013
+ };
25936
26014
  var resolveSportsSectionMarkets = ({
25937
- tabKey,
26015
+ tab,
25938
26016
  eventMarkets,
25939
26017
  sectionMarkets
25940
26018
  }) => {
25941
- const effectiveSectionMarkets = sectionMarkets.length > 0 ? sectionMarkets : eventMarkets.filter((market) => resolveMarketSectionTabKey(market) === tabKey);
26019
+ const effectiveSectionMarkets = sectionMarkets.length > 0 ? sectionMarkets : eventMarkets.filter((market) => resolveMarketSectionTabKey(market) === tab.key);
25942
26020
  const filteredSectionMarkets = effectiveSectionMarkets.filter(
25943
- (market) => resolveMarketSectionTabKey(market) === tabKey
26021
+ (market) => resolveMarketSectionTabKey(market) === tab.key
25944
26022
  );
25945
- if (tabKey === "other") {
26023
+ if (tab.key === "other" || tab.key === `stat:${SPORTS_GENERIC_STAT}`) {
25946
26024
  const seenIds = new Set(filteredSectionMarkets.map((market) => market.id));
25947
- const strayOtherMarkets = eventMarkets.filter(
25948
- (market) => !seenIds.has(market.id) && resolveMarketSectionTabKey(market) === "other"
26025
+ const strayMarkets = eventMarkets.filter(
26026
+ (market) => !seenIds.has(market.id) && resolveMarketSectionTabKey(market) === tab.key
25949
26027
  );
25950
- return [...filteredSectionMarkets, ...strayOtherMarkets];
26028
+ return [...filteredSectionMarkets, ...strayMarkets];
25951
26029
  }
25952
- if (tabKey !== "game_lines") return filteredSectionMarkets;
26030
+ if (tab.kind !== "game_lines") return filteredSectionMarkets;
25953
26031
  const dedupeEventMarketsOfType = (type) => {
25954
26032
  const dedupedMarkets = [];
25955
26033
  const seenKeys = /* @__PURE__ */ new Set();
@@ -25962,7 +26040,7 @@ var resolveSportsSectionMarkets = ({
25962
26040
  seenKeys.add(key);
25963
26041
  dedupedMarkets.push(market);
25964
26042
  }
25965
- return dedupedMarkets;
26043
+ return dropDecomposedLegsMergedIntoSingle(dedupedMarkets);
25966
26044
  };
25967
26045
  const eventMoneylineMarkets = dedupeEventMarketsOfType("moneyline");
25968
26046
  const eventToAdvanceMarkets = dedupeEventMarketsOfType("to_advance");
@@ -26049,7 +26127,9 @@ var resolveSpreadOutcomeTeamNames = (activeMarket, groupMarkets) => {
26049
26127
  return toTrimmedString((_b = (_a = market.venueMarketOutcomes) == null ? void 0 : _a[index]) == null ? void 0 : _b.title);
26050
26128
  }).filter((title2) => isSpreadTeamTitle(title2));
26051
26129
  if (cleanTitles.length === 0) return null;
26052
- return cleanTitles.reduce((longest, title2) => title2.length > longest.length ? title2 : longest);
26130
+ return cleanTitles.reduce(
26131
+ (longest, title2) => title2.length > longest.length ? title2 : longest
26132
+ );
26053
26133
  };
26054
26134
  return { favored: pickName(0), dog: pickName(1) };
26055
26135
  };
@@ -26058,9 +26138,7 @@ var resolveCombinedMoneylineLegLabel = (market) => {
26058
26138
  return toTrimmedString(typedMarket.shortTitle) || toTrimmedString(market.question);
26059
26139
  };
26060
26140
  var areCombinedMoneylineLegsDistinct = (markets) => {
26061
- const labels = markets.map(
26062
- (market) => resolveCombinedMoneylineLegLabel(market).toLowerCase()
26063
- );
26141
+ const labels = markets.map((market) => resolveCombinedMoneylineLegLabel(market).toLowerCase());
26064
26142
  return labels.every((label2) => label2.length > 0) && new Set(labels).size === labels.length;
26065
26143
  };
26066
26144
  var resolveDisplayGroupFamilyKey = (market) => {
@@ -26345,6 +26423,15 @@ var buildSportsSlideFromGroup = (group) => {
26345
26423
  defaultStopIndex
26346
26424
  };
26347
26425
  };
26426
+ var formatSportsPeriodGrammarLabel = (period) => {
26427
+ const grammarMatch = SPORTS_PERIOD_GRAMMAR_PATTERN.exec(period);
26428
+ if (!grammarMatch) return null;
26429
+ if (grammarMatch[1]) {
26430
+ const family = grammarMatch[1].charAt(0).toUpperCase() + grammarMatch[1].slice(1);
26431
+ return `${family} ${Number(grammarMatch[2])}`;
26432
+ }
26433
+ return `First ${Number(grammarMatch[3])} Innings`;
26434
+ };
26348
26435
  var resolveSportsCategoryTokens = (event) => {
26349
26436
  return new Set(
26350
26437
  event.categories.flatMap((entry) => {
@@ -26367,39 +26454,20 @@ var isNonStandardSportsLikeEvent = (event) => {
26367
26454
  return ESPORTS_TITLE_PATTERN.test(question) || SERIES_SCOPE_PATTERN.test(question);
26368
26455
  });
26369
26456
  };
26370
- var resolveVisibleSportsSectionTabDefinitions = (event) => {
26371
- const presentTabKeys = /* @__PURE__ */ new Set();
26372
- for (const market of event.venueMarkets) {
26373
- const tabKey = resolveMarketSectionTabKey(market);
26374
- if (tabKey) presentTabKeys.add(tabKey);
26375
- }
26376
- let definitions = SPORTS_SECTION_TAB_DEFINITIONS.filter(
26377
- (definition) => presentTabKeys.has(definition.key)
26378
- );
26379
- if (isNonStandardSportsLikeEvent(event)) {
26380
- definitions = definitions.filter(
26381
- (definition) => SPORTS_NON_STANDARD_VISIBLE_TAB_KEY_SET.has(definition.key)
26382
- );
26383
- }
26384
- return definitions;
26385
- };
26386
26457
  var mergeSportsSectionMarketsIntoEvent = ({
26387
26458
  event,
26388
26459
  sectionMarketsByKey
26389
26460
  }) => {
26390
- var _a;
26391
26461
  const orderedVenueMarkets = [...event.venueMarkets];
26392
26462
  const seenMarketIds = new Set(orderedVenueMarkets.map((market) => market.id));
26393
- for (const sectionKey of SPORTS_SECTION_TAB_DEFINITIONS.map((definition) => definition.key)) {
26394
- for (const market of (_a = sectionMarketsByKey[sectionKey]) != null ? _a : []) {
26463
+ for (const markets of Object.values(sectionMarketsByKey)) {
26464
+ for (const market of markets != null ? markets : []) {
26395
26465
  if (seenMarketIds.has(market.id)) continue;
26396
26466
  seenMarketIds.add(market.id);
26397
26467
  orderedVenueMarkets.push(market);
26398
26468
  }
26399
26469
  }
26400
- return __spreadProps(__spreadValues({}, event), {
26401
- venueMarkets: orderedVenueMarkets
26402
- });
26470
+ return __spreadProps(__spreadValues({}, event), { venueMarkets: orderedVenueMarkets });
26403
26471
  };
26404
26472
 
26405
26473
  // src/pages/event-market/sports-market-card.tsx
@@ -26650,6 +26718,15 @@ function SportsLineRail({
26650
26718
 
26651
26719
  // src/pages/event-market/sports-market-card.tsx
26652
26720
  var import_jsx_runtime169 = require("react/jsx-runtime");
26721
+ var resolveSportsLineOutcomeSide = (outcome) => {
26722
+ var _a;
26723
+ for (const candidate of [outcome.label, outcome.title]) {
26724
+ if (typeof candidate !== "string") continue;
26725
+ const matchedSide = (_a = candidate.trim().toLowerCase().match(/(?:^|\s)(over|under)(?=\s|$)/)) == null ? void 0 : _a[1];
26726
+ if (matchedSide === "over" || matchedSide === "under") return matchedSide;
26727
+ }
26728
+ return null;
26729
+ };
26653
26730
  var SportsMarketCard = ({
26654
26731
  group,
26655
26732
  venueMarkets,
@@ -26812,16 +26889,22 @@ var SportsMarketCard = ({
26812
26889
  setSelectedLineIndex(index);
26813
26890
  const market = (_a2 = slide.stops[index]) == null ? void 0 : _a2.market;
26814
26891
  if (!market) return;
26815
- const isGroupBeingTraded = group.markets.some(
26816
- (groupMarket) => groupMarket.id === (tradingContext == null ? void 0 : tradingContext.selectedMarketId)
26817
- );
26818
- if (!isGroupBeingTraded) return;
26819
26892
  const previousOutcomeIndex = previousMarket ? previousMarket.venueMarketOutcomes.findIndex(
26820
26893
  (outcome) => outcome.id === (tradingContext == null ? void 0 : tradingContext.selectedOutcomeId)
26821
26894
  ) : -1;
26822
- const nextOutcome = (_b2 = previousOutcomeIndex >= 0 ? market.venueMarketOutcomes[previousOutcomeIndex] : void 0) != null ? _b2 : market.venueMarketOutcomes[0];
26895
+ const previousOutcome = previousOutcomeIndex >= 0 ? previousMarket == null ? void 0 : previousMarket.venueMarketOutcomes[previousOutcomeIndex] : void 0;
26896
+ const previousOutcomeSide = previousOutcome ? resolveSportsLineOutcomeSide(previousOutcome) : null;
26897
+ const matchingSideOutcomes = previousOutcomeSide ? market.venueMarketOutcomes.filter(
26898
+ (outcome) => resolveSportsLineOutcomeSide(outcome) === previousOutcomeSide
26899
+ ) : [];
26900
+ const matchingSideOutcome = matchingSideOutcomes.length === 1 ? matchingSideOutcomes[0] : void 0;
26901
+ const nextOutcome = (_b2 = matchingSideOutcome != null ? matchingSideOutcome : previousOutcomeIndex >= 0 ? market.venueMarketOutcomes[previousOutcomeIndex] : void 0) != null ? _b2 : market.venueMarketOutcomes[0];
26823
26902
  if (nextOutcome) {
26824
26903
  tradingContext == null ? void 0 : tradingContext.selectMarketAndOutcome(market.id, nextOutcome.id);
26904
+ onOutcomeSelect == null ? void 0 : onOutcomeSelect(group.id, {
26905
+ marketId: market.id,
26906
+ outcomeId: nextOutcome.id
26907
+ });
26825
26908
  } else {
26826
26909
  tradingContext == null ? void 0 : tradingContext.selectMarket(market.id, market);
26827
26910
  }
@@ -26867,24 +26950,48 @@ SportsMarketCard.displayName = "SportsMarketCard";
26867
26950
 
26868
26951
  // src/pages/event-market/sports-markets.tsx
26869
26952
  var import_jsx_runtime170 = require("react/jsx-runtime");
26870
- var resolveSportsSectionLabel = (labels, key) => {
26871
- switch (key) {
26953
+ var STAT_LABEL_OVERRIDES = {
26954
+ rbis: "RBIs",
26955
+ hits_runs_rbis: "Hits + Runs + RBIs",
26956
+ ot: "OT"
26957
+ };
26958
+ var formatStatLabel = (stat) => {
26959
+ var _a;
26960
+ return (_a = STAT_LABEL_OVERRIDES[stat]) != null ? _a : stat.split("_").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
26961
+ };
26962
+ var LEGACY_STAT_LABEL_KEYS = {
26963
+ corners: "cornersTab",
26964
+ goals: "goalsTab",
26965
+ assists: "assistsTab",
26966
+ shots: "shotsTab"
26967
+ };
26968
+ var resolveSportsSectionLabel = (labels, tab) => {
26969
+ var _a, _b, _c, _d, _e;
26970
+ const sports = labels.eventMarketPage.sports;
26971
+ switch (tab.kind) {
26872
26972
  case "game_lines":
26873
- return labels.eventMarketPage.sports.gameLinesTab;
26874
- case "halves":
26875
- return labels.eventMarketPage.sports.halvesTab;
26973
+ return sports.gameLinesTab;
26876
26974
  case "exact_score":
26877
- return labels.eventMarketPage.sports.exactScoreTab;
26878
- case "corners":
26879
- return labels.eventMarketPage.sports.cornersTab;
26880
- case "goals":
26881
- return labels.eventMarketPage.sports.goalsTab;
26882
- case "assists":
26883
- return labels.eventMarketPage.sports.assistsTab;
26884
- case "shots":
26885
- return labels.eventMarketPage.sports.shotsTab;
26975
+ return sports.exactScoreTab;
26886
26976
  case "other":
26887
- return labels.eventMarketPage.sports.otherTab;
26977
+ return sports.otherTab;
26978
+ case "stat": {
26979
+ if (tab.stat === "player_props") return sports.playerPropsTab;
26980
+ const legacyLabelKey = tab.stat ? LEGACY_STAT_LABEL_KEYS[tab.stat] : void 0;
26981
+ return legacyLabelKey ? sports[legacyLabelKey] : formatStatLabel((_a = tab.stat) != null ? _a : "");
26982
+ }
26983
+ case "period": {
26984
+ switch (tab.periodFamily) {
26985
+ case "halves":
26986
+ return sports.halvesTab;
26987
+ case "quarters":
26988
+ return sports.quartersTab;
26989
+ case "sets":
26990
+ return sports.setsTab;
26991
+ default:
26992
+ return (_e = (_c = formatSportsPeriodGrammarLabel((_b = tab.periodFamily) != null ? _b : "")) == null ? void 0 : _c.replace(/^First /, "")) != null ? _e : formatStatLabel((_d = tab.periodFamily) != null ? _d : "");
26993
+ }
26994
+ }
26888
26995
  }
26889
26996
  };
26890
26997
  var SportsTabButton = ({
@@ -26972,18 +27079,23 @@ var SportsMarkets = ({
26972
27079
  }
26973
27080
  return merged;
26974
27081
  }, [event.venueMarkets, gameMarkets]);
26975
- const visibleSectionDefinitions = (0, import_react44.useMemo)(
26976
- () => resolveVisibleSportsSectionTabDefinitions(__spreadProps(__spreadValues({}, event), { venueMarkets: tabSourceMarkets })),
27082
+ const visibleTabs = (0, import_react44.useMemo)(
27083
+ () => resolveVisibleSportsSectionTabs(__spreadProps(__spreadValues({}, event), { venueMarkets: tabSourceMarkets })),
26977
27084
  [event, tabSourceMarkets]
26978
27085
  );
26979
- const shouldRenderTabs = visibleSectionDefinitions.length > 1 && tabSourceMarkets.length > 1;
26980
- const [activeTabKey, setActiveTabKey] = (0, import_react44.useState)(
26981
- (_b = (_a = visibleSectionDefinitions[0]) == null ? void 0 : _a.key) != null ? _b : "game_lines"
27086
+ const shouldRenderTabs = visibleTabs.length > 1 && tabSourceMarkets.length > 1;
27087
+ const [activeTabKey, setActiveTabKey] = (0, import_react44.useState)((_b = (_a = visibleTabs[0]) == null ? void 0 : _a.key) != null ? _b : "game_lines");
27088
+ const activeTab = (0, import_react44.useMemo)(
27089
+ () => {
27090
+ var _a2, _b2;
27091
+ return (_b2 = (_a2 = visibleTabs.find((tab) => tab.key === activeTabKey)) != null ? _a2 : visibleTabs[0]) != null ? _b2 : { key: "game_lines", kind: "game_lines" };
27092
+ },
27093
+ [visibleTabs, activeTabKey]
26982
27094
  );
26983
27095
  const [expandedGroupId, setExpandedGroupId] = (0, import_react44.useState)(null);
26984
27096
  const [stableMarketsByTab, setStableMarketsByTab] = (0, import_react44.useState)({});
26985
- const activeTabLabel = resolveSportsSectionLabel(labels, activeTabKey);
26986
- const sectionFilters = resolveSportsSectionFilters(activeTabKey);
27097
+ const activeTabLabel = resolveSportsSectionLabel(labels, activeTab);
27098
+ const sectionFilters = resolveSportsSectionFilters(activeTab);
26987
27099
  const sectionMarketsQuery = (0, import_hooks68.useVenueMarkets)({
26988
27100
  aggKey: event.aggKey ? [event.aggKey] : void 0,
26989
27101
  sportsMarketType: sectionFilters.sportsMarketType,
@@ -27006,26 +27118,25 @@ var SportsMarkets = ({
27006
27118
  } = sectionMarketsQuery;
27007
27119
  const resolvedSectionMarkets = (0, import_react44.useMemo)(
27008
27120
  () => resolveSportsSectionMarkets({
27009
- tabKey: activeTabKey,
27121
+ tab: activeTab,
27010
27122
  eventMarkets: tabSourceMarkets,
27011
27123
  sectionMarkets
27012
27124
  }),
27013
- [activeTabKey, tabSourceMarkets, sectionMarkets]
27125
+ [activeTab, tabSourceMarkets, sectionMarkets]
27014
27126
  );
27015
27127
  const isSectionSettled = !isSectionLoading && !hasNextPage && !isFetchingNextPage;
27016
27128
  const stableSectionMarkets = stableMarketsByTab[activeTabKey];
27017
- const displayedSectionMarkets = stableSectionMarkets != null ? stableSectionMarkets : isSectionSettled ? resolvedSectionMarkets : [];
27129
+ const displayedSectionMarkets = (0, import_react44.useMemo)(
27130
+ () => stableSectionMarkets != null ? stableSectionMarkets : isSectionSettled ? resolvedSectionMarkets : [],
27131
+ [stableSectionMarkets, isSectionSettled, resolvedSectionMarkets]
27132
+ );
27018
27133
  const periodGroups = (0, import_react44.useMemo)(
27019
27134
  () => groupSportsMarketsByPeriod(displayedSectionMarkets),
27020
27135
  [displayedSectionMarkets]
27021
27136
  );
27022
- const displayedPeriodGroups = (0, import_react44.useMemo)(
27023
- () => activeTabKey === "game_lines" ? periodGroups.filter((periodGroup) => periodGroup.key === "full") : periodGroups,
27024
- [activeTabKey, periodGroups]
27025
- );
27026
27137
  const allGroups = (0, import_react44.useMemo)(
27027
- () => displayedPeriodGroups.flatMap((periodGroup) => periodGroup.groups),
27028
- [displayedPeriodGroups]
27138
+ () => periodGroups.flatMap((periodGroup) => periodGroup.groups),
27139
+ [periodGroups]
27029
27140
  );
27030
27141
  (0, import_react44.useEffect)(() => {
27031
27142
  if (hasNextPage && !isFetchingNextPage) {
@@ -27059,9 +27170,9 @@ var SportsMarkets = ({
27059
27170
  }, [activeTabKey, displayedSectionMarkets, hasAggKey, onSectionMarketsChange]);
27060
27171
  (0, import_react44.useEffect)(() => {
27061
27172
  var _a2, _b2;
27062
- if (visibleSectionDefinitions.some((definition) => definition.key === activeTabKey)) return;
27063
- setActiveTabKey((_b2 = (_a2 = visibleSectionDefinitions[0]) == null ? void 0 : _a2.key) != null ? _b2 : "game_lines");
27064
- }, [activeTabKey, visibleSectionDefinitions]);
27173
+ if (visibleTabs.some((tab) => tab.key === activeTabKey)) return;
27174
+ setActiveTabKey((_b2 = (_a2 = visibleTabs[0]) == null ? void 0 : _a2.key) != null ? _b2 : "game_lines");
27175
+ }, [activeTabKey, visibleTabs]);
27065
27176
  const lastActiveTabRef = (0, import_react44.useRef)(null);
27066
27177
  (0, import_react44.useEffect)(() => {
27067
27178
  if (allGroups.length === 0) return;
@@ -27108,14 +27219,14 @@ var SportsMarkets = ({
27108
27219
  role: "tablist",
27109
27220
  "aria-label": labels.eventMarketPage.sports.sectionTabsAria,
27110
27221
  className: "flex flex-nowrap items-center gap-2 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
27111
- children: visibleSectionDefinitions.map((definition) => /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(
27222
+ children: visibleTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(
27112
27223
  SportsTabButton,
27113
27224
  {
27114
- isActive: definition.key === activeTabKey,
27115
- label: resolveSportsSectionLabel(labels, definition.key),
27116
- onClick: () => setActiveTabKey(definition.key)
27225
+ isActive: tab.key === activeTabKey,
27226
+ label: resolveSportsSectionLabel(labels, tab),
27227
+ onClick: () => setActiveTabKey(tab.key)
27117
27228
  },
27118
- definition.key
27229
+ tab.key
27119
27230
  ))
27120
27231
  }
27121
27232
  ) : null,
@@ -27129,7 +27240,7 @@ var SportsMarkets = ({
27129
27240
  classNames: { root: "min-h-[220px]" }
27130
27241
  }
27131
27242
  ) : null,
27132
- displayedPeriodGroups.map((periodGroup) => {
27243
+ periodGroups.map((periodGroup) => {
27133
27244
  return /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(
27134
27245
  "section",
27135
27246
  {
@@ -27186,7 +27297,7 @@ var SportsEventMarketPage = ({
27186
27297
  }, [event, sectionMarketsByKey]);
27187
27298
  const eventTradingState = (0, import_react45.useMemo)(() => (0, import_hooks69.resolveEventTradingState)(composedEvent), [composedEvent]);
27188
27299
  const hasSportsSections = (0, import_react45.useMemo)(
27189
- () => resolveVisibleSportsSectionTabDefinitions(event).length > 0,
27300
+ () => resolveVisibleSportsSectionTabs(event).length > 0,
27190
27301
  [event]
27191
27302
  );
27192
27303
  const stickyOrderPanelState = resolveEventMarketPageStickyState({
package/dist/index.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  UserProfilePage,
12
12
  buildAggTxExplorerHref,
13
13
  useHomePageModals
14
- } from "./chunk-AJJ73RM4.mjs";
14
+ } from "./chunk-TQL5I4GX.mjs";
15
15
  import {
16
16
  EventList,
17
17
  EventListItem,