@agg-build/ui 1.2.10 → 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-5MTIBPDY.mjs → chunk-3ZSNHGAB.mjs} +784 -390
  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-XKADJNAJ.mjs → chunk-YP75TIY6.mjs} +601 -326
  8. package/dist/events.js +1988 -1549
  9. package/dist/events.mjs +3 -3
  10. package/dist/index.js +5343 -4227
  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 +3619 -2691
  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 +30 -10
  43. package/dist/types/events/market-details/orderbook-aggregation.d.ts +30 -10
  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,21 +904,78 @@ var accumulateSideLevels = ({
882
904
  };
883
905
  var collectEligibleVenueOutcomes = ({
884
906
  venueMarkets,
885
- selectedOutcomeLabel
907
+ selectedOutcomeLabel,
908
+ selectedOutcomeId
886
909
  }) => {
887
- var _a;
910
+ var _a, _b, _c;
888
911
  if (!selectedOutcomeLabel) return [];
889
912
  const semanticLabel = toSemanticOutcomeLabel(selectedOutcomeLabel);
890
913
  const seenMarketIds = /* @__PURE__ */ new Set();
891
914
  const seenOutcomeIds = /* @__PURE__ */ new Set();
892
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
+ }
893
972
  for (const market of venueMarkets) {
894
973
  if (seenMarketIds.has(market.id)) continue;
895
974
  const parentOutcome = sortOutcomes(market.venueMarketOutcomes).find(
896
975
  (outcome) => matchesSelectedOutcomeLabel(outcome, selectedOutcomeLabel)
897
976
  );
898
977
  if (!parentOutcome) continue;
899
- const refs = (_a = parentOutcome.matchedVenueMarketOutcomes) != null ? _a : [];
978
+ const refs = (_b = parentOutcome.matchedVenueMarketOutcomes) != null ? _b : [];
900
979
  if (refs.length === 0) continue;
901
980
  seenMarketIds.add(market.id);
902
981
  seenOutcomeIds.add(parentOutcome.id);
@@ -933,6 +1012,13 @@ var collectEligibleVenueOutcomes = ({
933
1012
  (outcome) => matchesSelectedOutcomeLabel(outcome, selectedOutcomeLabel)
934
1013
  );
935
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;
1021
+ }
936
1022
  seenMarketIds.add(market.id);
937
1023
  seenOutcomeIds.add(matchedOutcome.id);
938
1024
  result.push({
@@ -947,11 +1033,14 @@ var collectEligibleVenueOutcomes = ({
947
1033
  };
948
1034
  var collectEligibleVenueOutcomeIds = ({
949
1035
  venueMarkets,
950
- selectedOutcomeLabel
1036
+ selectedOutcomeLabel,
1037
+ selectedOutcomeId
951
1038
  }) => {
952
- return collectEligibleVenueOutcomes({ venueMarkets, selectedOutcomeLabel }).map(
953
- (eligibleOutcome) => eligibleOutcome.outcomeId
954
- );
1039
+ return collectEligibleVenueOutcomes({
1040
+ venueMarkets,
1041
+ selectedOutcomeLabel,
1042
+ selectedOutcomeId
1043
+ }).map((eligibleOutcome) => eligibleOutcome.outcomeId);
955
1044
  };
956
1045
  var mergeVenueOutcomeOrderbooks = ({
957
1046
  eligibleOutcomes,
@@ -1058,14 +1147,15 @@ SettlementSummary.displayName = "SettlementSummary";
1058
1147
  // src/events/item-details/index.tsx
1059
1148
  import {
1060
1149
  CHART_TIME_RANGES,
1150
+ mergeBestPricesPreferringLive,
1061
1151
  optimizedImageUrl as optimizedImageUrl2,
1062
1152
  resolveEventTradingState,
1063
- timeRangeToInterval,
1064
1153
  useEventOrderbookData,
1065
1154
  useLabels as useLabels5,
1155
+ useLiveBestPrices,
1066
1156
  useLiveOutcomePrices,
1067
1157
  useMarketChart,
1068
- useMidpoints,
1158
+ useRollingChartWindow,
1069
1159
  useSdkUiConfig as useSdkUiConfig2,
1070
1160
  useVenueEvent as useVenueEvent2
1071
1161
  } from "@agg-build/hooks";
@@ -1179,6 +1269,35 @@ var ChartTypeSwitch = ({
1179
1269
  };
1180
1270
  ChartTypeSwitch.displayName = "ChartTypeSwitch";
1181
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
+
1182
1301
  // src/events/shared/chart-venue-selection.ts
1183
1302
  import { sortVenues as sortVenues2 } from "@agg-build/hooks";
1184
1303
  var resolveChartVenueOutcomes = ({
@@ -1835,12 +1954,17 @@ var EventListItemDetailsGraphSection = ({
1835
1954
  classNames,
1836
1955
  selectedChartType,
1837
1956
  venueMarkets,
1957
+ selectedMarketId,
1838
1958
  livePrices,
1839
1959
  wsLivePrices,
1840
1960
  restMidpoints,
1841
- live
1961
+ bestMidpoint,
1962
+ bestPrices,
1963
+ live,
1964
+ rangeOverride,
1965
+ onRangeOverrideChange
1842
1966
  }) => {
1843
- 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;
1844
1968
  const labels = useLabels5();
1845
1969
  const tradingContext = useEventTradingContext();
1846
1970
  const [selectedGraphVenue, setSelectedGraphVenue] = useState3(null);
@@ -1861,24 +1985,33 @@ var EventListItemDetailsGraphSection = ({
1861
1985
  general: { theme }
1862
1986
  } = useSdkUiConfig2();
1863
1987
  const isDarkTheme = theme === "dark";
1864
- const timeWindow = useMemo5(() => {
1865
- return getTimeWindowByRange(selectedChartTimeRange);
1866
- }, [selectedChartTimeRange]);
1988
+ const effectiveChartTimeRange = rangeOverride != null ? rangeOverride : selectedChartTimeRange;
1989
+ const rollingWindow = useRollingChartWindow({ range: effectiveChartTimeRange });
1867
1990
  const availableMarkets = useMemo5(() => {
1991
+ var _a2, _b2, _c2, _d2;
1868
1992
  if (venueMarkets.length === 0) return [];
1869
- return normalizeVenueMarketCluster(venueMarkets, tradingContext == null ? void 0 : tradingContext.selectedMarketId);
1870
- }, [tradingContext == null ? void 0 : tradingContext.selectedMarketId, venueMarkets]);
1871
- 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;
1872
2004
  const availableVenueOutcomes = useMemo5(() => {
1873
2005
  return resolveChartVenueOutcomes({
1874
2006
  eligibleVenueOutcomes: collectEligibleVenueOutcomes({
1875
2007
  venueMarkets: availableMarkets,
1876
- selectedOutcomeLabel: resolvedChartOutcomeLabel
2008
+ selectedOutcomeLabel: resolvedChartOutcomeLabel,
2009
+ selectedOutcomeId: chartScopedOutcomeId
1877
2010
  }),
1878
2011
  livePrices
1879
2012
  });
1880
- }, [availableMarkets, livePrices, resolvedChartOutcomeLabel]);
1881
- 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;
1882
2015
  const {
1883
2016
  data: scopedMarketChartData,
1884
2017
  isLoading: isScopedMarketChartLoading,
@@ -1887,17 +2020,56 @@ var EventListItemDetailsGraphSection = ({
1887
2020
  } = useMarketChart({
1888
2021
  marketId: chartPrimaryOutcomeId,
1889
2022
  venueMarketIds: availableVenueOutcomes.map((item) => item.outcome.id),
1890
- interval: timeRangeToInterval(selectedChartTimeRange),
1891
- startTs: timeWindow.startTs * 1e3,
1892
- endTs: timeWindow.endTs * 1e3,
2023
+ interval: rollingWindow.interval,
2024
+ startTs: rollingWindow.startTs * 1e3,
2025
+ endTs: rollingWindow.endTs * 1e3,
1893
2026
  enabled: availableVenueOutcomes.length > 0,
1894
- 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
1895
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
+ ]);
1896
2062
  const selectedMarketOutcomes = useMemo5(() => {
1897
2063
  var _a2, _b2;
1898
2064
  const selectedMarket = (_b2 = (_a2 = tradingContext == null ? void 0 : tradingContext.selectedMarket) != null ? _a2 : availableMarkets[0]) != null ? _b2 : null;
1899
2065
  if (!selectedMarket) return [];
1900
- 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
+ });
1901
2073
  }, [availableMarkets, tradingContext == null ? void 0 : tradingContext.selectedMarket]);
1902
2074
  const resolvedVenueChartSeries = useMemo5(() => {
1903
2075
  return resolveMarketChartVenueSeries({
@@ -1924,11 +2096,12 @@ var EventListItemDetailsGraphSection = ({
1924
2096
  }, [availableVenueOutcomes, chartAvailableVenueOutcomes, tradingContext == null ? void 0 : tradingContext.selectedVenue]);
1925
2097
  const activeGraphVenue = selectedChartType === "candlestick" ? selectedGraphVenue != null ? selectedGraphVenue : defaultCandlestickVenue : selectedGraphVenue;
1926
2098
  const visibleChartSeries = useMemo5(() => {
1927
- if (!activeGraphVenue) {
1928
- return resolvedVenueChartSeries;
1929
- }
1930
- return resolvedVenueChartSeries.filter((seriesItem) => seriesItem.venue === activeGraphVenue);
1931
- }, [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]);
1932
2105
  const chartLiveState = useMemo5(() => {
1933
2106
  return resolveMarketChartLiveState({
1934
2107
  chartData: scopedMarketChartData,
@@ -1968,7 +2141,7 @@ var EventListItemDetailsGraphSection = ({
1968
2141
  height: 300,
1969
2142
  isLoading: isScopedMarketChartLoading,
1970
2143
  chartType: selectedChartType,
1971
- 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,
1972
2145
  lineValue: chartLiveState.lineValue,
1973
2146
  showSeriesControls: selectedMarketOutcomes.length > 0,
1974
2147
  renderSeriesControls: ({ handleSeriesChange }) => {
@@ -2057,12 +2230,21 @@ var EventListItemDetailsGraphSection = ({
2057
2230
  tradingContext == null ? void 0 : tradingContext.selectOutcome(outcomeId);
2058
2231
  },
2059
2232
  options: selectedMarketOutcomes.map((outcome) => {
2060
- var _a3, _b3;
2061
- 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
+ });
2062
2244
  return {
2063
2245
  value: outcome.id,
2064
- label: `${outcome.label} ${formatProbabilityCents(price)}`,
2065
- 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)}`
2066
2248
  };
2067
2249
  })
2068
2250
  }
@@ -2083,12 +2265,17 @@ var EventListItemDetailsContent = ({
2083
2265
  detailsStats,
2084
2266
  eventTradingState,
2085
2267
  ariaLabel,
2086
- onClick
2268
+ onClick,
2269
+ midpointsResult
2087
2270
  }) => {
2088
- var _a, _b;
2271
+ var _a, _b, _c, _d;
2089
2272
  const [selectedChartType, setSelectedChartType] = useState3("line");
2090
2273
  const lastAppliedEventSyncKeyRef = useRef2(null);
2091
2274
  const lastAppliedDefaultRef = useRef2(null);
2275
+ const [chartRangeOverride, setChartRangeOverride] = useState3(null);
2276
+ useEffect2(() => {
2277
+ setChartRangeOverride(null);
2278
+ }, [event.id]);
2092
2279
  const config = useSdkUiConfig2();
2093
2280
  const labels = useLabels5();
2094
2281
  const tradingContext = useEventTradingContext();
@@ -2103,18 +2290,24 @@ var EventListItemDetailsContent = ({
2103
2290
  scopedSelectedMarketId
2104
2291
  );
2105
2292
  const wsLivePrices = useLiveOutcomePrices(resolvedEventTradingState.displayMarkets);
2106
- const midpointsClusterMarkets = useMemo5(() => {
2107
- if (resolvedEventTradingState.isTradingDisabled) return [];
2108
- return normalizeVenueMarketCluster(
2109
- resolvedEventTradingState.displayMarkets,
2110
- scopedSelectedMarketId
2111
- );
2112
- }, [
2113
- resolvedEventTradingState.displayMarkets,
2114
- resolvedEventTradingState.isTradingDisabled,
2115
- scopedSelectedMarketId
2116
- ]);
2117
- 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
+ );
2118
2311
  const livePrices = useMemo5(() => {
2119
2312
  if (!restMidpoints.size) return wsLivePrices;
2120
2313
  if (!wsLivePrices.size) return restMidpoints;
@@ -2223,7 +2416,7 @@ var EventListItemDetailsContent = ({
2223
2416
  {
2224
2417
  className: classNames == null ? void 0 : classNames.headerPills,
2225
2418
  options: marketOptions,
2226
- selectedValue: (_b = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id) != null ? _b : "",
2419
+ selectedValue: (_c = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id) != null ? _c : "",
2227
2420
  onChange: (marketId) => {
2228
2421
  tradingContext == null ? void 0 : tradingContext.selectMarket(marketId);
2229
2422
  }
@@ -2274,10 +2467,15 @@ var EventListItemDetailsContent = ({
2274
2467
  selectedChartType,
2275
2468
  venueInfo,
2276
2469
  venueMarkets,
2470
+ selectedMarketId: (_d = scopedSelectedMarket == null ? void 0 : scopedSelectedMarket.id) != null ? _d : null,
2277
2471
  livePrices,
2278
2472
  wsLivePrices,
2279
2473
  restMidpoints,
2280
- live: false
2474
+ bestMidpoint,
2475
+ bestPrices,
2476
+ live: false,
2477
+ rangeOverride: chartRangeOverride,
2478
+ onRangeOverrideChange: setChartRangeOverride
2281
2479
  }
2282
2480
  ),
2283
2481
  /* @__PURE__ */ jsxs4(
@@ -2307,7 +2505,8 @@ var EventListItemDetailsContent = ({
2307
2505
  ),
2308
2506
  /* @__PURE__ */ jsx5("span", { "aria-hidden": "true", className: "hidden h-4 w-px bg-agg-separator md:block" }),
2309
2507
  CHART_TIME_RANGES.map((timeRange) => {
2310
- const isActive = timeRange === config.chart.selectedChartTimeRange;
2508
+ const effectiveRange = chartRangeOverride != null ? chartRangeOverride : config.chart.selectedChartTimeRange;
2509
+ const isActive = timeRange === effectiveRange;
2311
2510
  return /* @__PURE__ */ jsx5(
2312
2511
  Button,
2313
2512
  {
@@ -2324,6 +2523,7 @@ var EventListItemDetailsContent = ({
2324
2523
  onClick: (e) => {
2325
2524
  e.stopPropagation();
2326
2525
  e.preventDefault();
2526
+ setChartRangeOverride(null);
2327
2527
  config.chart.setSelectedChartTimeRange(timeRange);
2328
2528
  },
2329
2529
  children: timeRange === "ALL" ? labels.eventItemDetails.allTimeRange : timeRange
@@ -2459,30 +2659,23 @@ var useCenterOrderbookSpread = ({
2459
2659
  rowCount,
2460
2660
  enabled = true
2461
2661
  }) => {
2462
- const hasAutoCenteredRef = useRef3(false);
2463
2662
  const hasUserScrolledRef = useRef3(false);
2464
2663
  const animationFrameRef = useRef3(null);
2465
2664
  const retryCountRef = useRef3(0);
2466
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
+ }, []);
2467
2671
  useLayoutEffect2(() => {
2468
- const cancelPendingFrame = () => {
2469
- if (animationFrameRef.current === null) return;
2470
- window.cancelAnimationFrame(animationFrameRef.current);
2471
- animationFrameRef.current = null;
2472
- };
2473
- hasAutoCenteredRef.current = false;
2474
2672
  hasUserScrolledRef.current = false;
2475
2673
  retryCountRef.current = 0;
2476
2674
  cancelPendingFrame();
2477
- }, [resetKey]);
2675
+ }, [cancelPendingFrame, resetKey]);
2478
2676
  useLayoutEffect2(() => {
2479
2677
  const container = containerRef.current;
2480
2678
  if (!container) return;
2481
- const cancelPendingFrame = () => {
2482
- if (animationFrameRef.current === null) return;
2483
- window.cancelAnimationFrame(animationFrameRef.current);
2484
- animationFrameRef.current = null;
2485
- };
2486
2679
  const handleUserScrollIntent = () => {
2487
2680
  hasUserScrolledRef.current = true;
2488
2681
  cancelPendingFrame();
@@ -2502,93 +2695,81 @@ var useCenterOrderbookSpread = ({
2502
2695
  container.removeEventListener("keydown", handleKeyDown);
2503
2696
  cancelPendingFrame();
2504
2697
  };
2505
- }, [containerRef]);
2698
+ }, [cancelPendingFrame, containerRef]);
2506
2699
  useLayoutEffect2(() => {
2507
2700
  if (!enabled) return;
2508
- if (hasAutoCenteredRef.current || hasUserScrolledRef.current) return;
2509
2701
  let isCancelled = false;
2510
- let resizeObserver = null;
2511
- const cancelPendingFrame = () => {
2512
- if (animationFrameRef.current === null) return;
2513
- window.cancelAnimationFrame(animationFrameRef.current);
2514
- animationFrameRef.current = null;
2515
- };
2516
- const disconnectResizeObserver = () => {
2517
- resizeObserver == null ? void 0 : resizeObserver.disconnect();
2518
- resizeObserver = null;
2519
- };
2520
- const scheduleMeasurement = () => {
2521
- cancelPendingFrame();
2522
- animationFrameRef.current = window.requestAnimationFrame(measureAndCenter);
2523
- };
2524
- const setupResizeObserverFallback = () => {
2525
- if (resizeObserver) return;
2526
- const container = containerRef.current;
2527
- if (!container) return;
2528
- resizeObserver = new ResizeObserver(() => {
2529
- if (isCancelled || hasAutoCenteredRef.current || hasUserScrolledRef.current) {
2530
- disconnectResizeObserver();
2531
- return;
2532
- }
2533
- if (container.clientHeight <= 0) return;
2534
- disconnectResizeObserver();
2535
- retryCountRef.current = 0;
2536
- scheduleMeasurement();
2537
- });
2538
- resizeObserver.observe(container);
2539
- };
2540
- const scheduleRetry = () => {
2541
- if (isCancelled || hasUserScrolledRef.current || hasAutoCenteredRef.current) return;
2542
- if (retryCountRef.current >= maxAutoCenterAttempts) {
2543
- setupResizeObserverFallback();
2544
- return;
2545
- }
2546
- retryCountRef.current += 1;
2547
- scheduleMeasurement();
2548
- };
2549
2702
  const measureAndCenter = () => {
2550
- if (isCancelled) return;
2551
- const container = containerRef.current;
2703
+ animationFrameRef.current = null;
2704
+ if (isCancelled || hasUserScrolledRef.current) return;
2705
+ const container2 = containerRef.current;
2552
2706
  const spread = spreadRef.current;
2553
- if (!container || !spread) {
2707
+ if (!container2 || !spread) {
2554
2708
  scheduleRetry();
2555
2709
  return;
2556
2710
  }
2557
- const containerHeight = container.clientHeight;
2711
+ const containerHeight = container2.clientHeight;
2558
2712
  if (containerHeight <= 0) {
2559
2713
  scheduleRetry();
2560
2714
  return;
2561
2715
  }
2562
- const containerRect = container.getBoundingClientRect();
2716
+ const containerRect = container2.getBoundingClientRect();
2563
2717
  const spreadRect = spread.getBoundingClientRect();
2564
2718
  if (containerRect.height <= 0 || spreadRect.height <= 0) {
2565
2719
  scheduleRetry();
2566
2720
  return;
2567
2721
  }
2568
- const spreadOffsetTop = container.scrollTop + (spreadRect.top - containerRect.top);
2569
- 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);
2570
2724
  if (maxScrollTop === 0) {
2571
2725
  retryCountRef.current = 0;
2572
- animationFrameRef.current = null;
2573
2726
  return;
2574
2727
  }
2575
2728
  const targetScrollTop = Math.max(
2576
2729
  0,
2577
2730
  Math.min(maxScrollTop, spreadOffsetTop - containerHeight / 2 + spreadRect.height / 2)
2578
2731
  );
2579
- container.scrollTo({ top: targetScrollTop, behavior: "auto" });
2580
- hasAutoCenteredRef.current = true;
2732
+ container2.scrollTop = targetScrollTop;
2581
2733
  retryCountRef.current = 0;
2582
- animationFrameRef.current = null;
2583
- disconnectResizeObserver();
2584
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;
2585
2765
  scheduleMeasurement();
2586
2766
  return () => {
2587
2767
  isCancelled = true;
2588
2768
  cancelPendingFrame();
2589
- disconnectResizeObserver();
2769
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
2770
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
2590
2771
  };
2591
- }, [containerRef, enabled, resetKey, rowCount, spreadRef]);
2772
+ }, [cancelPendingFrame, containerRef, enabled, resetKey, rowCount, spreadRef]);
2592
2773
  const recenter = useCallback2(() => {
2593
2774
  const container = containerRef.current;
2594
2775
  const spread = spreadRef.current;
@@ -2924,15 +3105,16 @@ import {
2924
3105
  CHART_TIME_RANGES as CHART_TIME_RANGES2,
2925
3106
  findLivePriceById,
2926
3107
  MarketStatus,
3108
+ mergeBestPricesPreferringLive as mergeBestPricesPreferringLive2,
2927
3109
  optimizedImageUrl as optimizedImageUrl3,
2928
3110
  resolveMarketTradingState,
2929
- timeRangeToInterval as timeRangeToInterval2,
2930
- useEventTradingContext as useEventTradingContext2,
3111
+ useEventTradingContext as useEventTradingContext3,
2931
3112
  useLabels as useLabels6,
3113
+ useLiveBestPrices as useLiveBestPrices2,
2932
3114
  useLiveOutcomePrices as useLiveOutcomePrices2,
2933
3115
  useMarketChart as useMarketChart2,
2934
3116
  useMarketOrderbook,
2935
- useMidpoints as useMidpoints2,
3117
+ useRollingChartWindow as useRollingChartWindow2,
2936
3118
  useSdkUiConfig as useSdkUiConfig3,
2937
3119
  useVenueMarkets as useVenueMarkets2,
2938
3120
  useViewportMidpoints
@@ -2945,17 +3127,17 @@ var marketDetailsOutcomeButtonToneClasses = {
2945
3127
  positive: {
2946
3128
  activeSurface: "bg-agg-success/15",
2947
3129
  border: "border-agg-success/50",
2948
- defaultSurface: "bg-agg-success/5",
2949
- hoverSurface: "hover:bg-agg-success/10",
2950
- 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",
2951
3133
  text: "text-agg-success!"
2952
3134
  },
2953
3135
  negative: {
2954
3136
  activeSurface: "bg-agg-error/15",
2955
3137
  border: "border-agg-error/50",
2956
- defaultSurface: "bg-agg-error/5",
2957
- hoverSurface: "hover:bg-agg-error/10",
2958
- 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",
2959
3141
  text: "text-agg-error!"
2960
3142
  }
2961
3143
  };
@@ -2988,6 +3170,7 @@ var MarketDetailsOutcomeButton = ({
2988
3170
  item,
2989
3171
  onSelect
2990
3172
  }) => {
3173
+ var _a;
2991
3174
  const classNames = getMarketDetailsOutcomeButtonClassNames({
2992
3175
  enableAnimations,
2993
3176
  isSelected,
@@ -3014,7 +3197,7 @@ var MarketDetailsOutcomeButton = ({
3014
3197
  as: "span",
3015
3198
  variant: isSelected ? "body-strong" : "body",
3016
3199
  className: cn("whitespace-nowrap truncate", classNames.text),
3017
- children: item.title
3200
+ children: (_a = item.title) != null ? _a : item.label
3018
3201
  }
3019
3202
  ),
3020
3203
  /* @__PURE__ */ jsx8(
@@ -3035,21 +3218,6 @@ MarketDetailsOutcomeButton.displayName = "MarketDetailsOutcomeButton";
3035
3218
 
3036
3219
  // src/events/market-details/index.tsx
3037
3220
  import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
3038
- var MarketDetailsLoadingState = ({
3039
- isOpened = marketDetailsDefaultIsOpened,
3040
- ariaLabel,
3041
- classNames
3042
- }) => {
3043
- const labels = useLabels6();
3044
- return /* @__PURE__ */ jsx9(
3045
- Skeleton,
3046
- {
3047
- view: isOpened ? "market-details-detailed" : "market-details-minified",
3048
- className: classNames == null ? void 0 : classNames.root,
3049
- ariaLabel: ariaLabel != null ? ariaLabel : labels.marketDetails.loading
3050
- }
3051
- );
3052
- };
3053
3221
  var MarketDetailsUnavailableState = ({
3054
3222
  ariaLabel,
3055
3223
  classNames
@@ -3103,9 +3271,11 @@ var MarketDetailsContent = ({
3103
3271
  onOutcomeSelect,
3104
3272
  live,
3105
3273
  midpointsFallback,
3106
- midpointsFallbackVenues
3274
+ midpointsFallbackVenues,
3275
+ suppressOutcomeFallbackSelection,
3276
+ midpointsResult
3107
3277
  }) => {
3108
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
3278
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3109
3279
  const config = useSdkUiConfig3();
3110
3280
  const {
3111
3281
  features: { enableAnimations },
@@ -3114,9 +3284,61 @@ var MarketDetailsContent = ({
3114
3284
  } = config;
3115
3285
  const isDarkTheme = theme === "dark";
3116
3286
  const labels = useLabels6();
3117
- const tradingContext = useEventTradingContext2();
3287
+ const tradingContext = useEventTradingContext3();
3118
3288
  const detailsContentId = useId();
3289
+ const tradeSide = (_a = tradingContext == null ? void 0 : tradingContext.tradeSide) != null ? _a : "buy";
3119
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]);
3120
3342
  const model = useMemo6(() => {
3121
3343
  return buildMarketDetailsModel({
3122
3344
  venueMarkets,
@@ -3124,17 +3346,18 @@ var MarketDetailsContent = ({
3124
3346
  title,
3125
3347
  image,
3126
3348
  formatCompactCurrency: config.formatting.formatCompactCurrency,
3127
- labels
3349
+ labels,
3350
+ tradableVenues
3128
3351
  });
3129
- }, [config.formatting.formatCompactCurrency, venueMarkets, image, labels, marketId, title]);
3130
- const resolvedMarket = useMemo6(() => {
3131
- return resolveMarketFromVenueMarkets(venueMarkets, marketId);
3132
- }, [venueMarkets, marketId]);
3133
- const clusterMidpointMarkets = useMemo6(() => {
3134
- if (!controlledIsOpened || !resolvedMarket) return [];
3135
- return resolvedMarket.venueMarkets;
3136
- }, [controlledIsOpened, resolvedMarket]);
3137
- 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
+ ]);
3138
3361
  const livePrices = useMemo6(() => {
3139
3362
  const merged = /* @__PURE__ */ new Map();
3140
3363
  if (midpointsFallback == null ? void 0 : midpointsFallback.size) {
@@ -3158,7 +3381,6 @@ var MarketDetailsContent = ({
3158
3381
  const marketTradingState = useMemo6(() => {
3159
3382
  return resolveMarketTradingState(scopedMarketForCard);
3160
3383
  }, [scopedMarketForCard]);
3161
- const isResolvedMarket = marketTradingState.kind === "resolved";
3162
3384
  const isOutcomeSelectionLocked = marketTradingState.isTradingDisabled;
3163
3385
  const isUpcomingMarket = marketTradingState.kind === "unopened";
3164
3386
  const marketStatePresentation = resolveTradingStatePresentation(labels, marketTradingState);
@@ -3178,11 +3400,30 @@ var MarketDetailsContent = ({
3178
3400
  const selectedTimeRange = config.chart.selectedChartTimeRange;
3179
3401
  const setSelectedTimeRange = config.chart.setSelectedChartTimeRange;
3180
3402
  const effectiveSelectedTab = isResolvedMarket ? "graph" : selectedTab;
3181
- const effectiveChartTimeRange = isResolvedMarket ? "ALL" : selectedTimeRange;
3403
+ const [chartRangeOverride, setChartRangeOverride] = useState4(null);
3404
+ const effectiveChartTimeRange = isResolvedMarket ? "ALL" : chartRangeOverride != null ? chartRangeOverride : selectedTimeRange;
3182
3405
  const [selectedChartType, setSelectedChartType] = useState4("line");
3183
- const scopedSelectedOutcome = (_a = tradingContext == null ? void 0 : tradingContext.selectedOutcome) != null ? _a : null;
3184
- const selectedOutcomeId = (_b = scopedSelectedOutcome == null ? void 0 : scopedSelectedOutcome.id) != null ? _b : null;
3185
- 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;
3186
3427
  const selectOutcome = tradingContext == null ? void 0 : tradingContext.selectOutcome;
3187
3428
  const [selectedGraphVenue, setSelectedGraphVenue] = useState4(null);
3188
3429
  const [chartOutcomeLabel, setChartOutcomeLabel] = useState4(selectedOutcomeLabel);
@@ -3196,6 +3437,9 @@ var MarketDetailsContent = ({
3196
3437
  var _a2;
3197
3438
  if (!isOpened || !model) return;
3198
3439
  if (isOutcomeSelectionLocked) return;
3440
+ if ((tradingContext == null ? void 0 : tradingContext.selectedMarketId) && tradingContext.selectedMarketId !== model.market.id) {
3441
+ return;
3442
+ }
3199
3443
  if (selectedOutcomeId) return;
3200
3444
  const initialLabel = resolveInitialOutcomeLabel(model.outcomeLabels, defaultOutcomeLabel);
3201
3445
  if (!initialLabel) return;
@@ -3210,71 +3454,130 @@ var MarketDetailsContent = ({
3210
3454
  isOutcomeSelectionLocked,
3211
3455
  model,
3212
3456
  selectedOutcomeId,
3457
+ tradingContext == null ? void 0 : tradingContext.selectedMarketId,
3213
3458
  selectOutcome
3214
3459
  ]);
3215
3460
  const headerOutcomeItems = useMemo6(() => {
3216
3461
  if (!model) return [];
3217
- const items = resolveHeaderOutcomeItems(model.market.venueMarkets);
3462
+ const items = resolveHeaderOutcomeItems(model.market.venueMarkets, scopedMarketForCard);
3218
3463
  return items.map((item) => {
3219
- const clusterPrice = clusterMidpoints.get(item.id);
3220
- if (clusterPrice != null) {
3221
- const bestVenue = clusterVenueByOutcomeId.get(item.id);
3222
- return __spreadValues(__spreadProps(__spreadValues({}, item), { probability: clusterPrice }), bestVenue ? { venue: bestVenue } : {});
3223
- }
3464
+ var _a2;
3224
3465
  const fallbackPrice = midpointsFallback == null ? void 0 : midpointsFallback.get(item.id);
3225
- if (fallbackPrice != null) {
3226
- const bestVenue = midpointsFallbackVenues == null ? void 0 : midpointsFallbackVenues.get(item.id);
3227
- 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 } : {});
3228
3490
  }
3229
- const wsPrice = findLivePriceById(wsLivePrices, item.id);
3230
- 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;
3231
3497
  });
3232
3498
  }, [
3499
+ clusterBestMidpoint,
3500
+ clusterBestMidpointVenue,
3501
+ clusterBestMidpointsByOutcomeId,
3502
+ clusterBestPrices,
3503
+ clusterBestPriceVenuesByOutcomeId,
3233
3504
  model,
3234
- clusterMidpoints,
3505
+ scopedMarketForCard,
3235
3506
  clusterVenueByOutcomeId,
3507
+ isResolvedMarket,
3508
+ (_d = marketTradingState.winningOutcome) == null ? void 0 : _d.id,
3236
3509
  midpointsFallback,
3237
3510
  midpointsFallbackVenues,
3511
+ tradeSide,
3238
3512
  wsLivePrices
3239
3513
  ]);
3240
3514
  const headlineProbability = useMemo6(() => {
3241
3515
  var _a2, _b2, _c2, _d2;
3242
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
+ }
3243
3522
  const yesOutcome = resolveYesOutcome(scopedMarketForCard);
3244
3523
  const displayOutcome = yesOutcome != null ? yesOutcome : (_b2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _b2.reduce(
3245
3524
  (acc, outcome) => outcome.price > acc.price ? outcome : acc,
3246
3525
  (_a2 = scopedMarketForCard.venueMarketOutcomes) == null ? void 0 : _a2[0]
3247
3526
  );
3248
- const restPrice = (_c2 = clusterMidpoints.get(displayOutcome.id)) != null ? _c2 : midpointsFallback == null ? void 0 : midpointsFallback.get(displayOutcome.id);
3249
- 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;
3250
3539
  return (_d2 = findLivePriceById(wsLivePrices, displayOutcome.id)) != null ? _d2 : displayOutcome.price;
3251
- }, [model, scopedMarketForCard, clusterMidpoints, midpointsFallback, wsLivePrices]);
3540
+ }, [
3541
+ clusterBestMidpoint,
3542
+ clusterBestMidpointsByOutcomeId,
3543
+ clusterBestPrices,
3544
+ model,
3545
+ scopedMarketForCard,
3546
+ isResolvedMarket,
3547
+ midpointsFallback,
3548
+ wsLivePrices
3549
+ ]);
3252
3550
  const selectedOutcomesByVenue = useMemo6(() => {
3253
3551
  if (!model) return [];
3254
3552
  return collectEligibleVenueOutcomes({
3255
3553
  venueMarkets: model.market.venueMarkets,
3256
- 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
3257
3560
  });
3258
- }, [model, selectedOutcomeLabel]);
3561
+ }, [model, selectedOutcomeLabel, selectedOutcomeId]);
3259
3562
  const resolvedChartOutcomeLabel = chartOutcomeLabel != null ? chartOutcomeLabel : selectedOutcomeLabel;
3563
+ const chartSelectedOutcomeId = selectedOutcomeId && resolvedChartOutcomeLabel === selectedOutcomeLabel ? selectedOutcomeId : null;
3260
3564
  const chartOutcomesByVenue = useMemo6(() => {
3261
3565
  if (!model) return [];
3262
3566
  return resolveChartVenueOutcomes({
3263
3567
  eligibleVenueOutcomes: collectEligibleVenueOutcomes({
3264
3568
  venueMarkets: model.market.venueMarkets,
3265
- selectedOutcomeLabel: resolvedChartOutcomeLabel
3569
+ selectedOutcomeLabel: resolvedChartOutcomeLabel,
3570
+ selectedOutcomeId: chartSelectedOutcomeId
3266
3571
  }),
3267
3572
  livePrices
3268
3573
  });
3269
- }, [livePrices, model, resolvedChartOutcomeLabel]);
3574
+ }, [livePrices, model, resolvedChartOutcomeLabel, chartSelectedOutcomeId]);
3270
3575
  const chartEnabled = isOpened && effectiveSelectedTab === "graph";
3271
3576
  const orderBookEnabled = isOpened && effectiveSelectedTab === "order-book" && !marketTradingState.isTradingDisabled;
3272
- const timeWindow = useMemo6(() => {
3273
- return getTimeWindowByRange(effectiveChartTimeRange);
3274
- }, [effectiveChartTimeRange]);
3275
- const primaryVenueMarketId = (_e = (_d = selectedOutcomesByVenue[0]) == null ? void 0 : _d.market.id) != null ? _e : null;
3276
- const primaryOutcomeId = (_g = (_f = selectedOutcomesByVenue[0]) == null ? void 0 : _f.outcome.id) != null ? _g : null;
3277
- 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;
3278
3581
  const chartVenueOutcomeIds = useMemo6(() => {
3279
3582
  return chartOutcomesByVenue.map((item) => item.outcome.id);
3280
3583
  }, [chartOutcomesByVenue]);
@@ -3286,12 +3589,43 @@ var MarketDetailsContent = ({
3286
3589
  } = useMarketChart2({
3287
3590
  marketId: chartPrimaryOutcomeId,
3288
3591
  venueMarketIds: chartVenueOutcomeIds,
3289
- interval: timeRangeToInterval2(effectiveChartTimeRange),
3290
- startTs: timeWindow.startTs * 1e3,
3291
- endTs: timeWindow.endTs * 1e3,
3592
+ interval: rollingWindow.interval,
3593
+ startTs: rollingWindow.startTs * 1e3,
3594
+ endTs: rollingWindow.endTs * 1e3,
3292
3595
  enabled: chartEnabled && !!chartPrimaryOutcomeId,
3293
- 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
3294
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
+ ]);
3295
3629
  const marketOrderbookResult = useMarketOrderbook({
3296
3630
  marketId: primaryVenueMarketId,
3297
3631
  enabled: orderBookEnabled && !!primaryVenueMarketId,
@@ -3345,6 +3679,7 @@ var MarketDetailsContent = ({
3345
3679
  0,
3346
3680
  isDarkTheme
3347
3681
  );
3682
+ const domainStartTs = rollingWindow.startTs;
3348
3683
  return resolveMarketChartDisplaySeries({
3349
3684
  chartData: marketChartData,
3350
3685
  selectedVenue: selectedGraphVenue,
@@ -3354,13 +3689,16 @@ var MarketDetailsContent = ({
3354
3689
  id: `${resolvedChartOutcomeLabel != null ? resolvedChartOutcomeLabel : "graph"}-${seriesItem.venue}-${chartPrimaryOutcomeId != null ? chartPrimaryOutcomeId : "chart"}`,
3355
3690
  venue: selectedGraphVenue != null ? selectedGraphVenue : seriesItem.venue,
3356
3691
  color: seriesItem.venue === "aggregate" ? baseColor : resolveSeriesColor(seriesItem.venue, 0, isDarkTheme),
3357
- 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)
3358
3695
  };
3359
3696
  });
3360
3697
  }, [
3361
3698
  isDarkTheme,
3362
3699
  chartPrimaryOutcomeId,
3363
3700
  marketChartData,
3701
+ rollingWindow.startTs,
3364
3702
  selectedGraphVenue,
3365
3703
  resolvedChartOutcomeLabel,
3366
3704
  chartAvailableOutcomesByVenue,
@@ -3388,11 +3726,19 @@ var MarketDetailsContent = ({
3388
3726
  item,
3389
3727
  shouldNotifyOutcomeSelect = false
3390
3728
  }) => {
3729
+ var _a2, _b2;
3391
3730
  if (isOutcomeSelectionLocked) return;
3392
3731
  if (item == null ? void 0 : item.id) {
3393
- 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
+ }
3394
3740
  if (shouldNotifyOutcomeSelect && model) {
3395
- 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 });
3396
3742
  }
3397
3743
  }
3398
3744
  };
@@ -3487,26 +3833,24 @@ var MarketDetailsContent = ({
3487
3833
  {
3488
3834
  className: cn(
3489
3835
  "agg-market-card-header",
3490
- "cursor-pointer",
3491
3836
  "flex flex-col items-stretch gap-3 px-5 py-3 md:flex-row md:flex-nowrap md:items-center md:justify-between",
3492
3837
  isOpened && "pb-3",
3493
3838
  classNames == null ? void 0 : classNames.header
3494
3839
  ),
3495
- onClick: handleToggleExpanded,
3496
3840
  children: [
3497
3841
  /* @__PURE__ */ jsxs7(
3498
3842
  "button",
3499
3843
  {
3500
- type: "button",
3501
3844
  className: cn(
3502
3845
  "agg-market-card-summary",
3503
3846
  "flex min-w-0 w-full items-center justify-between gap-4 text-left md:flex-1",
3504
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"
3505
3848
  ),
3849
+ type: "button",
3850
+ onClick: handleToggleExpanded,
3506
3851
  "aria-expanded": isOpened,
3507
3852
  "aria-controls": detailsContentId,
3508
3853
  "aria-label": isOpened ? labels.marketDetails.toggleCloseDetailsAria(model.title) : labels.marketDetails.toggleOpenDetailsAria(model.title),
3509
- onClick: handleToggleExpanded,
3510
3854
  children: [
3511
3855
  /* @__PURE__ */ jsxs7("div", { className: "agg-market-summary flex min-w-24 flex-1 items-center gap-3 md:gap-4", children: [
3512
3856
  /* @__PURE__ */ jsx9(
@@ -3535,7 +3879,7 @@ var MarketDetailsContent = ({
3535
3879
  children: model.subtitle
3536
3880
  }
3537
3881
  ) }),
3538
- 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: [
3539
3883
  /* @__PURE__ */ jsxs7(
3540
3884
  "span",
3541
3885
  {
@@ -3565,75 +3909,60 @@ var MarketDetailsContent = ({
3565
3909
  ]
3566
3910
  }
3567
3911
  ),
3568
- marketTradingState.kind === "resolved" && marketTradingState.winningOutcome ? /* @__PURE__ */ jsx9(
3569
- "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",
3570
3914
  {
3571
- className: "agg-outcomes flex w-full items-center justify-end md:w-auto md:shrink-0",
3572
- onClick: (e) => e.stopPropagation(),
3573
- children: /* @__PURE__ */ jsxs7(
3574
- "span",
3575
- {
3576
- className: cn(
3577
- "w-full md:w-auto md:min-w-35 inline-flex h-9 items-center justify-center gap-2 rounded-agg-full",
3578
- "border px-5 py-1.5 text-agg-sm font-agg-bold",
3579
- getMotionClassName(
3580
- enableAnimations,
3581
- "transition-[background-color,border-color,color] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)]"
3582
- ),
3583
- "border-transparent bg-agg-secondary-hover"
3584
- ),
3585
- children: [
3586
- /* @__PURE__ */ jsx9(
3587
- Icon,
3588
- {
3589
- name: marketTradingState.winningOutcome.label.trim().toLowerCase() === "yes" ? "check-circle" : "cross-circle",
3590
- size: "small",
3591
- className: cn(
3592
- "h-4 w-4",
3593
- marketTradingState.winningOutcome.label.trim().toLowerCase() === "yes" ? "text-agg-success" : "text-agg-error"
3594
- )
3595
- }
3596
- ),
3597
- /* @__PURE__ */ jsx9(Typography, { variant: "body", children: labels.eventMarketPage.resolvedOutcome(marketTradingState.winningOutcome.label) })
3598
- ]
3599
- }
3600
- )
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
+ ]
3601
3938
  }
3602
- ) : isUpcomingMarket ? /* @__PURE__ */ jsx9(
3603
- "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",
3604
3941
  {
3605
- className: "agg-outcomes flex w-full items-center justify-end md:w-auto md:shrink-0",
3606
- onClick: (e) => e.stopPropagation(),
3607
- children: /* @__PURE__ */ jsxs7(
3608
- "span",
3609
- {
3610
- className: cn(
3611
- "min-w-35 inline-flex h-9 items-center justify-center gap-2 rounded-agg-full",
3612
- "border px-5 py-1.5 text-agg-xs font-agg-bold uppercase tracking-[0.08em]",
3613
- resolveTradingStateBadgeClassName(marketTradingState.kind)
3614
- ),
3615
- children: [
3616
- /* @__PURE__ */ jsx9(
3617
- Icon,
3618
- {
3619
- name: marketStatePresentation.iconName,
3620
- size: "small",
3621
- className: "h-3.5 w-3.5",
3622
- "aria-hidden": "true"
3623
- }
3624
- ),
3625
- /* @__PURE__ */ jsx9("span", { children: marketStatePresentation.badgeLabel })
3626
- ]
3627
- }
3628
- )
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
+ ]
3629
3959
  }
3630
- ) : /* @__PURE__ */ jsx9(
3960
+ ) }) : /* @__PURE__ */ jsx9(
3631
3961
  "div",
3632
3962
  {
3633
3963
  className: "agg-outcomes flex w-full flex-wrap gap-2 md:w-auto md:shrink-0 md:flex-nowrap",
3634
3964
  role: "tablist",
3635
3965
  "aria-label": labels.marketDetails.marketOutcomesAria,
3636
- onClick: (e) => e.stopPropagation(),
3637
3966
  onKeyDown: (eventToHandle) => handleOutcomeKeyDown(eventToHandle),
3638
3967
  children: headerOutcomeItems.map((item) => {
3639
3968
  const isActiveOutcome = item.id === selectedOutcomeId;
@@ -3751,7 +4080,7 @@ var MarketDetailsContent = ({
3751
4080
  height: 260,
3752
4081
  isLoading: isMarketChartLoading,
3753
4082
  chartType: selectedChartType,
3754
- 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,
3755
4084
  lineValue: graphLiveState.lineValue,
3756
4085
  classNames: { root: "agg-chart-region w-full" },
3757
4086
  showSeriesControls: chartAvailableOutcomesByVenue.length > 0 || headerOutcomeItems.length > 0,
@@ -3807,12 +4136,12 @@ var MarketDetailsContent = ({
3807
4136
  setChartOutcomeLabel(outcome.label);
3808
4137
  },
3809
4138
  options: headerOutcomeItems.map((outcome) => {
4139
+ var _a3, _b3;
3810
4140
  const price = outcome.probability;
3811
- const outcomeLabel = `${outcome.label} ${formatProbabilityCents(price)}`;
3812
4141
  return {
3813
4142
  value: outcome.id,
3814
- label: outcomeLabel,
3815
- 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)}`
3816
4145
  };
3817
4146
  })
3818
4147
  }
@@ -3867,6 +4196,7 @@ var MarketDetailsContent = ({
3867
4196
  e.preventDefault();
3868
4197
  e.stopPropagation();
3869
4198
  if (isDisabled) return;
4199
+ setChartRangeOverride(null);
3870
4200
  setSelectedTimeRange(timeRange);
3871
4201
  },
3872
4202
  children: timeRange === "ALL" ? labels.eventItemDetails.allTimeRange : timeRange
@@ -3903,8 +4233,16 @@ var MarketDetailsContent = ({
3903
4233
  };
3904
4234
  var MarketDetails = (_a) => {
3905
4235
  var _b = _a, { isOpened } = _b, props = __objRest(_b, ["isOpened"]);
4236
+ const labels = useLabels6();
3906
4237
  if (props.isLoading) {
3907
- 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
+ );
3908
4246
  }
3909
4247
  if ("venueMarkets" in props && props.venueMarkets) {
3910
4248
  return /* @__PURE__ */ jsx9(
@@ -3969,16 +4307,17 @@ var MarketDetailsList = ({
3969
4307
  onClick,
3970
4308
  onOutcomeSelect,
3971
4309
  onExpandedMarketChange,
4310
+ autoSelectFallbackMarket = true,
3972
4311
  defaultTab,
3973
4312
  classNames,
3974
- live
4313
+ live,
4314
+ midpointsResult
3975
4315
  }) => {
3976
4316
  var _a, _b;
3977
4317
  const labels = useLabels6();
3978
- const tradingContext = useEventTradingContext2();
4318
+ const tradingContext = useEventTradingContext3();
3979
4319
  const selectedMarketId = (_a = tradingContext == null ? void 0 : tradingContext.selectedMarketId) != null ? _a : null;
3980
- const [expandedMarketId, setExpandedMarketId] = useState4(selectedMarketId);
3981
- const previousSelectedMarketIdRef = useRef5(selectedMarketId);
4320
+ const [expandedMarketId, setExpandedMarketId] = useState4(null);
3982
4321
  const [areResolvedMarketsVisible, setAreResolvedMarketsVisible] = useState4(false);
3983
4322
  const resolvedEventId = eventId || "";
3984
4323
  const {
@@ -4052,7 +4391,12 @@ var MarketDetailsList = ({
4052
4391
  return [...groupedMarkets.primary, ...visibleResolvedMarkets];
4053
4392
  }, [groupedMarkets.primary, visibleResolvedMarkets]);
4054
4393
  const hasPrefetchedMarkets = !!providedMarkets || !!((_b = eventTradingState == null ? void 0 : eventTradingState.marketStates) == null ? void 0 : _b.length);
4055
- 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);
4056
4400
  useEffect4(() => {
4057
4401
  if (isResolvedEvent) {
4058
4402
  setAreResolvedMarketsVisible(false);
@@ -4062,13 +4406,6 @@ var MarketDetailsList = ({
4062
4406
  setAreResolvedMarketsVisible(false);
4063
4407
  }
4064
4408
  }, [groupedMarkets.resolved.length, isResolvedEvent]);
4065
- useEffect4(() => {
4066
- if (previousSelectedMarketIdRef.current === selectedMarketId) return;
4067
- previousSelectedMarketIdRef.current = selectedMarketId;
4068
- if (!selectedMarketId) return;
4069
- if (!displayedMarkets.some((market) => market.id === selectedMarketId)) return;
4070
- setExpandedMarketId(selectedMarketId);
4071
- }, [displayedMarkets, selectedMarketId]);
4072
4409
  useEffect4(() => {
4073
4410
  if (displayedMarkets.length === 0) return;
4074
4411
  if (selectedMarketId && displayedMarkets.some((market) => market.id === selectedMarketId)) {
@@ -4083,21 +4420,14 @@ var MarketDetailsList = ({
4083
4420
  if (!fallbackSelectableMarket) {
4084
4421
  return;
4085
4422
  }
4086
- if (!expandedMarketId) {
4087
- setExpandedMarketId(fallbackSelectableMarket.id);
4088
- }
4423
+ if (!autoSelectFallbackMarket) return;
4089
4424
  tradingContext == null ? void 0 : tradingContext.selectMarket(fallbackSelectableMarket.id, fallbackSelectableMarket);
4090
- }, [displayedMarkets, expandedMarketId, selectedMarketId, sourceMarkets, tradingContext]);
4425
+ }, [autoSelectFallbackMarket, displayedMarkets, selectedMarketId, sourceMarkets, tradingContext]);
4091
4426
  useEffect4(() => {
4092
- var _a2, _b2;
4093
4427
  if (!expandedMarketId) return;
4094
4428
  if (displayedMarkets.some((market) => market.id === expandedMarketId)) return;
4095
- if (selectedMarketId && displayedMarkets.some((market) => market.id === selectedMarketId)) {
4096
- setExpandedMarketId(selectedMarketId);
4097
- return;
4098
- }
4099
- setExpandedMarketId((_b2 = (_a2 = displayedMarkets[0]) == null ? void 0 : _a2.id) != null ? _b2 : null);
4100
- }, [displayedMarkets, expandedMarketId, selectedMarketId]);
4429
+ setExpandedMarketId(null);
4430
+ }, [displayedMarkets, expandedMarketId]);
4101
4431
  const handleToggle = (marketId, market) => {
4102
4432
  if (marketId === expandedMarketId) {
4103
4433
  setExpandedMarketId(null);
@@ -4111,22 +4441,14 @@ var MarketDetailsList = ({
4111
4441
  tradingContext == null ? void 0 : tradingContext.selectMarket(market.id, market);
4112
4442
  };
4113
4443
  if (!hasPrefetchedMarkets && isLoading) {
4114
- return /* @__PURE__ */ jsxs7("div", { className: cn("agg-market-list flex flex-col gap-3", classNames == null ? void 0 : classNames.root), children: [
4115
- /* @__PURE__ */ jsx9(
4116
- MarketDetailsLoadingState,
4117
- {
4118
- isOpened: true,
4119
- classNames: { root: cn("agg-market-list-item", classNames == null ? void 0 : classNames.item) }
4120
- }
4121
- ),
4122
- /* @__PURE__ */ jsx9(
4123
- MarketDetailsLoadingState,
4124
- {
4125
- isOpened: false,
4126
- classNames: { root: cn("agg-market-list-item", classNames == null ? void 0 : classNames.item) }
4127
- }
4128
- )
4129
- ] });
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
+ );
4130
4452
  }
4131
4453
  if (!hasPrefetchedMarkets && error) {
4132
4454
  return /* @__PURE__ */ jsx9(
@@ -4157,17 +4479,25 @@ var MarketDetailsList = ({
4157
4479
  marketId: market.id,
4158
4480
  venueMarkets: sourceMarkets,
4159
4481
  isOpened: expandedMarketId === market.id,
4482
+ suppressOutcomeFallbackSelection: market.id !== selectedMarketId,
4160
4483
  onOpenChange: (marketId) => {
4161
4484
  onClick == null ? void 0 : onClick(market);
4162
4485
  handleToggle(marketId, market);
4163
4486
  },
4164
- 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
+ },
4165
4494
  defaultTab,
4166
4495
  ariaLabel: market.question,
4167
4496
  classNames: { root: cn("agg-market-list-item", classNames == null ? void 0 : classNames.item) },
4168
4497
  live,
4169
4498
  midpointsFallback,
4170
- midpointsFallbackVenues
4499
+ midpointsFallbackVenues,
4500
+ midpointsResult
4171
4501
  }
4172
4502
  ) }, market.id);
4173
4503
  return /* @__PURE__ */ jsxs7("div", { className: cn("agg-market-list flex flex-col gap-3", classNames == null ? void 0 : classNames.root), children: [
@@ -4177,7 +4507,7 @@ var MarketDetailsList = ({
4177
4507
  {
4178
4508
  variant: "tertiary",
4179
4509
  size: "small",
4180
- className: "agg-market-view-resolved-toggle self-start",
4510
+ className: "agg-market-view-resolved-toggle self-start my-2",
4181
4511
  onClick: () => {
4182
4512
  setAreResolvedMarketsVisible((isVisible) => !isVisible);
4183
4513
  },
@@ -4207,6 +4537,72 @@ import { useEffect as useEffect6, useMemo as useMemo8, useRef as useRef7, useSta
4207
4537
  // src/events/list/event-list-tabs.tsx
4208
4538
  import { useAppConfig, useLabels as useLabels7 } from "@agg-build/hooks";
4209
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
4210
4606
  import { jsx as jsx10 } from "react/jsx-runtime";
4211
4607
  var renderTabIcon = (tab, isActive) => {
4212
4608
  if (tab.venueLogo) {
@@ -4396,7 +4792,7 @@ var EventList = ({
4396
4792
  isFetchingNextPage,
4397
4793
  isPlaceholderData,
4398
4794
  loadedPageCount
4399
- } = useVenueEvents(__spreadProps(__spreadValues({
4795
+ } = useVenueEvents({
4400
4796
  queryKeyScope: "event-list",
4401
4797
  venues,
4402
4798
  search,
@@ -4406,13 +4802,9 @@ var EventList = ({
4406
4802
  status: [MarketStatus2.open],
4407
4803
  sortBy: "volume24hr",
4408
4804
  sortDir: "desc",
4409
- endDateFrom
4410
- }, !search ? {
4411
- minYesPrice: 0.03,
4412
- maxYesPrice: 0.97
4413
- } : {}), {
4805
+ endDateFrom,
4414
4806
  initialPages: initialLoadedPageCount
4415
- }));
4807
+ });
4416
4808
  useEffect6(() => {
4417
4809
  if (stateRef) {
4418
4810
  stateRef.current = { venueTab: activeTabValue, loadedPageCount };
@@ -4500,7 +4892,8 @@ var EventList = ({
4500
4892
  onEventClick,
4501
4893
  onMarketClick,
4502
4894
  getMarketHref,
4503
- href: getEventHref == null ? void 0 : getEventHref(event)
4895
+ href: getEventHref == null ? void 0 : getEventHref(event),
4896
+ marketStatus: MarketStatus2.open
4504
4897
  },
4505
4898
  event.id
4506
4899
  )),
@@ -4522,14 +4915,14 @@ var EventList = ({
4522
4915
  icon: /* @__PURE__ */ jsx11(Icon, { name: "search-empty" })
4523
4916
  }
4524
4917
  ) }) : null,
4525
- isError ? /* @__PURE__ */ jsx11(
4918
+ isError ? /* @__PURE__ */ jsx11("div", { className: "col-span-full w-full", children: /* @__PURE__ */ jsx11(
4526
4919
  StateMessage,
4527
4920
  {
4528
4921
  title: labels.eventList.errorTitle,
4529
4922
  description: labels.eventList.errorDescription,
4530
4923
  icon: /* @__PURE__ */ jsx11(Icon, { name: "warning" })
4531
4924
  }
4532
- ) : null
4925
+ ) }) : null
4533
4926
  ] }),
4534
4927
  shouldPaginate && hasNextPage ? /* @__PURE__ */ jsx11("div", { ref: loadMoreRef, className: "agg-event-list-sentinel h-px w-full", "aria-hidden": true }) : null
4535
4928
  ] });
@@ -4550,6 +4943,7 @@ export {
4550
4943
  Orderbook,
4551
4944
  MarketDetails,
4552
4945
  MarketDetailsList,
4946
+ DEFAULT_EVENTS_LIMIT,
4553
4947
  useEventListTabs,
4554
4948
  EventListTabs,
4555
4949
  useEventListTabsHeaderOverflow,