@agg-build/ui 2.4.0 → 2.4.2

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.
@@ -385,6 +385,7 @@ import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useSta
385
385
 
386
386
  // src/pages/event-market/sports-event-market.utils.ts
387
387
  var SPORTS_MARKET_TYPE_KEYS = [
388
+ "to_advance",
388
389
  "moneyline",
389
390
  "spread",
390
391
  "total",
@@ -526,6 +527,7 @@ var SPORTS_PERIOD_ORDER = [
526
527
  "other"
527
528
  ];
528
529
  var SPORTS_MARKET_TYPE_ORDER = [
530
+ "to_advance",
529
531
  "moneyline",
530
532
  "spread",
531
533
  "total",
@@ -624,6 +626,9 @@ var resolveFallbackSportsMarketCategory = (market) => {
624
626
  return null;
625
627
  };
626
628
  var resolveMarketSectionTabKey = (market) => {
629
+ if (normalizeSportsMarketType(market.sportsMarketType) === "to_advance") {
630
+ return "game_lines";
631
+ }
627
632
  const normalizedCategory = normalizeSportsMarketCategory(market.marketCategory);
628
633
  const fallbackCategory = !normalizedCategory || normalizedCategory === "other" ? resolveFallbackSportsMarketCategory(market) : null;
629
634
  const category = fallbackCategory != null ? fallbackCategory : normalizedCategory;
@@ -667,25 +672,32 @@ var resolveSportsSectionMarkets = ({
667
672
  return [...filteredSectionMarkets, ...strayOtherMarkets];
668
673
  }
669
674
  if (tabKey !== "game_lines") return filteredSectionMarkets;
670
- const eventMoneylineMarkets = (() => {
675
+ const dedupeEventMarketsOfType = (type) => {
671
676
  const dedupedMarkets = [];
672
- const seenMoneylineKeys = /* @__PURE__ */ new Set();
677
+ const seenKeys = /* @__PURE__ */ new Set();
673
678
  for (const market of eventMarkets) {
674
- if (normalizeSportsMarketType(market.sportsMarketType) !== "moneyline" || resolveMarketSectionTabKey(market) !== "game_lines") {
679
+ if (normalizeSportsMarketType(market.sportsMarketType) !== type || resolveMarketSectionTabKey(market) !== "game_lines") {
675
680
  continue;
676
681
  }
677
- const moneylineKey = resolveSportsMarketAggKey(market) || market.id;
678
- if (seenMoneylineKeys.has(moneylineKey)) continue;
679
- seenMoneylineKeys.add(moneylineKey);
682
+ const key = resolveSportsMarketAggKey(market) || market.id;
683
+ if (seenKeys.has(key)) continue;
684
+ seenKeys.add(key);
680
685
  dedupedMarkets.push(market);
681
686
  }
682
687
  return dedupedMarkets;
683
- })();
684
- if (eventMoneylineMarkets.length === 0) return filteredSectionMarkets;
685
- const lineSectionMarkets = filteredSectionMarkets.filter(
688
+ };
689
+ const eventMoneylineMarkets = dedupeEventMarketsOfType("moneyline");
690
+ const eventToAdvanceMarkets = dedupeEventMarketsOfType("to_advance");
691
+ const sectionWithoutAdvance = filteredSectionMarkets.filter(
692
+ (market) => normalizeSportsMarketType(market.sportsMarketType) !== "to_advance"
693
+ );
694
+ if (eventMoneylineMarkets.length === 0) {
695
+ return [...eventToAdvanceMarkets, ...sectionWithoutAdvance];
696
+ }
697
+ const lineSectionMarkets = sectionWithoutAdvance.filter(
686
698
  (market) => normalizeSportsMarketType(market.sportsMarketType) !== "moneyline" && resolveMarketSectionTabKey(market) === "game_lines"
687
699
  );
688
- return [...eventMoneylineMarkets, ...lineSectionMarkets];
700
+ return [...eventToAdvanceMarkets, ...eventMoneylineMarkets, ...lineSectionMarkets];
689
701
  };
690
702
  var resolveSportsMarketCardVariant = (market) => {
691
703
  var _a;
@@ -763,6 +775,16 @@ var resolveSpreadOutcomeTeamNames = (activeMarket, groupMarkets) => {
763
775
  };
764
776
  return { favored: pickName(0), dog: pickName(1) };
765
777
  };
778
+ var resolveCombinedMoneylineLegLabel = (market) => {
779
+ const typedMarket = market;
780
+ return toTrimmedString(typedMarket.shortTitle) || toTrimmedString(market.question);
781
+ };
782
+ var areCombinedMoneylineLegsDistinct = (markets) => {
783
+ const labels = markets.map(
784
+ (market) => resolveCombinedMoneylineLegLabel(market).toLowerCase()
785
+ );
786
+ return labels.every((label) => label.length > 0) && new Set(labels).size === labels.length;
787
+ };
766
788
  var resolveDisplayGroupFamilyKey = (market) => {
767
789
  var _a, _b, _c;
768
790
  const normalizedQuestion = sanitizeFamilyValue(toTrimmedString(market.question));
@@ -775,6 +797,9 @@ var resolveDisplayGroupFamilyKey = (market) => {
775
797
  if (isBinarySportsMoneylineMarket(market)) {
776
798
  return `${period}|moneyline|${marketCategory}`;
777
799
  }
800
+ if (sportsMarketType === "to_advance") {
801
+ return `${period}|to_advance`;
802
+ }
778
803
  const lineFamily = resolveSportsLineFamilyKey(market);
779
804
  if (sportsMarketType === "spread") {
780
805
  const spreadFamily = resolveSpreadFamilyKey(market);
@@ -810,6 +835,7 @@ var resolveDisplayGroupTitle = (market, groupMarkets = [market]) => {
810
835
  const sportsMarketType = normalizeSportsMarketType(market.sportsMarketType);
811
836
  const question = toTrimmedString(market.question);
812
837
  if (isBinarySportsMoneylineMarket(market)) return "Moneyline";
838
+ if (sportsMarketType === "to_advance") return "Team to Advance";
813
839
  if (sportsMarketType === "spread") return "Spreads";
814
840
  if (!question) {
815
841
  return sportsMarketType != null ? sportsMarketType : market.id;
@@ -852,7 +878,16 @@ var buildSportsMarketDisplayGroups = (markets) => {
852
878
  }
853
879
  const groups = Array.from(groupsByKey.entries()).map(([id, groupMarkets]) => {
854
880
  var _a2;
855
- const orderedMarkets = sortMarketsByLineValue(groupMarkets);
881
+ const isToAdvanceGroup = groupMarkets.some(
882
+ (market) => normalizeSportsMarketType(market.sportsMarketType) === "to_advance"
883
+ );
884
+ const orderedMarkets = isToAdvanceGroup ? [...groupMarkets].sort((left, right) => {
885
+ var _a3, _b;
886
+ const leftSingle = resolveSportsMarketAggKey(left).endsWith("_adv") ? 0 : 1;
887
+ const rightSingle = resolveSportsMarketAggKey(right).endsWith("_adv") ? 0 : 1;
888
+ if (leftSingle !== rightSingle) return leftSingle - rightSingle;
889
+ return ((_a3 = right.volume) != null ? _a3 : 0) - ((_b = left.volume) != null ? _b : 0);
890
+ }) : sortMarketsByLineValue(groupMarkets);
856
891
  const firstMarket = orderedMarkets[0];
857
892
  const sportsMarketType = normalizeSportsMarketType(firstMarket == null ? void 0 : firstMarket.sportsMarketType);
858
893
  const marketCategory = normalizeSportsMarketCategory(firstMarket == null ? void 0 : firstMarket.marketCategory);
@@ -960,6 +995,7 @@ var resolveHighestVolumeIndex = (markets) => {
960
995
  return bestIndex;
961
996
  };
962
997
  var resolveSlideKind = (group) => {
998
+ if (group.sportsMarketType === "to_advance") return "to_advance";
963
999
  if (group.sportsMarketType === "moneyline") return "moneyline";
964
1000
  if (group.sportsMarketType === "spread") return "spread";
965
1001
  if (group.sportsMarketType === "total") return "total";
@@ -1365,7 +1401,10 @@ var SportsMarketCard = ({
1365
1401
  () => group.markets.filter((market) => isBinarySportsMoneylineMarket(market)),
1366
1402
  [group.markets]
1367
1403
  );
1368
- const isCombinedMoneylineGroup = group.sportsMarketType === "moneyline" && combinedMoneylineMarkets.length > 1 && combinedMoneylineMarkets.length === group.markets.length;
1404
+ const isCombinedMoneylineGroup = group.sportsMarketType === "moneyline" && combinedMoneylineMarkets.length > 1 && combinedMoneylineMarkets.length === group.markets.length && // Per-leg pills need distinct labels — unmerged cross-venue duplicates of
1405
+ // one 2-way single ("Match Winner" ×2) would render the same Yes price
1406
+ // twice as two options; fall back to the standard team-pill card instead.
1407
+ areCombinedMoneylineLegsDistinct(combinedMoneylineMarkets);
1369
1408
  const preferredResolvedMoneylineMarket = useMemo(() => {
1370
1409
  var _a2, _b2;
1371
1410
  if (!isCombinedMoneylineGroup) return null;
@@ -1429,18 +1468,17 @@ var SportsMarketCard = ({
1429
1468
  const combinedMoneylineHeaderOutcomeItems = useMemo(() => {
1430
1469
  if (!isCombinedMoneylineGroup) return void 0;
1431
1470
  return combinedMoneylineMarkets.flatMap((market, index) => {
1432
- var _a2, _b2;
1433
- const typedMarket = market;
1471
+ var _a2;
1434
1472
  const yesOutcome = market.venueMarketOutcomes.find(
1435
1473
  (outcome) => outcome.label.trim().toLowerCase() === "yes"
1436
1474
  );
1437
1475
  if (!yesOutcome) return [];
1438
- const label = ((_a2 = typedMarket.shortTitle) == null ? void 0 : _a2.trim()) || market.question.trim();
1476
+ const label = resolveCombinedMoneylineLegLabel(market);
1439
1477
  if (!label) return [];
1440
1478
  const probability = midpointsResult == null ? void 0 : getDisplayOutcomePrice({
1441
1479
  outcomeId: yesOutcome.id,
1442
1480
  outcomeLabel: yesOutcome.label,
1443
- bestMidpointsByOutcomeId: (_b2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _b2 : midpointsResult.prices
1481
+ bestMidpointsByOutcomeId: (_a2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _a2 : midpointsResult.prices
1444
1482
  });
1445
1483
  return [
1446
1484
  {
package/dist/index.js CHANGED
@@ -23201,6 +23201,7 @@ var import_react40 = require("react");
23201
23201
 
23202
23202
  // src/pages/event-market/sports-event-market.utils.ts
23203
23203
  var SPORTS_MARKET_TYPE_KEYS = [
23204
+ "to_advance",
23204
23205
  "moneyline",
23205
23206
  "spread",
23206
23207
  "total",
@@ -23342,6 +23343,7 @@ var SPORTS_PERIOD_ORDER = [
23342
23343
  "other"
23343
23344
  ];
23344
23345
  var SPORTS_MARKET_TYPE_ORDER = [
23346
+ "to_advance",
23345
23347
  "moneyline",
23346
23348
  "spread",
23347
23349
  "total",
@@ -23440,6 +23442,9 @@ var resolveFallbackSportsMarketCategory = (market) => {
23440
23442
  return null;
23441
23443
  };
23442
23444
  var resolveMarketSectionTabKey = (market) => {
23445
+ if (normalizeSportsMarketType(market.sportsMarketType) === "to_advance") {
23446
+ return "game_lines";
23447
+ }
23443
23448
  const normalizedCategory = normalizeSportsMarketCategory(market.marketCategory);
23444
23449
  const fallbackCategory = !normalizedCategory || normalizedCategory === "other" ? resolveFallbackSportsMarketCategory(market) : null;
23445
23450
  const category = fallbackCategory != null ? fallbackCategory : normalizedCategory;
@@ -23483,25 +23488,32 @@ var resolveSportsSectionMarkets = ({
23483
23488
  return [...filteredSectionMarkets, ...strayOtherMarkets];
23484
23489
  }
23485
23490
  if (tabKey !== "game_lines") return filteredSectionMarkets;
23486
- const eventMoneylineMarkets = (() => {
23491
+ const dedupeEventMarketsOfType = (type) => {
23487
23492
  const dedupedMarkets = [];
23488
- const seenMoneylineKeys = /* @__PURE__ */ new Set();
23493
+ const seenKeys = /* @__PURE__ */ new Set();
23489
23494
  for (const market of eventMarkets) {
23490
- if (normalizeSportsMarketType(market.sportsMarketType) !== "moneyline" || resolveMarketSectionTabKey(market) !== "game_lines") {
23495
+ if (normalizeSportsMarketType(market.sportsMarketType) !== type || resolveMarketSectionTabKey(market) !== "game_lines") {
23491
23496
  continue;
23492
23497
  }
23493
- const moneylineKey = resolveSportsMarketAggKey(market) || market.id;
23494
- if (seenMoneylineKeys.has(moneylineKey)) continue;
23495
- seenMoneylineKeys.add(moneylineKey);
23498
+ const key = resolveSportsMarketAggKey(market) || market.id;
23499
+ if (seenKeys.has(key)) continue;
23500
+ seenKeys.add(key);
23496
23501
  dedupedMarkets.push(market);
23497
23502
  }
23498
23503
  return dedupedMarkets;
23499
- })();
23500
- if (eventMoneylineMarkets.length === 0) return filteredSectionMarkets;
23501
- const lineSectionMarkets = filteredSectionMarkets.filter(
23504
+ };
23505
+ const eventMoneylineMarkets = dedupeEventMarketsOfType("moneyline");
23506
+ const eventToAdvanceMarkets = dedupeEventMarketsOfType("to_advance");
23507
+ const sectionWithoutAdvance = filteredSectionMarkets.filter(
23508
+ (market) => normalizeSportsMarketType(market.sportsMarketType) !== "to_advance"
23509
+ );
23510
+ if (eventMoneylineMarkets.length === 0) {
23511
+ return [...eventToAdvanceMarkets, ...sectionWithoutAdvance];
23512
+ }
23513
+ const lineSectionMarkets = sectionWithoutAdvance.filter(
23502
23514
  (market) => normalizeSportsMarketType(market.sportsMarketType) !== "moneyline" && resolveMarketSectionTabKey(market) === "game_lines"
23503
23515
  );
23504
- return [...eventMoneylineMarkets, ...lineSectionMarkets];
23516
+ return [...eventToAdvanceMarkets, ...eventMoneylineMarkets, ...lineSectionMarkets];
23505
23517
  };
23506
23518
  var resolveSportsMarketCardVariant = (market) => {
23507
23519
  var _a;
@@ -23579,6 +23591,16 @@ var resolveSpreadOutcomeTeamNames = (activeMarket, groupMarkets) => {
23579
23591
  };
23580
23592
  return { favored: pickName(0), dog: pickName(1) };
23581
23593
  };
23594
+ var resolveCombinedMoneylineLegLabel = (market) => {
23595
+ const typedMarket = market;
23596
+ return toTrimmedString(typedMarket.shortTitle) || toTrimmedString(market.question);
23597
+ };
23598
+ var areCombinedMoneylineLegsDistinct = (markets) => {
23599
+ const labels = markets.map(
23600
+ (market) => resolveCombinedMoneylineLegLabel(market).toLowerCase()
23601
+ );
23602
+ return labels.every((label2) => label2.length > 0) && new Set(labels).size === labels.length;
23603
+ };
23582
23604
  var resolveDisplayGroupFamilyKey = (market) => {
23583
23605
  var _a, _b, _c;
23584
23606
  const normalizedQuestion = sanitizeFamilyValue(toTrimmedString(market.question));
@@ -23591,6 +23613,9 @@ var resolveDisplayGroupFamilyKey = (market) => {
23591
23613
  if (isBinarySportsMoneylineMarket(market)) {
23592
23614
  return `${period}|moneyline|${marketCategory}`;
23593
23615
  }
23616
+ if (sportsMarketType === "to_advance") {
23617
+ return `${period}|to_advance`;
23618
+ }
23594
23619
  const lineFamily = resolveSportsLineFamilyKey(market);
23595
23620
  if (sportsMarketType === "spread") {
23596
23621
  const spreadFamily = resolveSpreadFamilyKey(market);
@@ -23626,6 +23651,7 @@ var resolveDisplayGroupTitle = (market, groupMarkets = [market]) => {
23626
23651
  const sportsMarketType = normalizeSportsMarketType(market.sportsMarketType);
23627
23652
  const question = toTrimmedString(market.question);
23628
23653
  if (isBinarySportsMoneylineMarket(market)) return "Moneyline";
23654
+ if (sportsMarketType === "to_advance") return "Team to Advance";
23629
23655
  if (sportsMarketType === "spread") return "Spreads";
23630
23656
  if (!question) {
23631
23657
  return sportsMarketType != null ? sportsMarketType : market.id;
@@ -23668,7 +23694,16 @@ var buildSportsMarketDisplayGroups = (markets) => {
23668
23694
  }
23669
23695
  const groups = Array.from(groupsByKey.entries()).map(([id, groupMarkets]) => {
23670
23696
  var _a2;
23671
- const orderedMarkets = sortMarketsByLineValue(groupMarkets);
23697
+ const isToAdvanceGroup = groupMarkets.some(
23698
+ (market) => normalizeSportsMarketType(market.sportsMarketType) === "to_advance"
23699
+ );
23700
+ const orderedMarkets = isToAdvanceGroup ? [...groupMarkets].sort((left, right) => {
23701
+ var _a3, _b;
23702
+ const leftSingle = resolveSportsMarketAggKey(left).endsWith("_adv") ? 0 : 1;
23703
+ const rightSingle = resolveSportsMarketAggKey(right).endsWith("_adv") ? 0 : 1;
23704
+ if (leftSingle !== rightSingle) return leftSingle - rightSingle;
23705
+ return ((_a3 = right.volume) != null ? _a3 : 0) - ((_b = left.volume) != null ? _b : 0);
23706
+ }) : sortMarketsByLineValue(groupMarkets);
23672
23707
  const firstMarket = orderedMarkets[0];
23673
23708
  const sportsMarketType = normalizeSportsMarketType(firstMarket == null ? void 0 : firstMarket.sportsMarketType);
23674
23709
  const marketCategory = normalizeSportsMarketCategory(firstMarket == null ? void 0 : firstMarket.marketCategory);
@@ -23776,6 +23811,7 @@ var resolveHighestVolumeIndex = (markets) => {
23776
23811
  return bestIndex;
23777
23812
  };
23778
23813
  var resolveSlideKind = (group) => {
23814
+ if (group.sportsMarketType === "to_advance") return "to_advance";
23779
23815
  if (group.sportsMarketType === "moneyline") return "moneyline";
23780
23816
  if (group.sportsMarketType === "spread") return "spread";
23781
23817
  if (group.sportsMarketType === "total") return "total";
@@ -24175,7 +24211,10 @@ var SportsMarketCard = ({
24175
24211
  () => group.markets.filter((market) => isBinarySportsMoneylineMarket(market)),
24176
24212
  [group.markets]
24177
24213
  );
24178
- const isCombinedMoneylineGroup = group.sportsMarketType === "moneyline" && combinedMoneylineMarkets.length > 1 && combinedMoneylineMarkets.length === group.markets.length;
24214
+ const isCombinedMoneylineGroup = group.sportsMarketType === "moneyline" && combinedMoneylineMarkets.length > 1 && combinedMoneylineMarkets.length === group.markets.length && // Per-leg pills need distinct labels — unmerged cross-venue duplicates of
24215
+ // one 2-way single ("Match Winner" ×2) would render the same Yes price
24216
+ // twice as two options; fall back to the standard team-pill card instead.
24217
+ areCombinedMoneylineLegsDistinct(combinedMoneylineMarkets);
24179
24218
  const preferredResolvedMoneylineMarket = (0, import_react39.useMemo)(() => {
24180
24219
  var _a2, _b2;
24181
24220
  if (!isCombinedMoneylineGroup) return null;
@@ -24239,18 +24278,17 @@ var SportsMarketCard = ({
24239
24278
  const combinedMoneylineHeaderOutcomeItems = (0, import_react39.useMemo)(() => {
24240
24279
  if (!isCombinedMoneylineGroup) return void 0;
24241
24280
  return combinedMoneylineMarkets.flatMap((market, index) => {
24242
- var _a2, _b2;
24243
- const typedMarket = market;
24281
+ var _a2;
24244
24282
  const yesOutcome = market.venueMarketOutcomes.find(
24245
24283
  (outcome) => outcome.label.trim().toLowerCase() === "yes"
24246
24284
  );
24247
24285
  if (!yesOutcome) return [];
24248
- const label2 = ((_a2 = typedMarket.shortTitle) == null ? void 0 : _a2.trim()) || market.question.trim();
24286
+ const label2 = resolveCombinedMoneylineLegLabel(market);
24249
24287
  if (!label2) return [];
24250
24288
  const probability = midpointsResult == null ? void 0 : getDisplayOutcomePrice({
24251
24289
  outcomeId: yesOutcome.id,
24252
24290
  outcomeLabel: yesOutcome.label,
24253
- bestMidpointsByOutcomeId: (_b2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _b2 : midpointsResult.prices
24291
+ bestMidpointsByOutcomeId: (_a2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _a2 : midpointsResult.prices
24254
24292
  });
24255
24293
  return [
24256
24294
  {
package/dist/index.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  UserProfilePage,
12
12
  buildAggTxExplorerHref,
13
13
  useHomePageModals
14
- } from "./chunk-JNYACAEW.mjs";
14
+ } from "./chunk-EOCHFD2U.mjs";
15
15
  import {
16
16
  EventList,
17
17
  EventListItem,
package/dist/pages.js CHANGED
@@ -21012,6 +21012,7 @@ var import_react37 = require("react");
21012
21012
 
21013
21013
  // src/pages/event-market/sports-event-market.utils.ts
21014
21014
  var SPORTS_MARKET_TYPE_KEYS = [
21015
+ "to_advance",
21015
21016
  "moneyline",
21016
21017
  "spread",
21017
21018
  "total",
@@ -21153,6 +21154,7 @@ var SPORTS_PERIOD_ORDER = [
21153
21154
  "other"
21154
21155
  ];
21155
21156
  var SPORTS_MARKET_TYPE_ORDER = [
21157
+ "to_advance",
21156
21158
  "moneyline",
21157
21159
  "spread",
21158
21160
  "total",
@@ -21251,6 +21253,9 @@ var resolveFallbackSportsMarketCategory = (market) => {
21251
21253
  return null;
21252
21254
  };
21253
21255
  var resolveMarketSectionTabKey = (market) => {
21256
+ if (normalizeSportsMarketType(market.sportsMarketType) === "to_advance") {
21257
+ return "game_lines";
21258
+ }
21254
21259
  const normalizedCategory = normalizeSportsMarketCategory(market.marketCategory);
21255
21260
  const fallbackCategory = !normalizedCategory || normalizedCategory === "other" ? resolveFallbackSportsMarketCategory(market) : null;
21256
21261
  const category = fallbackCategory != null ? fallbackCategory : normalizedCategory;
@@ -21294,25 +21299,32 @@ var resolveSportsSectionMarkets = ({
21294
21299
  return [...filteredSectionMarkets, ...strayOtherMarkets];
21295
21300
  }
21296
21301
  if (tabKey !== "game_lines") return filteredSectionMarkets;
21297
- const eventMoneylineMarkets = (() => {
21302
+ const dedupeEventMarketsOfType = (type) => {
21298
21303
  const dedupedMarkets = [];
21299
- const seenMoneylineKeys = /* @__PURE__ */ new Set();
21304
+ const seenKeys = /* @__PURE__ */ new Set();
21300
21305
  for (const market of eventMarkets) {
21301
- if (normalizeSportsMarketType(market.sportsMarketType) !== "moneyline" || resolveMarketSectionTabKey(market) !== "game_lines") {
21306
+ if (normalizeSportsMarketType(market.sportsMarketType) !== type || resolveMarketSectionTabKey(market) !== "game_lines") {
21302
21307
  continue;
21303
21308
  }
21304
- const moneylineKey = resolveSportsMarketAggKey(market) || market.id;
21305
- if (seenMoneylineKeys.has(moneylineKey)) continue;
21306
- seenMoneylineKeys.add(moneylineKey);
21309
+ const key = resolveSportsMarketAggKey(market) || market.id;
21310
+ if (seenKeys.has(key)) continue;
21311
+ seenKeys.add(key);
21307
21312
  dedupedMarkets.push(market);
21308
21313
  }
21309
21314
  return dedupedMarkets;
21310
- })();
21311
- if (eventMoneylineMarkets.length === 0) return filteredSectionMarkets;
21312
- const lineSectionMarkets = filteredSectionMarkets.filter(
21315
+ };
21316
+ const eventMoneylineMarkets = dedupeEventMarketsOfType("moneyline");
21317
+ const eventToAdvanceMarkets = dedupeEventMarketsOfType("to_advance");
21318
+ const sectionWithoutAdvance = filteredSectionMarkets.filter(
21319
+ (market) => normalizeSportsMarketType(market.sportsMarketType) !== "to_advance"
21320
+ );
21321
+ if (eventMoneylineMarkets.length === 0) {
21322
+ return [...eventToAdvanceMarkets, ...sectionWithoutAdvance];
21323
+ }
21324
+ const lineSectionMarkets = sectionWithoutAdvance.filter(
21313
21325
  (market) => normalizeSportsMarketType(market.sportsMarketType) !== "moneyline" && resolveMarketSectionTabKey(market) === "game_lines"
21314
21326
  );
21315
- return [...eventMoneylineMarkets, ...lineSectionMarkets];
21327
+ return [...eventToAdvanceMarkets, ...eventMoneylineMarkets, ...lineSectionMarkets];
21316
21328
  };
21317
21329
  var resolveSportsMarketCardVariant = (market) => {
21318
21330
  var _a;
@@ -21390,6 +21402,16 @@ var resolveSpreadOutcomeTeamNames = (activeMarket, groupMarkets) => {
21390
21402
  };
21391
21403
  return { favored: pickName(0), dog: pickName(1) };
21392
21404
  };
21405
+ var resolveCombinedMoneylineLegLabel = (market) => {
21406
+ const typedMarket = market;
21407
+ return toTrimmedString(typedMarket.shortTitle) || toTrimmedString(market.question);
21408
+ };
21409
+ var areCombinedMoneylineLegsDistinct = (markets) => {
21410
+ const labels = markets.map(
21411
+ (market) => resolveCombinedMoneylineLegLabel(market).toLowerCase()
21412
+ );
21413
+ return labels.every((label2) => label2.length > 0) && new Set(labels).size === labels.length;
21414
+ };
21393
21415
  var resolveDisplayGroupFamilyKey = (market) => {
21394
21416
  var _a, _b, _c;
21395
21417
  const normalizedQuestion = sanitizeFamilyValue(toTrimmedString(market.question));
@@ -21402,6 +21424,9 @@ var resolveDisplayGroupFamilyKey = (market) => {
21402
21424
  if (isBinarySportsMoneylineMarket(market)) {
21403
21425
  return `${period}|moneyline|${marketCategory}`;
21404
21426
  }
21427
+ if (sportsMarketType === "to_advance") {
21428
+ return `${period}|to_advance`;
21429
+ }
21405
21430
  const lineFamily = resolveSportsLineFamilyKey(market);
21406
21431
  if (sportsMarketType === "spread") {
21407
21432
  const spreadFamily = resolveSpreadFamilyKey(market);
@@ -21437,6 +21462,7 @@ var resolveDisplayGroupTitle = (market, groupMarkets = [market]) => {
21437
21462
  const sportsMarketType = normalizeSportsMarketType(market.sportsMarketType);
21438
21463
  const question = toTrimmedString(market.question);
21439
21464
  if (isBinarySportsMoneylineMarket(market)) return "Moneyline";
21465
+ if (sportsMarketType === "to_advance") return "Team to Advance";
21440
21466
  if (sportsMarketType === "spread") return "Spreads";
21441
21467
  if (!question) {
21442
21468
  return sportsMarketType != null ? sportsMarketType : market.id;
@@ -21479,7 +21505,16 @@ var buildSportsMarketDisplayGroups = (markets) => {
21479
21505
  }
21480
21506
  const groups = Array.from(groupsByKey.entries()).map(([id, groupMarkets]) => {
21481
21507
  var _a2;
21482
- const orderedMarkets = sortMarketsByLineValue(groupMarkets);
21508
+ const isToAdvanceGroup = groupMarkets.some(
21509
+ (market) => normalizeSportsMarketType(market.sportsMarketType) === "to_advance"
21510
+ );
21511
+ const orderedMarkets = isToAdvanceGroup ? [...groupMarkets].sort((left, right) => {
21512
+ var _a3, _b;
21513
+ const leftSingle = resolveSportsMarketAggKey(left).endsWith("_adv") ? 0 : 1;
21514
+ const rightSingle = resolveSportsMarketAggKey(right).endsWith("_adv") ? 0 : 1;
21515
+ if (leftSingle !== rightSingle) return leftSingle - rightSingle;
21516
+ return ((_a3 = right.volume) != null ? _a3 : 0) - ((_b = left.volume) != null ? _b : 0);
21517
+ }) : sortMarketsByLineValue(groupMarkets);
21483
21518
  const firstMarket = orderedMarkets[0];
21484
21519
  const sportsMarketType = normalizeSportsMarketType(firstMarket == null ? void 0 : firstMarket.sportsMarketType);
21485
21520
  const marketCategory = normalizeSportsMarketCategory(firstMarket == null ? void 0 : firstMarket.marketCategory);
@@ -21587,6 +21622,7 @@ var resolveHighestVolumeIndex = (markets) => {
21587
21622
  return bestIndex;
21588
21623
  };
21589
21624
  var resolveSlideKind = (group) => {
21625
+ if (group.sportsMarketType === "to_advance") return "to_advance";
21590
21626
  if (group.sportsMarketType === "moneyline") return "moneyline";
21591
21627
  if (group.sportsMarketType === "spread") return "spread";
21592
21628
  if (group.sportsMarketType === "total") return "total";
@@ -21986,7 +22022,10 @@ var SportsMarketCard = ({
21986
22022
  () => group.markets.filter((market) => isBinarySportsMoneylineMarket(market)),
21987
22023
  [group.markets]
21988
22024
  );
21989
- const isCombinedMoneylineGroup = group.sportsMarketType === "moneyline" && combinedMoneylineMarkets.length > 1 && combinedMoneylineMarkets.length === group.markets.length;
22025
+ const isCombinedMoneylineGroup = group.sportsMarketType === "moneyline" && combinedMoneylineMarkets.length > 1 && combinedMoneylineMarkets.length === group.markets.length && // Per-leg pills need distinct labels — unmerged cross-venue duplicates of
22026
+ // one 2-way single ("Match Winner" ×2) would render the same Yes price
22027
+ // twice as two options; fall back to the standard team-pill card instead.
22028
+ areCombinedMoneylineLegsDistinct(combinedMoneylineMarkets);
21990
22029
  const preferredResolvedMoneylineMarket = (0, import_react36.useMemo)(() => {
21991
22030
  var _a2, _b2;
21992
22031
  if (!isCombinedMoneylineGroup) return null;
@@ -22050,18 +22089,17 @@ var SportsMarketCard = ({
22050
22089
  const combinedMoneylineHeaderOutcomeItems = (0, import_react36.useMemo)(() => {
22051
22090
  if (!isCombinedMoneylineGroup) return void 0;
22052
22091
  return combinedMoneylineMarkets.flatMap((market, index) => {
22053
- var _a2, _b2;
22054
- const typedMarket = market;
22092
+ var _a2;
22055
22093
  const yesOutcome = market.venueMarketOutcomes.find(
22056
22094
  (outcome) => outcome.label.trim().toLowerCase() === "yes"
22057
22095
  );
22058
22096
  if (!yesOutcome) return [];
22059
- const label2 = ((_a2 = typedMarket.shortTitle) == null ? void 0 : _a2.trim()) || market.question.trim();
22097
+ const label2 = resolveCombinedMoneylineLegLabel(market);
22060
22098
  if (!label2) return [];
22061
22099
  const probability = midpointsResult == null ? void 0 : getDisplayOutcomePrice({
22062
22100
  outcomeId: yesOutcome.id,
22063
22101
  outcomeLabel: yesOutcome.label,
22064
- bestMidpointsByOutcomeId: (_b2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _b2 : midpointsResult.prices
22102
+ bestMidpointsByOutcomeId: (_a2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _a2 : midpointsResult.prices
22065
22103
  });
22066
22104
  return [
22067
22105
  {
package/dist/pages.mjs CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  UserProfilePage,
9
9
  buildAggTxExplorerHref,
10
10
  useHomePageModals
11
- } from "./chunk-JNYACAEW.mjs";
11
+ } from "./chunk-EOCHFD2U.mjs";
12
12
  import "./chunk-MDO3NMXP.mjs";
13
13
  import {
14
14
  DEPOSIT_MODAL_OPEN_EVENT,
@@ -1,7 +1,7 @@
1
1
  import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
2
2
  export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
3
3
  export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
4
- export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["moneyline", "spread", "total", "prop", "completion", "other"];
4
+ export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
5
5
  export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
6
6
  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"];
7
7
  /**
@@ -81,7 +81,7 @@ export declare const normalizeSportsMarketGroup: (value: string | null | undefin
81
81
  * recognizable grouping metadata, so the page can fall back to the default,
82
82
  * ungrouped market list instead of inventing an empty tab.
83
83
  */
84
- export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question">) => SportsSectionTabKey | null;
84
+ export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
85
85
  export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
86
86
  marketGroup?: SportsMarketGroupKey[];
87
87
  marketCategory?: SportsMarketCategoryKey[];
@@ -132,9 +132,20 @@ export declare const resolveSpreadOutcomeTeamNames: (activeMarket: VenueMarket,
132
132
  favored: string | null;
133
133
  dog: string | null;
134
134
  };
135
+ /** The per-leg pill label for a combined (decomposed) moneyline group. */
136
+ export declare const resolveCombinedMoneylineLegLabel: (market: VenueMarket) => string;
137
+ /**
138
+ * Combined per-leg moneyline pills are only meaningful when every leg carries a
139
+ * DISTINCT label. Cross-venue duplicates of the SAME 2-way single that never
140
+ * merged (e.g. poly + predict "… (BO5) - Match Winner") collapse to identical
141
+ * labels — rendering them as separate pills shows the same Yes price twice as
142
+ * if it were two different options. Non-distinct → the card falls back to the
143
+ * standard single-market rendering (team-title pills).
144
+ */
145
+ export declare const areCombinedMoneylineLegsDistinct: (markets: VenueMarket[]) => boolean;
135
146
  export declare const buildSportsMarketDisplayGroups: (markets: VenueMarket[]) => SportsMarketDisplayGroup[];
136
147
  export declare const groupSportsMarketsByPeriod: (markets: VenueMarket[]) => SportsPeriodGroup[];
137
- export type SportsGameLineSlideKind = "moneyline" | "spread" | "total" | "other";
148
+ export type SportsGameLineSlideKind = "to_advance" | "moneyline" | "spread" | "total" | "other";
138
149
  export type SportsGameLineSlideStop = {
139
150
  /** Display value for the ladder chip, e.g. "1.5", "216.5". */
140
151
  value: string;
@@ -1,7 +1,7 @@
1
1
  import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
2
2
  export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
3
3
  export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
4
- export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["moneyline", "spread", "total", "prop", "completion", "other"];
4
+ export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
5
5
  export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
6
6
  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"];
7
7
  /**
@@ -81,7 +81,7 @@ export declare const normalizeSportsMarketGroup: (value: string | null | undefin
81
81
  * recognizable grouping metadata, so the page can fall back to the default,
82
82
  * ungrouped market list instead of inventing an empty tab.
83
83
  */
84
- export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question">) => SportsSectionTabKey | null;
84
+ export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
85
85
  export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
86
86
  marketGroup?: SportsMarketGroupKey[];
87
87
  marketCategory?: SportsMarketCategoryKey[];
@@ -132,9 +132,20 @@ export declare const resolveSpreadOutcomeTeamNames: (activeMarket: VenueMarket,
132
132
  favored: string | null;
133
133
  dog: string | null;
134
134
  };
135
+ /** The per-leg pill label for a combined (decomposed) moneyline group. */
136
+ export declare const resolveCombinedMoneylineLegLabel: (market: VenueMarket) => string;
137
+ /**
138
+ * Combined per-leg moneyline pills are only meaningful when every leg carries a
139
+ * DISTINCT label. Cross-venue duplicates of the SAME 2-way single that never
140
+ * merged (e.g. poly + predict "… (BO5) - Match Winner") collapse to identical
141
+ * labels — rendering them as separate pills shows the same Yes price twice as
142
+ * if it were two different options. Non-distinct → the card falls back to the
143
+ * standard single-market rendering (team-title pills).
144
+ */
145
+ export declare const areCombinedMoneylineLegsDistinct: (markets: VenueMarket[]) => boolean;
135
146
  export declare const buildSportsMarketDisplayGroups: (markets: VenueMarket[]) => SportsMarketDisplayGroup[];
136
147
  export declare const groupSportsMarketsByPeriod: (markets: VenueMarket[]) => SportsPeriodGroup[];
137
- export type SportsGameLineSlideKind = "moneyline" | "spread" | "total" | "other";
148
+ export type SportsGameLineSlideKind = "to_advance" | "moneyline" | "spread" | "total" | "other";
138
149
  export type SportsGameLineSlideStop = {
139
150
  /** Display value for the ladder chip, e.g. "1.5", "216.5". */
140
151
  value: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agg-build/ui",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
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",