@agg-build/ui 1.3.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/{chunk-ONVP7YWS.mjs → chunk-3OI2ZLLT.mjs} +94 -39
  2. package/dist/{chunk-UFC7L74C.mjs → chunk-C5M2OOM3.mjs} +1 -1
  3. package/dist/{chunk-QUZWA34R.mjs → chunk-DXF2LMNN.mjs} +512 -503
  4. package/dist/{chunk-5ALBEKAT.mjs → chunk-R6FBYAY5.mjs} +246 -194
  5. package/dist/{chunk-6PQ6O6M5.mjs → chunk-Y6PVXAUQ.mjs} +34 -90
  6. package/dist/{chunk-YWJIYEJV.mjs → chunk-YAEA6EDG.mjs} +31 -18
  7. package/dist/{chunk-55ODXLOS.mjs → chunk-YMVD6Q2A.mjs} +1 -1
  8. package/dist/events.js +894 -903
  9. package/dist/events.mjs +3 -3
  10. package/dist/index.js +2609 -2530
  11. package/dist/index.mjs +9 -7
  12. package/dist/modals.js +278 -171
  13. package/dist/modals.mjs +5 -3
  14. package/dist/pages.js +2014 -1991
  15. package/dist/pages.mjs +6 -6
  16. package/dist/primitives.js +526 -475
  17. package/dist/primitives.mjs +1 -1
  18. package/dist/styles.css +1 -1
  19. package/dist/tailwind.css +1 -1
  20. package/dist/trading.js +28 -15
  21. package/dist/trading.mjs +4 -4
  22. package/dist/types/events/list/category-sidebar.d.mts +33 -0
  23. package/dist/types/events/list/category-sidebar.d.ts +33 -0
  24. package/dist/types/events/list/event-list-tabs.d.mts +2 -0
  25. package/dist/types/events/list/event-list-tabs.d.ts +2 -0
  26. package/dist/types/events/list/event-list.utils.d.mts +0 -4
  27. package/dist/types/events/list/event-list.utils.d.ts +0 -4
  28. package/dist/types/events/list/index.d.mts +1 -0
  29. package/dist/types/events/list/index.d.ts +1 -0
  30. package/dist/types/pages/event-market/event-market.types.d.mts +1 -0
  31. package/dist/types/pages/event-market/event-market.types.d.ts +1 -0
  32. package/dist/types/pages/user-profile/index.d.mts +1 -1
  33. package/dist/types/pages/user-profile/index.d.ts +1 -1
  34. package/dist/types/pages/user-profile/user-profile.types.d.mts +1 -0
  35. package/dist/types/pages/user-profile/user-profile.types.d.ts +1 -0
  36. package/dist/types/shared/use-horizontal-scroll-state.d.mts +15 -0
  37. package/dist/types/shared/use-horizontal-scroll-state.d.ts +15 -0
  38. package/dist/types/withdraw/index.d.mts +9 -1
  39. package/dist/types/withdraw/index.d.ts +9 -1
  40. package/dist/types/withdraw/steps/withdraw-amount.d.mts +10 -1
  41. package/dist/types/withdraw/steps/withdraw-amount.d.ts +10 -1
  42. package/dist/types/withdraw/withdraw-modal.types.d.mts +8 -0
  43. package/dist/types/withdraw/withdraw-modal.types.d.ts +8 -0
  44. package/package.json +3 -3
@@ -4955,7 +4955,7 @@ var Footer = ({
4955
4955
  "div",
4956
4956
  {
4957
4957
  className: cn(
4958
- "agg-footer-inner mx-auto flex h-10 w-full max-w-[1360px] px-6 lg:px-10 items-center justify-between",
4958
+ "agg-footer-inner mx-auto flex h-10 w-full max-w-[1440px] px-6 lg:px-10 items-center justify-between",
4959
4959
  classNames == null ? void 0 : classNames.inner
4960
4960
  ),
4961
4961
  children: [
@@ -5094,321 +5094,6 @@ import {
5094
5094
  // src/events/list/event-list.utils.ts
5095
5095
  import { MarketStatus } from "@agg-build/hooks";
5096
5096
  import { VENUES } from "@agg-build/sdk";
5097
-
5098
- // src/events/item/event-list-item.utils.ts
5099
- import { MAX_PRICE_GAP_PCT, MIN_PRICE_GAP_PCT } from "@agg-build/hooks";
5100
-
5101
- // src/events/shared/venue-market-cluster.ts
5102
- var toNonEmptyString = (value) => {
5103
- if (typeof value !== "string") return void 0;
5104
- const trimmedValue = value.trim();
5105
- return trimmedValue ? trimmedValue : void 0;
5106
- };
5107
- var addGraphEdge = (adjacencyById, fromMarketId, toMarketId) => {
5108
- var _a, _b;
5109
- if (fromMarketId === toMarketId) return;
5110
- const fromNeighbors = (_a = adjacencyById.get(fromMarketId)) != null ? _a : /* @__PURE__ */ new Set();
5111
- fromNeighbors.add(toMarketId);
5112
- adjacencyById.set(fromMarketId, fromNeighbors);
5113
- const toNeighbors = (_b = adjacencyById.get(toMarketId)) != null ? _b : /* @__PURE__ */ new Set();
5114
- toNeighbors.add(fromMarketId);
5115
- adjacencyById.set(toMarketId, toNeighbors);
5116
- };
5117
- var dedupeSourceMarketsById = (markets) => {
5118
- const seenMarketIds = /* @__PURE__ */ new Set();
5119
- return markets.filter((market) => {
5120
- if (seenMarketIds.has(market.id)) {
5121
- return false;
5122
- }
5123
- seenMarketIds.add(market.id);
5124
- return true;
5125
- });
5126
- };
5127
- var collectDirectRelationMarkets = (market) => {
5128
- var _a, _b, _c;
5129
- const relationMarkets = [];
5130
- const seenRelationIds = /* @__PURE__ */ new Set();
5131
- const addRelationMarket = (relationMarket) => {
5132
- if (!relationMarket) return;
5133
- if (seenRelationIds.has(relationMarket.id)) return;
5134
- seenRelationIds.add(relationMarket.id);
5135
- relationMarkets.push(relationMarket);
5136
- };
5137
- for (const matchedVenueMarket of (_a = market.matchedVenueMarkets) != null ? _a : []) {
5138
- addRelationMarket(matchedVenueMarket);
5139
- }
5140
- addRelationMarket(
5141
- (_c = (_b = market.matchEntry) == null ? void 0 : _b.targetVenueMarket) != null ? _c : void 0
5142
- );
5143
- return relationMarkets;
5144
- };
5145
- var collectUniqueRelatedMarkets = (markets, sourceMarketsById) => {
5146
- const relatedMarketsById = /* @__PURE__ */ new Map();
5147
- for (const market of markets) {
5148
- for (const relatedMarket of collectDirectRelationMarkets(market)) {
5149
- if (sourceMarketsById.has(relatedMarket.id) || relatedMarketsById.has(relatedMarket.id)) {
5150
- continue;
5151
- }
5152
- relatedMarketsById.set(relatedMarket.id, relatedMarket);
5153
- }
5154
- }
5155
- return Array.from(relatedMarketsById.values());
5156
- };
5157
- var normalizeVenueMarketCluster = (markets, selectedMarketId) => {
5158
- var _a, _b;
5159
- if (markets.length === 0) return [];
5160
- const orderedSourceMarkets = dedupeSourceMarketsById(markets);
5161
- const sourceMarketsById = new Map(orderedSourceMarkets.map((market) => [market.id, market]));
5162
- const orderedRelatedMarkets = collectUniqueRelatedMarkets(
5163
- orderedSourceMarkets,
5164
- sourceMarketsById
5165
- );
5166
- const relatedMarketsById = new Map(orderedRelatedMarkets.map((market) => [market.id, market]));
5167
- const resolvedSelectedMarketId = toNonEmptyString(selectedMarketId);
5168
- if (!resolvedSelectedMarketId) {
5169
- return [...orderedSourceMarkets, ...orderedRelatedMarkets];
5170
- }
5171
- const adjacencyById = /* @__PURE__ */ new Map();
5172
- for (const market of orderedSourceMarkets) {
5173
- for (const relatedMarket of collectDirectRelationMarkets(market)) {
5174
- addGraphEdge(adjacencyById, market.id, relatedMarket.id);
5175
- }
5176
- const targetVenueMarketId = toNonEmptyString((_a = market.matchEntry) == null ? void 0 : _a.targetVenueMarketId);
5177
- if (targetVenueMarketId) {
5178
- addGraphEdge(adjacencyById, market.id, targetVenueMarketId);
5179
- }
5180
- }
5181
- if (!sourceMarketsById.has(resolvedSelectedMarketId) && !relatedMarketsById.has(resolvedSelectedMarketId)) {
5182
- return [];
5183
- }
5184
- const visitedMarketIds = /* @__PURE__ */ new Set();
5185
- const queue = [resolvedSelectedMarketId];
5186
- while (queue.length > 0) {
5187
- const currentMarketId = queue.shift();
5188
- if (!currentMarketId || visitedMarketIds.has(currentMarketId)) {
5189
- continue;
5190
- }
5191
- visitedMarketIds.add(currentMarketId);
5192
- const neighborMarketIds = adjacencyById.get(currentMarketId);
5193
- for (const neighborMarketId of Array.from(neighborMarketIds != null ? neighborMarketIds : /* @__PURE__ */ new Set())) {
5194
- if (!visitedMarketIds.has(neighborMarketId)) {
5195
- queue.push(neighborMarketId);
5196
- }
5197
- }
5198
- }
5199
- const orderedClusterMarkets = [];
5200
- const appendedMarketIds = /* @__PURE__ */ new Set();
5201
- const appendMarket = (market) => {
5202
- if (!market) return;
5203
- if (!visitedMarketIds.has(market.id)) return;
5204
- if (appendedMarketIds.has(market.id)) return;
5205
- appendedMarketIds.add(market.id);
5206
- orderedClusterMarkets.push(market);
5207
- };
5208
- appendMarket(
5209
- (_b = sourceMarketsById.get(resolvedSelectedMarketId)) != null ? _b : relatedMarketsById.get(resolvedSelectedMarketId)
5210
- );
5211
- for (const market of orderedSourceMarkets) {
5212
- appendMarket(market);
5213
- }
5214
- for (const market of orderedRelatedMarkets) {
5215
- appendMarket(market);
5216
- }
5217
- return orderedClusterMarkets;
5218
- };
5219
-
5220
- // src/events/item/event-list-item.utils.ts
5221
- var resolveEventListItemEvent = (fetchedEvent) => {
5222
- if (!fetchedEvent) return void 0;
5223
- if (!fetchedEvent.venueMarkets || fetchedEvent.venueMarkets.length === 0) return void 0;
5224
- return fetchedEvent;
5225
- };
5226
- var normalizeProbability = (value) => {
5227
- if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
5228
- if (value < 0) return 0;
5229
- if (value > 1) return 1;
5230
- return value;
5231
- };
5232
- var formatWholePercent = (value) => {
5233
- return `${Math.round(value * 100)}%`;
5234
- };
5235
- var hasDateLabel = (outcome) => {
5236
- return !!toDate(outcome.label);
5237
- };
5238
- var isYesLabel = (label2) => label2.trim().toLowerCase() === "yes";
5239
- var isNoLabel = (label2) => label2.trim().toLowerCase() === "no";
5240
- var hasBinaryOutcomes = (outcomes) => {
5241
- return outcomes.some((o) => isYesLabel(o.label)) && outcomes.some((o) => isNoLabel(o.label));
5242
- };
5243
- var sortYesFirst = (outcomes) => {
5244
- return [...outcomes].sort((a, b) => {
5245
- if (isYesLabel(a.label) && !isYesLabel(b.label)) return -1;
5246
- if (!isYesLabel(a.label) && isYesLabel(b.label)) return 1;
5247
- return 0;
5248
- });
5249
- };
5250
- var resolveYesOutcome = (market) => {
5251
- return market.venueMarketOutcomes.find((outcome) => isYesLabel(outcome.label));
5252
- };
5253
- var resolveYesOutcomeProbability = (market) => {
5254
- var _a;
5255
- return normalizeProbability((_a = resolveYesOutcome(market)) == null ? void 0 : _a.price);
5256
- };
5257
- var formatMarketProbabilityPercent = (value, formatPercent = formatWholePercent) => {
5258
- const probability = normalizeProbability(value);
5259
- if (probability == null) return "-";
5260
- const formattedValue = formatPercent(probability);
5261
- if (probability > 0 && formattedValue === formatPercent(0)) {
5262
- return "<1%";
5263
- }
5264
- return formattedValue;
5265
- };
5266
- var formatPriceGapPercent = (value) => {
5267
- if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
5268
- if (value < MIN_PRICE_GAP_PCT) return void 0;
5269
- if (value > MAX_PRICE_GAP_PCT) return void 0;
5270
- return `${Math.round(value)}%`;
5271
- };
5272
- var sortOutcomes = (outcomes) => {
5273
- if (outcomes.length <= 1) return outcomes;
5274
- if (hasBinaryOutcomes(outcomes)) {
5275
- return sortYesFirst(outcomes);
5276
- }
5277
- const now = Date.now();
5278
- if (outcomes.some(hasDateLabel)) {
5279
- return [...outcomes].sort((a, b) => {
5280
- var _a, _b, _c, _d;
5281
- const aDate = (_b = (_a = toDate(a.label)) == null ? void 0 : _a.getTime()) != null ? _b : 0;
5282
- const bDate = (_d = (_c = toDate(b.label)) == null ? void 0 : _c.getTime()) != null ? _d : 0;
5283
- return Math.abs(aDate - now) - Math.abs(bDate - now);
5284
- });
5285
- }
5286
- return [...outcomes].sort((a, b) => {
5287
- var _a, _b;
5288
- const aPrice = (_a = normalizeProbability(a.price)) != null ? _a : 0;
5289
- const bPrice = (_b = normalizeProbability(b.price)) != null ? _b : 0;
5290
- return bPrice - aPrice;
5291
- });
5292
- };
5293
- var compareVisibleOutcomeRows = (left, right) => {
5294
- var _a, _b;
5295
- const leftDate = toDate(resolveOutcomeTitle(left.outcome));
5296
- const rightDate = toDate(resolveOutcomeTitle(right.outcome));
5297
- if (leftDate && rightDate) {
5298
- return leftDate.getTime() - rightDate.getTime();
5299
- }
5300
- const leftProbability = (_a = normalizeProbability(left.outcome.price)) != null ? _a : -1;
5301
- const rightProbability = (_b = normalizeProbability(right.outcome.price)) != null ? _b : -1;
5302
- return rightProbability - leftProbability;
5303
- };
5304
- var shouldReplaceVisibleOutcome = (current, next) => {
5305
- var _a, _b;
5306
- const currentVolume = typeof current.market.volume === "number" ? current.market.volume : -1;
5307
- const nextVolume = typeof next.market.volume === "number" ? next.market.volume : -1;
5308
- if (currentVolume !== nextVolume) {
5309
- return nextVolume > currentVolume;
5310
- }
5311
- const currentProbability = (_a = normalizeProbability(current.outcome.price)) != null ? _a : -1;
5312
- const nextProbability = (_b = normalizeProbability(next.outcome.price)) != null ? _b : -1;
5313
- return nextProbability > currentProbability;
5314
- };
5315
- var resolveVisibleOutcomes = (venueMarkets) => {
5316
- const visibleOutcomesByLabel = /* @__PURE__ */ new Map();
5317
- venueMarkets.forEach((market) => {
5318
- const title2 = market.question;
5319
- const canonicalOutcome = sortOutcomes(market.venueMarketOutcomes)[0];
5320
- if (!canonicalOutcome) return;
5321
- const normalizedTitle = title2.trim().toLowerCase();
5322
- const nextVisibleOutcome = {
5323
- venue: market.venue,
5324
- market,
5325
- outcome: canonicalOutcome,
5326
- title: title2
5327
- };
5328
- const currentVisibleOutcome = visibleOutcomesByLabel.get(normalizedTitle);
5329
- if (!currentVisibleOutcome || shouldReplaceVisibleOutcome(currentVisibleOutcome, nextVisibleOutcome)) {
5330
- visibleOutcomesByLabel.set(normalizedTitle, nextVisibleOutcome);
5331
- }
5332
- });
5333
- return [...visibleOutcomesByLabel.values()].sort(compareVisibleOutcomeRows).slice(0, Math.max(1, 2));
5334
- };
5335
- var dedupeVenueMarketsById = (venueMarkets) => {
5336
- const seenClusterIds = /* @__PURE__ */ new Set();
5337
- return venueMarkets.filter((venueMarket) => {
5338
- var _a;
5339
- if (seenClusterIds.has(venueMarket.id)) {
5340
- return false;
5341
- }
5342
- seenClusterIds.add(venueMarket.id);
5343
- for (const sibling of (_a = venueMarket.matchedVenueMarkets) != null ? _a : []) {
5344
- seenClusterIds.add(sibling.id);
5345
- }
5346
- return true;
5347
- });
5348
- };
5349
- var resolveOutcomeTitle = (outcome) => {
5350
- var _a, _b;
5351
- return (_b = (_a = outcome == null ? void 0 : outcome.title) != null ? _a : outcome == null ? void 0 : outcome.label) == null ? void 0 : _b.trim();
5352
- };
5353
- var selectPrimaryVenueMarket = (venueMarkets) => {
5354
- if (venueMarkets.length === 0) return void 0;
5355
- if (venueMarkets.length === 1) return venueMarkets[0];
5356
- return [...venueMarkets].sort((a, b) => {
5357
- const aVolume = typeof a.volume === "number" ? a.volume : -1;
5358
- const bVolume = typeof b.volume === "number" ? b.volume : -1;
5359
- return bVolume - aVolume;
5360
- })[0];
5361
- };
5362
- var resolveTileImage = (event, primaryVenueMarket, imageOverride) => {
5363
- if (typeof imageOverride === "string" && imageOverride.trim()) {
5364
- return imageOverride;
5365
- }
5366
- if (typeof event.image === "string" && event.image.trim()) {
5367
- return event.image;
5368
- }
5369
- if (typeof (primaryVenueMarket == null ? void 0 : primaryVenueMarket.image) === "string" && primaryVenueMarket.image.trim()) {
5370
- return primaryVenueMarket.image;
5371
- }
5372
- return void 0;
5373
- };
5374
- var formatCountLabel = (count, singular, plural) => {
5375
- return `${count} ${count === 1 ? singular : plural}`;
5376
- };
5377
- var getVenueSummary = (venueMarkets, options) => {
5378
- const normalizedVenueMarkets = normalizeVenueMarketCluster(venueMarkets);
5379
- const tradableVenues = options == null ? void 0 : options.tradableVenues;
5380
- const isVenueTradable = (venue) => {
5381
- if (tradableVenues == null) return true;
5382
- return tradableVenues.has(venue);
5383
- };
5384
- const uniqueVenues = Array.from(
5385
- new Set(
5386
- normalizedVenueMarkets.filter((market) => isVenueTradable(market.venue)).map((market) => market.venue)
5387
- )
5388
- );
5389
- return {
5390
- marketCount: normalizedVenueMarkets.length,
5391
- venueCount: uniqueVenues.length,
5392
- singleVenue: uniqueVenues.length === 1 ? uniqueVenues[0] : void 0
5393
- };
5394
- };
5395
- var resolveVenueLabel = (venue, venueInfo, labels) => {
5396
- var _a, _b;
5397
- if (!venue) return labels.eventItem.venueSingular;
5398
- return (_b = (_a = venueInfo == null ? void 0 : venueInfo[venue]) == null ? void 0 : _a.label) != null ? _b : labels.venues[venue];
5399
- };
5400
- var resolveDisplayVolume = (eventVolume, venueMarkets) => {
5401
- if (typeof eventVolume === "number" && eventVolume > 0) return eventVolume;
5402
- const clusterMarkets = normalizeVenueMarketCluster(venueMarkets);
5403
- const marketSum = clusterMarkets.reduce(
5404
- (acc, m) => acc + (typeof m.volume === "number" ? m.volume : 0),
5405
- 0
5406
- );
5407
- if (marketSum > 0) return marketSum;
5408
- return void 0;
5409
- };
5410
-
5411
- // src/events/list/event-list.utils.ts
5412
5097
  var filterOpenEvents = (events) => {
5413
5098
  return events.filter((event) => {
5414
5099
  var _a;
@@ -5488,43 +5173,7 @@ var mapEventToEventListItemEvent = (event) => {
5488
5173
  return event;
5489
5174
  };
5490
5175
  var filterEventsByTabValue = (events, _tabValue) => {
5491
- return events;
5492
- };
5493
- var sortMarketsByYesOddsDesc = (markets) => {
5494
- return markets.map((market, index) => ({
5495
- market,
5496
- index,
5497
- yesProbability: resolveYesOutcomeProbability(market)
5498
- })).sort((left, right) => {
5499
- const leftHasYesProbability = left.yesProbability != null;
5500
- const rightHasYesProbability = right.yesProbability != null;
5501
- if (leftHasYesProbability !== rightHasYesProbability) {
5502
- return leftHasYesProbability ? -1 : 1;
5503
- }
5504
- if (left.yesProbability != null && right.yesProbability != null) {
5505
- if (left.yesProbability !== right.yesProbability) {
5506
- return right.yesProbability - left.yesProbability;
5507
- }
5508
- }
5509
- return left.index - right.index;
5510
- }).map(({ market }) => market);
5511
- };
5512
- var resolveMarketVolume = (market) => {
5513
- if (typeof market.volume !== "number") return 0;
5514
- if (!Number.isFinite(market.volume)) return 0;
5515
- return market.volume;
5516
- };
5517
- var sortMarketsByVolumeDesc = (markets) => {
5518
- return markets.map((market, index) => ({
5519
- market,
5520
- index,
5521
- volume: resolveMarketVolume(market)
5522
- })).sort((left, right) => {
5523
- if (left.volume !== right.volume) {
5524
- return right.volume - left.volume;
5525
- }
5526
- return left.index - right.index;
5527
- }).map(({ market }) => market);
5176
+ return events;
5528
5177
  };
5529
5178
  var sortCategoriesForNavigation = (categories) => {
5530
5179
  return [...categories].sort((left, right) => {
@@ -6855,70 +6504,381 @@ var resolveVenueLogoIsColor = ({
6855
6504
  }) => {
6856
6505
  return isMonochromatic ? false : isColor;
6857
6506
  };
6858
-
6859
- // src/primitives/venue-logo/index.tsx
6860
- import { jsx as jsx117 } from "react/jsx-runtime";
6861
- var VenueLogo = ({
6862
- venue,
6863
- variant = "icon",
6864
- isColor = true,
6865
- isMonochromatic = false,
6866
- color,
6867
- size = "medium",
6868
- className,
6869
- ariaLabel,
6870
- title: title2
6871
- }) => {
6507
+
6508
+ // src/primitives/venue-logo/index.tsx
6509
+ import { jsx as jsx117 } from "react/jsx-runtime";
6510
+ var VenueLogo = ({
6511
+ venue,
6512
+ variant = "icon",
6513
+ isColor = true,
6514
+ isMonochromatic = false,
6515
+ color,
6516
+ size = "medium",
6517
+ className,
6518
+ ariaLabel,
6519
+ title: title2
6520
+ }) => {
6521
+ var _a, _b;
6522
+ const labels = useLabels9();
6523
+ const sizeClass = sizeClasses2[size];
6524
+ const resolvedLabel = resolveVenueLogoLabel({
6525
+ ariaLabel,
6526
+ labels,
6527
+ venue,
6528
+ venueFallbackLabels: venueLogoLabels
6529
+ });
6530
+ const isUnknownVenue = !(venue in venueLogoRegistry);
6531
+ if (isUnknownVenue && process.env.NODE_ENV === "development") {
6532
+ console.warn(`[AggUI] Unknown venue "${venue}" \u2014 using default logo`);
6533
+ }
6534
+ if (variant === "logo") {
6535
+ return /* @__PURE__ */ jsx117(
6536
+ RemoteImage,
6537
+ {
6538
+ src: (_a = venueLogoUrlRegistry[venue]) != null ? _a : DEFAULT_VENUE_LOGO_URL,
6539
+ alt: resolvedLabel || DEFAULT_VENUE_LABEL,
6540
+ title: title2,
6541
+ className: cn("shrink-0 rounded-agg-lg object-cover", sizeClass, className)
6542
+ }
6543
+ );
6544
+ }
6545
+ const Component2 = (_b = venueLogoRegistry[venue]) != null ? _b : DefaultVenueIcon;
6546
+ const resolvedIsColor = resolveVenueLogoIsColor({
6547
+ isColor,
6548
+ isMonochromatic
6549
+ });
6550
+ return /* @__PURE__ */ jsx117(
6551
+ Component2,
6552
+ {
6553
+ className: cn("group/agg-venue-logo", "shrink-0", sizeClass, className),
6554
+ isColor: resolvedIsColor,
6555
+ color,
6556
+ "aria-label": resolvedLabel || DEFAULT_VENUE_LABEL,
6557
+ title: title2
6558
+ }
6559
+ );
6560
+ };
6561
+ VenueLogo.displayName = "VenueLogo";
6562
+
6563
+ // src/primitives/search/search.constants.ts
6564
+ var DEFAULT_SEARCH_LIMIT = 5;
6565
+ var MIN_SEARCH_LENGTH = 3;
6566
+ var SEARCH_DEBOUNCE_MS = 300;
6567
+
6568
+ // src/primitives/search/search.utils.ts
6569
+ import { VENUES as VENUES2 } from "@agg-build/sdk";
6570
+ import dayjs2 from "dayjs";
6571
+
6572
+ // src/events/item/event-list-item.utils.ts
6573
+ import { MAX_PRICE_GAP_PCT, MIN_PRICE_GAP_PCT } from "@agg-build/hooks";
6574
+
6575
+ // src/events/shared/venue-market-cluster.ts
6576
+ var toNonEmptyString = (value) => {
6577
+ if (typeof value !== "string") return void 0;
6578
+ const trimmedValue = value.trim();
6579
+ return trimmedValue ? trimmedValue : void 0;
6580
+ };
6581
+ var addGraphEdge = (adjacencyById, fromMarketId, toMarketId) => {
6582
+ var _a, _b;
6583
+ if (fromMarketId === toMarketId) return;
6584
+ const fromNeighbors = (_a = adjacencyById.get(fromMarketId)) != null ? _a : /* @__PURE__ */ new Set();
6585
+ fromNeighbors.add(toMarketId);
6586
+ adjacencyById.set(fromMarketId, fromNeighbors);
6587
+ const toNeighbors = (_b = adjacencyById.get(toMarketId)) != null ? _b : /* @__PURE__ */ new Set();
6588
+ toNeighbors.add(fromMarketId);
6589
+ adjacencyById.set(toMarketId, toNeighbors);
6590
+ };
6591
+ var dedupeSourceMarketsById = (markets) => {
6592
+ const seenMarketIds = /* @__PURE__ */ new Set();
6593
+ return markets.filter((market) => {
6594
+ if (seenMarketIds.has(market.id)) {
6595
+ return false;
6596
+ }
6597
+ seenMarketIds.add(market.id);
6598
+ return true;
6599
+ });
6600
+ };
6601
+ var collectDirectRelationMarkets = (market) => {
6602
+ var _a, _b, _c;
6603
+ const relationMarkets = [];
6604
+ const seenRelationIds = /* @__PURE__ */ new Set();
6605
+ const addRelationMarket = (relationMarket) => {
6606
+ if (!relationMarket) return;
6607
+ if (seenRelationIds.has(relationMarket.id)) return;
6608
+ seenRelationIds.add(relationMarket.id);
6609
+ relationMarkets.push(relationMarket);
6610
+ };
6611
+ for (const matchedVenueMarket of (_a = market.matchedVenueMarkets) != null ? _a : []) {
6612
+ addRelationMarket(matchedVenueMarket);
6613
+ }
6614
+ addRelationMarket(
6615
+ (_c = (_b = market.matchEntry) == null ? void 0 : _b.targetVenueMarket) != null ? _c : void 0
6616
+ );
6617
+ return relationMarkets;
6618
+ };
6619
+ var collectUniqueRelatedMarkets = (markets, sourceMarketsById) => {
6620
+ const relatedMarketsById = /* @__PURE__ */ new Map();
6621
+ for (const market of markets) {
6622
+ for (const relatedMarket of collectDirectRelationMarkets(market)) {
6623
+ if (sourceMarketsById.has(relatedMarket.id) || relatedMarketsById.has(relatedMarket.id)) {
6624
+ continue;
6625
+ }
6626
+ relatedMarketsById.set(relatedMarket.id, relatedMarket);
6627
+ }
6628
+ }
6629
+ return Array.from(relatedMarketsById.values());
6630
+ };
6631
+ var normalizeVenueMarketCluster = (markets, selectedMarketId) => {
6632
+ var _a, _b;
6633
+ if (markets.length === 0) return [];
6634
+ const orderedSourceMarkets = dedupeSourceMarketsById(markets);
6635
+ const sourceMarketsById = new Map(orderedSourceMarkets.map((market) => [market.id, market]));
6636
+ const orderedRelatedMarkets = collectUniqueRelatedMarkets(
6637
+ orderedSourceMarkets,
6638
+ sourceMarketsById
6639
+ );
6640
+ const relatedMarketsById = new Map(orderedRelatedMarkets.map((market) => [market.id, market]));
6641
+ const resolvedSelectedMarketId = toNonEmptyString(selectedMarketId);
6642
+ if (!resolvedSelectedMarketId) {
6643
+ return [...orderedSourceMarkets, ...orderedRelatedMarkets];
6644
+ }
6645
+ const adjacencyById = /* @__PURE__ */ new Map();
6646
+ for (const market of orderedSourceMarkets) {
6647
+ for (const relatedMarket of collectDirectRelationMarkets(market)) {
6648
+ addGraphEdge(adjacencyById, market.id, relatedMarket.id);
6649
+ }
6650
+ const targetVenueMarketId = toNonEmptyString((_a = market.matchEntry) == null ? void 0 : _a.targetVenueMarketId);
6651
+ if (targetVenueMarketId) {
6652
+ addGraphEdge(adjacencyById, market.id, targetVenueMarketId);
6653
+ }
6654
+ }
6655
+ if (!sourceMarketsById.has(resolvedSelectedMarketId) && !relatedMarketsById.has(resolvedSelectedMarketId)) {
6656
+ return [];
6657
+ }
6658
+ const visitedMarketIds = /* @__PURE__ */ new Set();
6659
+ const queue = [resolvedSelectedMarketId];
6660
+ while (queue.length > 0) {
6661
+ const currentMarketId = queue.shift();
6662
+ if (!currentMarketId || visitedMarketIds.has(currentMarketId)) {
6663
+ continue;
6664
+ }
6665
+ visitedMarketIds.add(currentMarketId);
6666
+ const neighborMarketIds = adjacencyById.get(currentMarketId);
6667
+ for (const neighborMarketId of Array.from(neighborMarketIds != null ? neighborMarketIds : /* @__PURE__ */ new Set())) {
6668
+ if (!visitedMarketIds.has(neighborMarketId)) {
6669
+ queue.push(neighborMarketId);
6670
+ }
6671
+ }
6672
+ }
6673
+ const orderedClusterMarkets = [];
6674
+ const appendedMarketIds = /* @__PURE__ */ new Set();
6675
+ const appendMarket = (market) => {
6676
+ if (!market) return;
6677
+ if (!visitedMarketIds.has(market.id)) return;
6678
+ if (appendedMarketIds.has(market.id)) return;
6679
+ appendedMarketIds.add(market.id);
6680
+ orderedClusterMarkets.push(market);
6681
+ };
6682
+ appendMarket(
6683
+ (_b = sourceMarketsById.get(resolvedSelectedMarketId)) != null ? _b : relatedMarketsById.get(resolvedSelectedMarketId)
6684
+ );
6685
+ for (const market of orderedSourceMarkets) {
6686
+ appendMarket(market);
6687
+ }
6688
+ for (const market of orderedRelatedMarkets) {
6689
+ appendMarket(market);
6690
+ }
6691
+ return orderedClusterMarkets;
6692
+ };
6693
+
6694
+ // src/events/item/event-list-item.utils.ts
6695
+ var resolveEventListItemEvent = (fetchedEvent) => {
6696
+ if (!fetchedEvent) return void 0;
6697
+ if (!fetchedEvent.venueMarkets || fetchedEvent.venueMarkets.length === 0) return void 0;
6698
+ return fetchedEvent;
6699
+ };
6700
+ var normalizeProbability = (value) => {
6701
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
6702
+ if (value < 0) return 0;
6703
+ if (value > 1) return 1;
6704
+ return value;
6705
+ };
6706
+ var formatWholePercent = (value) => {
6707
+ return `${Math.round(value * 100)}%`;
6708
+ };
6709
+ var hasDateLabel = (outcome) => {
6710
+ return !!toDate(outcome.label);
6711
+ };
6712
+ var isYesLabel = (label2) => label2.trim().toLowerCase() === "yes";
6713
+ var isNoLabel = (label2) => label2.trim().toLowerCase() === "no";
6714
+ var hasBinaryOutcomes = (outcomes) => {
6715
+ return outcomes.some((o) => isYesLabel(o.label)) && outcomes.some((o) => isNoLabel(o.label));
6716
+ };
6717
+ var sortYesFirst = (outcomes) => {
6718
+ return [...outcomes].sort((a, b) => {
6719
+ if (isYesLabel(a.label) && !isYesLabel(b.label)) return -1;
6720
+ if (!isYesLabel(a.label) && isYesLabel(b.label)) return 1;
6721
+ return 0;
6722
+ });
6723
+ };
6724
+ var resolveYesOutcome = (market) => {
6725
+ return market.venueMarketOutcomes.find((outcome) => isYesLabel(outcome.label));
6726
+ };
6727
+ var formatMarketProbabilityPercent = (value, formatPercent = formatWholePercent) => {
6728
+ const probability = normalizeProbability(value);
6729
+ if (probability == null) return "-";
6730
+ const formattedValue = formatPercent(probability);
6731
+ if (probability > 0 && formattedValue === formatPercent(0)) {
6732
+ return "<1%";
6733
+ }
6734
+ return formattedValue;
6735
+ };
6736
+ var formatPriceGapPercent = (value) => {
6737
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
6738
+ if (value < MIN_PRICE_GAP_PCT) return void 0;
6739
+ if (value > MAX_PRICE_GAP_PCT) return void 0;
6740
+ return `${Math.round(value)}%`;
6741
+ };
6742
+ var sortOutcomes = (outcomes) => {
6743
+ if (outcomes.length <= 1) return outcomes;
6744
+ if (hasBinaryOutcomes(outcomes)) {
6745
+ return sortYesFirst(outcomes);
6746
+ }
6747
+ const now = Date.now();
6748
+ if (outcomes.some(hasDateLabel)) {
6749
+ return [...outcomes].sort((a, b) => {
6750
+ var _a, _b, _c, _d;
6751
+ const aDate = (_b = (_a = toDate(a.label)) == null ? void 0 : _a.getTime()) != null ? _b : 0;
6752
+ const bDate = (_d = (_c = toDate(b.label)) == null ? void 0 : _c.getTime()) != null ? _d : 0;
6753
+ return Math.abs(aDate - now) - Math.abs(bDate - now);
6754
+ });
6755
+ }
6756
+ return [...outcomes].sort((a, b) => {
6757
+ var _a, _b;
6758
+ const aPrice = (_a = normalizeProbability(a.price)) != null ? _a : 0;
6759
+ const bPrice = (_b = normalizeProbability(b.price)) != null ? _b : 0;
6760
+ return bPrice - aPrice;
6761
+ });
6762
+ };
6763
+ var compareVisibleOutcomeRows = (left, right) => {
6872
6764
  var _a, _b;
6873
- const labels = useLabels9();
6874
- const sizeClass = sizeClasses2[size];
6875
- const resolvedLabel = resolveVenueLogoLabel({
6876
- ariaLabel,
6877
- labels,
6878
- venue,
6879
- venueFallbackLabels: venueLogoLabels
6880
- });
6881
- const isUnknownVenue = !(venue in venueLogoRegistry);
6882
- if (isUnknownVenue && process.env.NODE_ENV === "development") {
6883
- console.warn(`[AggUI] Unknown venue "${venue}" \u2014 using default logo`);
6765
+ const leftDate = toDate(resolveOutcomeTitle(left.outcome));
6766
+ const rightDate = toDate(resolveOutcomeTitle(right.outcome));
6767
+ if (leftDate && rightDate) {
6768
+ return leftDate.getTime() - rightDate.getTime();
6884
6769
  }
6885
- if (variant === "logo") {
6886
- return /* @__PURE__ */ jsx117(
6887
- RemoteImage,
6888
- {
6889
- src: (_a = venueLogoUrlRegistry[venue]) != null ? _a : DEFAULT_VENUE_LOGO_URL,
6890
- alt: resolvedLabel || DEFAULT_VENUE_LABEL,
6891
- title: title2,
6892
- className: cn("shrink-0 rounded-agg-lg object-cover", sizeClass, className)
6893
- }
6894
- );
6770
+ const leftProbability = (_a = normalizeProbability(left.outcome.price)) != null ? _a : -1;
6771
+ const rightProbability = (_b = normalizeProbability(right.outcome.price)) != null ? _b : -1;
6772
+ return rightProbability - leftProbability;
6773
+ };
6774
+ var shouldReplaceVisibleOutcome = (current, next) => {
6775
+ var _a, _b;
6776
+ const currentVolume = typeof current.market.volume === "number" ? current.market.volume : -1;
6777
+ const nextVolume = typeof next.market.volume === "number" ? next.market.volume : -1;
6778
+ if (currentVolume !== nextVolume) {
6779
+ return nextVolume > currentVolume;
6895
6780
  }
6896
- const Component2 = (_b = venueLogoRegistry[venue]) != null ? _b : DefaultVenueIcon;
6897
- const resolvedIsColor = resolveVenueLogoIsColor({
6898
- isColor,
6899
- isMonochromatic
6900
- });
6901
- return /* @__PURE__ */ jsx117(
6902
- Component2,
6903
- {
6904
- className: cn("group/agg-venue-logo", "shrink-0", sizeClass, className),
6905
- isColor: resolvedIsColor,
6906
- color,
6907
- "aria-label": resolvedLabel || DEFAULT_VENUE_LABEL,
6781
+ const currentProbability = (_a = normalizeProbability(current.outcome.price)) != null ? _a : -1;
6782
+ const nextProbability = (_b = normalizeProbability(next.outcome.price)) != null ? _b : -1;
6783
+ return nextProbability > currentProbability;
6784
+ };
6785
+ var resolveVisibleOutcomes = (venueMarkets) => {
6786
+ const visibleOutcomesByLabel = /* @__PURE__ */ new Map();
6787
+ venueMarkets.forEach((market) => {
6788
+ const title2 = market.question;
6789
+ const canonicalOutcome = sortOutcomes(market.venueMarketOutcomes)[0];
6790
+ if (!canonicalOutcome) return;
6791
+ const normalizedTitle = title2.trim().toLowerCase();
6792
+ const nextVisibleOutcome = {
6793
+ venue: market.venue,
6794
+ market,
6795
+ outcome: canonicalOutcome,
6908
6796
  title: title2
6797
+ };
6798
+ const currentVisibleOutcome = visibleOutcomesByLabel.get(normalizedTitle);
6799
+ if (!currentVisibleOutcome || shouldReplaceVisibleOutcome(currentVisibleOutcome, nextVisibleOutcome)) {
6800
+ visibleOutcomesByLabel.set(normalizedTitle, nextVisibleOutcome);
6801
+ }
6802
+ });
6803
+ return [...visibleOutcomesByLabel.values()].sort(compareVisibleOutcomeRows).slice(0, Math.max(1, 2));
6804
+ };
6805
+ var dedupeVenueMarketsById = (venueMarkets) => {
6806
+ const seenClusterIds = /* @__PURE__ */ new Set();
6807
+ return venueMarkets.filter((venueMarket) => {
6808
+ var _a;
6809
+ if (seenClusterIds.has(venueMarket.id)) {
6810
+ return false;
6811
+ }
6812
+ seenClusterIds.add(venueMarket.id);
6813
+ for (const sibling of (_a = venueMarket.matchedVenueMarkets) != null ? _a : []) {
6814
+ seenClusterIds.add(sibling.id);
6909
6815
  }
6816
+ return true;
6817
+ });
6818
+ };
6819
+ var resolveOutcomeTitle = (outcome) => {
6820
+ var _a, _b;
6821
+ return (_b = (_a = outcome == null ? void 0 : outcome.title) != null ? _a : outcome == null ? void 0 : outcome.label) == null ? void 0 : _b.trim();
6822
+ };
6823
+ var selectPrimaryVenueMarket = (venueMarkets) => {
6824
+ if (venueMarkets.length === 0) return void 0;
6825
+ if (venueMarkets.length === 1) return venueMarkets[0];
6826
+ return [...venueMarkets].sort((a, b) => {
6827
+ const aVolume = typeof a.volume === "number" ? a.volume : -1;
6828
+ const bVolume = typeof b.volume === "number" ? b.volume : -1;
6829
+ return bVolume - aVolume;
6830
+ })[0];
6831
+ };
6832
+ var resolveTileImage = (event, primaryVenueMarket, imageOverride) => {
6833
+ if (typeof imageOverride === "string" && imageOverride.trim()) {
6834
+ return imageOverride;
6835
+ }
6836
+ if (typeof event.image === "string" && event.image.trim()) {
6837
+ return event.image;
6838
+ }
6839
+ if (typeof (primaryVenueMarket == null ? void 0 : primaryVenueMarket.image) === "string" && primaryVenueMarket.image.trim()) {
6840
+ return primaryVenueMarket.image;
6841
+ }
6842
+ return void 0;
6843
+ };
6844
+ var formatCountLabel = (count, singular, plural) => {
6845
+ return `${count} ${count === 1 ? singular : plural}`;
6846
+ };
6847
+ var getVenueSummary = (venueMarkets, options) => {
6848
+ const normalizedVenueMarkets = normalizeVenueMarketCluster(venueMarkets);
6849
+ const tradableVenues = options == null ? void 0 : options.tradableVenues;
6850
+ const isVenueTradable = (venue) => {
6851
+ if (tradableVenues == null) return true;
6852
+ return tradableVenues.has(venue);
6853
+ };
6854
+ const uniqueVenues = Array.from(
6855
+ new Set(
6856
+ normalizedVenueMarkets.filter((market) => isVenueTradable(market.venue)).map((market) => market.venue)
6857
+ )
6910
6858
  );
6859
+ return {
6860
+ marketCount: normalizedVenueMarkets.length,
6861
+ venueCount: uniqueVenues.length,
6862
+ singleVenue: uniqueVenues.length === 1 ? uniqueVenues[0] : void 0
6863
+ };
6864
+ };
6865
+ var resolveVenueLabel = (venue, venueInfo, labels) => {
6866
+ var _a, _b;
6867
+ if (!venue) return labels.eventItem.venueSingular;
6868
+ return (_b = (_a = venueInfo == null ? void 0 : venueInfo[venue]) == null ? void 0 : _a.label) != null ? _b : labels.venues[venue];
6869
+ };
6870
+ var resolveDisplayVolume = (eventVolume, venueMarkets) => {
6871
+ if (typeof eventVolume === "number" && eventVolume > 0) return eventVolume;
6872
+ const clusterMarkets = normalizeVenueMarketCluster(venueMarkets);
6873
+ const marketSum = clusterMarkets.reduce(
6874
+ (acc, m) => acc + (typeof m.volume === "number" ? m.volume : 0),
6875
+ 0
6876
+ );
6877
+ if (marketSum > 0) return marketSum;
6878
+ return void 0;
6911
6879
  };
6912
- VenueLogo.displayName = "VenueLogo";
6913
-
6914
- // src/primitives/search/search.constants.ts
6915
- var DEFAULT_SEARCH_LIMIT = 5;
6916
- var MIN_SEARCH_LENGTH = 3;
6917
- var SEARCH_DEBOUNCE_MS = 300;
6918
6880
 
6919
6881
  // src/primitives/search/search.utils.ts
6920
- import { VENUES as VENUES2 } from "@agg-build/sdk";
6921
- import dayjs2 from "dayjs";
6922
6882
  var formatSearchContextLabel = (value) => {
6923
6883
  if (!dayjs2(value).isValid()) return value;
6924
6884
  return dayjs2(value).format("MMMM D, YYYY");
@@ -7556,7 +7516,7 @@ var Header = ({
7556
7516
  "div",
7557
7517
  {
7558
7518
  className: cn(
7559
- "agg-header-inner mx-auto flex h-auto w-full max-w-[1360px] px-6 lg:px-10 items-center gap-2 md:gap-4 py-5",
7519
+ "agg-header-inner mx-auto flex h-auto w-full max-w-[1440px] px-6 lg:px-10 items-center gap-2 md:gap-4 py-5",
7560
7520
  classNames == null ? void 0 : classNames.inner
7561
7521
  ),
7562
7522
  children: [
@@ -8598,7 +8558,37 @@ StateMessage.displayName = "StateMessage";
8598
8558
 
8599
8559
  // src/primitives/tabs/index.tsx
8600
8560
  import { useLabels as useLabels16, useSdkUiConfig as useSdkUiConfig15 } from "@agg-build/hooks";
8601
- import { useCallback as useCallback5, useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useMemo as useMemo7, useRef as useRef8, useState as useState9 } from "react";
8561
+ import { useCallback as useCallback6, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useMemo as useMemo7, useRef as useRef9, useState as useState10 } from "react";
8562
+
8563
+ // src/shared/use-horizontal-scroll-state.ts
8564
+ import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef8, useState as useState9 } from "react";
8565
+ var useHorizontalScrollState = () => {
8566
+ const containerRef = useRef8(null);
8567
+ const [canScrollLeft, setCanScrollLeft] = useState9(false);
8568
+ const [canScrollRight, setCanScrollRight] = useState9(false);
8569
+ const update = useCallback5(() => {
8570
+ const el = containerRef.current;
8571
+ if (!el) return;
8572
+ const maxScroll = el.scrollWidth - el.clientWidth;
8573
+ setCanScrollLeft(el.scrollLeft > 4);
8574
+ setCanScrollRight(maxScroll - el.scrollLeft > 4);
8575
+ }, []);
8576
+ useEffect8(() => {
8577
+ const el = containerRef.current;
8578
+ if (!el) return;
8579
+ el.addEventListener("scroll", update, { passive: true });
8580
+ return () => el.removeEventListener("scroll", update);
8581
+ }, [update]);
8582
+ useEffect8(() => {
8583
+ if (typeof ResizeObserver === "undefined") return;
8584
+ const el = containerRef.current;
8585
+ if (!el) return;
8586
+ const ro = new ResizeObserver(() => update());
8587
+ ro.observe(el);
8588
+ return () => ro.disconnect();
8589
+ }, [update]);
8590
+ return { containerRef, canScrollLeft, canScrollRight, update };
8591
+ };
8602
8592
 
8603
8593
  // src/primitives/tabs/tabs.constants.ts
8604
8594
  var MOBILE_TABS_MEDIA_QUERY = "(max-width: 736px)";
@@ -8672,8 +8662,8 @@ var Tabs = ({
8672
8662
  const {
8673
8663
  features: { enableAnimations }
8674
8664
  } = useSdkUiConfig15();
8675
- const buttonRefs = useRef8([]);
8676
- const dragStateRef = useRef8({
8665
+ const buttonRefs = useRef9([]);
8666
+ const dragStateRef = useRef9({
8677
8667
  isPointerDown: false,
8678
8668
  isDragging: false,
8679
8669
  pointerId: null,
@@ -8681,20 +8671,21 @@ var Tabs = ({
8681
8671
  startClientY: 0,
8682
8672
  startScrollLeft: 0
8683
8673
  });
8684
- const suppressClickRef = useRef8(false);
8674
+ const suppressClickRef = useRef9(false);
8685
8675
  const resolvedAriaLabel = ariaLabel != null ? ariaLabel : labels.common.tabsAria;
8686
- const [isMobileViewport, setIsMobileViewport] = useState9(false);
8687
- const [isDraggingTabs, setIsDraggingTabs] = useState9(false);
8688
- const [activeUnderlineStyle, setActiveUnderlineStyle] = useState9({
8676
+ const [isMobileViewport, setIsMobileViewport] = useState10(false);
8677
+ const [isDraggingTabs, setIsDraggingTabs] = useState10(false);
8678
+ const [activeUnderlineStyle, setActiveUnderlineStyle] = useState10({
8689
8679
  transform: "translateX(0px)",
8690
8680
  width: 0,
8691
8681
  opacity: 0
8692
8682
  });
8693
- const [scrollAffordanceState, setScrollAffordanceState] = useState9({
8694
- showStart: false,
8695
- showEnd: false
8696
- });
8697
- const tabListRef = useRef8(null);
8683
+ const {
8684
+ containerRef: tabListRef,
8685
+ canScrollLeft,
8686
+ canScrollRight,
8687
+ update: updateScrollState
8688
+ } = useHorizontalScrollState();
8698
8689
  const isBarVariant = variant === "bar";
8699
8690
  const resolvedOverflowBehavior = useMemo7(() => {
8700
8691
  if (overflowBehavior) return overflowBehavior;
@@ -8703,7 +8694,7 @@ var Tabs = ({
8703
8694
  }, [isBarVariant, isMobileViewport, overflowBehavior]);
8704
8695
  const shouldUseOverflowScroll = resolvedOverflowBehavior === "scroll";
8705
8696
  const shouldUseOverflowSelect = resolvedOverflowBehavior === "select";
8706
- useEffect8(() => {
8697
+ useEffect9(() => {
8707
8698
  if (typeof window === "undefined") return;
8708
8699
  const mediaQueryList = window.matchMedia(MOBILE_TABS_MEDIA_QUERY);
8709
8700
  const handleMediaQueryChange = (event) => {
@@ -8721,22 +8712,6 @@ var Tabs = ({
8721
8712
  mediaQueryList.removeListener(handleMediaQueryChange);
8722
8713
  };
8723
8714
  }, []);
8724
- const updateScrollAffordances = useCallback5(() => {
8725
- if (!shouldUseOverflowScroll) {
8726
- setScrollAffordanceState({
8727
- showStart: false,
8728
- showEnd: false
8729
- });
8730
- return;
8731
- }
8732
- const tabListElement = tabListRef.current;
8733
- if (!tabListElement) return;
8734
- const maxScrollLeft = tabListElement.scrollWidth - tabListElement.clientWidth;
8735
- setScrollAffordanceState({
8736
- showStart: tabListElement.scrollLeft > 4,
8737
- showEnd: maxScrollLeft - tabListElement.scrollLeft > 4
8738
- });
8739
- }, [shouldUseOverflowScroll]);
8740
8715
  const renderedItems = useMemo7(() => {
8741
8716
  return items.map((item) => __spreadProps(__spreadValues({}, item), {
8742
8717
  disabled: item.disabled || item.isComingSoon
@@ -8875,7 +8850,7 @@ var Tabs = ({
8875
8850
  event == null ? void 0 : event.stopPropagation();
8876
8851
  suppressClickRef.current = false;
8877
8852
  };
8878
- const updateActiveUnderline = useCallback5(() => {
8853
+ const updateActiveUnderline = useCallback6(() => {
8879
8854
  if (isBarVariant) {
8880
8855
  setActiveUnderlineStyle({
8881
8856
  transform: "translateX(0px)",
@@ -8901,39 +8876,36 @@ var Tabs = ({
8901
8876
  useLayoutEffect3(() => {
8902
8877
  updateActiveUnderline();
8903
8878
  }, [updateActiveUnderline]);
8904
- useEffect8(() => {
8879
+ useEffect9(() => {
8905
8880
  if (isBarVariant || !shouldUseOverflowScroll) return;
8906
8881
  const tabListElement = tabListRef.current;
8907
8882
  if (!tabListElement) return;
8908
8883
  const handleScroll = () => {
8909
8884
  updateActiveUnderline();
8910
- updateScrollAffordances();
8911
8885
  };
8912
8886
  tabListElement.addEventListener("scroll", handleScroll, { passive: true });
8913
- updateScrollAffordances();
8914
8887
  return () => {
8915
8888
  tabListElement.removeEventListener("scroll", handleScroll);
8916
8889
  };
8917
- }, [isBarVariant, shouldUseOverflowScroll, updateActiveUnderline, updateScrollAffordances]);
8918
- useEffect8(() => {
8890
+ }, [isBarVariant, shouldUseOverflowScroll, tabListRef, updateActiveUnderline]);
8891
+ useEffect9(() => {
8919
8892
  if (!shouldUseOverflowScroll) return;
8920
- updateScrollAffordances();
8921
- }, [renderedItems, shouldUseOverflowScroll, updateScrollAffordances, value]);
8922
- useEffect8(() => {
8923
- if (isBarVariant && !shouldUseOverflowScroll) return;
8893
+ updateScrollState();
8894
+ }, [renderedItems, shouldUseOverflowScroll, updateScrollState, value]);
8895
+ useEffect9(() => {
8896
+ if (isBarVariant || !shouldUseOverflowScroll) return;
8924
8897
  if (typeof ResizeObserver === "undefined") return;
8925
8898
  const tabListElement = tabListRef.current;
8926
8899
  if (!tabListElement) return;
8927
8900
  const resizeObserver = new ResizeObserver(() => {
8928
8901
  updateActiveUnderline();
8929
- updateScrollAffordances();
8930
8902
  });
8931
8903
  resizeObserver.observe(tabListElement);
8932
8904
  return () => {
8933
8905
  resizeObserver.disconnect();
8934
8906
  };
8935
- }, [isBarVariant, shouldUseOverflowScroll, updateActiveUnderline, updateScrollAffordances]);
8936
- useEffect8(() => {
8907
+ }, [isBarVariant, shouldUseOverflowScroll, tabListRef, updateActiveUnderline]);
8908
+ useEffect9(() => {
8937
8909
  if (!shouldUseOverflowScroll) return;
8938
8910
  const tabListElement = tabListRef.current;
8939
8911
  if (!tabListElement) return;
@@ -9080,7 +9052,7 @@ var Tabs = ({
9080
9052
  "agg-tab-scroll-start",
9081
9053
  "pointer-events-none absolute top-0 bottom-0 left-0 z-10 w-12 md:w-18 bg-linear-to-r from-agg-secondary via-agg-secondary to-transparent",
9082
9054
  getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9083
- scrollAffordanceState.showStart ? "opacity-100" : "opacity-0"
9055
+ canScrollLeft ? "opacity-100" : "opacity-0"
9084
9056
  )
9085
9057
  }
9086
9058
  ),
@@ -9092,24 +9064,63 @@ var Tabs = ({
9092
9064
  "agg-tab-scroll-end",
9093
9065
  "pointer-events-none absolute top-0 right-0 bottom-0 z-10 w-12 md:w-18 bg-linear-to-l from-agg-secondary via-agg-secondary to-transparent",
9094
9066
  getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9095
- scrollAffordanceState.showEnd ? "opacity-100" : "opacity-0"
9067
+ canScrollRight ? "opacity-100" : "opacity-0"
9096
9068
  )
9097
9069
  }
9098
9070
  )
9099
9071
  ] }) : null,
9100
- shouldUseOverflowScroll && isBarVariant ? /* @__PURE__ */ jsx127(
9101
- "span",
9102
- {
9103
- "aria-hidden": true,
9104
- className: cn(
9105
- "agg-tab-scroll-end",
9106
- "pointer-events-none absolute top-0 right-0 bottom-0 z-10 w-[120px] overflow-hidden rounded-r-[8px] bg-linear-to-l from-agg-secondary from-[20%] via-agg-secondary/85 to-transparent",
9107
- getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9108
- scrollAffordanceState.showEnd ? "opacity-100" : "opacity-0"
9109
- ),
9110
- children: /* @__PURE__ */ jsx127("span", { className: "absolute inset-y-0 right-3 inline-flex items-center text-agg-foreground", children: /* @__PURE__ */ jsx127(Icon, { name: "chevron-right", size: "small", color: "currentColor" }) })
9111
- }
9112
- ) : null
9072
+ shouldUseOverflowScroll && isBarVariant ? /* @__PURE__ */ jsxs120(Fragment9, { children: [
9073
+ /* @__PURE__ */ jsx127(
9074
+ "button",
9075
+ {
9076
+ type: "button",
9077
+ "aria-label": labels.common.scrollTabsLeft,
9078
+ tabIndex: -1,
9079
+ className: cn(
9080
+ "agg-tab-scroll-start",
9081
+ "absolute top-0 bottom-0 left-0 z-10 w-20 rounded-l-agg-lg",
9082
+ "inline-flex items-center justify-start pl-2",
9083
+ "bg-linear-to-r from-agg-secondary from-[25%] via-agg-secondary/80 to-transparent",
9084
+ "cursor-pointer",
9085
+ getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9086
+ canScrollLeft ? "opacity-100" : "opacity-0 pointer-events-none"
9087
+ ),
9088
+ onClick: () => {
9089
+ var _a;
9090
+ (_a = tabListRef.current) == null ? void 0 : _a.scrollBy({
9091
+ left: -200,
9092
+ behavior: getScrollBehavior(enableAnimations)
9093
+ });
9094
+ },
9095
+ children: /* @__PURE__ */ jsx127(Icon, { name: "chevron-left", size: "small", color: "currentColor" })
9096
+ }
9097
+ ),
9098
+ /* @__PURE__ */ jsx127(
9099
+ "button",
9100
+ {
9101
+ type: "button",
9102
+ "aria-label": labels.common.scrollTabsRight,
9103
+ tabIndex: -1,
9104
+ className: cn(
9105
+ "agg-tab-scroll-end",
9106
+ "absolute top-0 right-0 bottom-0 z-10 w-20 rounded-r-agg-lg",
9107
+ "inline-flex items-center justify-end pr-2",
9108
+ "bg-linear-to-l from-agg-secondary from-[25%] via-agg-secondary/80 to-transparent",
9109
+ "cursor-pointer",
9110
+ getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9111
+ canScrollRight ? "opacity-100" : "opacity-0 pointer-events-none"
9112
+ ),
9113
+ onClick: () => {
9114
+ var _a;
9115
+ (_a = tabListRef.current) == null ? void 0 : _a.scrollBy({
9116
+ left: 200,
9117
+ behavior: getScrollBehavior(enableAnimations)
9118
+ });
9119
+ },
9120
+ children: /* @__PURE__ */ jsx127(Icon, { name: "chevron-right", size: "small", color: "currentColor" })
9121
+ }
9122
+ )
9123
+ ] }) : null
9113
9124
  ]
9114
9125
  }
9115
9126
  );
@@ -9120,11 +9131,11 @@ Tabs.displayName = "Tabs";
9120
9131
  import * as RadixToast from "@radix-ui/react-toast";
9121
9132
  import {
9122
9133
  createContext,
9123
- useCallback as useCallback6,
9134
+ useCallback as useCallback7,
9124
9135
  useContext,
9125
- useEffect as useEffect9,
9126
- useRef as useRef9,
9127
- useState as useState10
9136
+ useEffect as useEffect10,
9137
+ useRef as useRef10,
9138
+ useState as useState11
9128
9139
  } from "react";
9129
9140
  import { jsx as jsx128, jsxs as jsxs121 } from "react/jsx-runtime";
9130
9141
  var DEFAULT_DURATION_MS = 5e3;
@@ -9149,12 +9160,12 @@ function ToastProvider({
9149
9160
  swipeThreshold = 50,
9150
9161
  viewportClassName
9151
9162
  }) {
9152
- const [toasts, setToasts] = useState10([]);
9153
- const idRef = useRef9(0);
9154
- const dismiss = useCallback6((id) => {
9163
+ const [toasts, setToasts] = useState11([]);
9164
+ const idRef = useRef10(0);
9165
+ const dismiss = useCallback7((id) => {
9155
9166
  setToasts((current) => current.filter((entry) => entry.id !== id));
9156
9167
  }, []);
9157
- const toast = useCallback6(
9168
+ const toast = useCallback7(
9158
9169
  (message, options) => {
9159
9170
  const id = ++idRef.current;
9160
9171
  setToasts((current) => {
@@ -9199,31 +9210,31 @@ function ToastProvider({
9199
9210
  ] }) });
9200
9211
  }
9201
9212
  function ToastRow({ entry, onOpenChange }) {
9202
- const [isOpen, setIsOpen] = useState10(true);
9213
+ const [isOpen, setIsOpen] = useState11(true);
9203
9214
  const hasAutoDismiss = entry.durationMs > 0 && Number.isFinite(entry.durationMs);
9204
9215
  const duration = hasAutoDismiss ? entry.durationMs : Number.POSITIVE_INFINITY;
9205
- const timeoutRef = useRef9(null);
9206
- const closeTimeoutRef = useRef9(null);
9207
- const remainingMsRef = useRef9(duration);
9208
- const timerStartedAtRef = useRef9(null);
9209
- const onOpenChangeRef = useRef9(onOpenChange);
9216
+ const timeoutRef = useRef10(null);
9217
+ const closeTimeoutRef = useRef10(null);
9218
+ const remainingMsRef = useRef10(duration);
9219
+ const timerStartedAtRef = useRef10(null);
9220
+ const onOpenChangeRef = useRef10(onOpenChange);
9210
9221
  const rootStyle = {
9211
9222
  "--agg-toast-duration": `${duration}ms`
9212
9223
  };
9213
- useEffect9(() => {
9224
+ useEffect10(() => {
9214
9225
  onOpenChangeRef.current = onOpenChange;
9215
9226
  }, [onOpenChange]);
9216
- const clearDismissTimer = useCallback6(() => {
9227
+ const clearDismissTimer = useCallback7(() => {
9217
9228
  if (!timeoutRef.current) return;
9218
9229
  clearTimeout(timeoutRef.current);
9219
9230
  timeoutRef.current = null;
9220
9231
  }, []);
9221
- const clearCloseTimer = useCallback6(() => {
9232
+ const clearCloseTimer = useCallback7(() => {
9222
9233
  if (!closeTimeoutRef.current) return;
9223
9234
  clearTimeout(closeTimeoutRef.current);
9224
9235
  closeTimeoutRef.current = null;
9225
9236
  }, []);
9226
- const handleOpenChange = useCallback6(
9237
+ const handleOpenChange = useCallback7(
9227
9238
  (open) => {
9228
9239
  if (open) {
9229
9240
  clearCloseTimer();
@@ -9240,7 +9251,7 @@ function ToastRow({ entry, onOpenChange }) {
9240
9251
  },
9241
9252
  [clearCloseTimer, clearDismissTimer]
9242
9253
  );
9243
- const startDismissTimer = useCallback6(() => {
9254
+ const startDismissTimer = useCallback7(() => {
9244
9255
  if (!hasAutoDismiss) return;
9245
9256
  clearDismissTimer();
9246
9257
  timerStartedAtRef.current = Date.now();
@@ -9248,18 +9259,18 @@ function ToastRow({ entry, onOpenChange }) {
9248
9259
  handleOpenChange(false);
9249
9260
  }, remainingMsRef.current);
9250
9261
  }, [clearDismissTimer, handleOpenChange, hasAutoDismiss]);
9251
- const handlePauseDismissTimer = useCallback6(() => {
9262
+ const handlePauseDismissTimer = useCallback7(() => {
9252
9263
  if (!hasAutoDismiss || timerStartedAtRef.current === null) return;
9253
9264
  const elapsedMs = Date.now() - timerStartedAtRef.current;
9254
9265
  remainingMsRef.current = Math.max(0, remainingMsRef.current - elapsedMs);
9255
9266
  timerStartedAtRef.current = null;
9256
9267
  clearDismissTimer();
9257
9268
  }, [clearDismissTimer, hasAutoDismiss]);
9258
- const handleResumeDismissTimer = useCallback6(() => {
9269
+ const handleResumeDismissTimer = useCallback7(() => {
9259
9270
  if (!hasAutoDismiss || timerStartedAtRef.current !== null) return;
9260
9271
  startDismissTimer();
9261
9272
  }, [hasAutoDismiss, startDismissTimer]);
9262
- useEffect9(() => {
9273
+ useEffect10(() => {
9263
9274
  remainingMsRef.current = duration;
9264
9275
  startDismissTimer();
9265
9276
  return () => {
@@ -9565,25 +9576,10 @@ export {
9565
9576
  CopyButton,
9566
9577
  CurrencyInput,
9567
9578
  Footer,
9568
- normalizeVenueMarketCluster,
9569
- resolveEventListItemEvent,
9570
- normalizeProbability,
9571
- resolveYesOutcome,
9572
- formatMarketProbabilityPercent,
9573
- formatPriceGapPercent,
9574
- sortOutcomes,
9575
- dedupeVenueMarketsById,
9576
- resolveOutcomeTitle,
9577
- selectPrimaryVenueMarket,
9578
- getVenueSummary,
9579
- resolveVenueLabel,
9580
- resolveDisplayVolume,
9581
9579
  filterOpenEvents,
9582
9580
  splitEventsByLifecycle,
9583
9581
  mapEventToEventListItemEvent,
9584
9582
  filterEventsByTabValue,
9585
- sortMarketsByYesOddsDesc,
9586
- sortMarketsByVolumeDesc,
9587
9583
  sortCategoriesForNavigation,
9588
9584
  resolveCategoryIdsFromPath,
9589
9585
  resolveTabVenus,
@@ -9604,6 +9600,19 @@ export {
9604
9600
  DEFAULT_VENUE_COLOR,
9605
9601
  fallbackLineColors,
9606
9602
  VenueLogo,
9603
+ normalizeVenueMarketCluster,
9604
+ resolveEventListItemEvent,
9605
+ normalizeProbability,
9606
+ resolveYesOutcome,
9607
+ formatMarketProbabilityPercent,
9608
+ formatPriceGapPercent,
9609
+ sortOutcomes,
9610
+ dedupeVenueMarketsById,
9611
+ resolveOutcomeTitle,
9612
+ selectPrimaryVenueMarket,
9613
+ getVenueSummary,
9614
+ resolveVenueLabel,
9615
+ resolveDisplayVolume,
9607
9616
  Search,
9608
9617
  Header,
9609
9618
  InlineAlert,