@agg-build/ui 1.3.0 → 2.0.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.
@@ -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;
@@ -5487,45 +5172,9 @@ var mapEventToEventListItemEvent = (event) => {
5487
5172
  if (!event.venueMarkets || event.venueMarkets.length === 0) return null;
5488
5173
  return event;
5489
5174
  };
5490
- 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);
5528
- };
5175
+ var filterEventsByTabValue = (events, _tabValue) => {
5176
+ return events;
5177
+ };
5529
5178
  var sortCategoriesForNavigation = (categories) => {
5530
5179
  return [...categories].sort((left, right) => {
5531
5180
  const leftIsOther = left.name.trim().toLowerCase() === "other";
@@ -6821,104 +6470,415 @@ var lineColorByVenue = {
6821
6470
  [Venue9.hyperliquid]: "#97FCE4"
6822
6471
  }
6823
6472
  };
6824
- var resolveVenueLineColor = (venue, isDarkTheme) => {
6825
- return lineColorByVenue[isDarkTheme ? "dark" : "light"][venue];
6473
+ var resolveVenueLineColor = (venue, isDarkTheme) => {
6474
+ return lineColorByVenue[isDarkTheme ? "dark" : "light"][venue];
6475
+ };
6476
+ var DEFAULT_VENUE_COLOR = "#94a3b8";
6477
+ var fallbackLineColors = [
6478
+ DEFAULT_VENUE_COLOR,
6479
+ "#7AF2D3",
6480
+ "#C14BFF",
6481
+ "#FFB703",
6482
+ "#3A86FF",
6483
+ "#8AC926",
6484
+ "#FF6F61",
6485
+ "#6A4C93",
6486
+ "#00BBF9",
6487
+ "#F15BB5",
6488
+ "#2EC4B6"
6489
+ ];
6490
+
6491
+ // src/primitives/venue-logo/venue-logo.utils.ts
6492
+ var resolveVenueLogoLabel = ({
6493
+ ariaLabel,
6494
+ labels,
6495
+ venue,
6496
+ venueFallbackLabels
6497
+ }) => {
6498
+ var _a;
6499
+ return (_a = ariaLabel != null ? ariaLabel : labels.venues[venue]) != null ? _a : venueFallbackLabels[venue];
6500
+ };
6501
+ var resolveVenueLogoIsColor = ({
6502
+ isColor,
6503
+ isMonochromatic
6504
+ }) => {
6505
+ return isMonochromatic ? false : isColor;
6506
+ };
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;
6826
6735
  };
6827
- var DEFAULT_VENUE_COLOR = "#94a3b8";
6828
- var fallbackLineColors = [
6829
- DEFAULT_VENUE_COLOR,
6830
- "#7AF2D3",
6831
- "#C14BFF",
6832
- "#FFB703",
6833
- "#3A86FF",
6834
- "#8AC926",
6835
- "#FF6F61",
6836
- "#6A4C93",
6837
- "#00BBF9",
6838
- "#F15BB5",
6839
- "#2EC4B6"
6840
- ];
6841
-
6842
- // src/primitives/venue-logo/venue-logo.utils.ts
6843
- var resolveVenueLogoLabel = ({
6844
- ariaLabel,
6845
- labels,
6846
- venue,
6847
- venueFallbackLabels
6848
- }) => {
6849
- var _a;
6850
- return (_a = ariaLabel != null ? ariaLabel : labels.venues[venue]) != null ? _a : venueFallbackLabels[venue];
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)}%`;
6851
6741
  };
6852
- var resolveVenueLogoIsColor = ({
6853
- isColor,
6854
- isMonochromatic
6855
- }) => {
6856
- return isMonochromatic ? false : isColor;
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
+ });
6857
6762
  };
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
- }) => {
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");
@@ -9565,25 +9525,10 @@ export {
9565
9525
  CopyButton,
9566
9526
  CurrencyInput,
9567
9527
  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
9528
  filterOpenEvents,
9582
9529
  splitEventsByLifecycle,
9583
9530
  mapEventToEventListItemEvent,
9584
9531
  filterEventsByTabValue,
9585
- sortMarketsByYesOddsDesc,
9586
- sortMarketsByVolumeDesc,
9587
9532
  sortCategoriesForNavigation,
9588
9533
  resolveCategoryIdsFromPath,
9589
9534
  resolveTabVenus,
@@ -9604,6 +9549,19 @@ export {
9604
9549
  DEFAULT_VENUE_COLOR,
9605
9550
  fallbackLineColors,
9606
9551
  VenueLogo,
9552
+ normalizeVenueMarketCluster,
9553
+ resolveEventListItemEvent,
9554
+ normalizeProbability,
9555
+ resolveYesOutcome,
9556
+ formatMarketProbabilityPercent,
9557
+ formatPriceGapPercent,
9558
+ sortOutcomes,
9559
+ dedupeVenueMarketsById,
9560
+ resolveOutcomeTitle,
9561
+ selectPrimaryVenueMarket,
9562
+ getVenueSummary,
9563
+ resolveVenueLabel,
9564
+ resolveDisplayVolume,
9607
9565
  Search,
9608
9566
  Header,
9609
9567
  InlineAlert,