@agg-build/ui 2.1.4 → 2.2.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.
Files changed (37) hide show
  1. package/dist/{chunk-T4YZGAYS.mjs → chunk-5MRFY5ZQ.mjs} +1 -1
  2. package/dist/{chunk-BW7S2YR3.mjs → chunk-73MO7MYG.mjs} +21 -17
  3. package/dist/{chunk-TBZWRUFB.mjs → chunk-BTRFSEPC.mjs} +97 -61
  4. package/dist/{chunk-FLESSOSU.mjs → chunk-DTOI4V6P.mjs} +47 -10
  5. package/dist/{chunk-XHE2VO3S.mjs → chunk-HNLA44SY.mjs} +2 -2
  6. package/dist/{chunk-VP76G6PN.mjs → chunk-MIAAL7BL.mjs} +79 -23
  7. package/dist/{chunk-R2YNZJZ3.mjs → chunk-TR7HUVY7.mjs} +1 -1
  8. package/dist/events.js +93 -52
  9. package/dist/events.mjs +3 -3
  10. package/dist/index.js +214 -93
  11. package/dist/index.mjs +7 -7
  12. package/dist/modals.mjs +3 -3
  13. package/dist/pages.js +214 -93
  14. package/dist/pages.mjs +6 -6
  15. package/dist/primitives.js +70 -23
  16. package/dist/primitives.mjs +1 -1
  17. package/dist/trading.js +17 -14
  18. package/dist/trading.mjs +4 -4
  19. package/dist/types/events/item/event-list-item.types.d.mts +2 -2
  20. package/dist/types/events/item/event-list-item.types.d.ts +2 -2
  21. package/dist/types/events/item/event-list-item.utils.d.mts +2 -1
  22. package/dist/types/events/item/event-list-item.utils.d.ts +2 -1
  23. package/dist/types/events/item-details/event-list-item-details.types.d.mts +0 -1
  24. package/dist/types/events/item-details/event-list-item-details.types.d.ts +0 -1
  25. package/dist/types/events/market-details/market-details.types.d.mts +1 -0
  26. package/dist/types/events/market-details/market-details.types.d.ts +1 -0
  27. package/dist/types/events/shared/chart-venue-selection.d.mts +2 -1
  28. package/dist/types/events/shared/chart-venue-selection.d.ts +2 -1
  29. package/dist/types/pages/event-market/sports-event-market.utils.d.mts +15 -1
  30. package/dist/types/pages/event-market/sports-event-market.utils.d.ts +15 -1
  31. package/dist/types/primitives/search/search.types.d.mts +1 -0
  32. package/dist/types/primitives/search/search.types.d.ts +1 -0
  33. package/dist/types/primitives/search/search.utils.d.mts +4 -1
  34. package/dist/types/primitives/search/search.utils.d.ts +4 -1
  35. package/dist/types/trading/types.d.mts +2 -1
  36. package/dist/types/trading/types.d.ts +2 -1
  37. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -7037,6 +7037,13 @@ var formatPriceGapPercent = (value) => {
7037
7037
  return `${Math.round(value)}%`;
7038
7038
  };
7039
7039
  var sortOutcomes = (outcomes) => {
7040
+ return sortOutcomesWithPrices(outcomes);
7041
+ };
7042
+ var resolveOutcomeProbability = (outcome, priceByOutcomeId) => {
7043
+ const resolvedPrice = priceByOutcomeId === void 0 ? outcome.price : priceByOutcomeId.has(outcome.id) ? priceByOutcomeId.get(outcome.id) : void 0;
7044
+ return normalizeProbability(resolvedPrice);
7045
+ };
7046
+ var sortOutcomesWithPrices = (outcomes, priceByOutcomeId) => {
7040
7047
  if (outcomes.length <= 1) return outcomes;
7041
7048
  if (hasBinaryOutcomes(outcomes)) {
7042
7049
  return sortYesFirst(outcomes);
@@ -7052,38 +7059,41 @@ var sortOutcomes = (outcomes) => {
7052
7059
  }
7053
7060
  return [...outcomes].sort((a, b) => {
7054
7061
  var _a, _b;
7055
- const aPrice = (_a = normalizeProbability(a.price)) != null ? _a : 0;
7056
- const bPrice = (_b = normalizeProbability(b.price)) != null ? _b : 0;
7062
+ const aPrice = (_a = resolveOutcomeProbability(a, priceByOutcomeId)) != null ? _a : 0;
7063
+ const bPrice = (_b = resolveOutcomeProbability(b, priceByOutcomeId)) != null ? _b : 0;
7057
7064
  return bPrice - aPrice;
7058
7065
  });
7059
7066
  };
7060
- var compareVisibleOutcomeRows = (left, right) => {
7067
+ var compareVisibleOutcomeRows = (left, right, priceByOutcomeId) => {
7061
7068
  var _a, _b;
7062
7069
  const leftDate = toDate(resolveOutcomeTitle(left.outcome));
7063
7070
  const rightDate = toDate(resolveOutcomeTitle(right.outcome));
7064
7071
  if (leftDate && rightDate) {
7065
7072
  return leftDate.getTime() - rightDate.getTime();
7066
7073
  }
7067
- const leftProbability = (_a = normalizeProbability(left.outcome.price)) != null ? _a : -1;
7068
- const rightProbability = (_b = normalizeProbability(right.outcome.price)) != null ? _b : -1;
7074
+ const leftProbability = (_a = resolveOutcomeProbability(left.outcome, priceByOutcomeId)) != null ? _a : -1;
7075
+ const rightProbability = (_b = resolveOutcomeProbability(right.outcome, priceByOutcomeId)) != null ? _b : -1;
7069
7076
  return rightProbability - leftProbability;
7070
7077
  };
7071
- var shouldReplaceVisibleOutcome = (current, next) => {
7078
+ var shouldReplaceVisibleOutcome = (current, next, priceByOutcomeId) => {
7072
7079
  var _a, _b;
7073
7080
  const currentVolume = typeof current.market.volume === "number" ? current.market.volume : -1;
7074
7081
  const nextVolume = typeof next.market.volume === "number" ? next.market.volume : -1;
7075
7082
  if (currentVolume !== nextVolume) {
7076
7083
  return nextVolume > currentVolume;
7077
7084
  }
7078
- const currentProbability = (_a = normalizeProbability(current.outcome.price)) != null ? _a : -1;
7079
- const nextProbability = (_b = normalizeProbability(next.outcome.price)) != null ? _b : -1;
7085
+ const currentProbability = (_a = resolveOutcomeProbability(current.outcome, priceByOutcomeId)) != null ? _a : -1;
7086
+ const nextProbability = (_b = resolveOutcomeProbability(next.outcome, priceByOutcomeId)) != null ? _b : -1;
7080
7087
  return nextProbability > currentProbability;
7081
7088
  };
7082
- var resolveVisibleOutcomes = (venueMarkets) => {
7089
+ var resolveVisibleOutcomes = (venueMarkets, priceByOutcomeId) => {
7083
7090
  const visibleOutcomesByLabel = /* @__PURE__ */ new Map();
7084
7091
  venueMarkets.forEach((market) => {
7085
7092
  const title2 = market.question;
7086
- const canonicalOutcome = sortOutcomes(market.venueMarketOutcomes)[0];
7093
+ const canonicalOutcome = sortOutcomesWithPrices(
7094
+ market.venueMarketOutcomes,
7095
+ priceByOutcomeId
7096
+ )[0];
7087
7097
  if (!canonicalOutcome) return;
7088
7098
  const normalizedTitle = title2.trim().toLowerCase();
7089
7099
  const nextVisibleOutcome = {
@@ -7093,11 +7103,11 @@ var resolveVisibleOutcomes = (venueMarkets) => {
7093
7103
  title: title2
7094
7104
  };
7095
7105
  const currentVisibleOutcome = visibleOutcomesByLabel.get(normalizedTitle);
7096
- if (!currentVisibleOutcome || shouldReplaceVisibleOutcome(currentVisibleOutcome, nextVisibleOutcome)) {
7106
+ if (!currentVisibleOutcome || shouldReplaceVisibleOutcome(currentVisibleOutcome, nextVisibleOutcome, priceByOutcomeId)) {
7097
7107
  visibleOutcomesByLabel.set(normalizedTitle, nextVisibleOutcome);
7098
7108
  }
7099
7109
  });
7100
- return [...visibleOutcomesByLabel.values()].sort(compareVisibleOutcomeRows).slice(0, Math.max(1, 2));
7110
+ return [...visibleOutcomesByLabel.values()].sort((left, right) => compareVisibleOutcomeRows(left, right, priceByOutcomeId)).slice(0, Math.max(1, 2));
7101
7111
  };
7102
7112
  var dedupeVenueMarketsById = (venueMarkets) => {
7103
7113
  const seenClusterIds = /* @__PURE__ */ new Set();
@@ -7177,18 +7187,19 @@ var toVenueLogoName = (value) => {
7177
7187
  if (!venueLogoNameSet.has(value)) return null;
7178
7188
  return value;
7179
7189
  };
7180
- var mapVenueEventToSearchResult = (event, labels, formatPercent, formatCompactCurrency) => {
7181
- var _a, _b;
7190
+ var mapVenueEventToSearchResult = (event, labels, formatPercent, formatCompactCurrency, options) => {
7191
+ var _a, _b, _c;
7182
7192
  const primaryVenueMarket = selectPrimaryVenueMarket(event.venueMarkets);
7183
7193
  if (!primaryVenueMarket) return null;
7184
7194
  const primaryVenue = toVenueLogoName(primaryVenueMarket.venue);
7185
7195
  if (!primaryVenue) return null;
7186
- const visibleOutcome = resolveVisibleOutcomes(event.venueMarkets)[0];
7196
+ const visibleOutcome = resolveVisibleOutcomes(event.venueMarkets, options == null ? void 0 : options.priceByOutcomeId)[0];
7187
7197
  if (!visibleOutcome) return null;
7188
- const probability = normalizeProbability(visibleOutcome.outcome.price);
7189
- if (probability == null) return null;
7198
+ const probability = normalizeProbability(
7199
+ (_a = options == null ? void 0 : options.priceByOutcomeId) == null ? void 0 : _a.get(visibleOutcome.outcome.id)
7200
+ );
7190
7201
  const resolvedTitle = formatEventTitleWithDateSuffix({
7191
- title: (_a = event == null ? void 0 : event.title) != null ? _a : "",
7202
+ title: (_b = event == null ? void 0 : event.title) != null ? _b : "",
7192
7203
  categories: event.categories,
7193
7204
  structureType: event.structureType,
7194
7205
  gameStartTime: event.gameStartTime,
@@ -7210,13 +7221,14 @@ var mapVenueEventToSearchResult = (event, labels, formatPercent, formatCompactCu
7210
7221
  return {
7211
7222
  id: event.id,
7212
7223
  title: resolvedTitle,
7213
- thumbnailSrc: (_b = resolveTileImage(event, primaryVenueMarket, void 0)) != null ? _b : "",
7224
+ thumbnailSrc: (_c = resolveTileImage(event, primaryVenueMarket, void 0)) != null ? _c : "",
7214
7225
  thumbnailAlt: resolvedTitle,
7215
7226
  venue: primaryVenue,
7216
7227
  visibleVenues,
7217
7228
  marketSummaryLabel,
7218
7229
  volumeLabel,
7219
7230
  valueLabel: formatMarketProbabilityPercent(probability, formatPercent),
7231
+ isValueLoading: probability == null && (options == null ? void 0 : options.isPriceLoading) === true,
7220
7232
  contextLabel: formatSearchContextLabel(visibleOutcome.title)
7221
7233
  };
7222
7234
  };
@@ -7326,7 +7338,16 @@ var SearchResultRow = ({
7326
7338
  children: [
7327
7339
  /* @__PURE__ */ (0, import_jsx_runtime119.jsx)(VenueLogo, { venue: item.venue, size: "small" }),
7328
7340
  /* @__PURE__ */ (0, import_jsx_runtime119.jsxs)("div", { className: "flex min-w-0 flex-1 items-baseline gap-2", children: [
7329
- /* @__PURE__ */ (0, import_jsx_runtime119.jsx)(
7341
+ item.isValueLoading ? /* @__PURE__ */ (0, import_jsx_runtime119.jsx)(
7342
+ "span",
7343
+ {
7344
+ "aria-hidden": "true",
7345
+ className: cn(
7346
+ "agg-search-result-value-loading",
7347
+ "h-5 w-12 shrink-0 rounded-agg-sm bg-agg-separator animate-pulse"
7348
+ )
7349
+ }
7350
+ ) : /* @__PURE__ */ (0, import_jsx_runtime119.jsx)(
7330
7351
  "p",
7331
7352
  {
7332
7353
  className: cn(
@@ -7439,6 +7460,24 @@ var Search = ({
7439
7460
  () => filterOpenEvents(searchResults),
7440
7461
  [searchResults]
7441
7462
  );
7463
+ const visibleVenueMarkets = (0, import_react9.useMemo)(
7464
+ () => openEvents.flatMap((event) => {
7465
+ var _a;
7466
+ return (_a = event.venueMarkets) != null ? _a : [];
7467
+ }),
7468
+ [openEvents]
7469
+ );
7470
+ const livePrices = (0, import_hooks27.useLiveOutcomePrices)(visibleVenueMarkets);
7471
+ const midpointResult = (0, import_hooks27.useMidpoints)(visibleVenueMarkets);
7472
+ const searchDisplayPrices = (0, import_react9.useMemo)(() => {
7473
+ if (!midpointResult.bestMidpointsByOutcomeId.size) return livePrices;
7474
+ if (!livePrices.size) return midpointResult.bestMidpointsByOutcomeId;
7475
+ const merged = new Map(midpointResult.bestMidpointsByOutcomeId);
7476
+ for (const [outcomeId, price] of livePrices) {
7477
+ merged.set(outcomeId, price);
7478
+ }
7479
+ return merged;
7480
+ }, [livePrices, midpointResult.bestMidpointsByOutcomeId]);
7442
7481
  const { validatedResults, eventsByResultId } = (0, import_react9.useMemo)(() => {
7443
7482
  const nextEventsByResultId = /* @__PURE__ */ new Map();
7444
7483
  const nextResults = openEvents.map((event) => {
@@ -7446,7 +7485,11 @@ var Search = ({
7446
7485
  event,
7447
7486
  labels,
7448
7487
  formatPercent,
7449
- formatCompactCurrency
7488
+ formatCompactCurrency,
7489
+ {
7490
+ priceByOutcomeId: searchDisplayPrices,
7491
+ isPriceLoading: midpointResult.isLoading
7492
+ }
7450
7493
  );
7451
7494
  if (!item) return null;
7452
7495
  nextEventsByResultId.set(item.id, event);
@@ -7456,7 +7499,14 @@ var Search = ({
7456
7499
  validatedResults: nextResults,
7457
7500
  eventsByResultId: nextEventsByResultId
7458
7501
  };
7459
- }, [formatCompactCurrency, formatPercent, labels, openEvents]);
7502
+ }, [
7503
+ formatCompactCurrency,
7504
+ formatPercent,
7505
+ labels,
7506
+ midpointResult.isLoading,
7507
+ openEvents,
7508
+ searchDisplayPrices
7509
+ ]);
7460
7510
  const hasSearchValue = trimmedValue.length > 0;
7461
7511
  const shouldRenderDropdown = isFocused && shouldSearchValue && !searchConfig.result && !searchConfig.isShowingAllResults;
7462
7512
  const resolvedIsActive = isFocused;
@@ -10973,9 +11023,8 @@ var collectOutcomePrices = (market, outcome, priceByOutcomeId) => {
10973
11023
  const prices = [];
10974
11024
  const seenOutcomeKeys = /* @__PURE__ */ new Set();
10975
11025
  const addPrice = (priceMarket, priceOutcome) => {
10976
- var _a2;
10977
11026
  if (!priceMarket || !priceOutcome) return;
10978
- const resolvedPrice = (_a2 = priceByOutcomeId == null ? void 0 : priceByOutcomeId.get(priceOutcome.id)) != null ? _a2 : priceOutcome.price;
11027
+ const resolvedPrice = priceByOutcomeId === void 0 ? priceOutcome.price : priceByOutcomeId.has(priceOutcome.id) ? priceByOutcomeId.get(priceOutcome.id) : void 0;
10979
11028
  const normalizedPrice = normalizeProbability(resolvedPrice);
10980
11029
  if (normalizedPrice == null) return;
10981
11030
  const key = `${priceMarket.id}:${priceOutcome.id}`;
@@ -12878,13 +12927,8 @@ var resolveChartVenueOutcomes = ({
12878
12927
  }) => {
12879
12928
  if (eligibleVenueOutcomes.length <= 1) return eligibleVenueOutcomes;
12880
12929
  const sortedEligibleVenueOutcomes = [...eligibleVenueOutcomes].sort((left, right) => {
12881
- var _a, _b;
12882
- const leftProbability = normalizeProbability(
12883
- (_a = livePrices.get(left.outcome.id)) != null ? _a : left.outcome.price
12884
- );
12885
- const rightProbability = normalizeProbability(
12886
- (_b = livePrices.get(right.outcome.id)) != null ? _b : right.outcome.price
12887
- );
12930
+ const leftProbability = normalizeProbability(livePrices.get(left.outcome.id));
12931
+ const rightProbability = normalizeProbability(livePrices.get(right.outcome.id));
12888
12932
  const probabilityDifference = (leftProbability != null ? leftProbability : 2) - (rightProbability != null ? rightProbability : 2);
12889
12933
  if (probabilityDifference !== 0) return probabilityDifference;
12890
12934
  if (left.venue === right.venue) return 0;
@@ -13989,6 +14033,12 @@ var EventListItemDetailsNotFoundState = ({
13989
14033
  }
13990
14034
  );
13991
14035
  };
14036
+ var resolveResolvedOutcomePriceMap = (outcomes) => {
14037
+ if (!(outcomes == null ? void 0 : outcomes.length)) return null;
14038
+ if (!outcomes.some((outcome) => outcome.winner === true)) return null;
14039
+ if (outcomes.some((outcome) => outcome.winner == null)) return null;
14040
+ return new Map(outcomes.map((outcome) => [outcome.id, outcome.winner === true ? 1 : 0]));
14041
+ };
13992
14042
  var EventListItemDetailsGraphSection = ({
13993
14043
  classNames,
13994
14044
  selectedChartType,
@@ -14110,6 +14160,18 @@ var EventListItemDetailsGraphSection = ({
14110
14160
  });
14111
14161
  });
14112
14162
  }, [availableMarkets, tradingContext == null ? void 0 : tradingContext.selectedMarket]);
14163
+ const resolvedOutcomePriceByMarketId = (0, import_react24.useMemo)(() => {
14164
+ const map = /* @__PURE__ */ new Map();
14165
+ for (const market of availableMarkets) {
14166
+ const marketTradingState = (0, import_hooks48.resolveMarketTradingState)(market);
14167
+ if (marketTradingState.kind !== "resolved") continue;
14168
+ const outcomePriceMap = resolveResolvedOutcomePriceMap(market.venueMarketOutcomes);
14169
+ if (outcomePriceMap) {
14170
+ map.set(market.id, outcomePriceMap);
14171
+ }
14172
+ }
14173
+ return map;
14174
+ }, [availableMarkets]);
14113
14175
  const resolvedVenueChartSeries = (0, import_react24.useMemo)(() => {
14114
14176
  return resolveMarketChartVenueSeries({
14115
14177
  chartData: scopedMarketChartData,
@@ -14205,8 +14267,8 @@ var EventListItemDetailsGraphSection = ({
14205
14267
  classNames == null ? void 0 : classNames.outcomeBadges
14206
14268
  ),
14207
14269
  children: chartAvailableVenueOutcomes.map((item) => {
14208
- var _a3;
14209
- const percentage = (_a3 = wsLivePrices.get(item.outcome.id)) != null ? _a3 : item.outcome.price;
14270
+ var _a3, _b3;
14271
+ const percentage = (_b3 = (_a3 = resolvedOutcomePriceByMarketId.get(item.market.id)) == null ? void 0 : _a3.get(item.outcome.id)) != null ? _b3 : wsLivePrices.get(item.outcome.id);
14210
14272
  const text = formatMarketProbabilityPercent(percentage, formatPercent);
14211
14273
  const seriesId = `${item.venue}-chart`;
14212
14274
  const isActiveVenue = activeGraphVenue === item.venue;
@@ -14269,21 +14331,21 @@ var EventListItemDetailsGraphSection = ({
14269
14331
  tradingContext == null ? void 0 : tradingContext.selectOutcome(outcomeId);
14270
14332
  },
14271
14333
  options: selectedMarketOutcomes.map((outcome) => {
14272
- var _a3, _b3, _c3;
14273
- const price = getDisplayOutcomePrice({
14334
+ var _a3, _b3, _c3, _d3, _e2;
14335
+ const resolvedPrice = availableMarkets[0] == null ? void 0 : (_b3 = resolvedOutcomePriceByMarketId.get(((_a3 = tradingContext == null ? void 0 : tradingContext.selectedMarket) != null ? _a3 : availableMarkets[0]).id)) == null ? void 0 : _b3.get(outcome.id);
14336
+ const price = resolvedPrice != null ? resolvedPrice : getDisplayOutcomePrice({
14274
14337
  outcomeId: outcome.id,
14275
14338
  outcomeLabel: outcome.label,
14276
- selection: (_a3 = tradingContext == null ? void 0 : tradingContext.tradeSide) != null ? _a3 : "buy",
14339
+ selection: (_c3 = tradingContext == null ? void 0 : tradingContext.tradeSide) != null ? _c3 : "buy",
14277
14340
  bestPrices,
14278
14341
  bestMidpoint,
14279
14342
  bestMidpointsByOutcomeId: restMidpoints,
14280
- livePrices,
14281
- fallbackPrice: outcome.price
14343
+ livePrices
14282
14344
  });
14283
14345
  return {
14284
14346
  value: outcome.id,
14285
- label: `${(_b3 = outcome.title) != null ? _b3 : outcome.label} ${formatProbabilityCents(price)}`,
14286
- ariaLabel: `${(_c3 = outcome.title) != null ? _c3 : outcome.label} ${formatProbabilityCents(price)}`
14347
+ label: `${(_d3 = outcome.title) != null ? _d3 : outcome.label} ${formatProbabilityCents(price)}`,
14348
+ ariaLabel: `${(_e2 = outcome.title) != null ? _e2 : outcome.label} ${formatProbabilityCents(price)}`
14287
14349
  };
14288
14350
  })
14289
14351
  }
@@ -15363,6 +15425,34 @@ var getMarketDetailsOutcomeButtonClassNames = ({
15363
15425
  text: cn(isSelected ? toneClasses.text : "text-agg-foreground")
15364
15426
  };
15365
15427
  };
15428
+ var OutcomePriceContent = ({
15429
+ isLoading,
15430
+ isSelected,
15431
+ value,
15432
+ textClassName
15433
+ }) => {
15434
+ if (isLoading) {
15435
+ return /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
15436
+ "span",
15437
+ {
15438
+ "aria-hidden": "true",
15439
+ className: cn(
15440
+ "agg-market-details-outcome-price-loading",
15441
+ "h-4 w-10 shrink-0 rounded-agg-sm bg-agg-separator animate-pulse"
15442
+ )
15443
+ }
15444
+ );
15445
+ }
15446
+ return /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
15447
+ Typography,
15448
+ {
15449
+ as: "span",
15450
+ variant: isSelected ? "body-strong" : "body",
15451
+ className: cn("shrink-0 whitespace-nowrap", textClassName),
15452
+ children: formatProbabilityCents(value)
15453
+ }
15454
+ );
15455
+ };
15366
15456
  var MarketDetailsOutcomeButton = ({
15367
15457
  ariaControls,
15368
15458
  enableAnimations,
@@ -15418,12 +15508,12 @@ var MarketDetailsOutcomeButton = ({
15418
15508
  }
15419
15509
  ) : null,
15420
15510
  /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
15421
- Typography,
15511
+ OutcomePriceContent,
15422
15512
  {
15423
- as: "span",
15424
- variant: isSelected ? "body-strong" : "body",
15425
- className: cn("shrink-0 whitespace-nowrap", classNames.text),
15426
- children: formatProbabilityCents(item.probability)
15513
+ isLoading: item.isPriceLoading,
15514
+ isSelected,
15515
+ value: item.probability,
15516
+ textClassName: classNames.text
15427
15517
  }
15428
15518
  )
15429
15519
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)("div", { className: "inline-flex max-w-full items-center justify-center gap-1.5", children: [
@@ -15438,12 +15528,12 @@ var MarketDetailsOutcomeButton = ({
15438
15528
  }
15439
15529
  ),
15440
15530
  /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
15441
- Typography,
15531
+ OutcomePriceContent,
15442
15532
  {
15443
- as: "span",
15444
- variant: isSelected ? "body-strong" : "body",
15445
- className: cn("shrink-0 whitespace-nowrap", classNames.text),
15446
- children: formatProbabilityCents(item.probability)
15533
+ isLoading: item.isPriceLoading,
15534
+ isSelected,
15535
+ value: item.probability,
15536
+ textClassName: classNames.text
15447
15537
  }
15448
15538
  )
15449
15539
  ] })
@@ -15635,9 +15725,8 @@ var MarketDetailsGraphPanel = ({
15635
15725
  var _a2, _b2, _c2, _d;
15636
15726
  return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)("div", { className: "agg-chart-toolbar w-full flex flex-col gap-4 md:flex-row md:items-center md:justify-between", children: [
15637
15727
  /* @__PURE__ */ (0, import_jsx_runtime146.jsx)("div", { className: "agg-market-venues flex flex-wrap gap-2", children: chartAvailableOutcomesByVenue.map((item) => {
15638
- var _a3;
15639
15728
  const probability = formatProbabilityPercent(
15640
- (_a3 = wsLivePrices.get(item.outcome.id)) != null ? _a3 : item.outcome.price,
15729
+ wsLivePrices.get(item.outcome.id),
15641
15730
  formatPercent
15642
15731
  );
15643
15732
  const isActiveVenue = selectedGraphVenue === item.venue;
@@ -15848,16 +15937,8 @@ var MarketDetailsContent = ({
15848
15937
  isResolvedMarket ? [] : resolvedMarket == null ? void 0 : resolvedMarket.venueMarkets,
15849
15938
  (_b = scopedResolvedMarket == null ? void 0 : scopedResolvedMarket.id) != null ? _b : null
15850
15939
  );
15851
- const clusterMidpointResult = midpointsResult != null ? midpointsResult : {
15852
- prices: /* @__PURE__ */ new Map(),
15853
- bestMidpointsByOutcomeId: /* @__PURE__ */ new Map(),
15854
- venueByOutcomeId: /* @__PURE__ */ new Map(),
15855
- bestPrices: /* @__PURE__ */ new Map(),
15856
- bestPriceVenuesByOutcomeId: /* @__PURE__ */ new Map(),
15857
- isLoading: false,
15858
- bestMidpoint: void 0,
15859
- bestMidpointVenue: void 0
15860
- };
15940
+ const fetchedClusterMidpointResult = (0, import_hooks51.useMidpoints)(midpointsResult ? [] : clusterVenueMarkets);
15941
+ const clusterMidpointResult = midpointsResult != null ? midpointsResult : fetchedClusterMidpointResult;
15861
15942
  const clusterMidpoints = (_c = clusterMidpointResult.bestMidpointsByOutcomeId) != null ? _c : clusterMidpointResult.prices;
15862
15943
  const clusterBestMidpointsByOutcomeId = clusterMidpoints;
15863
15944
  const clusterVenueByOutcomeId = clusterMidpointResult.venueByOutcomeId;
@@ -16017,18 +16098,24 @@ var MarketDetailsContent = ({
16017
16098
  });
16018
16099
  const bestVenue = candidate == null ? void 0 : candidate.venue;
16019
16100
  const outcomeBestPrice = candidate == null ? void 0 : candidate.price;
16101
+ const isPriceLoading = !isResolvedMarket && outcomeBestPrice == null && clusterMidpointResult.isLoading;
16020
16102
  if (isResolvedMarket) {
16021
16103
  const isWinningOutcome = item.id === ((_a2 = marketTradingState.winningOutcome) == null ? void 0 : _a2.id);
16022
16104
  return __spreadValues(__spreadProps(__spreadValues({}, item), {
16023
- probability: isWinningOutcome ? 1 : 0
16105
+ probability: isWinningOutcome ? 1 : 0,
16106
+ isPriceLoading: false
16024
16107
  }), bestVenue ? { venue: bestVenue } : {});
16025
16108
  }
16026
16109
  if (outcomeBestPrice != null) {
16027
16110
  return __spreadValues(__spreadProps(__spreadValues({}, item), {
16028
- probability: outcomeBestPrice
16111
+ probability: outcomeBestPrice,
16112
+ isPriceLoading: false
16029
16113
  }), bestVenue ? { venue: bestVenue } : {});
16030
16114
  }
16031
- return item;
16115
+ return __spreadProps(__spreadValues({}, item), {
16116
+ probability: void 0,
16117
+ isPriceLoading
16118
+ });
16032
16119
  });
16033
16120
  }, [
16034
16121
  clusterBestMidpoint,
@@ -16050,7 +16137,7 @@ var MarketDetailsContent = ({
16050
16137
  wsBestCandidates
16051
16138
  ]);
16052
16139
  const headlineProbability = (0, import_react28.useMemo)(() => {
16053
- var _a2, _b2, _c2, _d2;
16140
+ var _a2;
16054
16141
  if (!model || !scopedMarketForCard) return void 0;
16055
16142
  if (isResolvedMarket) {
16056
16143
  const yesOutcome2 = resolveYesOutcome(scopedMarketForCard);
@@ -16058,10 +16145,7 @@ var MarketDetailsContent = ({
16058
16145
  return yesOutcome2.winner === true ? 1 : 0;
16059
16146
  }
16060
16147
  const yesOutcome = resolveYesOutcome(scopedMarketForCard);
16061
- const displayOutcome = yesOutcome != null ? yesOutcome : (_b2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _b2.reduce(
16062
- (acc, outcome) => outcome.price > acc.price ? outcome : acc,
16063
- (_a2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _a2[0]
16064
- );
16148
+ const displayOutcome = yesOutcome != null ? yesOutcome : (_a2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _a2[0];
16065
16149
  if (displayOutcome == null) return void 0;
16066
16150
  const referencePrice = getDisplayOutcomePrice({
16067
16151
  outcomeId: displayOutcome.id,
@@ -16071,10 +16155,10 @@ var MarketDetailsContent = ({
16071
16155
  bestMidpoint: clusterBestMidpoint,
16072
16156
  bestMidpointsByOutcomeId: clusterBestMidpointsByOutcomeId,
16073
16157
  livePrices: wsLivePrices,
16074
- fallbackPrice: (_c2 = midpointsFallback == null ? void 0 : midpointsFallback.get(displayOutcome.id)) != null ? _c2 : displayOutcome.price
16158
+ fallbackPrice: midpointsFallback == null ? void 0 : midpointsFallback.get(displayOutcome.id)
16075
16159
  });
16076
16160
  if (referencePrice != null) return referencePrice;
16077
- return (_d2 = (0, import_hooks51.findLivePriceById)(wsLivePrices, displayOutcome.id)) != null ? _d2 : displayOutcome.price;
16161
+ return (0, import_hooks51.findLivePriceById)(wsLivePrices, displayOutcome.id);
16078
16162
  }, [
16079
16163
  clusterBestMidpoint,
16080
16164
  clusterBestMidpointsByOutcomeId,
@@ -18394,7 +18478,7 @@ var mapVenueMarketOutcomesToPlaceOrderOutcomes = (venueMarketOutcomes) => {
18394
18478
  label: outcome.label,
18395
18479
  title: (_a = outcome.title) != null ? _a : null,
18396
18480
  price: outcome.price,
18397
- priceLabel: getTradingPriceLabel(outcome.price)
18481
+ priceLabel: outcome.price != null ? getTradingPriceLabel(outcome.price) : ""
18398
18482
  };
18399
18483
  });
18400
18484
  };
@@ -20614,16 +20698,10 @@ var PlaceOrder = ({
20614
20698
  scopedSelectedMarket ? [scopedSelectedMarket] : void 0
20615
20699
  );
20616
20700
  const wsBestPrices = (0, import_hooks57.useLiveBestPrices)(scopedSelectedMarket ? [scopedSelectedMarket] : void 0);
20617
- const clusterMidpointResult = midpointsResult != null ? midpointsResult : {
20618
- prices: /* @__PURE__ */ new Map(),
20619
- bestMidpointsByOutcomeId: /* @__PURE__ */ new Map(),
20620
- venueByOutcomeId: /* @__PURE__ */ new Map(),
20621
- bestPrices: /* @__PURE__ */ new Map(),
20622
- bestPriceVenuesByOutcomeId: /* @__PURE__ */ new Map(),
20623
- isLoading: false,
20624
- bestMidpoint: void 0,
20625
- bestMidpointVenue: void 0
20626
- };
20701
+ const fetchedClusterMidpointResult = (0, import_hooks57.useMidpoints)(
20702
+ midpointsResult ? [] : scopedSelectedMarket ? [scopedSelectedMarket] : []
20703
+ );
20704
+ const clusterMidpointResult = midpointsResult != null ? midpointsResult : fetchedClusterMidpointResult;
20627
20705
  const clusterBestMidpointsByOutcomeId = (_i = clusterMidpointResult.bestMidpointsByOutcomeId) != null ? _i : clusterMidpointResult.prices;
20628
20706
  const clusterBestMidpoint = clusterMidpointResult.bestMidpoint;
20629
20707
  const clusterBestPricesRest = clusterMidpointResult.bestPrices;
@@ -21806,11 +21884,11 @@ var PlaceOrder = ({
21806
21884
  bestPrices: clusterBestPrices,
21807
21885
  bestMidpoint: clusterBestMidpoint,
21808
21886
  bestMidpointsByOutcomeId: clusterBestMidpointsByOutcomeId,
21809
- livePrices,
21810
- fallbackPrice: outcome.price
21887
+ livePrices
21811
21888
  });
21812
21889
  const isActive = outcome.id === scopedSelectedOutcomeId;
21813
21890
  const isPositive = resolveIsPositiveOutcome(outcome, index);
21891
+ const isPriceLoading = clusterMidpointResult.isLoading && price == null;
21814
21892
  return /* @__PURE__ */ (0, import_jsx_runtime155.jsxs)(
21815
21893
  "button",
21816
21894
  {
@@ -21840,7 +21918,16 @@ var PlaceOrder = ({
21840
21918
  children: (_c2 = outcome.title) != null ? _c2 : outcome.label
21841
21919
  }
21842
21920
  ),
21843
- /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(Typography, { as: "span", variant: isActive ? "body-strong" : "body", children: formatProbabilityCents(price) })
21921
+ isPriceLoading ? /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(
21922
+ "span",
21923
+ {
21924
+ "aria-hidden": "true",
21925
+ className: cn(
21926
+ "agg-place-order-outcome-price-loading",
21927
+ "h-4 w-10 shrink-0 rounded-agg-sm bg-agg-separator animate-pulse"
21928
+ )
21929
+ }
21930
+ ) : /* @__PURE__ */ (0, import_jsx_runtime155.jsx)(Typography, { as: "span", variant: isActive ? "body-strong" : "body", children: formatProbabilityCents(price) })
21844
21931
  ]
21845
21932
  },
21846
21933
  outcome.id
@@ -23027,6 +23114,7 @@ var SPORTS_PERIOD_KEYS = [
23027
23114
  "first_5_innings",
23028
23115
  "other"
23029
23116
  ];
23117
+ var SPORTS_PERIOD_GRAMMAR_PATTERN = /^(?:(set|map|game|period|inning)_(\d{1,2})|first_(\d{1,2})_innings)$/;
23030
23118
  var SPORTS_MARKET_CATEGORY_KEYS = [
23031
23119
  "game_lines",
23032
23120
  "exact_score",
@@ -23155,9 +23243,22 @@ var stripLineValueFromQuestion = (question) => {
23155
23243
  const strippedQuestion = sanitizeFamilyValue(question);
23156
23244
  return strippedQuestion ? question.replace(/\(\s*[+-]?\d+(?:\.\d+)?\s*\)\s*$/g, "").replace(/\s+[+-]?\d+(?:\.\d+)?\s*$/g, "").replace(/\s+/g, " ").trim() : question.trim();
23157
23245
  };
23246
+ var SPORTS_PERIOD_FAMILY_ORDER = ["period", "inning", "set", "map", "game"];
23158
23247
  var getSportsPeriodOrderIndex = (period) => {
23248
+ var _a, _b;
23159
23249
  const periodIndex = SPORTS_PERIOD_ORDER.indexOf(period);
23160
- return periodIndex >= 0 ? periodIndex : SPORTS_PERIOD_ORDER.length;
23250
+ if (periodIndex >= 0) {
23251
+ return period === "other" ? Number.MAX_SAFE_INTEGER : periodIndex;
23252
+ }
23253
+ const grammarMatch = SPORTS_PERIOD_GRAMMAR_PATTERN.exec(period);
23254
+ if (grammarMatch) {
23255
+ const familyIndex = grammarMatch[1] ? SPORTS_PERIOD_FAMILY_ORDER.indexOf(
23256
+ grammarMatch[1]
23257
+ ) : SPORTS_PERIOD_FAMILY_ORDER.length;
23258
+ const scopeNumber = Number((_b = (_a = grammarMatch[2]) != null ? _a : grammarMatch[3]) != null ? _b : 0);
23259
+ return SPORTS_PERIOD_ORDER.length + familyIndex * 100 + scopeNumber;
23260
+ }
23261
+ return Number.MAX_SAFE_INTEGER - 1;
23161
23262
  };
23162
23263
  var getSportsMarketTypeOrderIndex = (sportsMarketType) => {
23163
23264
  if (!sportsMarketType) return SPORTS_MARKET_TYPE_ORDER.length;
@@ -23174,7 +23275,10 @@ var resolveSportsSectionDefinition = (key) => {
23174
23275
  var normalizeSportsPeriod = (value) => {
23175
23276
  const resolvedValue = toTrimmedString(value).toLowerCase();
23176
23277
  if (!resolvedValue) return "full";
23177
- return SPORTS_PERIOD_KEY_SET.has(resolvedValue) ? resolvedValue : "other";
23278
+ if (resolvedValue === "match") return "full";
23279
+ if (SPORTS_PERIOD_KEY_SET.has(resolvedValue)) return resolvedValue;
23280
+ if (SPORTS_PERIOD_GRAMMAR_PATTERN.test(resolvedValue)) return resolvedValue;
23281
+ return "other";
23178
23282
  };
23179
23283
  var normalizeSportsMarketType = (value) => {
23180
23284
  const resolvedValue = toTrimmedString(value).toLowerCase();
@@ -23257,8 +23361,7 @@ var isBinarySportsMoneylineMarket = (market) => {
23257
23361
  );
23258
23362
  const marketSubtype = toTrimmedString(market.marketSubtype).toLowerCase();
23259
23363
  const marketGroup = normalizeSportsMarketGroup(market.marketGroup);
23260
- const hasMoneylineAggKey = toTrimmedString(market.aggKey).includes("_ml_");
23261
- return (marketSubtype === "moneyline" || hasMoneylineAggKey) && marketGroup === "game_lines" && normalizeSportsPeriod(market.period) === "full" && normalizedOutcomeLabels.length === 2 && normalizedOutcomeLabels.every((label2) => YES_NO_LABELS.has(label2));
23364
+ return marketSubtype === "moneyline" && marketGroup === "game_lines" && normalizeSportsPeriod(market.period) === "full" && normalizedOutcomeLabels.length === 2 && normalizedOutcomeLabels.every((label2) => YES_NO_LABELS.has(label2));
23262
23365
  };
23263
23366
  var resolveDisplayGroupFamilyKey = (market) => {
23264
23367
  var _a, _b, _c;
@@ -23483,6 +23586,15 @@ var buildSportsSlideFromGroup = (group) => {
23483
23586
  defaultStopIndex
23484
23587
  };
23485
23588
  };
23589
+ var formatSportsPeriodGrammarLabel = (period) => {
23590
+ const grammarMatch = SPORTS_PERIOD_GRAMMAR_PATTERN.exec(period);
23591
+ if (!grammarMatch) return null;
23592
+ if (grammarMatch[1]) {
23593
+ const family = grammarMatch[1].charAt(0).toUpperCase() + grammarMatch[1].slice(1);
23594
+ return `${family} ${Number(grammarMatch[2])}`;
23595
+ }
23596
+ return `First ${Number(grammarMatch[3])} Innings`;
23597
+ };
23486
23598
  var resolveSportsCategoryTokens = (event) => {
23487
23599
  return new Set(
23488
23600
  event.categories.flatMap((entry) => {
@@ -23616,7 +23728,7 @@ var SportsMarketCard = ({
23616
23728
  const combinedMoneylineHeaderOutcomeItems = (0, import_react39.useMemo)(() => {
23617
23729
  if (!isCombinedMoneylineGroup) return void 0;
23618
23730
  return combinedMoneylineMarkets.flatMap((market, index) => {
23619
- var _a2;
23731
+ var _a2, _b2;
23620
23732
  const typedMarket = market;
23621
23733
  const yesOutcome = market.venueMarketOutcomes.find(
23622
23734
  (outcome) => outcome.label.trim().toLowerCase() === "yes"
@@ -23624,19 +23736,25 @@ var SportsMarketCard = ({
23624
23736
  if (!yesOutcome) return [];
23625
23737
  const label2 = ((_a2 = typedMarket.shortTitle) == null ? void 0 : _a2.trim()) || market.question.trim();
23626
23738
  if (!label2) return [];
23739
+ const probability = midpointsResult == null ? void 0 : getDisplayOutcomePrice({
23740
+ outcomeId: yesOutcome.id,
23741
+ outcomeLabel: yesOutcome.label,
23742
+ bestMidpointsByOutcomeId: (_b2 = midpointsResult.bestMidpointsByOutcomeId) != null ? _b2 : midpointsResult.prices
23743
+ });
23627
23744
  return [
23628
23745
  {
23629
23746
  id: yesOutcome.id,
23630
23747
  label: label2,
23631
23748
  title: label2,
23632
- probability: yesOutcome.price,
23749
+ probability,
23750
+ isPriceLoading: (midpointsResult == null ? void 0 : midpointsResult.isLoading) === true && probability == null,
23633
23751
  tone: index === 0 ? "positive" : "negative",
23634
23752
  variant: "outcome",
23635
23753
  venue: market.venue
23636
23754
  }
23637
23755
  ];
23638
23756
  });
23639
- }, [combinedMoneylineMarkets, isCombinedMoneylineGroup]);
23757
+ }, [combinedMoneylineMarkets, isCombinedMoneylineGroup, midpointsResult]);
23640
23758
  const headerOutcomeVariant = isCombinedMoneylineGroup ? "outcome" : resolveSportsMarketCardVariant(activeMarket);
23641
23759
  const handleLineSelect = (index) => {
23642
23760
  var _a2, _b2;
@@ -23720,6 +23838,7 @@ var resolveSportsSectionLabel = (labels, key) => {
23720
23838
  }
23721
23839
  };
23722
23840
  var resolveSportsPeriodLabel = (labels, period) => {
23841
+ var _a;
23723
23842
  switch (period) {
23724
23843
  case "full":
23725
23844
  return labels.eventMarketPage.sports.fullPeriod;
@@ -23747,6 +23866,8 @@ var resolveSportsPeriodLabel = (labels, period) => {
23747
23866
  return "1st 5 Innings";
23748
23867
  case "other":
23749
23868
  return labels.eventMarketPage.sports.otherPeriod;
23869
+ default:
23870
+ return (_a = formatSportsPeriodGrammarLabel(period)) != null ? _a : labels.eventMarketPage.sports.otherPeriod;
23750
23871
  }
23751
23872
  };
23752
23873
  var SportsTabButton = ({