@agg-build/ui 1.2.9 → 1.2.11

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 (100) hide show
  1. package/dist/{chunk-PFOSEY46.mjs → chunk-3ZSNHGAB.mjs} +835 -401
  2. package/dist/{chunk-5PSAIGOT.mjs → chunk-54PCEK6G.mjs} +137 -61
  3. package/dist/{chunk-7JKGAWU5.mjs → chunk-ENAGASVU.mjs} +1538 -1369
  4. package/dist/{chunk-K23CJ5UP.mjs → chunk-J7K2U44E.mjs} +481 -258
  5. package/dist/{chunk-5MDFM2MX.mjs → chunk-NWJHFGBZ.mjs} +1 -1
  6. package/dist/{chunk-QFW5NDJ6.mjs → chunk-SJLHOAKK.mjs} +1001 -1015
  7. package/dist/{chunk-PYKD4W4T.mjs → chunk-YP75TIY6.mjs} +601 -326
  8. package/dist/events.js +2038 -1559
  9. package/dist/events.mjs +3 -3
  10. package/dist/index.js +5417 -4261
  11. package/dist/index.mjs +56 -50
  12. package/dist/modals.js +3262 -2384
  13. package/dist/modals.mjs +3 -3
  14. package/dist/pages.js +3677 -2709
  15. package/dist/pages.mjs +6 -6
  16. package/dist/primitives.js +992 -918
  17. package/dist/primitives.mjs +5 -1
  18. package/dist/styles.css +1 -1
  19. package/dist/tailwind.css +1 -1
  20. package/dist/trading.js +1360 -1129
  21. package/dist/trading.mjs +4 -4
  22. package/dist/types/deposit/deposit-modal.types.d.mts +10 -1
  23. package/dist/types/deposit/deposit-modal.types.d.ts +10 -1
  24. package/dist/types/deposit/index.d.mts +1 -1
  25. package/dist/types/deposit/index.d.ts +1 -1
  26. package/dist/types/deposit/steps/crypto-transfer.d.mts +1 -2
  27. package/dist/types/deposit/steps/crypto-transfer.d.ts +1 -2
  28. package/dist/types/deposit/steps/deposit-method.d.mts +2 -1
  29. package/dist/types/deposit/steps/deposit-method.d.ts +2 -1
  30. package/dist/types/events/item/event-list-item.types.d.mts +3 -1
  31. package/dist/types/events/item/event-list-item.types.d.ts +3 -1
  32. package/dist/types/events/item/event-list-item.utils.d.mts +26 -2
  33. package/dist/types/events/item/event-list-item.utils.d.ts +26 -2
  34. package/dist/types/events/item-details/event-list-item-details.types.d.mts +30 -1
  35. package/dist/types/events/item-details/event-list-item-details.types.d.ts +30 -1
  36. package/dist/types/events/market-details/index.d.mts +1 -1
  37. package/dist/types/events/market-details/index.d.ts +1 -1
  38. package/dist/types/events/market-details/market-details.types.d.mts +27 -2
  39. package/dist/types/events/market-details/market-details.types.d.ts +27 -2
  40. package/dist/types/events/market-details/market-details.utils.d.mts +18 -4
  41. package/dist/types/events/market-details/market-details.utils.d.ts +18 -4
  42. package/dist/types/events/market-details/orderbook-aggregation.d.mts +38 -2
  43. package/dist/types/events/market-details/orderbook-aggregation.d.ts +38 -2
  44. package/dist/types/events/shared/chart-auto-fallback.d.mts +43 -0
  45. package/dist/types/events/shared/chart-auto-fallback.d.ts +43 -0
  46. package/dist/types/events/shared/display-outcome-price.d.mts +14 -0
  47. package/dist/types/events/shared/display-outcome-price.d.ts +14 -0
  48. package/dist/types/events/shared/display-outcome-venue.d.mts +30 -0
  49. package/dist/types/events/shared/display-outcome-venue.d.ts +30 -0
  50. package/dist/types/events/shared/display-reference-price.d.mts +4 -0
  51. package/dist/types/events/shared/display-reference-price.d.ts +4 -0
  52. package/dist/types/events/shared/select-outcome-price.d.mts +21 -0
  53. package/dist/types/events/shared/select-outcome-price.d.ts +21 -0
  54. package/dist/types/pages/user-profile/components/available-balance-card.d.mts +2 -1
  55. package/dist/types/pages/user-profile/components/available-balance-card.d.ts +2 -1
  56. package/dist/types/pages/user-profile/components/positions-value-card.d.mts +2 -1
  57. package/dist/types/pages/user-profile/components/positions-value-card.d.ts +2 -1
  58. package/dist/types/pages/user-profile/index.d.mts +2 -2
  59. package/dist/types/pages/user-profile/index.d.ts +2 -2
  60. package/dist/types/pages/user-profile/user-profile.types.d.mts +54 -1
  61. package/dist/types/pages/user-profile/user-profile.types.d.ts +54 -1
  62. package/dist/types/primitives/chart/chart.utils.d.mts +9 -10
  63. package/dist/types/primitives/chart/chart.utils.d.ts +9 -10
  64. package/dist/types/primitives/icon/index.d.mts +2 -1
  65. package/dist/types/primitives/icon/index.d.ts +2 -1
  66. package/dist/types/primitives/icon/registry.d.mts +8 -0
  67. package/dist/types/primitives/icon/registry.d.ts +8 -0
  68. package/dist/types/primitives/icon/svg/circle-xmark.d.mts +5 -0
  69. package/dist/types/primitives/icon/svg/circle-xmark.d.ts +5 -0
  70. package/dist/types/primitives/icon/svg/spinner.d.mts +5 -0
  71. package/dist/types/primitives/icon/svg/spinner.d.ts +5 -0
  72. package/dist/types/primitives/toast/index.d.mts +2 -0
  73. package/dist/types/primitives/toast/index.d.ts +2 -0
  74. package/dist/types/primitives/tooltip/tooltip.types.d.mts +1 -0
  75. package/dist/types/primitives/tooltip/tooltip.types.d.ts +1 -0
  76. package/dist/types/primitives/typography/index.d.mts +1 -1
  77. package/dist/types/primitives/typography/index.d.ts +1 -1
  78. package/dist/types/primitives/typography/typography.types.d.mts +2 -0
  79. package/dist/types/primitives/typography/typography.types.d.ts +2 -0
  80. package/dist/types/shared/transfer-fee-summary.d.mts +10 -0
  81. package/dist/types/shared/transfer-fee-summary.d.ts +10 -0
  82. package/dist/types/shared/utils.d.mts +3 -0
  83. package/dist/types/shared/utils.d.ts +3 -0
  84. package/dist/types/trading/place-order/index.d.mts +1 -1
  85. package/dist/types/trading/place-order/index.d.ts +1 -1
  86. package/dist/types/trading/place-order/index.place-order.execution-steps.d.mts +9 -0
  87. package/dist/types/trading/place-order/index.place-order.execution-steps.d.ts +9 -0
  88. package/dist/types/trading/place-order/index.place-order.types.d.mts +15 -2
  89. package/dist/types/trading/place-order/index.place-order.types.d.ts +15 -2
  90. package/dist/types/trading/place-order/index.place-order.utils.d.mts +49 -6
  91. package/dist/types/trading/place-order/index.place-order.utils.d.ts +49 -6
  92. package/dist/types/withdraw/index.d.mts +1 -1
  93. package/dist/types/withdraw/index.d.ts +1 -1
  94. package/dist/types/withdraw/steps/withdraw-success.d.mts +13 -7
  95. package/dist/types/withdraw/steps/withdraw-success.d.ts +13 -7
  96. package/dist/types/withdraw/steps/withdraw-success.utils.d.mts +2 -0
  97. package/dist/types/withdraw/steps/withdraw-success.utils.d.ts +2 -0
  98. package/dist/types/withdraw/withdraw-modal.types.d.mts +5 -0
  99. package/dist/types/withdraw/withdraw-modal.types.d.ts +5 -0
  100. package/package.json +3 -3
@@ -4,8 +4,8 @@ import {
4
4
  buildMarketDetailsModel,
5
5
  formatProbabilityCents,
6
6
  formatProbabilityPercent,
7
+ getDisplayOutcomePrice,
7
8
  getFirstSettlementParagraph,
8
- getTimeWindowByRange,
9
9
  resolveHeaderOutcomeItems,
10
10
  resolveInitialOutcomeLabel,
11
11
  resolveInitialTab,
@@ -15,19 +15,20 @@ import {
15
15
  resolveMarketFromVenueMarkets,
16
16
  resolveOtherTabRows,
17
17
  resolveOutcomesByVenue,
18
+ resolveScopedSelectedOutcome,
18
19
  resolveSeriesColor,
19
20
  resolveTradingStateBadgeClassName,
20
21
  resolveTradingStatePresentation,
21
22
  resolveUnifiedOrderBookEntries,
23
+ selectOutcomePrice,
22
24
  sortOutcomeSelectorOutcomes,
23
25
  useEventTradingContext
24
- } from "./chunk-5PSAIGOT.mjs";
26
+ } from "./chunk-54PCEK6G.mjs";
25
27
  import {
26
28
  AutocompleteSelect,
27
29
  Badge,
28
30
  Button,
29
31
  Card,
30
- DEFAULT_EVENTS_LIMIT,
31
32
  Icon,
32
33
  LineChart,
33
34
  MOBILE_TABS_MEDIA_QUERY,
@@ -46,7 +47,6 @@ import {
46
47
  __spreadProps,
47
48
  __spreadValues,
48
49
  baseCardClassName,
49
- buildSpreadByVenueMarketId,
50
50
  cn,
51
51
  dedupeVenueMarketsById,
52
52
  detailsBaseCardClassName,
@@ -54,17 +54,14 @@ import {
54
54
  formatCountLabel,
55
55
  formatMarketProbabilityPercent,
56
56
  formatPriceGapPercent,
57
- getDefaultEventListTabs,
58
57
  getMarketDetailsTabs,
59
58
  getMotionClassName,
60
- isYesLabel,
61
59
  mapEventToEventListItemEvent,
62
60
  marketDetailsBaseCardClassName,
63
61
  marketDetailsDefaultIsOpened,
64
62
  normalizeProbability,
65
63
  normalizeVenueMarketCluster,
66
64
  orderBookRowLimitDefault,
67
- resolveBestMidpointForMarket,
68
65
  resolveDisplayVolume,
69
66
  resolveEventListItemEvent,
70
67
  resolveOutcomeTitle,
@@ -73,14 +70,16 @@ import {
73
70
  sortMarketsByYesOddsDesc,
74
71
  sortOutcomes,
75
72
  splitEventsByLifecycle
76
- } from "./chunk-QFW5NDJ6.mjs";
73
+ } from "./chunk-SJLHOAKK.mjs";
77
74
 
78
75
  // src/events/item/index.tsx
79
76
  import {
80
77
  computePriceGaps,
81
78
  optimizedImageUrl,
82
79
  sortVenues,
80
+ useEventTradingContext as useEventTradingContext2,
83
81
  useLabels,
82
+ useMidpoints,
84
83
  useSdkUiConfig,
85
84
  useVenueEvent,
86
85
  useVenueMarketMidpoints,
@@ -98,6 +97,32 @@ var isErrorWithStatus = (error, status) => {
98
97
  return getErrorStatus(error) === status;
99
98
  };
100
99
 
100
+ // src/events/shared/display-outcome-venue.ts
101
+ var normalizeOutcomeLabel = (label) => {
102
+ return typeof label === "string" ? label.trim().toLowerCase() : "";
103
+ };
104
+ var getDisplayOutcomeVenue = ({
105
+ outcomeId,
106
+ outcomeLabel,
107
+ selection,
108
+ bestMidpointVenue,
109
+ bestVenueByOutcomeId,
110
+ bestPriceVenuesByOutcomeId,
111
+ fallbackVenue
112
+ }) => {
113
+ var _a;
114
+ if (selection && outcomeId) {
115
+ const sideVenues = bestPriceVenuesByOutcomeId == null ? void 0 : bestPriceVenuesByOutcomeId.get(outcomeId);
116
+ if (selection === "buy" && (sideVenues == null ? void 0 : sideVenues.bestAskVenue)) return sideVenues.bestAskVenue;
117
+ if (selection === "sell" && (sideVenues == null ? void 0 : sideVenues.bestBidVenue)) return sideVenues.bestBidVenue;
118
+ }
119
+ if (normalizeOutcomeLabel(outcomeLabel) === "yes" && bestMidpointVenue) {
120
+ return bestMidpointVenue;
121
+ }
122
+ const bestVenue = outcomeId ? bestVenueByOutcomeId == null ? void 0 : bestVenueByOutcomeId.get(outcomeId) : void 0;
123
+ return (_a = bestVenue != null ? bestVenue : fallbackVenue) != null ? _a : void 0;
124
+ };
125
+
101
126
  // src/events/item/index.tsx
102
127
  import { jsx, jsxs } from "react/jsx-runtime";
103
128
  var EventListItemLoadingState = ({
@@ -159,7 +184,6 @@ var EventListItemNotFoundState = ({
159
184
  );
160
185
  };
161
186
  var OUTCOMES_SCROLL_LOAD_THRESHOLD_PX = 16;
162
- var isNoLabel = (label) => label.trim().toLowerCase() === "no";
163
187
  var MARKET_ID_QUERY_PARAM = "marketId";
164
188
  var OUTCOME_ID_QUERY_PARAM = "outcomeId";
165
189
  var resolveMarketHrefFromEventHref = (eventHref, marketId, outcomeId) => {
@@ -182,18 +206,20 @@ var EventListItemContent = ({
182
206
  onMarketClick,
183
207
  getMarketHref,
184
208
  href,
185
- ariaLabel
209
+ ariaLabel,
210
+ marketStatus
186
211
  }) => {
212
+ var _a;
187
213
  const config = useSdkUiConfig();
188
214
  const labels = useLabels();
189
- const allVenueMarkets = useMemo(() => {
190
- return dedupeVenueMarketsById(event.venueMarkets);
191
- }, [event.venueMarkets]);
215
+ const tradingContext = useEventTradingContext2();
216
+ const tradeSide = (_a = tradingContext == null ? void 0 : tradingContext.tradeSide) != null ? _a : "buy";
217
+ const allVenueMarkets = useMemo(() => event.venueMarkets, [event.venueMarkets]);
192
218
  const resolvedTitle = event.title;
193
219
  const resolvedImage = event.image;
194
220
  const visibleVenueLogos = useMemo(() => {
195
- var _a;
196
- return sortVenues(Array.from(new Set(((_a = event.venues) != null ? _a : []).map((venue) => venue))));
221
+ var _a2;
222
+ return sortVenues(Array.from(new Set(((_a2 = event.venues) != null ? _a2 : []).map((venue) => venue))));
197
223
  }, [event.venues]);
198
224
  const resolvedMarketCount = typeof event.marketCount === "number" && Number.isFinite(event.marketCount) ? Math.max(0, Math.floor(event.marketCount)) : allVenueMarkets.length;
199
225
  const resolvedVenueCount = typeof event.venueCount === "number" && Number.isFinite(event.venueCount) ? Math.max(0, Math.floor(event.venueCount)) : visibleVenueLogos.length;
@@ -216,18 +242,19 @@ var EventListItemContent = ({
216
242
  venueEventId: event.id,
217
243
  enabled: shouldEnableLazyMarketLoading && isLazyMarketsQueryEnabled,
218
244
  sortBy: "yesPrice",
219
- sortDir: "desc"
245
+ sortDir: "desc",
246
+ status: marketStatus
220
247
  });
221
248
  const resolvedOutcomeMarkets = useMemo(() => {
222
249
  if (!isLazyMarketsQueryEnabled || lazyLoadedMarkets.length === 0) return allVenueMarkets;
223
250
  return dedupeVenueMarketsById([...allVenueMarkets, ...lazyLoadedMarkets]);
224
251
  }, [allVenueMarkets, isLazyMarketsQueryEnabled, lazyLoadedMarkets]);
225
252
  const midpointVenueMarketIds = useMemo(() => {
226
- var _a;
253
+ var _a2;
227
254
  const ids = [];
228
255
  for (const market of resolvedOutcomeMarkets) {
229
256
  ids.push(market.id);
230
- for (const sibling of (_a = market.matchedVenueMarkets) != null ? _a : []) {
257
+ for (const sibling of (_a2 = market.matchedVenueMarkets) != null ? _a2 : []) {
231
258
  ids.push(sibling.id);
232
259
  }
233
260
  }
@@ -235,17 +262,19 @@ var EventListItemContent = ({
235
262
  }, [resolvedOutcomeMarkets]);
236
263
  const {
237
264
  midpointsByVenueMarketId,
238
- midpointRows,
239
265
  isLoading: isLoadingMidpoints,
240
266
  isFetching: isFetchingMidpoints
241
267
  } = useVenueMarketMidpoints({
242
268
  venueMarketIds: midpointVenueMarketIds,
243
269
  enabled: midpointVenueMarketIds.length > 0
244
270
  });
245
- const spreadByVenueMarketId = useMemo(
246
- () => buildSpreadByVenueMarketId(midpointRows),
247
- [midpointRows]
248
- );
271
+ const {
272
+ prices: displayMidpointsByOutcomeId,
273
+ venueByOutcomeId: displayMidpointVenueByOutcomeId,
274
+ bestPrices: displayBestPricesByOutcomeId,
275
+ bestPriceVenuesByOutcomeId: displayBestPriceVenuesByOutcomeId,
276
+ isLoading: isDisplayMidpointsLoading
277
+ } = useMidpoints(resolvedOutcomeMarkets);
249
278
  const gapsByVenueMarketId = useMemo(
250
279
  () => computePriceGaps({
251
280
  markets: resolvedOutcomeMarkets,
@@ -253,7 +282,7 @@ var EventListItemContent = ({
253
282
  }),
254
283
  [resolvedOutcomeMarkets, midpointsByVenueMarketId]
255
284
  );
256
- const isMidpointQueryInFlight = isLoadingMidpoints || isFetchingMidpoints;
285
+ const isMidpointQueryInFlight = isLoadingMidpoints || isFetchingMidpoints || isDisplayMidpointsLoading;
257
286
  const shouldRenderLoadingOutcomeRow = shouldEnableLazyMarketLoading && (!isLazyMarketsQueryEnabled || isLoadingLazyMarkets || isFetchingNextLazyMarketsPage || hasNextLazyMarketsPage);
258
287
  const resolvedVolume = resolveDisplayVolume(event.volume, allVenueMarkets);
259
288
  const volumeLabel = typeof resolvedVolume === "number" ? `${config.formatting.formatCompactCurrency(resolvedVolume)} ${labels.eventItem.volumeSuffix}` : "";
@@ -366,7 +395,7 @@ var EventListItemContent = ({
366
395
  );
367
396
  };
368
397
  const renderOutcomePriceBadge = (probability, venue, shouldRenderLoadingSkeleton, market, outcome) => {
369
- var _a;
398
+ var _a2;
370
399
  if (shouldRenderLoadingSkeleton) {
371
400
  return /* @__PURE__ */ jsx(
372
401
  "div",
@@ -379,7 +408,7 @@ var EventListItemContent = ({
379
408
  );
380
409
  }
381
410
  if (typeof probability !== "number") return null;
382
- const marketHref = (_a = getMarketHref == null ? void 0 : getMarketHref(event, market, outcome)) != null ? _a : resolveMarketHrefFromEventHref(href, market.id, outcome.id);
411
+ const marketHref = (_a2 = getMarketHref == null ? void 0 : getMarketHref(event, market, outcome)) != null ? _a2 : resolveMarketHrefFromEventHref(href, market.id, outcome.id);
383
412
  const isInteractive = Boolean(onMarketClick || marketHref);
384
413
  return /* @__PURE__ */ jsx(
385
414
  Badge,
@@ -460,39 +489,26 @@ var EventListItemContent = ({
460
489
  ),
461
490
  onScroll: handleOutcomesScroll,
462
491
  children: [
463
- resolvedOutcomeMarkets.length === 1 ? (() => {
464
- var _a;
492
+ resolvedMarketCount === 1 && resolvedOutcomeMarkets.length === 1 ? (() => {
465
493
  const market = resolvedOutcomeMarkets[0];
466
- const bestMidpoint = resolveBestMidpointForMarket(
467
- market,
468
- midpointsByVenueMarketId,
469
- spreadByVenueMarketId
470
- );
471
- const marketMidpoint = bestMidpoint != null ? normalizeProbability(bestMidpoint.midpoint) : void 0;
472
- const bestVenue = (_a = bestMidpoint == null ? void 0 : bestMidpoint.venue) != null ? _a : market.venue;
473
- const hasYesOutcome = market.venueMarketOutcomes.some(
474
- (item) => isYesLabel(item.label)
475
- );
476
- const hasNoOutcome = market.venueMarketOutcomes.some((item) => isNoLabel(item.label));
477
- const shouldUseMidpoint = hasYesOutcome && hasNoOutcome;
478
494
  return sortOutcomes(market.venueMarketOutcomes).map((outcome) => {
479
- const probability = (() => {
480
- if (!shouldUseMidpoint) {
481
- return normalizeProbability(outcome.price);
482
- }
483
- if (marketMidpoint == null) {
484
- if (isMidpointQueryInFlight) return void 0;
485
- return normalizeProbability(outcome.price);
486
- }
487
- if (isYesLabel(outcome.label)) {
488
- return marketMidpoint;
489
- }
490
- if (isNoLabel(outcome.label)) {
491
- return normalizeProbability(1 - marketMidpoint);
492
- }
493
- return normalizeProbability(outcome.price);
494
- })();
495
- const shouldRenderMidpointSkeleton = shouldUseMidpoint && marketMidpoint == null && isMidpointQueryInFlight;
495
+ var _a2;
496
+ const resolvedDisplayPrice = selectOutcomePrice({
497
+ outcomeId: outcome.id,
498
+ selection: tradeSide,
499
+ bestPrices: displayBestPricesByOutcomeId,
500
+ bestMidpointsByOutcomeId: displayMidpointsByOutcomeId
501
+ });
502
+ const midpointProbability = resolvedDisplayPrice;
503
+ const probability = midpointProbability != null ? normalizeProbability(midpointProbability) : isMidpointQueryInFlight ? void 0 : normalizeProbability(outcome.price);
504
+ const displayVenue = (_a2 = getDisplayOutcomeVenue({
505
+ outcomeId: outcome.id,
506
+ selection: tradeSide,
507
+ bestVenueByOutcomeId: displayMidpointVenueByOutcomeId,
508
+ bestPriceVenuesByOutcomeId: displayBestPriceVenuesByOutcomeId,
509
+ fallbackVenue: market.venue
510
+ })) != null ? _a2 : market.venue;
511
+ const shouldRenderMidpointSkeleton = midpointProbability == null && isMidpointQueryInFlight;
496
512
  const arbitragePercent = arbitrageByOutcomeId == null ? void 0 : arbitrageByOutcomeId[outcome.id];
497
513
  const _priceGapPct = gapsByVenueMarketId.get(market.id);
498
514
  return /* @__PURE__ */ jsxs(
@@ -516,7 +532,7 @@ var EventListItemContent = ({
516
532
  renderArbitrage(arbitragePercent),
517
533
  renderOutcomePriceBadge(
518
534
  probability,
519
- bestVenue,
535
+ displayVenue,
520
536
  shouldRenderMidpointSkeleton,
521
537
  market,
522
538
  outcome
@@ -528,21 +544,27 @@ var EventListItemContent = ({
528
544
  );
529
545
  });
530
546
  })() : sortMarketsByYesOddsDesc(resolvedOutcomeMarkets).map((market) => {
531
- var _a, _b, _c;
547
+ var _a2, _b, _c;
532
548
  const yesOutcome = resolveYesOutcome(market);
533
549
  const displayOutcome = yesOutcome != null ? yesOutcome : (_b = market.venueMarketOutcomes) == null ? void 0 : _b.reduce(
534
550
  (acc, o) => o.price > acc.price ? o : acc,
535
- (_a = market.venueMarketOutcomes) == null ? void 0 : _a[0]
536
- );
537
- const bestMidpoint = resolveBestMidpointForMarket(
538
- market,
539
- midpointsByVenueMarketId,
540
- spreadByVenueMarketId
551
+ (_a2 = market.venueMarketOutcomes) == null ? void 0 : _a2[0]
541
552
  );
542
- const marketMidpoint = bestMidpoint != null ? normalizeProbability(bestMidpoint.midpoint) : void 0;
543
- const bestVenue = (_c = bestMidpoint == null ? void 0 : bestMidpoint.venue) != null ? _c : market.venue;
544
- const probability = marketMidpoint != null ? marketMidpoint : isMidpointQueryInFlight ? void 0 : normalizeProbability(displayOutcome == null ? void 0 : displayOutcome.price);
545
- const shouldRenderMidpointSkeleton = marketMidpoint == null && isMidpointQueryInFlight;
553
+ const midpointProbability = displayOutcome != null ? selectOutcomePrice({
554
+ outcomeId: displayOutcome.id,
555
+ selection: tradeSide,
556
+ bestPrices: displayBestPricesByOutcomeId,
557
+ bestMidpointsByOutcomeId: displayMidpointsByOutcomeId
558
+ }) : void 0;
559
+ const bestVenue = (_c = displayOutcome != null ? getDisplayOutcomeVenue({
560
+ outcomeId: displayOutcome.id,
561
+ selection: tradeSide,
562
+ bestVenueByOutcomeId: displayMidpointVenueByOutcomeId,
563
+ bestPriceVenuesByOutcomeId: displayBestPriceVenuesByOutcomeId,
564
+ fallbackVenue: market.venue
565
+ }) : void 0) != null ? _c : market.venue;
566
+ const probability = midpointProbability != null ? normalizeProbability(midpointProbability) : isMidpointQueryInFlight ? void 0 : normalizeProbability(displayOutcome == null ? void 0 : displayOutcome.price);
567
+ const shouldRenderMidpointSkeleton = midpointProbability == null && isMidpointQueryInFlight;
546
568
  const arbitragePercent = arbitrageByOutcomeId == null ? void 0 : arbitrageByOutcomeId[market.id];
547
569
  const outcomeTitle = market.question;
548
570
  const _priceGapPct = gapsByVenueMarketId.get(market.id);
@@ -720,12 +742,12 @@ var fromScaled = (value, precision) => {
720
742
  var toPriceKey = (price) => {
721
743
  return String(toScaled(price, PRICE_PRECISION));
722
744
  };
723
- var normalizeOutcomeLabel = (value) => {
745
+ var normalizeOutcomeLabel2 = (value) => {
724
746
  if (typeof value !== "string") return "";
725
747
  return value.trim().toLowerCase().replace(/[_-]+/g, " ").replace(/[^\p{L}\p{N}\s]/gu, " ").replace(/\s+/g, " ");
726
748
  };
727
749
  var toSemanticOutcomeLabel = (value) => {
728
- const normalizedValue = normalizeOutcomeLabel(value);
750
+ const normalizedValue = normalizeOutcomeLabel2(value);
729
751
  if (!normalizedValue) return "";
730
752
  if (POSITIVE_OUTCOME_KEYS.has(normalizedValue)) return "yes";
731
753
  if (NEGATIVE_OUTCOME_KEYS.has(normalizedValue)) return "no";
@@ -739,10 +761,10 @@ var getOutcomeLabelCandidates = (outcome) => {
739
761
  );
740
762
  };
741
763
  var matchesSelectedOutcomeLabel = (outcome, selectedOutcomeLabel) => {
742
- const normalizedSelectedLabel = normalizeOutcomeLabel(selectedOutcomeLabel);
764
+ const normalizedSelectedLabel = normalizeOutcomeLabel2(selectedOutcomeLabel);
743
765
  const semanticSelectedLabel = toSemanticOutcomeLabel(selectedOutcomeLabel);
744
766
  return getOutcomeLabelCandidates(outcome).some((candidate) => {
745
- const normalizedCandidate = normalizeOutcomeLabel(candidate);
767
+ const normalizedCandidate = normalizeOutcomeLabel2(candidate);
746
768
  if (!normalizedCandidate) return false;
747
769
  return normalizedCandidate === normalizedSelectedLabel || toSemanticOutcomeLabel(candidate) === semanticSelectedLabel;
748
770
  });
@@ -882,36 +904,143 @@ var accumulateSideLevels = ({
882
904
  };
883
905
  var collectEligibleVenueOutcomes = ({
884
906
  venueMarkets,
885
- selectedOutcomeLabel
907
+ selectedOutcomeLabel,
908
+ selectedOutcomeId
886
909
  }) => {
910
+ var _a, _b, _c;
887
911
  if (!selectedOutcomeLabel) return [];
912
+ const semanticLabel = toSemanticOutcomeLabel(selectedOutcomeLabel);
913
+ const seenMarketIds = /* @__PURE__ */ new Set();
888
914
  const seenOutcomeIds = /* @__PURE__ */ new Set();
889
- return venueMarkets.flatMap((market) => {
915
+ const result = [];
916
+ if (selectedOutcomeId) {
917
+ for (const market of venueMarkets) {
918
+ const outcome = market.venueMarketOutcomes.find((o) => o.id === selectedOutcomeId);
919
+ if (!outcome) continue;
920
+ const refs = (_a = outcome.matchedVenueMarketOutcomes) != null ? _a : [];
921
+ if (refs.length > 0) {
922
+ seenMarketIds.add(market.id);
923
+ seenOutcomeIds.add(outcome.id);
924
+ result.push({
925
+ venue: market.venue,
926
+ market,
927
+ outcome,
928
+ outcomeId: outcome.id,
929
+ semanticLabel
930
+ });
931
+ for (const ref of refs) {
932
+ if (seenMarketIds.has(ref.venueMarketId)) continue;
933
+ const sibling = venueMarkets.find((m) => m.id === ref.venueMarketId);
934
+ if (!sibling) continue;
935
+ const siblingOutcome = sibling.venueMarketOutcomes.find(
936
+ (o) => o.id === ref.venueMarketOutcomeId
937
+ );
938
+ if (!siblingOutcome || seenOutcomeIds.has(siblingOutcome.id)) continue;
939
+ seenMarketIds.add(sibling.id);
940
+ seenOutcomeIds.add(siblingOutcome.id);
941
+ result.push({
942
+ venue: sibling.venue,
943
+ market: sibling,
944
+ outcome: siblingOutcome,
945
+ outcomeId: siblingOutcome.id,
946
+ semanticLabel
947
+ });
948
+ }
949
+ return result;
950
+ }
951
+ const hasOtherMarketWithRefs = venueMarkets.some((m) => {
952
+ var _a2, _b2;
953
+ if (m.id === market.id) return false;
954
+ const o = sortOutcomes(m.venueMarketOutcomes).find(
955
+ (o2) => matchesSelectedOutcomeLabel(o2, selectedOutcomeLabel)
956
+ );
957
+ return ((_b2 = (_a2 = o == null ? void 0 : o.matchedVenueMarketOutcomes) == null ? void 0 : _a2.length) != null ? _b2 : 0) > 0;
958
+ });
959
+ if (hasOtherMarketWithRefs) {
960
+ result.push({
961
+ venue: market.venue,
962
+ market,
963
+ outcome,
964
+ outcomeId: outcome.id,
965
+ semanticLabel
966
+ });
967
+ return result;
968
+ }
969
+ break;
970
+ }
971
+ }
972
+ for (const market of venueMarkets) {
973
+ if (seenMarketIds.has(market.id)) continue;
974
+ const parentOutcome = sortOutcomes(market.venueMarketOutcomes).find(
975
+ (outcome) => matchesSelectedOutcomeLabel(outcome, selectedOutcomeLabel)
976
+ );
977
+ if (!parentOutcome) continue;
978
+ const refs = (_b = parentOutcome.matchedVenueMarketOutcomes) != null ? _b : [];
979
+ if (refs.length === 0) continue;
980
+ seenMarketIds.add(market.id);
981
+ seenOutcomeIds.add(parentOutcome.id);
982
+ result.push({
983
+ venue: market.venue,
984
+ market,
985
+ outcome: parentOutcome,
986
+ outcomeId: parentOutcome.id,
987
+ semanticLabel
988
+ });
989
+ for (const ref of refs) {
990
+ if (seenMarketIds.has(ref.venueMarketId)) continue;
991
+ const sibling = venueMarkets.find((m) => m.id === ref.venueMarketId);
992
+ if (!sibling) continue;
993
+ const siblingOutcome = sibling.venueMarketOutcomes.find(
994
+ (o) => o.id === ref.venueMarketOutcomeId
995
+ );
996
+ if (!siblingOutcome || seenOutcomeIds.has(siblingOutcome.id)) continue;
997
+ seenMarketIds.add(sibling.id);
998
+ seenOutcomeIds.add(siblingOutcome.id);
999
+ result.push({
1000
+ venue: sibling.venue,
1001
+ market: sibling,
1002
+ outcome: siblingOutcome,
1003
+ outcomeId: siblingOutcome.id,
1004
+ semanticLabel
1005
+ });
1006
+ }
1007
+ break;
1008
+ }
1009
+ for (const market of venueMarkets) {
1010
+ if (seenMarketIds.has(market.id)) continue;
890
1011
  const matchedOutcome = sortOutcomes(market.venueMarketOutcomes).find(
891
1012
  (outcome) => matchesSelectedOutcomeLabel(outcome, selectedOutcomeLabel)
892
1013
  );
893
- if (!matchedOutcome || seenOutcomeIds.has(matchedOutcome.id)) {
894
- return [];
1014
+ if (!matchedOutcome || seenOutcomeIds.has(matchedOutcome.id)) continue;
1015
+ const candidateRefs = (_c = matchedOutcome.matchedVenueMarketOutcomes) != null ? _c : [];
1016
+ if (candidateRefs.length > 0) {
1017
+ const sharesAnchor = candidateRefs.some(
1018
+ (ref) => seenOutcomeIds.has(ref.venueMarketOutcomeId)
1019
+ );
1020
+ if (!sharesAnchor) continue;
895
1021
  }
1022
+ seenMarketIds.add(market.id);
896
1023
  seenOutcomeIds.add(matchedOutcome.id);
897
- return [
898
- {
899
- venue: market.venue,
900
- market,
901
- outcome: matchedOutcome,
902
- outcomeId: matchedOutcome.id,
903
- semanticLabel: toSemanticOutcomeLabel(selectedOutcomeLabel)
904
- }
905
- ];
906
- });
1024
+ result.push({
1025
+ venue: market.venue,
1026
+ market,
1027
+ outcome: matchedOutcome,
1028
+ outcomeId: matchedOutcome.id,
1029
+ semanticLabel
1030
+ });
1031
+ }
1032
+ return result;
907
1033
  };
908
1034
  var collectEligibleVenueOutcomeIds = ({
909
1035
  venueMarkets,
910
- selectedOutcomeLabel
1036
+ selectedOutcomeLabel,
1037
+ selectedOutcomeId
911
1038
  }) => {
912
- return collectEligibleVenueOutcomes({ venueMarkets, selectedOutcomeLabel }).map(
913
- (eligibleOutcome) => eligibleOutcome.outcomeId
914
- );
1039
+ return collectEligibleVenueOutcomes({
1040
+ venueMarkets,
1041
+ selectedOutcomeLabel,
1042
+ selectedOutcomeId
1043
+ }).map((eligibleOutcome) => eligibleOutcome.outcomeId);
915
1044
  };
916
1045
  var mergeVenueOutcomeOrderbooks = ({
917
1046
  eligibleOutcomes,
@@ -1018,14 +1147,15 @@ SettlementSummary.displayName = "SettlementSummary";
1018
1147
  // src/events/item-details/index.tsx
1019
1148
  import {
1020
1149
  CHART_TIME_RANGES,
1150
+ mergeBestPricesPreferringLive,
1021
1151
  optimizedImageUrl as optimizedImageUrl2,
1022
1152
  resolveEventTradingState,
1023
- timeRangeToInterval,
1024
1153
  useEventOrderbookData,
1025
1154
  useLabels as useLabels5,
1155
+ useLiveBestPrices,
1026
1156
  useLiveOutcomePrices,
1027
1157
  useMarketChart,
1028
- useMidpoints,
1158
+ useRollingChartWindow,
1029
1159
  useSdkUiConfig as useSdkUiConfig2,
1030
1160
  useVenueEvent as useVenueEvent2
1031
1161
  } from "@agg-build/hooks";
@@ -1139,6 +1269,35 @@ var ChartTypeSwitch = ({
1139
1269
  };
1140
1270
  ChartTypeSwitch.displayName = "ChartTypeSwitch";
1141
1271
 
1272
+ // src/events/shared/chart-auto-fallback.ts
1273
+ var isMarketChartEmpty = (data, options = {}) => {
1274
+ if (!data) return true;
1275
+ const minTime = options.minTimeSec;
1276
+ return !Object.values(data.venues).some((venue) => {
1277
+ const hasInWindowCandle = minTime != null ? venue.candles.some((candle) => candle.time >= minTime) : venue.candles.length > 0;
1278
+ if (hasInWindowCandle) return true;
1279
+ const live = venue.liveCandle;
1280
+ if (live == null) return false;
1281
+ if (minTime != null && live.time < minTime) return false;
1282
+ return true;
1283
+ });
1284
+ };
1285
+ var shouldAutoFallbackToAllRange = ({
1286
+ chartData,
1287
+ isLoading,
1288
+ error,
1289
+ currentRange,
1290
+ hasAlreadyFallenBack,
1291
+ domainStartTs
1292
+ }) => {
1293
+ if (hasAlreadyFallenBack) return false;
1294
+ if (currentRange === "ALL") return false;
1295
+ if (error != null) return false;
1296
+ if (isLoading) return false;
1297
+ if (!chartData) return false;
1298
+ return isMarketChartEmpty(chartData, { minTimeSec: domainStartTs });
1299
+ };
1300
+
1142
1301
  // src/events/shared/chart-venue-selection.ts
1143
1302
  import { sortVenues as sortVenues2 } from "@agg-build/hooks";
1144
1303
  var resolveChartVenueOutcomes = ({
@@ -1795,12 +1954,17 @@ var EventListItemDetailsGraphSection = ({
1795
1954
  classNames,
1796
1955
  selectedChartType,
1797
1956
  venueMarkets,
1957
+ selectedMarketId,
1798
1958
  livePrices,
1799
1959
  wsLivePrices,
1800
1960
  restMidpoints,
1801
- live
1961
+ bestMidpoint,
1962
+ bestPrices,
1963
+ live,
1964
+ rangeOverride,
1965
+ onRangeOverrideChange
1802
1966
  }) => {
1803
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1967
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1804
1968
  const labels = useLabels5();
1805
1969
  const tradingContext = useEventTradingContext();
1806
1970
  const [selectedGraphVenue, setSelectedGraphVenue] = useState3(null);
@@ -1821,24 +1985,33 @@ var EventListItemDetailsGraphSection = ({
1821
1985
  general: { theme }
1822
1986
  } = useSdkUiConfig2();
1823
1987
  const isDarkTheme = theme === "dark";
1824
- const timeWindow = useMemo5(() => {
1825
- return getTimeWindowByRange(selectedChartTimeRange);
1826
- }, [selectedChartTimeRange]);
1988
+ const effectiveChartTimeRange = rangeOverride != null ? rangeOverride : selectedChartTimeRange;
1989
+ const rollingWindow = useRollingChartWindow({ range: effectiveChartTimeRange });
1827
1990
  const availableMarkets = useMemo5(() => {
1991
+ var _a2, _b2, _c2, _d2;
1828
1992
  if (venueMarkets.length === 0) return [];
1829
- return normalizeVenueMarketCluster(venueMarkets, tradingContext == null ? void 0 : tradingContext.selectedMarketId);
1830
- }, [tradingContext == null ? void 0 : tradingContext.selectedMarketId, venueMarkets]);
1831
- const resolvedChartOutcomeLabel = (_g = chartOutcomeLabel != null ? chartOutcomeLabel : (_f = (_e = tradingContext == null ? void 0 : tradingContext.selectedOutcome) == null ? void 0 : _e.label) == null ? void 0 : _f.trim()) != null ? _g : null;
1993
+ const resolvedSelectedMarketId = (_d2 = (_c2 = (_a2 = tradingContext == null ? void 0 : tradingContext.selectedMarketId) != null ? _a2 : selectedMarketId) != null ? _c2 : (_b2 = venueMarkets[0]) == null ? void 0 : _b2.id) != null ? _d2 : null;
1994
+ return normalizeVenueMarketCluster(venueMarkets, resolvedSelectedMarketId);
1995
+ }, [selectedMarketId, tradingContext == null ? void 0 : tradingContext.selectedMarketId, venueMarkets]);
1996
+ const fallbackOutcomeLabel = useMemo5(() => {
1997
+ var _a2, _b2, _c2, _d2, _e2;
1998
+ const fallbackMarket = (_b2 = (_a2 = tradingContext == null ? void 0 : tradingContext.selectedMarket) != null ? _a2 : availableMarkets[0]) != null ? _b2 : null;
1999
+ if (!fallbackMarket) return null;
2000
+ return (_e2 = (_d2 = (_c2 = sortOutcomeSelectorOutcomes(fallbackMarket.venueMarketOutcomes)[0]) == null ? void 0 : _c2.label) == null ? void 0 : _d2.trim()) != null ? _e2 : null;
2001
+ }, [availableMarkets, tradingContext == null ? void 0 : tradingContext.selectedMarket]);
2002
+ const resolvedChartOutcomeLabel = (_h = (_g = chartOutcomeLabel != null ? chartOutcomeLabel : (_f = (_e = tradingContext == null ? void 0 : tradingContext.selectedOutcome) == null ? void 0 : _e.label) == null ? void 0 : _f.trim()) != null ? _g : fallbackOutcomeLabel) != null ? _h : null;
2003
+ const chartScopedOutcomeId = ((_i = tradingContext == null ? void 0 : tradingContext.selectedOutcome) == null ? void 0 : _i.id) && ((_j = tradingContext.selectedOutcome.label) == null ? void 0 : _j.trim()) === resolvedChartOutcomeLabel ? tradingContext.selectedOutcome.id : null;
1832
2004
  const availableVenueOutcomes = useMemo5(() => {
1833
2005
  return resolveChartVenueOutcomes({
1834
2006
  eligibleVenueOutcomes: collectEligibleVenueOutcomes({
1835
2007
  venueMarkets: availableMarkets,
1836
- selectedOutcomeLabel: resolvedChartOutcomeLabel
2008
+ selectedOutcomeLabel: resolvedChartOutcomeLabel,
2009
+ selectedOutcomeId: chartScopedOutcomeId
1837
2010
  }),
1838
2011
  livePrices
1839
2012
  });
1840
- }, [availableMarkets, livePrices, resolvedChartOutcomeLabel]);
1841
- const chartPrimaryOutcomeId = (_i = (_h = availableVenueOutcomes[0]) == null ? void 0 : _h.outcome.id) != null ? _i : null;
2013
+ }, [availableMarkets, livePrices, resolvedChartOutcomeLabel, chartScopedOutcomeId]);
2014
+ const chartPrimaryOutcomeId = (_l = (_k = availableVenueOutcomes[0]) == null ? void 0 : _k.outcome.id) != null ? _l : null;
1842
2015
  const {
1843
2016
  data: scopedMarketChartData,
1844
2017
  isLoading: isScopedMarketChartLoading,
@@ -1847,17 +2020,56 @@ var EventListItemDetailsGraphSection = ({
1847
2020
  } = useMarketChart({
1848
2021
  marketId: chartPrimaryOutcomeId,
1849
2022
  venueMarketIds: availableVenueOutcomes.map((item) => item.outcome.id),
1850
- interval: timeRangeToInterval(selectedChartTimeRange),
1851
- startTs: timeWindow.startTs * 1e3,
1852
- endTs: timeWindow.endTs * 1e3,
2023
+ interval: rollingWindow.interval,
2024
+ startTs: rollingWindow.startTs * 1e3,
2025
+ endTs: rollingWindow.endTs * 1e3,
1853
2026
  enabled: availableVenueOutcomes.length > 0,
1854
- live
2027
+ live,
2028
+ refetchIntervalMs: rollingWindow.refetchIntervalMs,
2029
+ // Stable cache key per user-selected range so revisits hit cache instead
2030
+ // of refetching every time the bucket boundary advances.
2031
+ rangeKey: rollingWindow.range
1855
2032
  });
2033
+ const hasAutoFallenBackRangeRef = useRef2(false);
2034
+ useEffect2(() => {
2035
+ hasAutoFallenBackRangeRef.current = false;
2036
+ }, [chartPrimaryOutcomeId]);
2037
+ useEffect2(() => {
2038
+ if (!shouldAutoFallbackToAllRange({
2039
+ chartData: scopedMarketChartData,
2040
+ isLoading: isScopedMarketChartLoading,
2041
+ error: scopedMarketChartError,
2042
+ currentRange: effectiveChartTimeRange,
2043
+ hasAlreadyFallenBack: hasAutoFallenBackRangeRef.current,
2044
+ // Ignore stale "courtesy" bars the API returns outside the
2045
+ // rolling window (e.g. a market that last traded 11h ago — its
2046
+ // last bar is in `candles` but our visible 1H window can't show
2047
+ // it, so for fallback purposes it doesn't count as data).
2048
+ domainStartTs: rollingWindow.startTs
2049
+ })) {
2050
+ return;
2051
+ }
2052
+ hasAutoFallenBackRangeRef.current = true;
2053
+ onRangeOverrideChange("ALL");
2054
+ }, [
2055
+ scopedMarketChartData,
2056
+ isScopedMarketChartLoading,
2057
+ scopedMarketChartError,
2058
+ effectiveChartTimeRange,
2059
+ onRangeOverrideChange,
2060
+ rollingWindow.startTs
2061
+ ]);
1856
2062
  const selectedMarketOutcomes = useMemo5(() => {
1857
2063
  var _a2, _b2;
1858
2064
  const selectedMarket = (_b2 = (_a2 = tradingContext == null ? void 0 : tradingContext.selectedMarket) != null ? _a2 : availableMarkets[0]) != null ? _b2 : null;
1859
2065
  if (!selectedMarket) return [];
1860
- return sortOutcomeSelectorOutcomes(selectedMarket.venueMarketOutcomes);
2066
+ return sortOutcomeSelectorOutcomes(selectedMarket.venueMarketOutcomes).map((outcome) => {
2067
+ var _a3;
2068
+ return __spreadProps(__spreadValues({}, outcome), {
2069
+ label: outcome.label,
2070
+ title: (_a3 = outcome.title) != null ? _a3 : null
2071
+ });
2072
+ });
1861
2073
  }, [availableMarkets, tradingContext == null ? void 0 : tradingContext.selectedMarket]);
1862
2074
  const resolvedVenueChartSeries = useMemo5(() => {
1863
2075
  return resolveMarketChartVenueSeries({
@@ -1884,11 +2096,12 @@ var EventListItemDetailsGraphSection = ({
1884
2096
  }, [availableVenueOutcomes, chartAvailableVenueOutcomes, tradingContext == null ? void 0 : tradingContext.selectedVenue]);
1885
2097
  const activeGraphVenue = selectedChartType === "candlestick" ? selectedGraphVenue != null ? selectedGraphVenue : defaultCandlestickVenue : selectedGraphVenue;
1886
2098
  const visibleChartSeries = useMemo5(() => {
1887
- if (!activeGraphVenue) {
1888
- return resolvedVenueChartSeries;
1889
- }
1890
- return resolvedVenueChartSeries.filter((seriesItem) => seriesItem.venue === activeGraphVenue);
1891
- }, [activeGraphVenue, resolvedVenueChartSeries]);
2099
+ const venueFiltered = activeGraphVenue ? resolvedVenueChartSeries.filter((seriesItem) => seriesItem.venue === activeGraphVenue) : resolvedVenueChartSeries;
2100
+ const domainStartTs = rollingWindow.startTs;
2101
+ return venueFiltered.map((seriesItem) => __spreadProps(__spreadValues({}, seriesItem), {
2102
+ points: seriesItem.points.filter((point) => point.time >= domainStartTs)
2103
+ }));
2104
+ }, [activeGraphVenue, resolvedVenueChartSeries, rollingWindow.startTs]);
1892
2105
  const chartLiveState = useMemo5(() => {
1893
2106
  return resolveMarketChartLiveState({
1894
2107
  chartData: scopedMarketChartData,
@@ -1928,7 +2141,7 @@ var EventListItemDetailsGraphSection = ({
1928
2141
  height: 300,
1929
2142
  isLoading: isScopedMarketChartLoading,
1930
2143
  chartType: selectedChartType,
1931
- liveCandle: selectedChartType === "candlestick" ? (_j = chartLiveState.liveCandle) != null ? _j : void 0 : void 0,
2144
+ liveCandle: selectedChartType === "candlestick" ? (_m = chartLiveState.liveCandle) != null ? _m : void 0 : void 0,
1932
2145
  lineValue: chartLiveState.lineValue,
1933
2146
  showSeriesControls: selectedMarketOutcomes.length > 0,
1934
2147
  renderSeriesControls: ({ handleSeriesChange }) => {
@@ -2017,12 +2230,21 @@ var EventListItemDetailsGraphSection = ({
2017
2230
  tradingContext == null ? void 0 : tradingContext.selectOutcome(outcomeId);
2018
2231
  },
2019
2232
  options: selectedMarketOutcomes.map((outcome) => {
2020
- var _a3, _b3;
2021
- const price = (_b3 = (_a3 = restMidpoints.get(outcome.id)) != null ? _a3 : livePrices.get(outcome.id)) != null ? _b3 : outcome.price;
2233
+ var _a3, _b3, _c3;
2234
+ const price = getDisplayOutcomePrice({
2235
+ outcomeId: outcome.id,
2236
+ outcomeLabel: outcome.label,
2237
+ selection: (_a3 = tradingContext == null ? void 0 : tradingContext.tradeSide) != null ? _a3 : "buy",
2238
+ bestPrices,
2239
+ bestMidpoint,
2240
+ bestMidpointsByOutcomeId: restMidpoints,
2241
+ livePrices,
2242
+ fallbackPrice: outcome.price
2243
+ });
2022
2244
  return {
2023
2245
  value: outcome.id,
2024
- label: `${outcome.label} ${formatProbabilityCents(price)}`,
2025
- ariaLabel: `${outcome.label} ${formatProbabilityCents(price)}`
2246
+ label: `${(_b3 = outcome.title) != null ? _b3 : outcome.label} ${formatProbabilityCents(price)}`,
2247
+ ariaLabel: `${(_c3 = outcome.title) != null ? _c3 : outcome.label} ${formatProbabilityCents(price)}`
2026
2248
  };
2027
2249
  })
2028
2250
  }
@@ -2043,12 +2265,17 @@ var EventListItemDetailsContent = ({
2043
2265
  detailsStats,
2044
2266
  eventTradingState,
2045
2267
  ariaLabel,
2046
- onClick
2268
+ onClick,
2269
+ midpointsResult
2047
2270
  }) => {
2048
- var _a, _b;
2271
+ var _a, _b, _c, _d;
2049
2272
  const [selectedChartType, setSelectedChartType] = useState3("line");
2050
2273
  const lastAppliedEventSyncKeyRef = useRef2(null);
2051
2274
  const lastAppliedDefaultRef = useRef2(null);
2275
+ const [chartRangeOverride, setChartRangeOverride] = useState3(null);
2276
+ useEffect2(() => {
2277
+ setChartRangeOverride(null);
2278
+ }, [event.id]);
2052
2279
  const config = useSdkUiConfig2();
2053
2280
  const labels = useLabels5();
2054
2281
  const tradingContext = useEventTradingContext();
@@ -2063,18 +2290,24 @@ var EventListItemDetailsContent = ({
2063
2290
  scopedSelectedMarketId
2064
2291
  );
2065
2292
  const wsLivePrices = useLiveOutcomePrices(resolvedEventTradingState.displayMarkets);
2066
- const midpointsClusterMarkets = useMemo5(() => {
2067
- if (resolvedEventTradingState.isTradingDisabled) return [];
2068
- return normalizeVenueMarketCluster(
2069
- resolvedEventTradingState.displayMarkets,
2070
- scopedSelectedMarketId
2071
- );
2072
- }, [
2073
- resolvedEventTradingState.displayMarkets,
2074
- resolvedEventTradingState.isTradingDisabled,
2075
- scopedSelectedMarketId
2076
- ]);
2077
- const { prices: restMidpoints } = useMidpoints(midpointsClusterMarkets);
2293
+ const wsBestPrices = useLiveBestPrices(resolvedEventTradingState.displayMarkets);
2294
+ const resolvedMidpointsResult = midpointsResult != null ? midpointsResult : {
2295
+ prices: /* @__PURE__ */ new Map(),
2296
+ bestMidpointsByOutcomeId: /* @__PURE__ */ new Map(),
2297
+ venueByOutcomeId: /* @__PURE__ */ new Map(),
2298
+ bestPrices: /* @__PURE__ */ new Map(),
2299
+ bestPriceVenuesByOutcomeId: /* @__PURE__ */ new Map(),
2300
+ isLoading: false,
2301
+ bestMidpoint: void 0,
2302
+ bestMidpointVenue: void 0
2303
+ };
2304
+ const restMidpoints = (_b = resolvedMidpointsResult.bestMidpointsByOutcomeId) != null ? _b : resolvedMidpointsResult.prices;
2305
+ const bestMidpoint = resolvedMidpointsResult.bestMidpoint;
2306
+ const restBestPrices = resolvedMidpointsResult.bestPrices;
2307
+ const bestPrices = useMemo5(
2308
+ () => mergeBestPricesPreferringLive(restBestPrices, wsBestPrices),
2309
+ [restBestPrices, wsBestPrices]
2310
+ );
2078
2311
  const livePrices = useMemo5(() => {
2079
2312
  if (!restMidpoints.size) return wsLivePrices;
2080
2313
  if (!wsLivePrices.size) return restMidpoints;
@@ -2183,7 +2416,7 @@ var EventListItemDetailsContent = ({
2183
2416
  {
2184
2417
  className: classNames == null ? void 0 : classNames.headerPills,
2185
2418
  options: marketOptions,
2186
- selectedValue: (_b = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id) != null ? _b : "",
2419
+ selectedValue: (_c = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id) != null ? _c : "",
2187
2420
  onChange: (marketId) => {
2188
2421
  tradingContext == null ? void 0 : tradingContext.selectMarket(marketId);
2189
2422
  }
@@ -2234,10 +2467,15 @@ var EventListItemDetailsContent = ({
2234
2467
  selectedChartType,
2235
2468
  venueInfo,
2236
2469
  venueMarkets,
2470
+ selectedMarketId: (_d = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id) != null ? _d : null,
2237
2471
  livePrices,
2238
2472
  wsLivePrices,
2239
2473
  restMidpoints,
2240
- live: false
2474
+ bestMidpoint,
2475
+ bestPrices,
2476
+ live: false,
2477
+ rangeOverride: chartRangeOverride,
2478
+ onRangeOverrideChange: setChartRangeOverride
2241
2479
  }
2242
2480
  ),
2243
2481
  /* @__PURE__ */ jsxs4(
@@ -2267,7 +2505,8 @@ var EventListItemDetailsContent = ({
2267
2505
  ),
2268
2506
  /* @__PURE__ */ jsx5("span", { "aria-hidden": "true", className: "hidden h-4 w-px bg-agg-separator md:block" }),
2269
2507
  CHART_TIME_RANGES.map((timeRange) => {
2270
- const isActive = timeRange === config.chart.selectedChartTimeRange;
2508
+ const effectiveRange = chartRangeOverride != null ? chartRangeOverride : config.chart.selectedChartTimeRange;
2509
+ const isActive = timeRange === effectiveRange;
2271
2510
  return /* @__PURE__ */ jsx5(
2272
2511
  Button,
2273
2512
  {
@@ -2284,6 +2523,7 @@ var EventListItemDetailsContent = ({
2284
2523
  onClick: (e) => {
2285
2524
  e.stopPropagation();
2286
2525
  e.preventDefault();
2526
+ setChartRangeOverride(null);
2287
2527
  config.chart.setSelectedChartTimeRange(timeRange);
2288
2528
  },
2289
2529
  children: timeRange === "ALL" ? labels.eventItemDetails.allTimeRange : timeRange
@@ -2419,30 +2659,23 @@ var useCenterOrderbookSpread = ({
2419
2659
  rowCount,
2420
2660
  enabled = true
2421
2661
  }) => {
2422
- const hasAutoCenteredRef = useRef3(false);
2423
2662
  const hasUserScrolledRef = useRef3(false);
2424
2663
  const animationFrameRef = useRef3(null);
2425
2664
  const retryCountRef = useRef3(0);
2426
2665
  const resetKey = marketId != null ? marketId : "";
2666
+ const cancelPendingFrame = useCallback2(() => {
2667
+ if (animationFrameRef.current === null) return;
2668
+ window.cancelAnimationFrame(animationFrameRef.current);
2669
+ animationFrameRef.current = null;
2670
+ }, []);
2427
2671
  useLayoutEffect2(() => {
2428
- const cancelPendingFrame = () => {
2429
- if (animationFrameRef.current === null) return;
2430
- window.cancelAnimationFrame(animationFrameRef.current);
2431
- animationFrameRef.current = null;
2432
- };
2433
- hasAutoCenteredRef.current = false;
2434
2672
  hasUserScrolledRef.current = false;
2435
2673
  retryCountRef.current = 0;
2436
2674
  cancelPendingFrame();
2437
- }, [resetKey]);
2675
+ }, [cancelPendingFrame, resetKey]);
2438
2676
  useLayoutEffect2(() => {
2439
2677
  const container = containerRef.current;
2440
2678
  if (!container) return;
2441
- const cancelPendingFrame = () => {
2442
- if (animationFrameRef.current === null) return;
2443
- window.cancelAnimationFrame(animationFrameRef.current);
2444
- animationFrameRef.current = null;
2445
- };
2446
2679
  const handleUserScrollIntent = () => {
2447
2680
  hasUserScrolledRef.current = true;
2448
2681
  cancelPendingFrame();
@@ -2462,93 +2695,81 @@ var useCenterOrderbookSpread = ({
2462
2695
  container.removeEventListener("keydown", handleKeyDown);
2463
2696
  cancelPendingFrame();
2464
2697
  };
2465
- }, [containerRef]);
2698
+ }, [cancelPendingFrame, containerRef]);
2466
2699
  useLayoutEffect2(() => {
2467
2700
  if (!enabled) return;
2468
- if (hasAutoCenteredRef.current || hasUserScrolledRef.current) return;
2469
2701
  let isCancelled = false;
2470
- let resizeObserver = null;
2471
- const cancelPendingFrame = () => {
2472
- if (animationFrameRef.current === null) return;
2473
- window.cancelAnimationFrame(animationFrameRef.current);
2474
- animationFrameRef.current = null;
2475
- };
2476
- const disconnectResizeObserver = () => {
2477
- resizeObserver == null ? void 0 : resizeObserver.disconnect();
2478
- resizeObserver = null;
2479
- };
2480
- const scheduleMeasurement = () => {
2481
- cancelPendingFrame();
2482
- animationFrameRef.current = window.requestAnimationFrame(measureAndCenter);
2483
- };
2484
- const setupResizeObserverFallback = () => {
2485
- if (resizeObserver) return;
2486
- const container = containerRef.current;
2487
- if (!container) return;
2488
- resizeObserver = new ResizeObserver(() => {
2489
- if (isCancelled || hasAutoCenteredRef.current || hasUserScrolledRef.current) {
2490
- disconnectResizeObserver();
2491
- return;
2492
- }
2493
- if (container.clientHeight <= 0) return;
2494
- disconnectResizeObserver();
2495
- retryCountRef.current = 0;
2496
- scheduleMeasurement();
2497
- });
2498
- resizeObserver.observe(container);
2499
- };
2500
- const scheduleRetry = () => {
2501
- if (isCancelled || hasUserScrolledRef.current || hasAutoCenteredRef.current) return;
2502
- if (retryCountRef.current >= maxAutoCenterAttempts) {
2503
- setupResizeObserverFallback();
2504
- return;
2505
- }
2506
- retryCountRef.current += 1;
2507
- scheduleMeasurement();
2508
- };
2509
2702
  const measureAndCenter = () => {
2510
- if (isCancelled) return;
2511
- const container = containerRef.current;
2703
+ animationFrameRef.current = null;
2704
+ if (isCancelled || hasUserScrolledRef.current) return;
2705
+ const container2 = containerRef.current;
2512
2706
  const spread = spreadRef.current;
2513
- if (!container || !spread) {
2707
+ if (!container2 || !spread) {
2514
2708
  scheduleRetry();
2515
2709
  return;
2516
2710
  }
2517
- const containerHeight = container.clientHeight;
2711
+ const containerHeight = container2.clientHeight;
2518
2712
  if (containerHeight <= 0) {
2519
2713
  scheduleRetry();
2520
2714
  return;
2521
2715
  }
2522
- const containerRect = container.getBoundingClientRect();
2716
+ const containerRect = container2.getBoundingClientRect();
2523
2717
  const spreadRect = spread.getBoundingClientRect();
2524
2718
  if (containerRect.height <= 0 || spreadRect.height <= 0) {
2525
2719
  scheduleRetry();
2526
2720
  return;
2527
2721
  }
2528
- const spreadOffsetTop = container.scrollTop + (spreadRect.top - containerRect.top);
2529
- const maxScrollTop = Math.max(0, container.scrollHeight - containerHeight);
2722
+ const spreadOffsetTop = container2.scrollTop + (spreadRect.top - containerRect.top);
2723
+ const maxScrollTop = Math.max(0, container2.scrollHeight - containerHeight);
2530
2724
  if (maxScrollTop === 0) {
2531
2725
  retryCountRef.current = 0;
2532
- animationFrameRef.current = null;
2533
2726
  return;
2534
2727
  }
2535
2728
  const targetScrollTop = Math.max(
2536
2729
  0,
2537
2730
  Math.min(maxScrollTop, spreadOffsetTop - containerHeight / 2 + spreadRect.height / 2)
2538
2731
  );
2539
- container.scrollTo({ top: targetScrollTop, behavior: "auto" });
2540
- hasAutoCenteredRef.current = true;
2732
+ container2.scrollTop = targetScrollTop;
2541
2733
  retryCountRef.current = 0;
2542
- animationFrameRef.current = null;
2543
- disconnectResizeObserver();
2544
2734
  };
2735
+ const scheduleMeasurement = () => {
2736
+ if (isCancelled || hasUserScrolledRef.current) return;
2737
+ if (animationFrameRef.current !== null) return;
2738
+ animationFrameRef.current = window.requestAnimationFrame(measureAndCenter);
2739
+ };
2740
+ const scheduleRetry = () => {
2741
+ if (isCancelled || hasUserScrolledRef.current) return;
2742
+ if (retryCountRef.current >= maxAutoCenterAttempts) return;
2743
+ retryCountRef.current += 1;
2744
+ if (animationFrameRef.current !== null) return;
2745
+ animationFrameRef.current = window.requestAnimationFrame(measureAndCenter);
2746
+ };
2747
+ const container = containerRef.current;
2748
+ let resizeObserver = null;
2749
+ let mutationObserver = null;
2750
+ if (container) {
2751
+ resizeObserver = new ResizeObserver(() => {
2752
+ if (isCancelled || hasUserScrolledRef.current) return;
2753
+ retryCountRef.current = 0;
2754
+ scheduleMeasurement();
2755
+ });
2756
+ resizeObserver.observe(container);
2757
+ mutationObserver = new MutationObserver(() => {
2758
+ if (isCancelled || hasUserScrolledRef.current) return;
2759
+ retryCountRef.current = 0;
2760
+ scheduleMeasurement();
2761
+ });
2762
+ mutationObserver.observe(container, { childList: true, subtree: true });
2763
+ }
2764
+ retryCountRef.current = 0;
2545
2765
  scheduleMeasurement();
2546
2766
  return () => {
2547
2767
  isCancelled = true;
2548
2768
  cancelPendingFrame();
2549
- disconnectResizeObserver();
2769
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
2770
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
2550
2771
  };
2551
- }, [containerRef, enabled, resetKey, rowCount, spreadRef]);
2772
+ }, [cancelPendingFrame, containerRef, enabled, resetKey, rowCount, spreadRef]);
2552
2773
  const recenter = useCallback2(() => {
2553
2774
  const container = containerRef.current;
2554
2775
  const spread = spreadRef.current;
@@ -2884,15 +3105,16 @@ import {
2884
3105
  CHART_TIME_RANGES as CHART_TIME_RANGES2,
2885
3106
  findLivePriceById,
2886
3107
  MarketStatus,
3108
+ mergeBestPricesPreferringLive as mergeBestPricesPreferringLive2,
2887
3109
  optimizedImageUrl as optimizedImageUrl3,
2888
3110
  resolveMarketTradingState,
2889
- timeRangeToInterval as timeRangeToInterval2,
2890
- useEventTradingContext as useEventTradingContext2,
3111
+ useEventTradingContext as useEventTradingContext3,
2891
3112
  useLabels as useLabels6,
3113
+ useLiveBestPrices as useLiveBestPrices2,
2892
3114
  useLiveOutcomePrices as useLiveOutcomePrices2,
2893
3115
  useMarketChart as useMarketChart2,
2894
3116
  useMarketOrderbook,
2895
- useMidpoints as useMidpoints2,
3117
+ useRollingChartWindow as useRollingChartWindow2,
2896
3118
  useSdkUiConfig as useSdkUiConfig3,
2897
3119
  useVenueMarkets as useVenueMarkets2,
2898
3120
  useViewportMidpoints
@@ -2905,17 +3127,17 @@ var marketDetailsOutcomeButtonToneClasses = {
2905
3127
  positive: {
2906
3128
  activeSurface: "bg-agg-success/15",
2907
3129
  border: "border-agg-success/50",
2908
- defaultSurface: "bg-agg-success/5",
2909
- hoverSurface: "hover:bg-agg-success/10",
2910
- pressedSurface: "active:bg-agg-success/15",
3130
+ defaultSurface: "bg-agg-secondary-hover",
3131
+ hoverSurface: "hover:bg-agg-tertiary",
3132
+ pressedSurface: "active:bg-agg-success/10",
2911
3133
  text: "text-agg-success!"
2912
3134
  },
2913
3135
  negative: {
2914
3136
  activeSurface: "bg-agg-error/15",
2915
3137
  border: "border-agg-error/50",
2916
- defaultSurface: "bg-agg-error/5",
2917
- hoverSurface: "hover:bg-agg-error/10",
2918
- pressedSurface: "active:bg-agg-error/15",
3138
+ defaultSurface: "bg-agg-secondary-hover",
3139
+ hoverSurface: "hover:bg-agg-tertiary",
3140
+ pressedSurface: "active:bg-agg-error/10",
2919
3141
  text: "text-agg-error!"
2920
3142
  }
2921
3143
  };
@@ -2948,6 +3170,7 @@ var MarketDetailsOutcomeButton = ({
2948
3170
  item,
2949
3171
  onSelect
2950
3172
  }) => {
3173
+ var _a;
2951
3174
  const classNames = getMarketDetailsOutcomeButtonClassNames({
2952
3175
  enableAnimations,
2953
3176
  isSelected,
@@ -2974,7 +3197,7 @@ var MarketDetailsOutcomeButton = ({
2974
3197
  as: "span",
2975
3198
  variant: isSelected ? "body-strong" : "body",
2976
3199
  className: cn("whitespace-nowrap truncate", classNames.text),
2977
- children: item.title
3200
+ children: (_a = item.title) != null ? _a : item.label
2978
3201
  }
2979
3202
  ),
2980
3203
  /* @__PURE__ */ jsx8(
@@ -2995,21 +3218,6 @@ MarketDetailsOutcomeButton.displayName = "MarketDetailsOutcomeButton";
2995
3218
 
2996
3219
  // src/events/market-details/index.tsx
2997
3220
  import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
2998
- var MarketDetailsLoadingState = ({
2999
- isOpened = marketDetailsDefaultIsOpened,
3000
- ariaLabel,
3001
- classNames
3002
- }) => {
3003
- const labels = useLabels6();
3004
- return /* @__PURE__ */ jsx9(
3005
- Skeleton,
3006
- {
3007
- view: isOpened ? "market-details-detailed" : "market-details-minified",
3008
- className: classNames == null ? void 0 : classNames.root,
3009
- ariaLabel: ariaLabel != null ? ariaLabel : labels.marketDetails.loading
3010
- }
3011
- );
3012
- };
3013
3221
  var MarketDetailsUnavailableState = ({
3014
3222
  ariaLabel,
3015
3223
  classNames
@@ -3063,9 +3271,11 @@ var MarketDetailsContent = ({
3063
3271
  onOutcomeSelect,
3064
3272
  live,
3065
3273
  midpointsFallback,
3066
- midpointsFallbackVenues
3274
+ midpointsFallbackVenues,
3275
+ suppressOutcomeFallbackSelection,
3276
+ midpointsResult
3067
3277
  }) => {
3068
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
3278
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3069
3279
  const config = useSdkUiConfig3();
3070
3280
  const {
3071
3281
  features: { enableAnimations },
@@ -3074,9 +3284,61 @@ var MarketDetailsContent = ({
3074
3284
  } = config;
3075
3285
  const isDarkTheme = theme === "dark";
3076
3286
  const labels = useLabels6();
3077
- const tradingContext = useEventTradingContext2();
3287
+ const tradingContext = useEventTradingContext3();
3078
3288
  const detailsContentId = useId();
3289
+ const tradeSide = (_a = tradingContext == null ? void 0 : tradingContext.tradeSide) != null ? _a : "buy";
3079
3290
  const wsLivePrices = useLiveOutcomePrices2(venueMarkets);
3291
+ const wsBestPrices = useLiveBestPrices2(venueMarkets);
3292
+ const resolvedMarket = useMemo6(() => {
3293
+ return resolveMarketFromVenueMarkets(venueMarkets, marketId);
3294
+ }, [venueMarkets, marketId]);
3295
+ const scopedResolvedMarket = useMemo6(() => {
3296
+ var _a2, _b2;
3297
+ if (!resolvedMarket) return null;
3298
+ return (_b2 = (_a2 = resolvedMarket.venueMarkets.find((venueMarket) => venueMarket.id === resolvedMarket.id)) != null ? _a2 : resolvedMarket.venueMarkets[0]) != null ? _b2 : null;
3299
+ }, [resolvedMarket]);
3300
+ const isResolvedMarket = resolveMarketTradingState(scopedResolvedMarket).kind === "resolved";
3301
+ const clusterMidpointResult = midpointsResult != null ? midpointsResult : {
3302
+ prices: /* @__PURE__ */ new Map(),
3303
+ bestMidpointsByOutcomeId: /* @__PURE__ */ new Map(),
3304
+ venueByOutcomeId: /* @__PURE__ */ new Map(),
3305
+ bestPrices: /* @__PURE__ */ new Map(),
3306
+ bestPriceVenuesByOutcomeId: /* @__PURE__ */ new Map(),
3307
+ isLoading: false,
3308
+ bestMidpoint: void 0,
3309
+ bestMidpointVenue: void 0
3310
+ };
3311
+ const clusterMidpoints = (_b = clusterMidpointResult.bestMidpointsByOutcomeId) != null ? _b : clusterMidpointResult.prices;
3312
+ const clusterBestMidpointsByOutcomeId = clusterMidpoints;
3313
+ const clusterVenueByOutcomeId = clusterMidpointResult.venueByOutcomeId;
3314
+ const clusterBestMidpoint = clusterMidpointResult.bestMidpoint;
3315
+ const clusterBestMidpointVenue = clusterMidpointResult.bestMidpointVenue;
3316
+ const clusterBestPricesRest = clusterMidpointResult.bestPrices;
3317
+ const clusterBestPrices = useMemo6(
3318
+ () => mergeBestPricesPreferringLive2(clusterBestPricesRest, wsBestPrices),
3319
+ [clusterBestPricesRest, wsBestPrices]
3320
+ );
3321
+ const clusterBestPriceVenuesByOutcomeId = clusterMidpointResult.bestPriceVenuesByOutcomeId;
3322
+ const clusterMidpointMarkets = useMemo6(() => {
3323
+ var _a2;
3324
+ if (!resolvedMarket) return [];
3325
+ return (_a2 = resolvedMarket.venueMarkets) != null ? _a2 : [];
3326
+ }, [resolvedMarket]);
3327
+ const tradableVenues = useMemo6(() => {
3328
+ var _a2;
3329
+ if (clusterMidpointMarkets.length === 0) return null;
3330
+ if (clusterMidpoints.size === 0) return null;
3331
+ const set = /* @__PURE__ */ new Set();
3332
+ for (const market of clusterMidpointMarkets) {
3333
+ for (const outcome of (_a2 = market.venueMarketOutcomes) != null ? _a2 : []) {
3334
+ if (clusterMidpoints.has(outcome.id)) {
3335
+ set.add(market.venue);
3336
+ break;
3337
+ }
3338
+ }
3339
+ }
3340
+ return set;
3341
+ }, [clusterMidpointMarkets, clusterMidpoints]);
3080
3342
  const model = useMemo6(() => {
3081
3343
  return buildMarketDetailsModel({
3082
3344
  venueMarkets,
@@ -3084,17 +3346,18 @@ var MarketDetailsContent = ({
3084
3346
  title,
3085
3347
  image,
3086
3348
  formatCompactCurrency: config.formatting.formatCompactCurrency,
3087
- labels
3349
+ labels,
3350
+ tradableVenues
3088
3351
  });
3089
- }, [config.formatting.formatCompactCurrency, venueMarkets, image, labels, marketId, title]);
3090
- const resolvedMarket = useMemo6(() => {
3091
- return resolveMarketFromVenueMarkets(venueMarkets, marketId);
3092
- }, [venueMarkets, marketId]);
3093
- const clusterMidpointMarkets = useMemo6(() => {
3094
- if (!controlledIsOpened || !resolvedMarket) return [];
3095
- return resolvedMarket.venueMarkets;
3096
- }, [controlledIsOpened, resolvedMarket]);
3097
- const { prices: clusterMidpoints, venueByOutcomeId: clusterVenueByOutcomeId } = useMidpoints2(clusterMidpointMarkets);
3352
+ }, [
3353
+ config.formatting.formatCompactCurrency,
3354
+ venueMarkets,
3355
+ image,
3356
+ labels,
3357
+ marketId,
3358
+ title,
3359
+ tradableVenues
3360
+ ]);
3098
3361
  const livePrices = useMemo6(() => {
3099
3362
  const merged = /* @__PURE__ */ new Map();
3100
3363
  if (midpointsFallback == null ? void 0 : midpointsFallback.size) {
@@ -3118,7 +3381,6 @@ var MarketDetailsContent = ({
3118
3381
  const marketTradingState = useMemo6(() => {
3119
3382
  return resolveMarketTradingState(scopedMarketForCard);
3120
3383
  }, [scopedMarketForCard]);
3121
- const isResolvedMarket = marketTradingState.kind === "resolved";
3122
3384
  const isOutcomeSelectionLocked = marketTradingState.isTradingDisabled;
3123
3385
  const isUpcomingMarket = marketTradingState.kind === "unopened";
3124
3386
  const marketStatePresentation = resolveTradingStatePresentation(labels, marketTradingState);
@@ -3138,11 +3400,30 @@ var MarketDetailsContent = ({
3138
3400
  const selectedTimeRange = config.chart.selectedChartTimeRange;
3139
3401
  const setSelectedTimeRange = config.chart.setSelectedChartTimeRange;
3140
3402
  const effectiveSelectedTab = isResolvedMarket ? "graph" : selectedTab;
3141
- const effectiveChartTimeRange = isResolvedMarket ? "ALL" : selectedTimeRange;
3403
+ const [chartRangeOverride, setChartRangeOverride] = useState4(null);
3404
+ const effectiveChartTimeRange = isResolvedMarket ? "ALL" : chartRangeOverride != null ? chartRangeOverride : selectedTimeRange;
3142
3405
  const [selectedChartType, setSelectedChartType] = useState4("line");
3143
- const scopedSelectedOutcome = (_a = tradingContext == null ? void 0 : tradingContext.selectedOutcome) != null ? _a : null;
3144
- const selectedOutcomeId = (_b = scopedSelectedOutcome == null ? void 0 : scopedSelectedOutcome.id) != null ? _b : null;
3145
- const selectedOutcomeLabel = (_c = scopedSelectedOutcome == null ? void 0 : scopedSelectedOutcome.label) != null ? _c : null;
3406
+ const scopedSelectedOutcomeState = useMemo6(() => {
3407
+ if (!model) {
3408
+ return {
3409
+ outcomeId: null,
3410
+ outcomeLabel: void 0
3411
+ };
3412
+ }
3413
+ return resolveScopedSelectedOutcome({
3414
+ venueMarkets: model.market.venueMarkets,
3415
+ selectedOutcomeId: tradingContext == null ? void 0 : tradingContext.selectedOutcomeId,
3416
+ defaultOutcomeLabel,
3417
+ suppressFallbackWhenSelectedOutcomeOutOfScope: suppressOutcomeFallbackSelection
3418
+ });
3419
+ }, [
3420
+ defaultOutcomeLabel,
3421
+ model,
3422
+ suppressOutcomeFallbackSelection,
3423
+ tradingContext == null ? void 0 : tradingContext.selectedOutcomeId
3424
+ ]);
3425
+ const selectedOutcomeId = scopedSelectedOutcomeState.outcomeId;
3426
+ const selectedOutcomeLabel = (_c = scopedSelectedOutcomeState.outcomeLabel) != null ? _c : null;
3146
3427
  const selectOutcome = tradingContext == null ? void 0 : tradingContext.selectOutcome;
3147
3428
  const [selectedGraphVenue, setSelectedGraphVenue] = useState4(null);
3148
3429
  const [chartOutcomeLabel, setChartOutcomeLabel] = useState4(selectedOutcomeLabel);
@@ -3156,6 +3437,9 @@ var MarketDetailsContent = ({
3156
3437
  var _a2;
3157
3438
  if (!isOpened || !model) return;
3158
3439
  if (isOutcomeSelectionLocked) return;
3440
+ if ((tradingContext == null ? void 0 : tradingContext.selectedMarketId) && tradingContext.selectedMarketId !== model.market.id) {
3441
+ return;
3442
+ }
3159
3443
  if (selectedOutcomeId) return;
3160
3444
  const initialLabel = resolveInitialOutcomeLabel(model.outcomeLabels, defaultOutcomeLabel);
3161
3445
  if (!initialLabel) return;
@@ -3170,71 +3454,130 @@ var MarketDetailsContent = ({
3170
3454
  isOutcomeSelectionLocked,
3171
3455
  model,
3172
3456
  selectedOutcomeId,
3457
+ tradingContext == null ? void 0 : tradingContext.selectedMarketId,
3173
3458
  selectOutcome
3174
3459
  ]);
3175
3460
  const headerOutcomeItems = useMemo6(() => {
3176
3461
  if (!model) return [];
3177
- const items = resolveHeaderOutcomeItems(model.market.venueMarkets);
3462
+ const items = resolveHeaderOutcomeItems(model.market.venueMarkets, scopedMarketForCard);
3178
3463
  return items.map((item) => {
3179
- const clusterPrice = clusterMidpoints.get(item.id);
3180
- if (clusterPrice != null) {
3181
- const bestVenue = clusterVenueByOutcomeId.get(item.id);
3182
- return __spreadValues(__spreadProps(__spreadValues({}, item), { probability: clusterPrice }), bestVenue ? { venue: bestVenue } : {});
3183
- }
3464
+ var _a2;
3184
3465
  const fallbackPrice = midpointsFallback == null ? void 0 : midpointsFallback.get(item.id);
3185
- if (fallbackPrice != null) {
3186
- const bestVenue = midpointsFallbackVenues == null ? void 0 : midpointsFallbackVenues.get(item.id);
3187
- return __spreadValues(__spreadProps(__spreadValues({}, item), { probability: fallbackPrice }), bestVenue ? { venue: bestVenue } : {});
3466
+ const bestVenue = getDisplayOutcomeVenue({
3467
+ outcomeId: item.id,
3468
+ outcomeLabel: item.label,
3469
+ selection: tradeSide,
3470
+ bestMidpointVenue: clusterBestMidpointVenue,
3471
+ bestVenueByOutcomeId: clusterVenueByOutcomeId,
3472
+ bestPriceVenuesByOutcomeId: clusterBestPriceVenuesByOutcomeId,
3473
+ fallbackVenue: midpointsFallbackVenues == null ? void 0 : midpointsFallbackVenues.get(item.id)
3474
+ });
3475
+ const outcomeBestPrice = getDisplayOutcomePrice({
3476
+ outcomeId: item.id,
3477
+ outcomeLabel: item.label,
3478
+ selection: tradeSide,
3479
+ bestPrices: clusterBestPrices,
3480
+ bestMidpoint: clusterBestMidpoint,
3481
+ bestMidpointsByOutcomeId: clusterBestMidpointsByOutcomeId,
3482
+ livePrices: wsLivePrices,
3483
+ fallbackPrice
3484
+ });
3485
+ if (isResolvedMarket) {
3486
+ const isWinningOutcome = item.id === ((_a2 = marketTradingState.winningOutcome) == null ? void 0 : _a2.id);
3487
+ return __spreadValues(__spreadProps(__spreadValues({}, item), {
3488
+ probability: isWinningOutcome ? 1 : 0
3489
+ }), bestVenue ? { venue: bestVenue } : {});
3188
3490
  }
3189
- const wsPrice = findLivePriceById(wsLivePrices, item.id);
3190
- return wsPrice != null ? __spreadProps(__spreadValues({}, item), { probability: wsPrice }) : item;
3491
+ if (outcomeBestPrice != null) {
3492
+ return __spreadValues(__spreadProps(__spreadValues({}, item), {
3493
+ probability: outcomeBestPrice
3494
+ }), bestVenue ? { venue: bestVenue } : {});
3495
+ }
3496
+ return item;
3191
3497
  });
3192
3498
  }, [
3499
+ clusterBestMidpoint,
3500
+ clusterBestMidpointVenue,
3501
+ clusterBestMidpointsByOutcomeId,
3502
+ clusterBestPrices,
3503
+ clusterBestPriceVenuesByOutcomeId,
3193
3504
  model,
3194
- clusterMidpoints,
3505
+ scopedMarketForCard,
3195
3506
  clusterVenueByOutcomeId,
3507
+ isResolvedMarket,
3508
+ (_d = marketTradingState.winningOutcome) == null ? void 0 : _d.id,
3196
3509
  midpointsFallback,
3197
3510
  midpointsFallbackVenues,
3511
+ tradeSide,
3198
3512
  wsLivePrices
3199
3513
  ]);
3200
3514
  const headlineProbability = useMemo6(() => {
3201
3515
  var _a2, _b2, _c2, _d2;
3202
3516
  if (!model || !scopedMarketForCard) return void 0;
3517
+ if (isResolvedMarket) {
3518
+ const yesOutcome2 = resolveYesOutcome(scopedMarketForCard);
3519
+ if (!yesOutcome2) return void 0;
3520
+ return yesOutcome2.winner === true ? 1 : 0;
3521
+ }
3203
3522
  const yesOutcome = resolveYesOutcome(scopedMarketForCard);
3204
3523
  const displayOutcome = yesOutcome != null ? yesOutcome : (_b2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _b2.reduce(
3205
3524
  (acc, outcome) => outcome.price > acc.price ? outcome : acc,
3206
3525
  (_a2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _a2[0]
3207
3526
  );
3208
- const restPrice = (_c2 = clusterMidpoints.get(displayOutcome.id)) != null ? _c2 : midpointsFallback == null ? void 0 : midpointsFallback.get(displayOutcome.id);
3209
- if (restPrice != null) return restPrice;
3527
+ if (displayOutcome == null) return void 0;
3528
+ const referencePrice = getDisplayOutcomePrice({
3529
+ outcomeId: displayOutcome.id,
3530
+ outcomeLabel: displayOutcome.label,
3531
+ selection: "buy",
3532
+ bestPrices: clusterBestPrices,
3533
+ bestMidpoint: clusterBestMidpoint,
3534
+ bestMidpointsByOutcomeId: clusterBestMidpointsByOutcomeId,
3535
+ livePrices: wsLivePrices,
3536
+ fallbackPrice: (_c2 = midpointsFallback == null ? void 0 : midpointsFallback.get(displayOutcome.id)) != null ? _c2 : displayOutcome.price
3537
+ });
3538
+ if (referencePrice != null) return referencePrice;
3210
3539
  return (_d2 = findLivePriceById(wsLivePrices, displayOutcome.id)) != null ? _d2 : displayOutcome.price;
3211
- }, [model, scopedMarketForCard, clusterMidpoints, midpointsFallback, wsLivePrices]);
3540
+ }, [
3541
+ clusterBestMidpoint,
3542
+ clusterBestMidpointsByOutcomeId,
3543
+ clusterBestPrices,
3544
+ model,
3545
+ scopedMarketForCard,
3546
+ isResolvedMarket,
3547
+ midpointsFallback,
3548
+ wsLivePrices
3549
+ ]);
3212
3550
  const selectedOutcomesByVenue = useMemo6(() => {
3213
3551
  if (!model) return [];
3214
3552
  return collectEligibleVenueOutcomes({
3215
3553
  venueMarkets: model.market.venueMarkets,
3216
- selectedOutcomeLabel
3554
+ selectedOutcomeLabel,
3555
+ // Critical for inversely-framed binaries: pass the exact outcome id so
3556
+ // collectEligibleVenueOutcomes pins to the user's chosen semantic side
3557
+ // instead of falling through to label-matching across other markets
3558
+ // (which surfaces opposite-side outcomes for kalshi per-team No-side).
3559
+ selectedOutcomeId
3217
3560
  });
3218
- }, [model, selectedOutcomeLabel]);
3561
+ }, [model, selectedOutcomeLabel, selectedOutcomeId]);
3219
3562
  const resolvedChartOutcomeLabel = chartOutcomeLabel != null ? chartOutcomeLabel : selectedOutcomeLabel;
3563
+ const chartSelectedOutcomeId = selectedOutcomeId && resolvedChartOutcomeLabel === selectedOutcomeLabel ? selectedOutcomeId : null;
3220
3564
  const chartOutcomesByVenue = useMemo6(() => {
3221
3565
  if (!model) return [];
3222
3566
  return resolveChartVenueOutcomes({
3223
3567
  eligibleVenueOutcomes: collectEligibleVenueOutcomes({
3224
3568
  venueMarkets: model.market.venueMarkets,
3225
- selectedOutcomeLabel: resolvedChartOutcomeLabel
3569
+ selectedOutcomeLabel: resolvedChartOutcomeLabel,
3570
+ selectedOutcomeId: chartSelectedOutcomeId
3226
3571
  }),
3227
3572
  livePrices
3228
3573
  });
3229
- }, [livePrices, model, resolvedChartOutcomeLabel]);
3574
+ }, [livePrices, model, resolvedChartOutcomeLabel, chartSelectedOutcomeId]);
3230
3575
  const chartEnabled = isOpened && effectiveSelectedTab === "graph";
3231
3576
  const orderBookEnabled = isOpened && effectiveSelectedTab === "order-book" && !marketTradingState.isTradingDisabled;
3232
- const timeWindow = useMemo6(() => {
3233
- return getTimeWindowByRange(effectiveChartTimeRange);
3234
- }, [effectiveChartTimeRange]);
3235
- const primaryVenueMarketId = (_e = (_d = selectedOutcomesByVenue[0]) == null ? void 0 : _d.market.id) != null ? _e : null;
3236
- const primaryOutcomeId = (_g = (_f = selectedOutcomesByVenue[0]) == null ? void 0 : _f.outcome.id) != null ? _g : null;
3237
- const chartPrimaryOutcomeId = (_i = (_h = chartOutcomesByVenue[0]) == null ? void 0 : _h.outcome.id) != null ? _i : null;
3577
+ const rollingWindow = useRollingChartWindow2({ range: effectiveChartTimeRange });
3578
+ const primaryVenueMarketId = (_f = (_e = selectedOutcomesByVenue[0]) == null ? void 0 : _e.market.id) != null ? _f : null;
3579
+ const primaryOutcomeId = (_h = (_g = selectedOutcomesByVenue[0]) == null ? void 0 : _g.outcome.id) != null ? _h : null;
3580
+ const chartPrimaryOutcomeId = (_j = (_i = chartOutcomesByVenue[0]) == null ? void 0 : _i.outcome.id) != null ? _j : null;
3238
3581
  const chartVenueOutcomeIds = useMemo6(() => {
3239
3582
  return chartOutcomesByVenue.map((item) => item.outcome.id);
3240
3583
  }, [chartOutcomesByVenue]);
@@ -3246,12 +3589,43 @@ var MarketDetailsContent = ({
3246
3589
  } = useMarketChart2({
3247
3590
  marketId: chartPrimaryOutcomeId,
3248
3591
  venueMarketIds: chartVenueOutcomeIds,
3249
- interval: timeRangeToInterval2(effectiveChartTimeRange),
3250
- startTs: timeWindow.startTs * 1e3,
3251
- endTs: timeWindow.endTs * 1e3,
3592
+ interval: rollingWindow.interval,
3593
+ startTs: rollingWindow.startTs * 1e3,
3594
+ endTs: rollingWindow.endTs * 1e3,
3252
3595
  enabled: chartEnabled && !!chartPrimaryOutcomeId,
3253
- live
3596
+ live,
3597
+ refetchIntervalMs: rollingWindow.refetchIntervalMs,
3598
+ // Stable cache key per user-selected range so tab/page revisits hit cache
3599
+ // instead of refetching on every bucket-boundary rollover.
3600
+ rangeKey: rollingWindow.range
3254
3601
  });
3602
+ const hasAutoFallenBackRangeRef = useRef5(false);
3603
+ useEffect4(() => {
3604
+ hasAutoFallenBackRangeRef.current = false;
3605
+ setChartRangeOverride(null);
3606
+ }, [chartPrimaryOutcomeId]);
3607
+ useEffect4(() => {
3608
+ if (!shouldAutoFallbackToAllRange({
3609
+ chartData: marketChartData,
3610
+ isLoading: isMarketChartLoading,
3611
+ error: marketChartError,
3612
+ currentRange: effectiveChartTimeRange,
3613
+ hasAlreadyFallenBack: hasAutoFallenBackRangeRef.current,
3614
+ // Ignore stale bars outside the rolling window — see comment on the
3615
+ // matching effect in event-list-item-details.
3616
+ domainStartTs: rollingWindow.startTs
3617
+ })) {
3618
+ return;
3619
+ }
3620
+ hasAutoFallenBackRangeRef.current = true;
3621
+ setChartRangeOverride("ALL");
3622
+ }, [
3623
+ marketChartData,
3624
+ isMarketChartLoading,
3625
+ marketChartError,
3626
+ effectiveChartTimeRange,
3627
+ rollingWindow.startTs
3628
+ ]);
3255
3629
  const marketOrderbookResult = useMarketOrderbook({
3256
3630
  marketId: primaryVenueMarketId,
3257
3631
  enabled: orderBookEnabled && !!primaryVenueMarketId,
@@ -3305,6 +3679,7 @@ var MarketDetailsContent = ({
3305
3679
  0,
3306
3680
  isDarkTheme
3307
3681
  );
3682
+ const domainStartTs = rollingWindow.startTs;
3308
3683
  return resolveMarketChartDisplaySeries({
3309
3684
  chartData: marketChartData,
3310
3685
  selectedVenue: selectedGraphVenue,
@@ -3314,13 +3689,16 @@ var MarketDetailsContent = ({
3314
3689
  id: `${resolvedChartOutcomeLabel != null ? resolvedChartOutcomeLabel : "graph"}-${seriesItem.venue}-${chartPrimaryOutcomeId != null ? chartPrimaryOutcomeId : "chart"}`,
3315
3690
  venue: selectedGraphVenue != null ? selectedGraphVenue : seriesItem.venue,
3316
3691
  color: seriesItem.venue === "aggregate" ? baseColor : resolveSeriesColor(seriesItem.venue, 0, isDarkTheme),
3317
- points: seriesItem.points
3692
+ // Constrain to the rolling [nowSec - rangeSeconds, …] domain so stale
3693
+ // bars don't bleed in across a range shrink or long mount.
3694
+ points: seriesItem.points.filter((point) => point.time >= domainStartTs)
3318
3695
  };
3319
3696
  });
3320
3697
  }, [
3321
3698
  isDarkTheme,
3322
3699
  chartPrimaryOutcomeId,
3323
3700
  marketChartData,
3701
+ rollingWindow.startTs,
3324
3702
  selectedGraphVenue,
3325
3703
  resolvedChartOutcomeLabel,
3326
3704
  chartAvailableOutcomesByVenue,
@@ -3348,11 +3726,19 @@ var MarketDetailsContent = ({
3348
3726
  item,
3349
3727
  shouldNotifyOutcomeSelect = false
3350
3728
  }) => {
3729
+ var _a2, _b2;
3351
3730
  if (isOutcomeSelectionLocked) return;
3352
3731
  if (item == null ? void 0 : item.id) {
3353
- tradingContext == null ? void 0 : tradingContext.selectOutcome(item.id);
3732
+ const targetMarket = (_a2 = model == null ? void 0 : model.market.venueMarkets.find(
3733
+ (venueMarket) => venueMarket.venueMarketOutcomes.some((outcome) => outcome.id === item.id)
3734
+ )) != null ? _a2 : null;
3735
+ if ((targetMarket == null ? void 0 : targetMarket.id) && targetMarket.id !== (tradingContext == null ? void 0 : tradingContext.selectedMarketId)) {
3736
+ tradingContext == null ? void 0 : tradingContext.selectMarketAndOutcome(targetMarket.id, item.id);
3737
+ } else {
3738
+ tradingContext == null ? void 0 : tradingContext.selectOutcome(item.id);
3739
+ }
3354
3740
  if (shouldNotifyOutcomeSelect && model) {
3355
- onOutcomeSelect == null ? void 0 : onOutcomeSelect({ marketId: model.market.id, outcomeId: item.id });
3741
+ onOutcomeSelect == null ? void 0 : onOutcomeSelect({ marketId: (_b2 = targetMarket == null ? void 0 : targetMarket.id) != null ? _b2 : model.market.id, outcomeId: item.id });
3356
3742
  }
3357
3743
  }
3358
3744
  };
@@ -3447,26 +3833,24 @@ var MarketDetailsContent = ({
3447
3833
  {
3448
3834
  className: cn(
3449
3835
  "agg-market-card-header",
3450
- "cursor-pointer",
3451
3836
  "flex flex-col items-stretch gap-3 px-5 py-3 md:flex-row md:flex-nowrap md:items-center md:justify-between",
3452
3837
  isOpened && "pb-3",
3453
3838
  classNames == null ? void 0 : classNames.header
3454
3839
  ),
3455
- onClick: handleToggleExpanded,
3456
3840
  children: [
3457
3841
  /* @__PURE__ */ jsxs7(
3458
3842
  "button",
3459
3843
  {
3460
- type: "button",
3461
3844
  className: cn(
3462
3845
  "agg-market-card-summary",
3463
3846
  "flex min-w-0 w-full items-center justify-between gap-4 text-left md:flex-1",
3464
3847
  "cursor-pointer rounded-agg-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-agg-primary focus-visible:ring-offset-0 focus-visible:ring-offset-agg-secondary"
3465
3848
  ),
3849
+ type: "button",
3850
+ onClick: handleToggleExpanded,
3466
3851
  "aria-expanded": isOpened,
3467
3852
  "aria-controls": detailsContentId,
3468
3853
  "aria-label": isOpened ? labels.marketDetails.toggleCloseDetailsAria(model.title) : labels.marketDetails.toggleOpenDetailsAria(model.title),
3469
- onClick: handleToggleExpanded,
3470
3854
  children: [
3471
3855
  /* @__PURE__ */ jsxs7("div", { className: "agg-market-summary flex min-w-24 flex-1 items-center gap-3 md:gap-4", children: [
3472
3856
  /* @__PURE__ */ jsx9(
@@ -3495,7 +3879,7 @@ var MarketDetailsContent = ({
3495
3879
  children: model.subtitle
3496
3880
  }
3497
3881
  ) }),
3498
- marketTradingState.isTradingDisabled && marketTradingState.kind !== "resolved" && !isUpcomingMarket ? /* @__PURE__ */ jsxs7("div", { className: "mt-2 flex flex-wrap items-center gap-2", children: [
3882
+ marketTradingState.isTradingDisabled && marketTradingState.kind !== "resolved" && !isUpcomingMarket ? /* @__PURE__ */ jsxs7("div", { className: "mt-2 flex flex-wrap items-center gap-2 justify-center md:justify-start", children: [
3499
3883
  /* @__PURE__ */ jsxs7(
3500
3884
  "span",
3501
3885
  {
@@ -3525,75 +3909,60 @@ var MarketDetailsContent = ({
3525
3909
  ]
3526
3910
  }
3527
3911
  ),
3528
- marketTradingState.kind === "resolved" && marketTradingState.winningOutcome ? /* @__PURE__ */ jsx9(
3529
- "div",
3912
+ marketTradingState.kind === "resolved" && marketTradingState.winningOutcome ? /* @__PURE__ */ jsx9("div", { className: "agg-outcomes flex w-full items-center justify-end md:w-auto md:shrink-0", children: /* @__PURE__ */ jsxs7(
3913
+ "span",
3530
3914
  {
3531
- className: "agg-outcomes flex w-full items-center justify-end md:w-auto md:shrink-0",
3532
- onClick: (e) => e.stopPropagation(),
3533
- children: /* @__PURE__ */ jsxs7(
3534
- "span",
3535
- {
3536
- className: cn(
3537
- "w-full md:w-auto md:min-w-35 inline-flex h-9 items-center justify-center gap-2 rounded-agg-full",
3538
- "border px-5 py-1.5 text-agg-sm font-agg-bold",
3539
- getMotionClassName(
3540
- enableAnimations,
3541
- "transition-[background-color,border-color,color] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)]"
3542
- ),
3543
- "border-transparent bg-agg-secondary-hover"
3544
- ),
3545
- children: [
3546
- /* @__PURE__ */ jsx9(
3547
- Icon,
3548
- {
3549
- name: marketTradingState.winningOutcome.label.trim().toLowerCase() === "yes" ? "check-circle" : "cross-circle",
3550
- size: "small",
3551
- className: cn(
3552
- "h-4 w-4",
3553
- marketTradingState.winningOutcome.label.trim().toLowerCase() === "yes" ? "text-agg-success" : "text-agg-error"
3554
- )
3555
- }
3556
- ),
3557
- /* @__PURE__ */ jsx9(Typography, { variant: "body", children: labels.eventMarketPage.resolvedOutcome(marketTradingState.winningOutcome.label) })
3558
- ]
3559
- }
3560
- )
3915
+ className: cn(
3916
+ "w-full md:w-auto md:min-w-35 inline-flex h-9 items-center justify-center gap-2 rounded-agg-full",
3917
+ "border px-5 py-1.5 text-agg-sm font-agg-bold",
3918
+ getMotionClassName(
3919
+ enableAnimations,
3920
+ "transition-[background-color,border-color,color] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)]"
3921
+ ),
3922
+ "border-transparent bg-agg-secondary-hover"
3923
+ ),
3924
+ children: [
3925
+ /* @__PURE__ */ jsx9(
3926
+ Icon,
3927
+ {
3928
+ name: marketTradingState.winningOutcome.label.trim().toLowerCase() === "yes" ? "check-circle" : "cross-circle",
3929
+ size: "small",
3930
+ className: cn(
3931
+ "h-4 w-4",
3932
+ marketTradingState.winningOutcome.label.trim().toLowerCase() === "yes" ? "text-agg-success" : "text-agg-error"
3933
+ )
3934
+ }
3935
+ ),
3936
+ /* @__PURE__ */ jsx9(Typography, { variant: "body", children: labels.eventMarketPage.resolvedOutcome(marketTradingState.winningOutcome.label) })
3937
+ ]
3561
3938
  }
3562
- ) : isUpcomingMarket ? /* @__PURE__ */ jsx9(
3563
- "div",
3939
+ ) }) : isUpcomingMarket ? /* @__PURE__ */ jsx9("div", { className: "agg-outcomes flex w-full items-center justify-end md:w-auto md:shrink-0", children: /* @__PURE__ */ jsxs7(
3940
+ "span",
3564
3941
  {
3565
- className: "agg-outcomes flex w-full items-center justify-end md:w-auto md:shrink-0",
3566
- onClick: (e) => e.stopPropagation(),
3567
- children: /* @__PURE__ */ jsxs7(
3568
- "span",
3569
- {
3570
- className: cn(
3571
- "min-w-35 inline-flex h-9 items-center justify-center gap-2 rounded-agg-full",
3572
- "border px-5 py-1.5 text-agg-xs font-agg-bold uppercase tracking-[0.08em]",
3573
- resolveTradingStateBadgeClassName(marketTradingState.kind)
3574
- ),
3575
- children: [
3576
- /* @__PURE__ */ jsx9(
3577
- Icon,
3578
- {
3579
- name: marketStatePresentation.iconName,
3580
- size: "small",
3581
- className: "h-3.5 w-3.5",
3582
- "aria-hidden": "true"
3583
- }
3584
- ),
3585
- /* @__PURE__ */ jsx9("span", { children: marketStatePresentation.badgeLabel })
3586
- ]
3587
- }
3588
- )
3942
+ className: cn(
3943
+ "min-w-35 inline-flex h-9 items-center justify-center gap-2 rounded-agg-full",
3944
+ "border px-5 py-1.5 text-agg-xs font-agg-bold uppercase tracking-[0.08em]",
3945
+ resolveTradingStateBadgeClassName(marketTradingState.kind)
3946
+ ),
3947
+ children: [
3948
+ /* @__PURE__ */ jsx9(
3949
+ Icon,
3950
+ {
3951
+ name: marketStatePresentation.iconName,
3952
+ size: "small",
3953
+ className: "h-3.5 w-3.5",
3954
+ "aria-hidden": "true"
3955
+ }
3956
+ ),
3957
+ /* @__PURE__ */ jsx9("span", { children: marketStatePresentation.badgeLabel })
3958
+ ]
3589
3959
  }
3590
- ) : /* @__PURE__ */ jsx9(
3960
+ ) }) : /* @__PURE__ */ jsx9(
3591
3961
  "div",
3592
3962
  {
3593
3963
  className: "agg-outcomes flex w-full flex-wrap gap-2 md:w-auto md:shrink-0 md:flex-nowrap",
3594
3964
  role: "tablist",
3595
3965
  "aria-label": labels.marketDetails.marketOutcomesAria,
3596
- onClick: (e) => e.stopPropagation(),
3597
3966
  onKeyDown: (eventToHandle) => handleOutcomeKeyDown(eventToHandle),
3598
3967
  children: headerOutcomeItems.map((item) => {
3599
3968
  const isActiveOutcome = item.id === selectedOutcomeId;
@@ -3711,7 +4080,7 @@ var MarketDetailsContent = ({
3711
4080
  height: 260,
3712
4081
  isLoading: isMarketChartLoading,
3713
4082
  chartType: selectedChartType,
3714
- liveCandle: selectedChartType === "candlestick" ? (_j = graphLiveState.liveCandle) != null ? _j : void 0 : void 0,
4083
+ liveCandle: selectedChartType === "candlestick" ? (_k = graphLiveState.liveCandle) != null ? _k : void 0 : void 0,
3715
4084
  lineValue: graphLiveState.lineValue,
3716
4085
  classNames: { root: "agg-chart-region w-full" },
3717
4086
  showSeriesControls: chartAvailableOutcomesByVenue.length > 0 || headerOutcomeItems.length > 0,
@@ -3767,12 +4136,12 @@ var MarketDetailsContent = ({
3767
4136
  setChartOutcomeLabel(outcome.label);
3768
4137
  },
3769
4138
  options: headerOutcomeItems.map((outcome) => {
4139
+ var _a3, _b3;
3770
4140
  const price = outcome.probability;
3771
- const outcomeLabel = `${outcome.label} ${formatProbabilityCents(price)}`;
3772
4141
  return {
3773
4142
  value: outcome.id,
3774
- label: outcomeLabel,
3775
- ariaLabel: outcomeLabel
4143
+ label: `${(_a3 = outcome == null ? void 0 : outcome.title) != null ? _a3 : outcome.label} ${formatProbabilityCents(price)}`,
4144
+ ariaLabel: `${(_b3 = outcome == null ? void 0 : outcome.title) != null ? _b3 : outcome.label} ${formatProbabilityCents(price)}`
3776
4145
  };
3777
4146
  })
3778
4147
  }
@@ -3827,6 +4196,7 @@ var MarketDetailsContent = ({
3827
4196
  e.preventDefault();
3828
4197
  e.stopPropagation();
3829
4198
  if (isDisabled) return;
4199
+ setChartRangeOverride(null);
3830
4200
  setSelectedTimeRange(timeRange);
3831
4201
  },
3832
4202
  children: timeRange === "ALL" ? labels.eventItemDetails.allTimeRange : timeRange
@@ -3863,8 +4233,16 @@ var MarketDetailsContent = ({
3863
4233
  };
3864
4234
  var MarketDetails = (_a) => {
3865
4235
  var _b = _a, { isOpened } = _b, props = __objRest(_b, ["isOpened"]);
4236
+ const labels = useLabels6();
3866
4237
  if (props.isLoading) {
3867
- return /* @__PURE__ */ jsx9(MarketDetailsLoadingState, { isOpened, classNames: props.classNames });
4238
+ return /* @__PURE__ */ jsx9(
4239
+ Skeleton,
4240
+ {
4241
+ view: "market-details-minified",
4242
+ className: cn("agg-market-list-item"),
4243
+ ariaLabel: labels.marketDetails.loading
4244
+ }
4245
+ );
3868
4246
  }
3869
4247
  if ("venueMarkets" in props && props.venueMarkets) {
3870
4248
  return /* @__PURE__ */ jsx9(
@@ -3929,16 +4307,17 @@ var MarketDetailsList = ({
3929
4307
  onClick,
3930
4308
  onOutcomeSelect,
3931
4309
  onExpandedMarketChange,
4310
+ autoSelectFallbackMarket = true,
3932
4311
  defaultTab,
3933
4312
  classNames,
3934
- live
4313
+ live,
4314
+ midpointsResult
3935
4315
  }) => {
3936
4316
  var _a, _b;
3937
4317
  const labels = useLabels6();
3938
- const tradingContext = useEventTradingContext2();
4318
+ const tradingContext = useEventTradingContext3();
3939
4319
  const selectedMarketId = (_a = tradingContext == null ? void 0 : tradingContext.selectedMarketId) != null ? _a : null;
3940
- const [expandedMarketId, setExpandedMarketId] = useState4(selectedMarketId);
3941
- const previousSelectedMarketIdRef = useRef5(selectedMarketId);
4320
+ const [expandedMarketId, setExpandedMarketId] = useState4(null);
3942
4321
  const [areResolvedMarketsVisible, setAreResolvedMarketsVisible] = useState4(false);
3943
4322
  const resolvedEventId = eventId || "";
3944
4323
  const {
@@ -4012,7 +4391,12 @@ var MarketDetailsList = ({
4012
4391
  return [...groupedMarkets.primary, ...visibleResolvedMarkets];
4013
4392
  }, [groupedMarkets.primary, visibleResolvedMarkets]);
4014
4393
  const hasPrefetchedMarkets = !!providedMarkets || !!((_b = eventTradingState == null ? void 0 : eventTradingState.marketStates) == null ? void 0 : _b.length);
4015
- const { prices: midpointsFallback, venueByOutcomeId: midpointsFallbackVenues } = useViewportMidpoints(displayedMarkets);
4394
+ const midpointEligibleMarkets = useMemo6(() => {
4395
+ return displayedMarkets.filter(
4396
+ (market) => resolveMarketTradingState(market).kind !== "resolved"
4397
+ );
4398
+ }, [displayedMarkets]);
4399
+ const { prices: midpointsFallback, venueByOutcomeId: midpointsFallbackVenues } = useViewportMidpoints(midpointEligibleMarkets);
4016
4400
  useEffect4(() => {
4017
4401
  if (isResolvedEvent) {
4018
4402
  setAreResolvedMarketsVisible(false);
@@ -4022,13 +4406,6 @@ var MarketDetailsList = ({
4022
4406
  setAreResolvedMarketsVisible(false);
4023
4407
  }
4024
4408
  }, [groupedMarkets.resolved.length, isResolvedEvent]);
4025
- useEffect4(() => {
4026
- if (previousSelectedMarketIdRef.current === selectedMarketId) return;
4027
- previousSelectedMarketIdRef.current = selectedMarketId;
4028
- if (!selectedMarketId) return;
4029
- if (!displayedMarkets.some((market) => market.id === selectedMarketId)) return;
4030
- setExpandedMarketId(selectedMarketId);
4031
- }, [displayedMarkets, selectedMarketId]);
4032
4409
  useEffect4(() => {
4033
4410
  if (displayedMarkets.length === 0) return;
4034
4411
  if (selectedMarketId && displayedMarkets.some((market) => market.id === selectedMarketId)) {
@@ -4043,21 +4420,14 @@ var MarketDetailsList = ({
4043
4420
  if (!fallbackSelectableMarket) {
4044
4421
  return;
4045
4422
  }
4046
- if (!expandedMarketId) {
4047
- setExpandedMarketId(fallbackSelectableMarket.id);
4048
- }
4423
+ if (!autoSelectFallbackMarket) return;
4049
4424
  tradingContext == null ? void 0 : tradingContext.selectMarket(fallbackSelectableMarket.id, fallbackSelectableMarket);
4050
- }, [displayedMarkets, expandedMarketId, selectedMarketId, sourceMarkets, tradingContext]);
4425
+ }, [autoSelectFallbackMarket, displayedMarkets, selectedMarketId, sourceMarkets, tradingContext]);
4051
4426
  useEffect4(() => {
4052
- var _a2, _b2;
4053
4427
  if (!expandedMarketId) return;
4054
4428
  if (displayedMarkets.some((market) => market.id === expandedMarketId)) return;
4055
- if (selectedMarketId && displayedMarkets.some((market) => market.id === selectedMarketId)) {
4056
- setExpandedMarketId(selectedMarketId);
4057
- return;
4058
- }
4059
- setExpandedMarketId((_b2 = (_a2 = displayedMarkets[0]) == null ? void 0 : _a2.id) != null ? _b2 : null);
4060
- }, [displayedMarkets, expandedMarketId, selectedMarketId]);
4429
+ setExpandedMarketId(null);
4430
+ }, [displayedMarkets, expandedMarketId]);
4061
4431
  const handleToggle = (marketId, market) => {
4062
4432
  if (marketId === expandedMarketId) {
4063
4433
  setExpandedMarketId(null);
@@ -4071,22 +4441,14 @@ var MarketDetailsList = ({
4071
4441
  tradingContext == null ? void 0 : tradingContext.selectMarket(market.id, market);
4072
4442
  };
4073
4443
  if (!hasPrefetchedMarkets && isLoading) {
4074
- return /* @__PURE__ */ jsxs7("div", { className: cn("agg-market-list flex flex-col gap-3", classNames == null ? void 0 : classNames.root), children: [
4075
- /* @__PURE__ */ jsx9(
4076
- MarketDetailsLoadingState,
4077
- {
4078
- isOpened: true,
4079
- classNames: { root: cn("agg-market-list-item", classNames == null ? void 0 : classNames.item) }
4080
- }
4081
- ),
4082
- /* @__PURE__ */ jsx9(
4083
- MarketDetailsLoadingState,
4084
- {
4085
- isOpened: false,
4086
- classNames: { root: cn("agg-market-list-item", classNames == null ? void 0 : classNames.item) }
4087
- }
4088
- )
4089
- ] });
4444
+ return /* @__PURE__ */ jsx9(
4445
+ Skeleton,
4446
+ {
4447
+ view: "market-details-minified",
4448
+ className: cn("agg-market-list-item"),
4449
+ ariaLabel: labels.marketDetails.loading
4450
+ }
4451
+ );
4090
4452
  }
4091
4453
  if (!hasPrefetchedMarkets && error) {
4092
4454
  return /* @__PURE__ */ jsx9(
@@ -4117,17 +4479,25 @@ var MarketDetailsList = ({
4117
4479
  marketId: market.id,
4118
4480
  venueMarkets: sourceMarkets,
4119
4481
  isOpened: expandedMarketId === market.id,
4482
+ suppressOutcomeFallbackSelection: market.id !== selectedMarketId,
4120
4483
  onOpenChange: (marketId) => {
4121
4484
  onClick == null ? void 0 : onClick(market);
4122
4485
  handleToggle(marketId, market);
4123
4486
  },
4124
- onOutcomeSelect,
4487
+ onOutcomeSelect: (selection) => {
4488
+ if (selection.marketId !== expandedMarketId) {
4489
+ setExpandedMarketId(selection.marketId);
4490
+ onExpandedMarketChange == null ? void 0 : onExpandedMarketChange(selection.marketId);
4491
+ }
4492
+ onOutcomeSelect == null ? void 0 : onOutcomeSelect(selection);
4493
+ },
4125
4494
  defaultTab,
4126
4495
  ariaLabel: market.question,
4127
4496
  classNames: { root: cn("agg-market-list-item", classNames == null ? void 0 : classNames.item) },
4128
4497
  live,
4129
4498
  midpointsFallback,
4130
- midpointsFallbackVenues
4499
+ midpointsFallbackVenues,
4500
+ midpointsResult
4131
4501
  }
4132
4502
  ) }, market.id);
4133
4503
  return /* @__PURE__ */ jsxs7("div", { className: cn("agg-market-list flex flex-col gap-3", classNames == null ? void 0 : classNames.root), children: [
@@ -4137,7 +4507,7 @@ var MarketDetailsList = ({
4137
4507
  {
4138
4508
  variant: "tertiary",
4139
4509
  size: "small",
4140
- className: "agg-market-view-resolved-toggle self-start",
4510
+ className: "agg-market-view-resolved-toggle self-start my-2",
4141
4511
  onClick: () => {
4142
4512
  setAreResolvedMarketsVisible((isVisible) => !isVisible);
4143
4513
  },
@@ -4167,6 +4537,72 @@ import { useEffect as useEffect6, useMemo as useMemo8, useRef as useRef7, useSta
4167
4537
  // src/events/list/event-list-tabs.tsx
4168
4538
  import { useAppConfig, useLabels as useLabels7 } from "@agg-build/hooks";
4169
4539
  import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo7, useRef as useRef6, useState as useState5 } from "react";
4540
+
4541
+ // src/events/list/event-list.constants.ts
4542
+ import { MatchStatus, Venue as Venue2 } from "@agg-build/sdk";
4543
+ var DEFAULT_EVENTS_LIMIT = 50;
4544
+ var getDefaultEventListTabs = (labels) => {
4545
+ return [
4546
+ {
4547
+ value: "matched",
4548
+ label: labels.eventList.matchedTab,
4549
+ iconName: "circle-overlap",
4550
+ matchStatus: [MatchStatus.matched, MatchStatus.verified]
4551
+ },
4552
+ {
4553
+ value: "all",
4554
+ label: labels.eventList.allTab,
4555
+ iconName: "apps"
4556
+ },
4557
+ {
4558
+ value: Venue2.polymarket,
4559
+ label: labels.venues.polymarket,
4560
+ venueLogo: Venue2.polymarket,
4561
+ venues: [Venue2.polymarket]
4562
+ },
4563
+ {
4564
+ value: Venue2.kalshi,
4565
+ label: labels.venues.kalshi,
4566
+ venueLogo: Venue2.kalshi,
4567
+ venues: [Venue2.kalshi]
4568
+ },
4569
+ {
4570
+ value: Venue2.limitless,
4571
+ label: labels.venues.limitless,
4572
+ venueLogo: Venue2.limitless,
4573
+ venues: [Venue2.limitless]
4574
+ },
4575
+ {
4576
+ value: Venue2.predict,
4577
+ label: labels.venues.predict,
4578
+ venueLogo: Venue2.predict,
4579
+ venues: [Venue2.predict]
4580
+ },
4581
+ {
4582
+ value: Venue2.hyperliquid,
4583
+ label: labels.venues.hyperliquid,
4584
+ venueLogo: Venue2.hyperliquid,
4585
+ venues: [Venue2.hyperliquid]
4586
+ // isComingSoon: true,
4587
+ },
4588
+ {
4589
+ value: Venue2.myriad,
4590
+ label: labels.venues.myriad,
4591
+ venueLogo: Venue2.myriad,
4592
+ venues: [Venue2.myriad]
4593
+ // isComingSoon: true,
4594
+ },
4595
+ {
4596
+ value: Venue2.opinion,
4597
+ label: labels.venues.opinion,
4598
+ venueLogo: Venue2.opinion,
4599
+ venues: [Venue2.opinion],
4600
+ isComingSoon: true
4601
+ }
4602
+ ];
4603
+ };
4604
+
4605
+ // src/events/list/event-list-tabs.tsx
4170
4606
  import { jsx as jsx10 } from "react/jsx-runtime";
4171
4607
  var renderTabIcon = (tab, isActive) => {
4172
4608
  if (tab.venueLogo) {
@@ -4356,7 +4792,7 @@ var EventList = ({
4356
4792
  isFetchingNextPage,
4357
4793
  isPlaceholderData,
4358
4794
  loadedPageCount
4359
- } = useVenueEvents(__spreadProps(__spreadValues({
4795
+ } = useVenueEvents({
4360
4796
  queryKeyScope: "event-list",
4361
4797
  venues,
4362
4798
  search,
@@ -4366,13 +4802,9 @@ var EventList = ({
4366
4802
  status: [MarketStatus2.open],
4367
4803
  sortBy: "volume24hr",
4368
4804
  sortDir: "desc",
4369
- endDateFrom
4370
- }, !search ? {
4371
- minYesPrice: 0.03,
4372
- maxYesPrice: 0.97
4373
- } : {}), {
4805
+ endDateFrom,
4374
4806
  initialPages: initialLoadedPageCount
4375
- }));
4807
+ });
4376
4808
  useEffect6(() => {
4377
4809
  if (stateRef) {
4378
4810
  stateRef.current = { venueTab: activeTabValue, loadedPageCount };
@@ -4460,7 +4892,8 @@ var EventList = ({
4460
4892
  onEventClick,
4461
4893
  onMarketClick,
4462
4894
  getMarketHref,
4463
- href: getEventHref == null ? void 0 : getEventHref(event)
4895
+ href: getEventHref == null ? void 0 : getEventHref(event),
4896
+ marketStatus: MarketStatus2.open
4464
4897
  },
4465
4898
  event.id
4466
4899
  )),
@@ -4482,14 +4915,14 @@ var EventList = ({
4482
4915
  icon: /* @__PURE__ */ jsx11(Icon, { name: "search-empty" })
4483
4916
  }
4484
4917
  ) }) : null,
4485
- isError ? /* @__PURE__ */ jsx11(
4918
+ isError ? /* @__PURE__ */ jsx11("div", { className: "col-span-full w-full", children: /* @__PURE__ */ jsx11(
4486
4919
  StateMessage,
4487
4920
  {
4488
4921
  title: labels.eventList.errorTitle,
4489
4922
  description: labels.eventList.errorDescription,
4490
4923
  icon: /* @__PURE__ */ jsx11(Icon, { name: "warning" })
4491
4924
  }
4492
- ) : null
4925
+ ) }) : null
4493
4926
  ] }),
4494
4927
  shouldPaginate && hasNextPage ? /* @__PURE__ */ jsx11("div", { ref: loadMoreRef, className: "agg-event-list-sentinel h-px w-full", "aria-hidden": true }) : null
4495
4928
  ] });
@@ -4510,6 +4943,7 @@ export {
4510
4943
  Orderbook,
4511
4944
  MarketDetails,
4512
4945
  MarketDetailsList,
4946
+ DEFAULT_EVENTS_LIMIT,
4513
4947
  useEventListTabs,
4514
4948
  EventListTabs,
4515
4949
  useEventListTabsHeaderOverflow,